Compare commits

...

541 Commits

Author SHA1 Message Date
4e37df26a3 2.31.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-04-10 20:33:54 +03:00
5e606573b1 2.31.0 2020-04-10 12:57:47 -04:00
b3974cb52a [webconsole] security hardening headers (closes #1464)
Signed-off-by: r4sas <r4sas@i2pmail.org>
2020-04-10 02:34:47 +00:00
b7c206c44b replace by new incoming session 2020-04-09 15:00:38 -04:00
49c1e47736 correct termination if session already exists 2020-04-08 18:02:12 -04:00
4e1319d874 handle ECIESFlag in DatabaseLookup at floodfill 2020-04-07 11:40:18 -04:00
a9436aa9af drop i2lua
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-04-03 14:31:38 +03:00
d503f07564 suppress GCC 7 (bug 77728) psabi note
Suppresses messages like that:
    note: parameter passing for argument of type <...> will change in GCC 7.1

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-04-03 14:31:38 +03:00
aa7750bfd3 keep sending new session reply until first established session message received 2020-04-02 21:48:39 -04:00
8872d1f389 mutex for m_RemoteIdentity 2020-04-01 09:54:10 -04:00
f21af4068f preferred crypto type for Decrypt 2020-03-31 17:35:51 -04:00
f4ca6bbb52 fixed race with identity verifier 2020-03-30 19:27:10 -04:00
869d0156ce handle Ack request 2020-03-26 19:03:38 -04:00
744e893dce check message length 2020-03-23 18:09:57 -04:00
fe9ac10f02 generate new tags based on last received index 2020-03-22 21:21:12 -04:00
6fb80f226a reopen socked and restart receiver on exception 2020-03-22 08:14:20 -04:00
ff19bab800 set only key correctly 2020-03-21 16:21:51 -04:00
962c2160c7 set actual LeaseSet2 buffer size 2020-03-20 17:43:37 -04:00
168da33d8b add comma
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-20 18:43:54 +03:00
b6b25dc9f3 update log messages
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-20 17:51:55 +03:00
3ca17fdc03 support multiple encryption keys 2020-03-19 18:33:42 -04:00
2249708097 [webconsole] remove excess tag
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-19 02:34:45 +03:00
2fcaa7d260 [webconsole] rework spoilers; print tags, leases, router info in table
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-19 02:27:07 +03:00
f3b0e57a54 publish multiple encryption keys 2020-03-18 18:03:03 -04:00
5da92437a1 set msg type for deliverystatus 2020-03-16 16:41:07 -04:00
b5bc05ac2b delete unconfirmed LeaseSet and DeliveryStatus 2020-03-14 16:35:34 -04:00
45145fa50a add ECIESX25519AEADRatchet session to delivery status 2020-03-14 09:33:48 -04:00
dd8200e8b0 cleanup websocks
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-12 03:50:21 +03:00
2f56547d5f Merge pull request #1477 from PurpleI2P/drop-websockets
drop websockets support
2020-03-11 12:37:38 +00:00
82bdcfbbcb Merge pull request #1491 from nonlinear-chaos-order-etc-etal/openssl
qt: delayed save in background. should be better ui experience
2020-03-10 11:39:07 -04:00
0e38e43315 some qt work. fixed on slow computers; now faster as delayed save is implemented 2020-03-10 23:22:49 +08:00
63746be4d5 resolve i2pd_qt.pro conflict 2020-03-10 21:50:57 +08:00
ee73ee365f some work on qt 2020-03-10 21:49:04 +08:00
3c53479864 update LeaseSet for ECIESX25519AEADRatchet sessions 2020-03-08 20:58:59 -04:00
4adc741de3 send DeliveryStatusMsg for LeaseSet 2020-03-08 18:13:41 -04:00
64da62dbe6 alsways store latest symmkey 2020-03-07 18:46:40 -05:00
dd9b5faa5c fixed crash on termination 2020-03-05 18:44:15 -05:00
51d018acc6 webconsole: add stream closing
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-03-05 04:14:39 +03:00
5eec580727 delete strem from destination upon termination 2020-03-04 18:31:22 -05:00
1e9a53da3f delete stream by id for HTTP interface 2020-03-04 15:54:09 -05:00
8dae044600 Merge pull request #1441 from noraj/patch-1
README: explicit linux distro supported
2020-03-03 18:07:01 +00:00
2d3fad2cdb correct proxy buffers 2020-03-02 16:24:00 -05:00
a59a8f62ca Merge pull request #1479 from wipedlifepotato/openssl
Pre init webview button. (android)
2020-03-01 21:17:14 -05:00
35cfa7d9fb Merge branch 'openssl' of github.com:wipedlifepotato/i2pd into openssl 2020-03-02 05:06:06 +03:00
c6ccb373a2 del geti2pdpath 2020-03-02 05:04:37 +03:00
b6368170ed Update README.md 2020-03-02 04:00:28 +03:00
35e8424293 preinit webview+configparser+README.md
tabulation fixes

configparser to comments

dont need

pre init webview

readme changes

delete submodules

webview in main menu

webview pre init

delete modules

delete submodules
2020-03-02 03:58:50 +03:00
e969d58689 handle ntcp2.proxy parameter 2020-03-01 15:11:54 -05:00
ae20e3aa95 NTCP2 proxy 2020-03-01 11:24:18 -05:00
de4cb74173 Merge pull request #1478 from unlnown542a/openssl
add ntcp2proxy support
2020-03-01 10:04:27 -05:00
4f0da87a7a add ntcp2proxy support 2020-03-01 14:35:24 +00:00
97f0347715 Update android stuff:
* switch to c++17
* use boost 1.72.0
* disable minify in release
* enable apk splitting (separate apk for every ABI)
* add version to output apk name

Signed-off-by: r4sas <r4sas@i2pmail.org>
2020-02-29 23:14:35 +00:00
2ffe62ba41 [[fallthrough]] if C++17 only 2020-02-29 09:21:50 -05:00
fe1724e7e6 switch travis-ci to xenial 2020-02-28 23:41:42 +03:00
2ac2da41cf cmake: fix else statement 2020-02-28 23:28:41 +03:00
ed574f9d79 use C++17 if available when configuring with cmake 2020-02-28 23:05:26 +03:00
e0cb26bd9e fixed fallthough warning for C++17 2020-02-28 14:15:41 -05:00
1893127e84 use fold expression if C++17 2020-02-28 14:05:51 -05:00
b02c9fb118 enable C++17 for gcc 2020-02-28 14:03:08 -05:00
bca0809918 cleanup removed websockets funtions
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-02-28 18:48:43 +03:00
00db527377 drop websockets support
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-02-27 14:58:06 +03:00
2c6e041ae2 rpm: make package buildable on mageia cauldron (#1476) 2020-02-26 13:41:35 +00:00
a0d6c654cc 2.30.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2020-02-25 20:08:50 +03:00
5115c27e72 2.30.0 2020-02-25 11:15:30 -05:00
d09c3ccb2d Merge pull request #1474 from rex4539/dead-strip
Pass -dead_strip -dead_strip_dylibs -bind_at_load on macOS
2020-02-24 18:16:20 +00:00
5c308026ac Pass -dead_strip -dead_strip_dylibs -bind_at_load on macOS 2020-02-21 11:12:00 +02:00
91919c6d64 check if both sides are ECIESx25519 2020-02-20 21:07:45 -05:00
7168738835 check ctx for null 2020-02-20 21:05:07 -05:00
9c9b723cf5 delete expired ECIESX25519AEADRatchet sessions and tags 2020-02-20 15:44:09 -05:00
50450923df don't add extra , to result string 2020-02-19 20:51:32 -05:00
f392edd66c single thread SAM by default 2020-02-19 13:27:28 -05:00
24b48e5d50 reseeds update 2020-02-18 17:45:04 -05:00
47f384a0e0 postpone SAM destination termination 2020-02-17 15:14:35 -05:00
88594887f9 fixed qt build 2020-02-16 17:44:36 -05:00
32e2f0b1fa correct termination of streaming destination 2020-02-15 16:30:10 -05:00
09ed57ad42 select preferred crypto from LeaseSet2 2020-02-12 11:09:20 -05:00
53a6162b0c generate more receive tags when needed 2020-02-09 17:19:42 -05:00
694d851cdb Symmetric Key Ratchet 2020-02-08 21:51:02 -05:00
8e53c30a00 correct calls sequence for tag and index 2020-02-07 22:08:55 -05:00
63e807b0b4 fixed crash on stop 2020-02-06 10:53:45 -05:00
012f22cc47 create session tags for ECIESX25519 2020-02-05 15:48:51 -05:00
9d891ab5dd single thread mode for SAM 2020-02-04 15:31:04 -05:00
d0e78be867 moved io_service away from ClientDestination 2020-02-04 14:17:23 -05:00
cbedebc9dd change minimal MTU size 2020-02-04 13:32:16 -05:00
969f9aa436 common RuunableBase with private inheritance 2020-02-04 11:48:56 -05:00
b982be5ff5 handle existing session message 2020-02-03 16:21:07 -05:00
2d154ee640 move RunnableService away from LeaseSetDestination 2020-02-02 18:58:58 -05:00
49810eb153 common RunnableService 2020-02-02 17:05:30 -05:00
85b88b8749 second x25519 for new session reply 2020-01-30 19:30:30 -05:00
239c8b5172 destination delivery instructions 2020-01-30 11:48:32 -05:00
8c800dc178 save aepk from new session message 2020-01-29 21:57:10 -05:00
cdd068d99a correct message size 2020-01-29 19:27:38 -05:00
48fa10b080 incoming ECIESX25519AEADRatchet messages hanler 2020-01-29 15:54:11 -05:00
a1dbec0fcb handle new session reply 2020-01-29 12:54:26 -05:00
abe668f1c3 fixed build error 2020-01-28 10:31:35 -05:00
77440c235d replaced map by unordered_map 2020-01-28 10:03:51 -05:00
fd1ee48dbe datetime and padding blocks 2020-01-23 14:26:40 -05:00
205e807b66 reset keys 2020-01-22 21:42:30 -05:00
34295adb05 attach LeaseSet clove 2020-01-22 14:26:47 -05:00
7c212bef63 add new session to the list after reply received 2020-01-22 11:27:47 -05:00
76f95644b7 fixed #1461. Use openssl's HKDF for 1.1.1 anf higher 2020-01-22 09:59:08 -05:00
928b90d5bc fixed #1461. Use openssl's HKDF for 1.1.1 anf higher 2020-01-22 09:50:50 -05:00
09c6c2a4f3 decode aepk and bepk back 2020-01-21 21:09:19 -05:00
2b2bd733e9 correct sharedkey for new outgoing session 2020-01-21 19:13:23 -05:00
0d2d7e5e71 fixed Elligator tests 2020-01-21 17:53:48 -05:00
6142e93252 session tag for ECIESx25519 sessions 2020-01-21 14:40:23 -05:00
ccec3376ba try another ephemeral keys if elligator encoding failes 2020-01-21 12:19:20 -05:00
f497a74ec4 set random two highest bits 2020-01-21 12:18:31 -05:00
0e666e7d6a encoding fail test 2020-01-21 10:53:11 -05:00
f498fabd27 fix for openssl 1.1 2020-01-21 10:52:51 -05:00
8b49a55442 ratchet tagsets 2020-01-20 15:17:38 -05:00
a26eb942a9 Merge pull request #1458 from neheb/jjjjj
replace random_shuffle with shuffle
2020-01-20 07:16:00 -05:00
eabcafa516 replace random_shuffle with shuffle
random_shuffle is gone with C++17.

Found and fixed with clang-tidy.
2020-01-19 18:09:04 -08:00
6cc388c1bc use HKDF for MixKey 2020-01-18 14:43:36 -05:00
62e39ddfbd new session reply 2020-01-17 14:11:15 -05:00
80373623cd create payload 2020-01-17 11:21:41 -05:00
451c3945f0 create new ECIESX25519AEADRatchet session if not found 2020-01-16 19:33:00 -05:00
00cb15d9b4 fixed tyypo 2020-01-16 18:03:51 -05:00
67dd59125e new outgoing ECIESX25519AEADRatchet session 2020-01-16 16:34:13 -05:00
b6800dd125 lookup ECIESX25519AEADRatchet session by static key 2020-01-16 15:45:22 -05:00
dc9da69509 derive ECIESX25519AEADRatchetSession from GarlicRoutingSession 2020-01-16 14:59:19 -05:00
d7d964bf57 GarlicRoutingSession/ElGamalAESSession split 2020-01-16 14:31:01 -05:00
bcfe44db54 handle tunnel delivery instructioin for ECIESx25519 2020-01-16 12:47:08 -05:00
376bf6ba72 correct message size for ECIESx25519 2020-01-15 19:22:42 -05:00
f651baab25 ECIESX25519AEADRatchetSession added 2020-01-15 15:13:43 -05:00
61752e2aab correct ciphertext length 2020-01-13 22:37:31 -05:00
b7d3fd959e Merge pull request #1454 from rex4539/dead-strip
Pass -dead_strip -dead_strip_dylibs -bind_at_load on macOS
2020-01-13 09:17:05 -05:00
7ac05f8487 Pass -dead_strip -dead_strip_dylibs -bind_at_load on macOS 2020-01-13 14:47:15 +02:00
4f70822b13 always persist crypto keys for public destinations 2020-01-12 10:03:30 -05:00
0007f304d0 don't pass from to HandleI2NPMessage 2020-01-07 15:20:55 -05:00
4afef91359 invoke HandleCloveI2NPMessage 2020-01-06 16:14:41 -05:00
815b6db0bf HandleCloveI2NPMessage 2020-01-06 15:31:20 -05:00
433d3bf582 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2020-01-06 14:38:13 -05:00
a335841509 pass msgID to HandleDeliveryStatus 2020-01-06 14:37:40 -05:00
26ad793d82 use unscoped storage (fixes usage on android 10)
Signed-off-by: r4sas <r4sas@i2pmail.org>
2020-01-05 23:04:08 +00:00
5337aa10f7 check AES tag first 2020-01-02 13:30:54 -05:00
9f79bdae9b encryptor for ECIES-X25519-AEAD-Ratchet 2019-12-19 15:59:15 -05:00
db84be2488 use HKDF for NTCP2 key derivation data phase 2019-12-18 20:48:30 -05:00
599ec62bb0 use HKDF for NTCP2 key derivation data phase 2019-12-18 20:45:47 -05:00
19a88300c6 decrypt payload section 2019-12-18 14:44:02 -05:00
b5d55e1ffb decrypt flags/static section 2019-12-17 16:34:47 -05:00
521fb83e38 initial code for ECIES-X25519-AEAD-Ratchet KDF 2019-12-17 16:18:40 -05:00
553d59c32b decryptor for ECIES-X25519-AEAD-Ratchet 2019-12-11 13:38:36 -05:00
9ed58e5186 encode with highY 2019-12-10 14:10:12 -05:00
36eaaa748c handle case when encoded key is (p-1)/2 2019-12-10 13:40:04 -05:00
4d7b86ca26 elligator test added 2019-12-10 13:20:23 -05:00
5faf84c732 correct conversion from Little Endian 2019-12-10 12:51:39 -05:00
d7b819267f check a for 0 in Legendre 2019-12-10 10:53:39 -05:00
7417867d0f implemented Legendre 2019-12-10 10:45:08 -05:00
8d74905257 0.9.44 2019-12-10 10:44:19 -05:00
c38298c06e Elligator decode 2019-12-09 16:11:46 -05:00
3100d587d1 use d%q 2019-12-09 13:23:17 -05:00
ba849d0300 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2019-12-06 20:29:29 -05:00
95df3e4b39 encode key 2019-12-06 20:29:03 -05:00
72492e33a0 appveyor: drop msys2 overwrite 2019-12-07 01:02:23 +00:00
934f1269f5 appveyor: replace deprecated --force in msys2 2019-12-07 00:59:33 +00:00
e6956d9bb0 calculate constants 2019-12-06 14:54:15 -05:00
2877900233 use 486662 for A 2019-12-05 16:13:59 -05:00
df1aa52e08 Elligator's encode 2019-12-05 16:03:11 -05:00
5fa2485a7d removed reseed.i2p.net.in 2019-12-04 17:27:16 -05:00
29f0e10411 Elligator added 2019-12-04 15:37:24 -05:00
39300a5bbf removed reseed.i2p.net.in 2019-11-28 17:49:36 -05:00
35d6268675 README: explicit linux distro supported
close #1440
2019-11-23 22:52:31 +01:00
0abb871f3f close socket after if accept failed 2019-11-20 13:00:50 -05:00
704fca969f handle accept errors 2019-11-20 12:05:32 -05:00
95debf8c80 update mingw build script
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2019-11-19 14:29:55 +03:00
dd94b77b2a use GetTickCount dll pointer, add USE_WINXP to makefile
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2019-11-19 13:51:14 +03:00
6cfe4fa580 handle sending errors 2019-11-18 14:13:31 -05:00
515c086099 Use GetProcAddress for inet_pton. Fixed build error 2019-11-12 15:06:04 -05:00
34ce06ac17 some cleanup 2019-11-12 14:19:14 -05:00
a104c9881e some cleanup 2019-11-12 11:57:34 -05:00
c3e3c091cc correct implementation of GetMTUWindows for WindowsXP 2019-11-12 11:35:59 -05:00
651240113c mark RI as unreachable if all connections failed 2019-11-12 10:03:33 -05:00
77189bf8e9 start over if an active session got disconnected 2019-11-12 09:38:22 -05:00
60fd3a4542 fixed #1434 use memset inster bzero 2019-11-12 07:17:57 -05:00
c66f9c8d6d reset connection attempts before reconnect 2019-11-12 06:46:08 -05:00
569088eaca 2.29.0 2019-10-21 12:02:43 -04:00
a7e8dd04fe 2.29.0 2019-10-21 11:50:59 -04:00
dfdd76a1bb fixed #1429. Don't use monotonic timer for Win32 2019-10-15 10:32:29 -04:00
28aac6f93b fix bogus date in changelogs
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2019-10-07 21:18:46 +03:00
c2f47119ce fixed #1424. Check if .b32.i2p address string is valid 2019-09-23 13:42:15 -04:00
d6b1d0d4fb remove incoming session from pending list when established 2019-09-22 21:01:34 -04:00
03a861745b removed CloseSession 2019-09-20 20:09:25 -04:00
9a7aed20e9 handle error for SessionConfrimed send 2019-09-19 16:54:23 -04:00
b7f17d4cb1 client auth flag for B33 address 2019-09-06 11:02:19 -04:00
2497c3d187 Merge pull request #1421 from nonlinear-chaos-order-etc/openssl
Fixes three upnp issues, probably including: probably fixed #1419
2019-09-05 15:51:11 -04:00
f7a084969a fixed #1387 2019-09-06 03:21:26 +08:00
2900bc26a5 fixed #1388 : took code from 736c95a870 and fixed it as https://github.com/PurpleI2P/i2pd/issues/1388#issuecomment-528495918 tells 2019-09-06 02:58:28 +08:00
2334c56a96 Merge pull request #1414 from nonlinear-chaos-order-etc/openssl
qt: fixed logging to window in release builds
2019-08-27 12:40:19 -04:00
90a5d02bf6 2.28.0 2019-08-27 10:17:32 -04:00
81d9626da9 qt: fixed logging to window in release builds 2019-08-27 21:56:36 +08:00
44a2549b81 2.28.0 2019-08-27 09:46:54 -04:00
a2b8d468bc Merge pull request #1412 from nonlinear-chaos-order-etc/openssl
qt: disabled broken UPnP + small qt debugging tweaks
2019-08-27 08:53:44 -04:00
d523f0cadd gitignored autosave files by qtcreator 2019-08-27 19:31:57 +08:00
99116ff097 qt: disabled upnp for now - until upnp fixed 2019-08-27 19:31:28 +08:00
3939ca9eb4 enabled default logging debug option for qt debug builds 2019-08-27 17:51:55 +08:00
b5aa67b491 tweaked debug logging in i2pd_qt 2019-08-27 17:10:53 +08:00
e42efec220 correct outet plain text length in case of authKeys 2019-08-26 07:35:11 -04:00
9d06aa2f6a pass authSalt or epk 2019-08-25 20:51:15 -04:00
80765a797b correct outer cipher text len 2019-08-25 19:14:53 -04:00
0b5509a1ed correct authClients offset 2019-08-25 14:54:43 -04:00
478d7b4a83 Merge pull request #1410 from nonlinear-chaos-order-etc/openssl
android various fixes and improvements
2019-08-24 07:31:12 -04:00
9d3b38141a android various fixes and improv 2019-08-24 19:13:10 +08:00
ab3a4d902e Merge pull request #1409 from nonlinear-chaos-order-etc/openssl
android - show battery optimiz. os dialog menu item added; translated all battery stuff into Russian
2019-08-24 07:03:15 -04:00
5eab5f2437 show battery optimiz. menu item now hidden if not supported by os 2019-08-24 18:00:11 +08:00
80f632c19a show battery optimiz. menu item added; translated all battery stuff into Russian 2019-08-24 17:50:30 +08:00
6e4f18543d added *.local to android/.gitignore 2019-08-24 17:04:04 +08:00
54586c9076 Merge pull request #1408 from docker-and-co/fix-dockerfile-non-existend-deps
fix dockerfile: remove unmet dependencies
2019-08-23 11:02:00 -04:00
351c899807 cleanup incoming streams on stop 2019-08-23 10:00:49 -04:00
fe45d431d7 fix dockerfile: remove unmet dependencies 2019-08-23 16:20:09 +03:00
488c2f6d05 bump SDK version 2019-08-22 09:45:49 -04:00
75ab0909b3 Merge pull request #1405 from nonlinear-chaos-order-etc/openssl
various Android stuff. Fixed #1400
2019-08-22 07:15:36 -04:00
8f82d563c1 various Android stuff. Fixed #1400 2019-08-22 10:00:50 +08:00
9bbce5dba6 fixed typo 2019-08-21 20:26:19 -04:00
099adab9ed Update README.md
update head badges links, add snapcraft badge
2019-08-16 21:45:44 +03:00
c8cbf425ac check and send netid for NTCP2 and SSU 2019-08-13 14:55:18 -04:00
ad9c11cd92 correct parsing of addreses containing # 2019-08-10 22:16:26 -04:00
3872c2a3f5 use published encrypted instead orig type 2019-08-07 16:18:00 -04:00
e6a09b49c9 published encrypted flag 2019-08-07 15:43:03 -04:00
db107602bd handle messages with \r\n 2019-08-02 13:48:39 -04:00
a6558a61a7 Recognize RedDSA_SHA512_Ed25519 signature type 2019-08-02 12:54:24 -04:00
254d2b82b3 fixed #1393. store streams by recvStreamID 2019-07-26 14:23:21 -04:00
97d9795fc9 pass encrepted LeaseSet auth keys 2019-07-16 16:31:17 -04:00
54071b0e5d set and handle unpublished LeaseSet flag 2019-07-16 11:48:30 -04:00
925e8316c7 read i2cp.leaseSetAuthType, i2cp.leaseSetClient.dh.nnn and i2cp.leaseSetClient.psk.nnn from tunnel config 2019-07-12 20:58:17 -04:00
99e1b74023 create encrypted LeaseSet2 with authentication 2019-07-12 15:40:59 -04:00
7d68ccca53 create encrypted LeaseSet2 with authentication 2019-07-12 15:37:32 -04:00
a090114066 send data message wih raw type fpr raw datagrams 2019-07-10 13:31:49 -04:00
a204841abb handle RAW SEND 2019-07-10 13:30:31 -04:00
cc451809cc send/receive raw datagrams through the SAM 2019-07-10 11:32:56 -04:00
a605e4bab6 send and recieve raw datagrams 2019-07-09 21:33:55 -04:00
3f0534134d check for malformed b33 2019-07-04 13:05:39 -04:00
3acfb129cd 2.27.0 2019-07-03 12:38:55 -04:00
6ccef66920 call shutdown before close 2019-06-26 10:47:16 -04:00
e9fa4e94a6 Merge pull request #1374 from rszibele/openssl
BOB: fix status command.
2019-06-25 18:28:43 -04:00
fecc0c4640 don't call destructor twice 2019-06-25 16:37:06 -04:00
b759294975 BOB: fix status command. 2019-06-25 19:18:40 +02:00
a23e845c03 BOB: improve comment and remove error log in list command 2019-06-25 19:04:27 +02:00
cb8373e487 BOB: status response now correctly starts with "OK DATA". 2019-06-25 17:59:44 +02:00
8e919ddc8e use monotonic clock for uptime 2019-06-19 11:43:04 -04:00
832a9ab6b5 don't set random NTCP2 port if already set 2019-06-18 15:47:58 -04:00
13732ac333 fix #1363 try connect in SSU's thread 2019-06-14 15:43:03 -04:00
3e932a55f4 fixed typo 2019-06-11 15:09:10 -04:00
74e8610ec9 DH auth for encrypted LeaseSet2 2019-06-11 10:40:53 -04:00
089a60ded6 Merge pull request #1367 from rszibele/openssl
fix build on BSDs, as "isset" is a defined macro.
2019-06-10 19:10:34 -04:00
c8eeefe194 fix build on BSDs, as "isset" is a defined macro. 2019-06-10 23:04:59 +02:00
85eeba14c1 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2019-06-08 21:24:16 -04:00
f6f45eab39 flood encrypted LeaseSet2 with store hash 2019-06-08 21:23:25 -04:00
a74065f775 [qt] dont build UnixDaemon.cpp 2019-06-09 01:04:43 +03:00
48d02f7e09 [qt] update headers, fix ChaCha source name, remove duplicates 2019-06-08 22:24:11 +03:00
e60549f8df [qt] fix build 2019-06-08 21:16:20 +03:00
41f4f4713e handle i2cp.leaseSetPrivKey 2019-06-07 14:51:08 -04:00
213a292fd5 correct offsets for auth data 2019-06-07 11:59:48 -04:00
79630e844b 2.26.0 2019-06-07 17:25:55 +03:00
1c9e46dbb3 2.26.0 2019-06-07 10:04:57 -04:00
0a299284f8 correct check for PSK auth 2019-06-06 13:58:31 -04:00
347a5f7346 pass secret to encrypted LeaseSet2 2019-06-06 12:33:33 -04:00
c6a903572c [HTTP] add PROFIND support 2019-06-06 18:07:17 +03:00
14f0d6d26b extract client auth data 2019-06-05 15:57:20 -04:00
485f105555 fixed typo 2019-06-04 15:12:19 -04:00
686c0b776f common blinding code for public and private keys 2019-06-04 14:47:40 -04:00
828862ea49 store hash for ECDSA blidning 2019-06-03 12:51:57 -04:00
c4dffa4dc8 remove obsolete reseeds 2019-06-01 09:37:02 -04:00
3c1906e3d4 Merge pull request #1360 from khumarahn/openssl
link libi2pd to boost and zlib
2019-06-01 09:28:54 -04:00
7147a3694c link libi2pd to boost and zlib 2019-06-01 12:57:09 +01:00
64707dbb22 key blinding test 2019-05-31 11:57:16 -04:00
554e8eeef3 [appveyor] remove gcc-ada and gcc-objc packages
https://github.com/msys2/MINGW-packages/issues/5434#issuecomment-496706950
2019-05-31 16:32:32 +03:00
5e10549543 disable NTCP by default 2019-05-30 19:18:56 -04:00
685f45bd76 publish/unpublish NTCP2 address depending on network status 2019-05-30 17:52:44 -04:00
61d84dd4c1 publish/unpublish NTCP2 address depending on network status 2019-05-30 17:48:49 -04:00
4d10593bb1 publish/unpublish NTCP2 address depending on network status 2019-05-30 16:11:35 -04:00
fbb8903774 correct buffer size for ECDSA blinding 2019-05-30 13:57:43 -04:00
e8cac91bb7 blind ECDSA public key 2019-05-29 15:48:35 -04:00
7328ffa036 Merge pull request #1359 from rszibele/openssl
BOB modifications.
2019-05-29 14:07:30 -04:00
a03e828317 BOB: status: forgot to pass destination for current tunnel. 2019-05-29 18:47:35 +02:00
93d4dc70cf BOB fixes. 2019-05-29 18:05:03 +02:00
8e3d16e9fb update ipv6 addresses from SSU rather than NTCP or NTCP2 2019-05-29 11:36:58 -04:00
07405e57b9 fixed typo 2019-05-25 14:58:10 -04:00
354c9187db detect our ipv6 address 2019-05-23 15:59:44 -04:00
af33df3004 common buffer size 2019-05-23 11:49:54 -04:00
78bfde237f allocate actual RouterInfo's buffer size 2019-05-23 09:34:04 -04:00
7b9033d678 allocate actual RouterInfo's buffer size 2019-05-23 09:32:07 -04:00
f784cfad46 correct RouterInfo buffer size 2019-05-23 06:56:41 -04:00
e40c139ff1 blind ECDSA private key 2019-05-22 16:15:11 -04:00
edf4f7695d fix #1352. correct response for 'list' command 2019-05-22 12:45:50 -04:00
60ec03237e blidning for ECDSA 2019-05-16 15:49:07 -04:00
a91641e427 fix #823, reindent code 2019-05-16 09:39:22 +03:00
5c3992018f fixed #1350 use GetAddress insted GetIdentHash 2019-05-15 14:22:19 -04:00
f5b682619f [webconsole] move b33 to spoiler, fix typo 2019-05-15 14:15:10 +03:00
743fa745b7 show b33 address for encrypted LeaseSet2 2019-05-14 14:42:10 -04:00
39400fd381 move key blinding code from LeaseSet.cpp to Blinding.cpp 2019-05-14 11:42:25 -04:00
5299ac35a6 create NTCP2 ipv6 address 2019-05-13 11:40:08 -04:00
ef76ed394c publish SSU ipv6 address if NTCP if disabled 2019-05-12 13:36:26 -04:00
1472637de7 skip introducers for non-SSU address 2019-05-11 07:27:34 -04:00
3b8baa85a3 2.25.0 2019-05-09 10:21:11 -04:00
73921b1024 fix ipv6 fallback address 2019-05-08 00:45:52 +03:00
ece140f18c [httpproxy] make addresshelper support configurable for every httpproxy 2019-04-25 23:06:14 +03:00
5e42947fbd always lookup SSU session if peer's endpoint doesn't match 2019-04-25 12:54:44 -04:00
1bfb9b02f5 make sure remote endpoint matches stored with 2019-04-24 11:40:58 -04:00
16a14c2b76 [android] set datadir path from system environment 2019-04-20 19:47:06 +00:00
f6199c6c17 print store hash for encrypted LeaseSet 2019-04-20 09:44:16 -04:00
d7e7f06e88 re-request encrypted LeaseSet 2019-04-17 15:53:07 -04:00
4c4e856a1a ntcp2.addressv6 parameter 2019-04-17 14:40:00 -04:00
07bbbbaf61 fixed gcc 4.7 build 2019-04-17 12:42:43 -04:00
3236827781 add/removed NTCP addresses 2019-04-16 21:04:04 -04:00
0be664cc3d publish NTCP2 address instead NTCP if NTCP is disabled 2019-04-15 16:32:16 -04:00
6cc6849ccc use published timestamp for blinding 2019-04-12 14:05:07 -04:00
5d5cd71714 limit expiration by next midnight for encrypted LS2 2019-04-12 11:13:46 -04:00
d248343517 Handle CreateLeaseSet2 I2CP message for encrypted leasesets 2019-04-11 14:06:53 -04:00
64d800427f allow HTTP headers without value 2019-04-10 15:25:09 -04:00
c4c896a833 publish encrypted LS2 2019-04-10 12:04:19 -04:00
b6b5bb3f75 publish LeaseSet with store hash 2019-04-09 15:36:10 -04:00
5d69bb7383 correct ecrypted LS2 layout 2019-04-09 10:34:05 -04:00
76e222079a Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2019-04-09 09:21:47 -04:00
73abb9278d correct ecrypted LS2 size 2019-04-09 09:21:38 -04:00
8fd843e7ce Merge pull request #1334 from rex4539/fix-typos
Fix typos
2019-04-08 17:36:55 -04:00
6a497a23d9 Fix typos 2019-04-08 22:22:42 +03:00
3ac74e1091 create encrypted LS2 2019-04-08 13:27:21 -04:00
ef0fb48f1f blind private keys 2019-04-05 16:03:58 -04:00
414ef2bc3d fixed gcc 4.7 build 2019-04-04 16:18:52 -04:00
ea791309ad moved credential and blinding to BlindedPublicKey 2019-04-02 16:32:18 -04:00
706da6e431 allow .b32.i2p in jump links 2019-04-02 13:11:49 -04:00
ed116e7cea add gcc 9 support 2019-03-30 13:05:32 +03:00
5b56f4007b counter is always in Little Endian 2019-03-29 18:45:31 -04:00
e2071542bf use 16 bytes iv for chacha20 2019-03-29 16:18:51 -04:00
cdb217b774 always initialize m_Pkey 2019-03-29 13:15:32 -04:00
079798940b lookup for b33 address 2019-03-29 11:59:59 -04:00
f1c24689bf fixed #1319. send correct response 2019-03-29 09:29:28 -04:00
1f9cf6ed7c show lookup keys 2019-03-28 19:00:56 -04:00
43f218410f correct b33 address length threshold 2019-03-28 18:48:38 -04:00
3fd9d5f641 save b33 addresses 2019-03-28 16:06:53 -04:00
f5ab8f2062 replaced GetIdentHash by GetAddress 2019-03-28 12:19:19 -04:00
8774a8fbc2 handle b33 addresses in I2P tunnels 2019-03-28 10:17:03 -04:00
6f4f0f03d2 handle b33 addresses in I2P tunnels 2019-03-28 09:57:34 -04:00
00b5fdce03 create stream to blinded dest 2019-03-27 16:04:46 -04:00
baee6a0d91 generic address for AdressBook 2019-03-27 15:19:10 -04:00
ff44bcc489 complete implementation of RedDSA 2019-03-24 18:42:52 -04:00
c797ac4268 Update README.md 2019-03-23 03:25:10 +03:00
d22a76d4d1 remove incorrect line 2019-03-22 23:40:59 +00:00
a6642e0ebc add script for packaging archive with android binaries 2019-03-22 23:37:20 +00:00
3d4d260a34 extract b33 address 2019-03-22 16:04:47 -04:00
8e4b9da97d pass blinded key instead identity for encrypted LS2 2019-03-22 15:32:13 -04:00
2be80ba30f Fix Docker build 2019-03-22 13:14:02 -04:00
2e44c88d6c [2.24.0][android] update addressbook 2019-03-21 18:34:39 +03:00
21eb1ce6c9 2.24.0 2019-03-21 11:30:12 -04:00
cdfd411df7 2.24.0 2019-03-21 10:58:59 -04:00
a6149ca90c [android] upload gradlew script 2019-03-21 00:09:49 +03:00
642435486c [android] add gradle wrapper, update buildtools version, fixes in code. 2019-03-20 23:49:54 +03:00
fc84d6c4b7 remove unused timer 2019-03-17 21:37:42 -04:00
aa4bddd6ec common HKDF 2019-03-15 12:25:20 -04:00
8ec12a1b65 fixed race condition for publishing 2019-03-10 09:22:42 -04:00
0fbf552e95 lookup and handle encrypted LeaseSet2 2019-03-07 14:52:59 -05:00
09b1b120d7 update LeaseSet2 if store type changed 2019-03-07 14:51:05 -05:00
557244bc3f verify blinding key for encrypted LS2 2019-03-07 11:55:47 -05:00
24c5ed1cff calculate store hash for encrypted LeaseSet2 2019-03-06 16:08:04 -05:00
32e55ebd0c blind public key for encrypted LeaseSet2 2019-03-05 15:51:24 -05:00
ea3070d02b derivation of subcredentials for LeaseSet2 2019-03-05 12:41:01 -05:00
9aaba49a9f decrypt and handle Layer 2 of encrypted LeaseSet 2 2019-03-04 15:47:35 -05:00
9b64be07a9 set chacha20 counter to 1 2019-03-04 15:08:03 -05:00
42c3c28ea7 [addressbook] reset eTags if addressbook can't be loaded 2019-03-04 18:29:29 +00:00
9e9236badb don't check TRANSIENT destination 2019-03-04 07:35:48 -05:00
560ebcec8d persist.addressbook parameter added 2019-03-01 14:42:20 -05:00
9b1fe4338b reuse_address for ipv6 acceptor 2019-02-28 16:00:26 -05:00
9188e3ad3f ChaCha20 decrypt 2019-02-28 13:31:51 -05:00
af65af5be9 H and HKDF for encrypted LeaseSet2 2019-02-27 15:52:47 -05:00
2f0115c300 handle RedDSA as EdDSA 2019-02-27 13:18:09 -05:00
0646461342 check published timestamp for LeaseSet2 2019-02-26 16:20:24 -05:00
ec30ec0996 Merge pull request #1304 from lifecoder-phoenix/openssl
Fix #1257
2019-02-25 07:01:33 -05:00
cdecb7a43c Fix #1257 2019-02-25 10:10:09 +01:00
aa9c1b66a0 Fix #1257 2019-02-25 09:57:18 +01:00
846eac29dc filter out unspecified addresses. Check floodfill status change 2019-02-24 18:26:58 -05:00
0f9e3c5b33 fix crash if public key is null 2019-02-22 13:17:43 -05:00
aa27746982 remove address string 2019-02-22 11:03:31 -05:00
d8a4954bf1 [NetDb] check PersistProfiles on load
* tabulation fixes
2019-02-22 18:37:32 +03:00
d40a029dae eliminate extra copy 2019-02-20 12:36:05 -05:00
96d961c393 correct public key for EdDSA trasient key 2019-02-15 15:03:58 -05:00
7b6814e32d correct flags 2019-02-14 21:22:49 -05:00
6fee2d3536 correct options szie 2019-02-14 17:49:23 -05:00
636fc633d4 send offline signature in streaming 2019-02-14 12:11:25 -05:00
72a239838e publish offline signature 2019-02-12 14:56:39 -05:00
a463dbc5fb Merge pull request #1295 from l-n-s/websocket_support
Support websocket connections over HTTP proxy
2019-02-12 12:30:44 -05:00
016ae3b9e9 rewrite for efficiency 2019-02-12 11:20:54 -05:00
7d0d421724 [windows] handle unexpected conditions (#1185) 2019-02-12 04:27:09 +03:00
83b5856a19 fix overflow warning, fix little typos 2019-02-12 03:09:29 +03:00
f617b27110 Support websocket connections over HTTP proxy 2019-02-11 17:18:01 -05:00
a91a0263cf update outproxy user-agent header rewrite 2019-02-12 00:51:47 +03:00
80ffe13f3e correct offline signature layout 2019-02-08 15:12:51 -05:00
1eb726c9bb create offline keys 2019-02-08 12:19:51 -05:00
1fa3ba8b42 read offline info 2019-02-07 16:04:31 -05:00
b6bfd66a49 use identity from LeaseSet 2019-02-06 21:19:44 -05:00
1be0e7ddaa [windows] add functional
* check tunnels count on graceful shutdown
* add tray menu item for accept/decline transit tunnels
2019-02-07 02:02:28 +03:00
2cac9b03ff common code for offline signatures 2019-02-06 13:36:03 -05:00
f5f4190803 catch error 10045 on stopping SAM acceptor (#1233), fix warning in util 2019-02-06 03:03:37 +03:00
a14d554947 fix tray icon disappearing, var type warning, code tabulation 2019-02-06 00:24:01 +03:00
6d9e5147b5 handle offline signature 2019-02-05 15:32:18 -05:00
841452cb9e Merge pull request #1292 from PurpleI2P/inet_pton_xp
inet_pton for winxp
2019-02-05 17:36:36 +03:00
9c76368dbc inet_pton for winxp 2019-02-05 14:13:23 +03:00
bd5122c6ea fixed build error 2019-02-01 17:41:12 -05:00
6643258618 implement Update for LeaseSet2 2019-02-01 12:55:13 -05:00
bc3f02cb6b fix #1290. copy correct size if message didn't fit previous 2019-01-31 16:03:10 -05:00
d848ae332a encryption keys priority 2019-01-30 14:10:40 -05:00
08ddc98303 initial LeaseSet2 support in I2CP 2019-01-29 11:30:31 -05:00
a3344c4290 resolve SIGNATURE_TYPE string values 2019-01-23 10:52:17 -05:00
22c1ce3ea5 don't pick port 9150 (Tor browser) 2019-01-23 09:53:30 -05:00
afb14e6782 [fedora] fix build in release on fc30+
fixes #1284
2019-01-22 04:57:53 +03:00
e177363377 [fedora] specify srcdir only if building at 30+ 2019-01-22 04:08:52 +03:00
ce213934c9 try fix build in fedora rawhide 2019-01-22 02:33:44 +03:00
af286ec52e try fix build in fedora rawhide 2019-01-22 02:32:51 +03:00
f7f2b7607b 2.23.0 2019-01-21 18:51:04 +03:00
60a282826c 2.23.0 2019-01-21 10:33:22 -05:00
3eba599aec [android] add addressbook in assets
Sources:
http://inr.i2p/export/alive-hosts.txt
http://stats.i2p/cgi-bin/newhosts.txt
http://i2p-projekt.i2p/hosts.txt
http://identiguy.i2p/hosts.txt

Updated: January ‎18, ‎2019, ‏‎12:00:01 PM
2019-01-18 23:59:22 +03:00
74d876f145 [android] update russian strings, add tunnels.d to assets list 2019-01-18 18:43:48 +03:00
d7609f119c [android] build libi2pd staticly, add update strings, fix messages 2019-01-18 15:44:30 +03:00
65c2c7d80b re-create LeaseSet if store type has changed 2019-01-16 19:00:17 -05:00
468a32a819 check LS2 transient key expires time 2019-01-15 18:56:26 -05:00
b89cf73ae2 correct encryption key type for LS2 2019-01-15 18:41:00 -05:00
9cf43dea1a handle i2cp.leaseSetEncType 2019-01-15 15:43:21 -05:00
670ffe2078 show LS2 in Leasets' list 2019-01-14 18:39:02 -05:00
884cf756ed remove invalid leasesets 2019-01-14 18:37:17 -05:00
e44ba54857 show correct LeaseSet's store type 2019-01-14 16:34:43 -05:00
3712749a94 extract timestamp for LS2 2019-01-14 13:49:27 -05:00
6569c4aa03 actual key size for LS2 2019-01-13 19:17:02 -05:00
d6b2b3c996 take key type for LS2 from identity 2019-01-13 08:34:34 -05:00
06c7900ece show LeaseSet type in destination 2019-01-12 18:26:31 -05:00
52a6a12a9a correct LS2 creation 2019-01-12 18:25:10 -05:00
e647603dce handle i2cp.leaseSetType parameter 2019-01-11 13:58:02 -05:00
dadf6174ba create standard LS2 2019-01-10 11:52:34 -05:00
84de7675c4 don't copy LS2 for signature verification 2019-01-10 10:57:57 -05:00
6311a80d0e use clang for android binary build 2019-01-10 09:47:11 -05:00
9504e69598 LocalLeaseSet2 added 2019-01-09 14:51:47 -05:00
5398b651f7 handle LS2 in destinations 2019-01-09 12:47:47 -05:00
b5596c4596 handle encrypted LS2 2019-01-08 11:26:50 -05:00
fdcea5537c show LeaseSet's store type 2019-01-08 09:35:15 -05:00
8ca8bc810d take elgamal percomputation from config 2019-01-08 09:23:14 -05:00
8f909b051f Merge pull request #1281 from neheb/b
Fix compilation without deprecated OpenSSL APIs
2019-01-06 20:12:51 -05:00
90f2b2d249 Fix compilation without deprecated OpenSSL APIs 2019-01-06 15:39:24 -08:00
f74b27c58c check if chacha20 and poly1305 is presented in openssl build 2019-01-06 17:43:05 -05:00
3f091f4748 remove i2pd-qt android project (closes #1279) 2019-01-06 19:46:17 +03:00
d84c9ad611 Merge pull request #1277 from l-n-s/update_zlib_version
CMake: bump version of ZLib
2019-01-04 23:48:44 +03:00
e55e15693d update LS2 leases 2019-01-02 15:40:48 -05:00
c54e6bafdb process meta LS2 2019-01-02 14:19:10 -05:00
2e56c4895d transient key signature verification 2019-01-02 09:43:18 -05:00
bce4224d6e extract and verify LS2 transient key 2019-01-01 17:00:37 -05:00
812e2814bc read flags from LS2 header 2018-12-31 14:23:48 -05:00
7cd17f8e1f build android app with llvm 2018-12-27 03:16:38 +03:00
6193b06708 LS2 signature verification and store type 2018-12-26 15:27:32 -05:00
12af68bdb5 initial support of LeaseSet2 2018-12-21 15:00:03 -05:00
881f7e9062 correct Authorization header 2018-12-21 10:50:23 -05:00
1db4076bbd CMake: bump version of ZLib 2018-12-19 12:19:30 -05:00
1933e44719 reseeds update 2018-12-17 20:14:12 -05:00
25441cb650 revert mingw makefile
ref: https://github.com/Alexpux/MINGW-packages/issues/4773
2018-12-14 21:44:38 +03:00
bc755ac32f [MSYS2] add boost version detection via pacman 2018-12-14 15:43:52 +03:00
1fa34be52a update mingw makefile 2018-12-14 09:29:41 +03:00
f7a6d57855 fixed bug with loval destination shared between http and socks proxy 2018-12-13 09:53:16 -05:00
8a987af244 initialize m_Pkey 2018-12-11 15:14:51 -05:00
65cbb06080 create ephemeral keys after getting connected 2018-12-07 19:24:46 -05:00
979ea9c252 removed address resolvers as discontinued 2018-12-07 12:27:06 -05:00
aa1f4ee72a fixed possible race condition 2018-12-07 12:25:26 -05:00
74ce485b73 EdDSA signatures by default 2018-12-06 13:13:20 -05:00
165e6508f8 EdDSA signatures by default 2018-12-05 14:58:50 -05:00
c7af2889fa removed dummy initializer 2018-12-05 14:56:40 -05:00
5ab3390434 don't create dummy initializer for android 2018-12-05 11:39:48 -05:00
67f60f1889 set openssl no_config before boost::asio:ssl 2018-12-04 21:20:12 -05:00
985a468d0f don't read openssl config file 2018-12-04 18:39:49 -05:00
34dc6fbdc1 check if session is terminated before sending 2018-12-04 16:10:52 -05:00
b57152cc25 common code for padding and sending termination and RouterInfo messages 2018-12-04 15:56:55 -05:00
dc9562e430 padding for termination message 2018-12-04 15:23:43 -05:00
05689fe183 padding for short messages 2018-12-04 15:00:10 -05:00
8f6f95211e eliminate extra copy of RouterInfo 2018-12-04 12:56:49 -05:00
f30b6c9e6e const reference to vector of buffers 2018-12-04 12:54:48 -05:00
12ac7d6a00 enable sending I2NP messages 2018-12-03 18:47:20 -05:00
10251a6447 fixed typo 2018-12-03 15:54:35 -05:00
089cbbc20a rollback 2018-12-03 14:51:27 -05:00
95ab68acd1 don't copy I2NP messages to NTCP2 frame 2018-12-03 14:14:36 -05:00
abc4f6c70b fixed bug with chacha20 encryption of short messages 2018-12-03 13:36:17 -05:00
8fc3a1f9c9 correct frame size for I2NP msgs 2018-12-03 12:29:24 -05:00
5c3d0fc02c create I2NP blocks 2018-12-02 17:24:31 -05:00
7efb47fed4 send NTCP2 frame from I2NP messages 2018-12-02 14:24:39 -05:00
7692332f0e don't inialize Chacha20 state twice 2018-11-30 21:31:06 -05:00
ef6db64e9f correct chacha20 for multiple messages 2018-11-30 16:21:11 -05:00
e68f1dbc99 AEAD/Chacha20/Poly1305 encrypt multiple buffers 2018-11-30 14:41:14 -05:00
0c9ebc36d4 remove AVX and SSE for CipherBlock XOR 2018-11-27 14:33:31 -05:00
fcd6eb7801 overwrite user-agent for outproxy requests 2018-11-27 19:57:40 +03:00
328c2182c2 alignment for tunnel message AES decryption 2018-11-27 10:35:17 -05:00
08706f5dfb fixed typo 2018-11-25 18:49:59 -05:00
d49f165f0d fixed build warning 2018-11-25 15:59:00 -05:00
cf0fc3a4a9 some performance improvements 2018-11-25 10:33:48 -05:00
72c8fd257c eliminate extra buffer for Poly1305 2018-11-24 15:39:37 -05:00
fa620e41a4 correct alignment for polyKey 2018-11-24 14:41:17 -05:00
b07f851ce7 Merge pull request #1272 from majestrate/openssl
expose poly1305 digest struct in poly1305.h
2018-11-24 14:24:09 -05:00
16b3108719 Merge remote-tracking branch 'purple/openssl' into openssl 2018-11-24 10:08:12 -05:00
f385c624c7 expose poly1305 digester 2018-11-24 10:07:17 -05:00
f7e9975192 restore BlockCipher XOR using SSE 2018-11-24 09:43:30 -05:00
cde989b59d don't compile compatibility code if openssl 1.1.1 2018-11-22 12:13:16 -05:00
c0e263abd3 default value for m_PersistProfiles 2018-11-22 11:30:44 -05:00
79c0c11e80 configure persist of peer profiles
* If persist.profiles = false, peer profiles not stored on disk
* remove inet_pton for windows
* update configs
2018-11-22 00:13:23 +03:00
ca671551c8 flood NTCP2 RouterInfo if requested 2018-11-21 13:24:54 -05:00
42ed312384 handle NTCP2 RouterInfo flag 2018-11-21 11:23:48 -05:00
0e9074aaba reduce start and stop time 2018-11-20 13:57:51 -05:00
7c1961d4ef Cancel Graceful Stop 2018-11-20 12:36:10 -05:00
71e57717c2 request memory permisssion for android >= 6 2018-11-19 15:53:16 -05:00
8a549b83a2 NTP sync in separate thread 2018-11-16 12:49:04 -05:00
d7081c5f23 handle RouterInfo from NTCP2 in netdb's thread 2018-11-14 20:52:54 -05:00
588d64a30b more NTP logging 2018-11-14 12:27:11 -05:00
8335bdf3d4 correct ntp servers 2018-11-14 11:47:50 -05:00
85394f2438 NTP time sync 2018-11-14 11:06:53 -05:00
42b556574f add fedora copr mageia support 2018-11-11 22:28:34 +03:00
f34e65ad9e Merge pull request #1268 from sokolas/webroot
Added configurable web console URL path
2018-11-10 15:08:40 -05:00
51352a6819 update debian/rpm tunnels.d storing
+ testing rpm changes: manpage and configs store
2018-11-10 03:28:24 +00:00
d9887ec370 bump i2pd version in appdata manifest 2018-11-09 14:05:10 -05:00
c994950aaf default webroot in config, webroot in automatic redirect instead of request path 2018-11-09 17:42:04 +03:00
a26ed6fe6c Merge remote-tracking branch 'upstream/openssl' into webroot 2018-11-09 16:30:54 +03:00
a12a7e73f9 redirect with webroot 2018-11-09 16:13:56 +03:00
779228857e 2.22.0 2018-11-09 02:22:55 +00:00
8d0b696d33 packages - tunnels.conf.d fix configs place, links 2018-11-07 18:41:04 +03:00
23ae220aa7 add webroot setting 2018-11-07 18:07:05 +03:00
b7940e0002 add tunnels.d to packages 2018-11-06 20:04:26 +03:00
b3fd8bd0ae check if keys are available before sending termination message 2018-11-04 18:51:25 -05:00
bffeb237de termination might be send for non-established session 2018-11-04 15:32:31 -05:00
23e3602ea1 common MixHash 2018-11-01 16:06:39 -04:00
34cfd205f6 create new static keys by X25519Keys 2018-11-01 10:43:31 -04:00
df3da8be7a Merge pull request #1264 from l-n-s/desktop
fix appdata manifest
2018-10-31 17:24:39 +00:00
940243f45e fix appdata manifest 2018-10-31 13:23:13 -04:00
75d6599143 Update desktop files (#1263)
* Rename files to freedesktop standarts

* Add application icons
2018-10-31 12:23:16 +00:00
929a27a5ac Add Desktop files (#1261)
* Add appstream and desktop files

* More metadata in appstream file
2018-10-30 07:48:02 +00:00
82ddee2104 Merge pull request #1260 from l-n-s/version_display
Add --version flag to display i2pd and system libraries versions
2018-10-28 11:01:46 -04:00
a141678119 Add --version flag to display i2pd and system libraries versions 2018-10-28 10:52:22 -04:00
96d109af81 fixed typo 2018-10-27 19:55:23 -04:00
a309eb9f3c faster CipherBlock XOR implementation for non-AVX 2018-10-27 18:41:05 -04:00
d034dab265 fill m3p2 with SessionRequest 2018-10-26 09:58:18 -04:00
883a035e5c Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2018-10-22 12:26:49 -04:00
a2e84e5a1e 2.21.1 2018-10-22 09:19:39 -04:00
d148898ad7 Merge remote-tracking branch 'purple/openssl' into openssl 2018-10-22 07:35:34 -04:00
36cf622979 Merge pull request #1258 from PurpleI2P/openssl
long I2NP messages
2018-10-15 09:30:56 -04:00
5e31e533e2 Merge pull request #1249 from PurpleI2P/openssl
2.21.0
2018-10-04 09:47:29 -04:00
5ecd04dd4f Merge pull request #1240 from PurpleI2P/openssl
eddsa from 1.1.1
2018-09-08 16:22:12 -04:00
fb26e78ecc Merge branch 'openssl' of https://github.com/purplei2p/i2pd into openssl 2018-08-25 14:03:21 -04:00
4c687036c4 enable socks outproxy 2018-08-25 14:01:57 -04:00
73b6338f62 Merge pull request #1229 from PurpleI2P/openssl
2.20
2018-08-23 11:21:49 -04:00
8490e7ca7c Merge pull request #1223 from PurpleI2P/openssl
recent changes
2018-08-14 13:50:44 -04:00
fb229d4064 Merge pull request #1203 from PurpleI2P/openssl
2.19
2018-06-26 13:58:07 -04:00
246 changed files with 12165 additions and 8439 deletions

8
.gitignore vendored
View File

@ -258,9 +258,15 @@ build/Makefile
# qt
qt/i2pd_qt/*.ui.autosave
qt/i2pd_qt/*.autosave
qt/i2pd_qt/*.ui.bk*
qt/i2pd_qt/*.ui_*
#unknown android stuff
android/libs/
#various logs
*LOGS/
qt/build-*.sh*

0
.gitmodules vendored Normal file
View File

View File

@ -4,7 +4,7 @@ cache:
os:
- linux
#- osx
dist: trusty
dist: xenial
sudo: required
compiler:
- g++

152
ChangeLog
View File

@ -1,6 +1,158 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.31.0] - 2020-04-10
### Added
- NTCP2 through HTTP proxy
- Publish LeaseSet2 for I2CP destinations
- Show status page on main activity for android
- Handle ECIESFlag in DatabaseLookup at floodfill
- C++17 features for eligible compilers
### Changed
- Droped Websockets and Lua support
- Send DeliveryStatusMsg for LeaseSet for ECIES-X25519-AEAD-Ratchet
- Keep sending new session reply until established for ECIES-X25519-AEAD-Ratchet
- Updated SSU log messages
- Reopen SSU socket on exception
- Security hardening headers in web console
- Various web console changes
- Various QT changes
### Fixed
- NTCP2 socket descriptors leak
- Race condition with router's identity in transport sessions
- Not terminated streams remain forever
## [2.30.0] - 2020-02-25
### Added
- Single threaded SAM
- Experimental support of ECIES-X25519-AEAD-Ratchet crypto type
### Changed
- Minimal MTU size is 1280 for ipv6
- Use unordered_map instead map for destination's sessions and tags list
- Use std::shuffle instead std::random_shuffle
- SAM is single threaded by default
- Reseeds list
### Fixed
- Correct termination of streaming destination
- Extra ',' in RouterInfo response in I2PControl
- SAM crash on session termination
- Storage for Android 10
## [2.29.0] - 2019-10-21
### Added
- Client auth flag for b33 address
### Changed
- Remove incoming NTCP2 session from pending list when established
- Handle errors for NTCP2 SessionConfrimed send
### Fixed
- Failure to start on Windows XP
- SAM crash if invalid lookup address
- Possible crash when UPnP enabled on shutdown
## [2.28.0] - 2019-08-27
### Added
- RAW datagrams in SAM
- Publishing encrypted LeaseSet2 with DH or PSH authentication
- Ability to disable battery optimization for Android
- Transport Network ID Check
### Changed
- Set and handle published encrypted flag for LeaseSet2
### Fixed
- ReceiveID changes in the same stream
- "\r\n" command terminator in SAM
- Addressbook lines with signatures
## [2.27.0] - 2019-07-03
### Added
- Support of PSK and DH authentication for encrypted LeaseSet2
### Changed
- Uptime is based on monotonic timer
### Fixed
- BOB status command response
- Correct NTCP2 port if NTCP is disabled
- Flood encrypted LeaseSet2 with store hash
## [2.26.0] - 2019-06-07
### Added
- HTTP method "PROPFIND"
- Detection of external ipv6 address through the SSU
- NTCP2 publishing depends on network status
### Changed
- ntcp is disabled by default, ntcp2 is published by default
- Response to BOB's "list" command
- ipv6 address is not longer NTCP's local endpoint's address
- Reseeds list
- HTTP_REFERER stripping in httpproxy (#823)
### Fixed
- Check and handle incorrect BOB input
- Ignore introducers for NTCP or NTCP2 addresses
- RouterInfo check from NTCP2
## [2.25.0] - 2019-05-09
### Added
- Create, publish and handle encrypted LeaseSet2
- Support of b33 addresses
- RedDSA key blinding
- .b32.i2p addresses in jump links
- ntcp2.addressv6 parameter
### Changed
- Allow HTTP headers without value
- Set data directory from external storage path for Android
- addresshelper support is configurable per tunnel
- gradlew script for android build
### Fixed
- Deletion of expired encrypted LeaseSet2 on floodfills
- ipv6 fallback address
- SSU incoming packets routing
## [2.24.0] - 2019-03-21
### Added
- Support of transient keys for LeaseSet2
- Support of encrypted LeaseSet2
- Recognize signature type 11 (RedDSA)
- Support websocket connections over HTTP proxy
- Ability to disable full addressbook persist
### Changed
- Don't load peer profiles if non-persistant
- REUSE_ADDR for ipv6 acceptors
- Reset eTags if addressbook can't be loaded
### Fixed
- Build with boost 1.70
- Filter out unspecified addresses from RouterInfo
- Check floodfill status change
- Correct SAM response for invalid key
- SAM crash on termination for Windows
- Race condition for publishing
## [2.23.0] - 2019-01-21
### Added
- Standard LeaseSet2 support
- Ability to adjust timestamps through the NTP
- Ability to disable peer profile persist
- Request permission for android >= 6
- Initial addressbook to android assets
- Cancel graceful shutdown for android
- Russian translation for android
### Changed
- Chacha20 and Poly1305 implementation
- Eliminate extra copy of NTCP2 send buffers
- Extract content of tunnel.d from assets on android
- Removed name resolvers from transports
- Update reseed certificates
### Fixed
- LeaseSet published content verification
- Exclude invalid LeaseSets from the list on a floodfill
- Build for OpenWrt with openssl 1.1.1
## [2.22.0] - 2018-11-09
### Added
- Multiple tunnel config files from tunnels.d folder
### Changed
- Fetch own RouterInfo upon SessionRequest for NTCP2
- Faster XOR between AES blocks for non AVX capable CPUs
### Fixed
- Fixed NTCP2 termination send
## [2.21.1] - 2018-10-22
### Changed
- cost=13 for unpublished NTCP2 address

View File

@ -27,10 +27,6 @@ else
LD_DEBUG = -s
endif
ifeq ($(WEBSOCKETS),1)
NEEDED_CXXFLAGS += -DWITH_EVENTS
endif
ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
ifeq ($(HOMEBREW),1)
@ -48,7 +44,7 @@ else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
include Makefile.mingw
else # not supported
$(error Not supported platform)
$(error Not supported platform)
endif
ifeq ($(USE_MESHNET),yes)

View File

@ -1,5 +1,5 @@
# set defaults instead redefine
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation -Wno-psabi
LDFLAGS ?= ${LD_DEBUG}
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
@ -15,15 +15,13 @@ ifeq ($(shell expr match $(CXX) 'clang'),5)
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # gcc 4.7 - 4.9
NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
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
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
NEEDED_CXXFLAGS += -std=c++11
LDLIBS = -latomic
else ifeq ($(shell expr match ${CXXVER} "[7-8]"),1) # gcc 7 ubuntu or gcc 8 arch
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc >= 7
NEEDED_CXXFLAGS += -std=c++17
LDLIBS = -latomic
else # not supported
$(error Compiler too old)

View File

@ -3,10 +3,12 @@ CXX = g++
WINDRES = windres
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
NEEDED_CXXFLAGS = -std=c++11
BOOST_SUFFIX = -mt
INCFLAGS = -Idaemon -I.
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++
# Boost libraries suffix
BOOST_SUFFIX = -mt
# UPNP Support
ifeq ($(USE_UPNP),yes)
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
@ -35,6 +37,10 @@ ifeq ($(USE_WIN32_APP), yes)
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif
ifeq ($(USE_WINXP_FLAGS), yes)
CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
endif
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
ifeq ($(USE_AESNI),1)
CPU_FLAGS += -maes

View File

@ -2,6 +2,9 @@ CXX = clang++
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX
INCFLAGS = -I/usr/local/include
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDFLAGS += -Wl,-dead_strip
LDFLAGS += -Wl,-dead_strip_dylibs
LDFLAGS += -Wl,-bind_at_load
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread

View File

@ -1,3 +1,8 @@
[![GitHub release](https://img.shields.io/github/release/PurpleI2P/i2pd.svg?label=latest%20release)](https://github.com/PurpleI2P/i2pd/releases/latest)
[![Snapcraft release](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd)
[![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE)
[![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions)
i2pd
====
@ -38,8 +43,12 @@ Resources
Installing
----------
The easiest way to install i2pd is by using
[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest).
The easiest way to install i2pd is by using precompiled packages and binaries.
You can fetch most of them on [release](https://github.com/PurpleI2P/i2pd/releases/latest) page.
Please see [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/install/) for more info.
Building
--------
See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build
i2pd from source on your OS.
@ -54,11 +63,13 @@ 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 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* CentOS / Fedora - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
* Docker image - [![Build Status](https://dockerbuildbadges.quelltext.eu/status.svg?organization=meeh&repository=i2pd)](https://hub.docker.com/r/meeh/i2pd/builds/)
* GNU/Linux - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
* Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* Docker image - [![Build Status](https://dockerbuildbadges.quelltext.eu/status.svg?organization=meeh&repository=i2pd)](https://hub.docker.com/r/meeh/i2pd/builds/)
* Snap - [![Snap Status](https://build.snapcraft.io/badge/PurpleI2P/i2pd-snap.svg)](https://build.snapcraft.io/user/PurpleI2P/i2pd-snap)
* FreeBSD
* Android
* iOS

View File

@ -50,7 +50,7 @@ namespace util
if (isDaemon)
{
LogPrint(eLogDebug, "Daemon: running as service");
I2PService service(SERVICE_NAME);
I2PService service((PSTR)SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());

View File

@ -13,10 +13,6 @@
#include "Win32App.h"
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
#define ID_ABOUT 2000
#define ID_EXIT 2001
#define ID_CONSOLE 2002
@ -24,17 +20,25 @@
#define ID_GRACEFUL_SHUTDOWN 2004
#define ID_STOP_GRACEFUL_SHUTDOWN 2005
#define ID_RELOAD 2006
#define ID_ACCEPT_TRANSIT 2007
#define ID_DECLINE_TRANSIT 2008
#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)
#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100
#define FRAME_UPDATE_TIMER 2101
#define IDT_GRACEFUL_TUNNELCHECK_TIMER 2102
namespace i2p
{
namespace win32
{
static DWORD GracefulShutdownEndtime = 0;
typedef DWORD (* IPN)();
IPN GetTickCountLocal = (IPN)GetProcAddress (GetModuleHandle ("KERNEL32.dll"), "GetTickCount");
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
{
HMENU hPopup = CreatePopupMenu();
@ -42,11 +46,17 @@ 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_RELOAD, "&Reload configs");
if(!i2p::context.AcceptsTunnels())
InsertMenu (hPopup, -1,
i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING,
ID_ACCEPT_TRANSIT, "Accept &transit");
else
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config");
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
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_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);
@ -148,7 +158,13 @@ namespace win32
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ());
s << "\n";
if (GracefulShutdownEndtime != 0)
{
DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000;
s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft);
}
else
s << "\n";
s << "Inbound: " << i2p::transport::transports.GetInBandwidth() / 1024 << " KiB/s; ";
s << "Outbound: " << i2p::transport::transports.GetOutBandwidth() / 1024 << " KiB/s\n";
s << "Received: "; ShowTransfered (s, i2p::transport::transports.GetTotalReceivedBytes());
@ -166,10 +182,13 @@ namespace win32
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static UINT s_uTaskbarRestart;
switch (uMsg)
{
case WM_CREATE:
{
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
AddTrayIcon (hWnd);
break;
}
@ -178,6 +197,7 @@ namespace win32
RemoveTrayIcon (hWnd);
KillTimer (hWnd, FRAME_UPDATE_TIMER);
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
PostQuitMessage (0);
break;
}
@ -197,10 +217,28 @@ namespace win32
PostMessage (hWnd, WM_CLOSE, 0, 0);
return 0;
}
case ID_ACCEPT_TRANSIT:
{
i2p::context.SetAcceptsTunnels (true);
std::stringstream text;
text << "I2Pd now accept transit tunnels";
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
return 0;
}
case ID_DECLINE_TRANSIT:
{
i2p::context.SetAcceptsTunnels (false);
std::stringstream text;
text << "I2Pd now decline new transit tunnels";
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
return 0;
}
case ID_GRACEFUL_SHUTDOWN:
{
i2p::context.SetAcceptsTunnels (false);
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second
GracefulShutdownEndtime = GetTickCountLocal() + 10*60*1000;
i2p::util::DaemonWin32::Instance ().isGraceful = true;
return 0;
}
@ -208,6 +246,8 @@ namespace win32
{
i2p::context.SetAcceptsTunnels (true);
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
GracefulShutdownEndtime = 0;
i2p::util::DaemonWin32::Instance ().isGraceful = false;
return 0;
}
@ -223,7 +263,7 @@ namespace win32
{
char buf[30];
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
return 0;
@ -290,14 +330,27 @@ namespace win32
}
case WM_TIMER:
{
if (wParam == IDT_GRACEFUL_SHUTDOWN_TIMER)
switch(wParam)
{
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
return 0;
}
if (wParam == FRAME_UPDATE_TIMER)
{
InvalidateRect(hWnd, NULL, TRUE);
case IDT_GRACEFUL_SHUTDOWN_TIMER:
{
GracefulShutdownEndtime = 0;
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
return 0;
}
case FRAME_UPDATE_TIMER:
{
InvalidateRect(hWnd, NULL, TRUE);
return 0;
}
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
{
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
PostMessage (hWnd, WM_CLOSE, 0, 0);
else
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
return 0;
}
}
break;
}
@ -318,6 +371,12 @@ namespace win32
EndPaint(hWnd, &ps);
break;
}
default:
{
if (uMsg == s_uTaskbarRestart)
AddTrayIcon (hWnd);
break;
}
}
return DefWindowProc( hWnd, uMsg, wParam, lParam);
}

View File

@ -297,7 +297,8 @@ void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartTyp
FreeHandles(schSCManager, schService);
return;
}
strncat(szPath, " --daemon", MAX_PATH);
char SvcOpt[] = " --daemon";
strncat(szPath, SvcOpt, strlen(SvcOpt));
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);

View File

@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.21.1"
#define I2Pd_ver "2.31.0"
#define I2Pd_Publisher "PurpleI2P"
[Setup]
@ -32,6 +32,7 @@ Source: ..\contrib\i2pd.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntex
Source: ..\contrib\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
[Icons]
Name: {group}\I2Pd; Filename: {app}\i2pd.exe

6
android/.gitignore vendored
View File

@ -12,7 +12,5 @@ local.properties
build.sh
android.iml
build
gradle
gradlew
gradlew.bat
*.iml
*.local

View File

@ -1,25 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd"
android:installLocation="auto"
android:versionCode="1"
android:versionName="2.21.1">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="28" />
android:installLocation="auto">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- normal perm, per https://developer.android.com/guide/topics/permissions/normal-permissions.html -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- required in API 26+ -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light.DarkActionBar"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
>
<receiver android:name=".NetworkStateChangeReceiver">
<intent-filter>
@ -53,5 +51,4 @@
android:value="org.purplei2p.i2pd.I2PDPermsAskerActivity" />
</activity>
</application>
</manifest>

19
android/README.md Normal file
View File

@ -0,0 +1,19 @@
# how to compile?
## Install the gradle + NDK or use android-studio
[https://gradle.org/install/](https://gradle.org/install/)
## Install the depencies
```
git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
git clone https://github.com/PurpleI2P/android-ifaddrs.git
git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
```
## Set libs in jni/Application.mk on 24 line:
```
# change to your own
I2PD_LIBS_PATH = /home/user/i2pd/android/
```
## compile apk file
gradle clean assembleRelease

View File

@ -0,0 +1,693 @@
00.i2p,zmzpltxslembpaupg3srh4bbhv5txgh5jmms6sfj4hzsvlv3xugq
0ipfs.i2p,cdii3ou5mve5sfxyirs6kogt4tbvivk2d6o25awbcbazjrlhjeza
0xcc.i2p,gawouxh2sg32cluwlqsnpy3dwedvoqtfroi4evvdvm2pfv7tdadq
1.fcp.freenet.i2p,cuxbeputgxn75ak4nr7ltp7fjktnzl5sul3wstwnsoytbbpb4ixq
102chan.i2p,xxu3lso4h2rh6wmrxiou3ax7r7la7x6dhoepnku3jvrlwp35pefq
1st.i2p,rduua7bhest6rwsmmyttzssfdw3p4eu6bgl3mb4hin32qo3x5zfq
2.fcp.freenet.i2p,ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
333.i2p,ctvfe2fimcsdfxmzmd42brnbf7ceenwrbroyjx3wzah5eudjyyza
55cancri.i2p,b4iqenefh2fr4xtuq6civfc6nhnia6e2yo36pf7vcgdvrwmh7xua
adab.i2p,pxjr6f2cig6v7v7ekam3smdnkqgmgseyy5cdwrozdyejm7jknkha
alice.i2p,iq26r2ls2qlkhbn62cvgb6a4iib7m5lkoulohdua5z6uvzlovjtq
always.i2p,wp43sdtuxum6gxbjvyeor35r5yvgtkp3dcu7dv47lx22zeb3relq
amazone.i2p,e6kq73lsxaeyiwpmykdbdo3uy4ppj64bl7y3viegp6mqrilqybqa
amiga.i2p,edy2xappzjjh7bxqounevji4wd2binqkv7gft4usrkan45xhbk5q
amobius.i2p,rj6432agdprun5baai2hj62xfhb4l75uvzl55dhj6z5zzoxv3htq
anarchistfaq.i2p,xosberjz2geveh5dcstztq5kwew6xx2brrqaorkjf2323bjzcd3q
animal.i2p,5iedafy32swqq4t2wcmjb4fvg3onscng7ct7wb237jkvrclaftla
anodex.i2p,25cb5kixhxm6i6c6wequrhi65mez4duc4l5qk6ictbik3tnxlu6a
anoncoin.i2p,nmi3loretkk4zbili32t2e5wyznwoxcsgzmd2z4ll3msgndyqpfa
anongw.i2p,owrnciwubb3f3dctvlmnaknb6tjdxtlzvv7klocb45mmhievdjhq
anonsfw.i2p,ir6hzi66izmvqx3usjl6br3nndkpazonlckrzt3gtltqcy5ralyq
anonymnet.i2p,77ouyl2ane7ffgydosd4ye42g67aomtc4jrusmi76lds5qonlffa
anonynanny.i2p,l2lnhq2dynnmf3m46tcbpcmbbn4kifjgt26go6n2hlapy4drhyja
anonyradio.i2p,cbobsax3rhoyjbk7ii2nd2fnl5bxh3x7bbearokyxgvmudn7o5bq
antipiracyagency.i2p,by4kcmklz7xnkai6ndfio47kts3rndm6wwleegtxghllimikdapq
antipiratbyran.i2p,y2qbhrvuciifbszaqqwxd5t75bomp7kzdqx4yxsrkaq542t75k3a
aosp.i2p,ly7raldsh2na2cgw5yvueyvqqjgx3vbqinecjrqdldgya76i2p2q
arc2.i2p,rnmosuwvtftfcrk5sk7zoyhyadh2g4dhe2mif5ml7qjisgkyw2na
archaicbinarybbs.i2p,t7o2tw36cffedgfr6kahewpkrntofnliuapji2e4rucl3os55epa
archiv.tutorials.i2p,lldr2miowq6353fxy44pnxfk37d6yn2f6kaivzecbmvvnnf5exyq
archive.i2p,x54d5st3dl6mwgfxj6raiekqkypo5pdvuex3n62szwju7hgefiyq
archive.syndie.i2p,abbyu5n3mh3nj7pe3b6byldrxswvva5ttxcafsnnseidanurq3kq
ardor-wallet.i2p,tm23k5ny3umhf6vf3kghnnwacli5zywq5wrr3xcqowbcofuyr4gq
ardvark.i2p,jcmw2sol3hruwc6rfinonx4e23pjkukkg7lg7xt7xb2gpiyyraiq
arf.i2p,o46lsq4u7udxg3qqlidrmpj4lb4nr7ldxmbb2x53nftndaeyxqeq
arkan.i2p,7o5y2lyyrjx5tf6l4fyumywui7msjv5azaaheatvw5sqj7mxbuvq
asciiwhite.i2p,itbzny5ktuenhjwjfqx3jravolhlj5wullhhr2m4qr6k2emnm5dq
aspnet.i2p,tsb7zqru57p4q2a7cto2lko4w5cg4lieglwm6t27c44fkphqmf2a
asylum.i2p,p45ejjw4p2q6nq3mzi6cm6ep35grtzshboidj2lojmrmic22noha
auchan.i2p,6vxz4yp3vhjwbkmxajj7wiikxafwujig63gkhjknbq6xh4rqpm5a
aum.i2p,ohdfneqxapfd3fwfbum4tut7z6k3rnr7rrguoxdrrfe2tln2kpbq
awup.i2p,v6g32duzrkacnrezfbll3pza5u37h7lnukr2wbsk6rqen6prhbga
b.i2p,272kt3gcx6wjurunzaiiwld7s5p4mpjewfubzmlcvw2vie62ckpq
bacardi.i2p,hivhnx2v47vh234c7coi2urj5cyvbl4bu3ypjr7snklortyqeljq
backup.i2p,kepphem42whle3rkfv26wcksmnegdbg6rdp6t3oobdkc2fmzrdkq
badfish.i2p,f6v26gyr4eipy3a7pi2voulw5qvob6dg7zij6xpo2ywbi5tvbu6a
badtoyz.i2p,3qz6ubtwlt2c4iasofjirkckq43u5fgkzyg7mlutcsym5gzhijna
barry.i2p,4kyahq53ol52n23l44tefgeaxqpp3cbb632t5k3umdvqcooevdzq
bash.i2p,s3wouoilbl3mrefxjhp4qoyujgok34e7y6vmpbu6hx4342ivqo4q
bdl.i2p,kp6fnuulenbjm7r26pfbmjcq3u7c7kvxeajodvgr5flcnskdgi5a
bdsm.i2p,pa7fxql5jljegg7j5tglhnnaod2sptq3gxvdn3ji6muqyhgn3poq
betaguru.i2p,d7cduwwhrcc2voameqfkvd66u3advu4jw2p6pysgax35vq6ovriq
beyond.i2p,uaicfqlrpjtitqbqkpfujanj5dollzfzee5glsuls67ekw6hlpoa
bible.i2p,pypz7ca24n3lyp4tm3kvncg3ltp3gd5pgnacc6zltoeffiyyegda
bible4u.i2p,xs6lr2g5jiaajtb3nkno2zmy34eipitrggooxb7wtey7uko7bqmq
bigbrother.i2p,tnxiifs6uticzyg6ac4lhv2l5luwi6xra7yngocro56ive5e4jsq
bitlox.i2p,lqw5khxcdntlv3u4vhn53upcqirplvnc4etjlmoytrzs66ytettq
bittorrent.i2p,pgax2vz572i4zsp6u6paox5xubmjrkqohq6g4hvlp6ruzzy56l5q
bk1k.i2p,nlyegmtyfffo5jfgg5h4dxxnlmqko2g36gpaye5a7vd3is35xxfq
bl.i2p,e73d6uhnfbylza6wqkhxejmqeyfb7thkzw35gn5ojmna64jzyk2a
black.i2p,sjwueu62qpe6dtv5b322k3f23fl4uz3w6qe6wcrwauiwpnymypfq
blackbox.i2p,7josyf7zjieoib3ovmr5a4dh5w64kmfh45lv5h436eljtgfegtqa
blackexchange.i2p,ztgr5kghkyn43fhhkuycroxgfti6cojo3vg4wdd3usqonyvrla5q
blog.curiosity.i2p,yiz6jec5k7ccxdgnh7msqa4ze52bqqmf6rpq6bqdyojra2erd4ta
blog.polecat.i2p,orlccceubewvxo3fbdyydq6e4uuidbs4xd5u2gyqbculnowo3ehq
blog.tinlans.i2p,ylkch2nkrwehakx4z6wiyjbeqwlgasknukdkex6r6yq4xusrjnda
bluebeam.i2p,lvxp3cbcfwtol57d5pmrsck32t7ndutlxubjb4smaf32bynhlk6a
blueheron.i2p,anfb5jrhixjmvkyxctqwkezqer7dbob22wge2bh6wsewbhgnftfa
bnc.i2p,fr4zbcygmx2vdct6nrabakfys4b4derm6jqu2ovppkgqillvlqxa
bob.i2p,i76m7dwm5hnapljendbie6fc5y3mjlkdlduo3tvbwiwmvhxbpyaa
bobcat.i2p,ftuukjtcquuvppt726w37boit7gp5hf2yxwfop35prx3grzzzxlq
bobthebuilder.i2p,qlahgthqhr4uojkkwahnper2cl3ro5f5gtzy5t4lzapbzo4osy6q
boerse.i2p,7633w56hd53sesr6b532r5qlbdnvyl5bnvama6ign6xryaxol4rq
bofh.i2p,auvuinzogu6gc4pwsgbjijuszxgcjygciu2wy53pfz7mo5nfpc5a
boing.i2p,bgsq33bh74j66hn4oh7oovlvuhhdyw22lq2qi2fnv3jyh2ryap3a
books.manveru.i2p,eb2tisc2vr5jvjqrixrozcujiucwxg4m722stxwho5666ipl67zq
bote.i2p,bhjhc3lsdqzoyhxwzyrd63kvyg4br6n2337d74blyintae66mr2a
bozo.i2p,7a2d23h6htprhzrol36vgwgklsbqrnuya4tbaaaspmaeaodt57iq
brittanyworld.i2p,e76umhhic3474sdxiuax25ixyfg7y3z7oojj4fmxvhgv3ruet6aa
bt.i2p,uhkuu54pg47zey76h45tnvsdtpkf5bthbtrjgnaloi5m54h4hlaq
bugfuzz.i2p,ubszn4gsf22vga67rvzzlg4qj2bfcq6o52fmxz46xruawqm6z7rq
burntout.i2p,lkep3fd7tjvxrs25crr2c3jy7xm4s7bqiua5r327zgpw37sgyerq
bytepay.i2p,7amc4ztwkzu3cgsaaaw3223ohuihn5hlsqc6gpf2rxdyptdkyugq
ca.i2pd.i2p,u5safmawcxj5vlrdtqrsqbsndkr5cfenpicgg5euu4xqm73yicba
cases.i2p,kmpmk2fmineaiwublteqlifg4fkmewnhmxqlcgg7qwecz6daj43a
cathugger.i2p,vq43xjjcnejqpzfprws5qzrea2siieshu4tglpdepql2w3w3bpba
cbs.i2p,u3lp7wazvq6opodzwjg5sc5w5kwxehmxd4wcdpt4s4j2k4dx4apq
cerapadus.i2p,zroed2cxga5zeuu6rcvmp2yfi77nzduw7yhdplbeuqkuyxwbrzaq
cerebrum.i2p,u5gtsfn267udwfh2uq35jiabkufifvcbgv456zz34cydutsiw2eq
cgan.i2p,43z65gdr52xe3fxmkumwp3dzhedu4tu4rdtzr24hz5b4awcpfbqa
chat.i2p,ollpwnp6yidc3obbb3famgt6rw5jg5w3k3a6z7hhaegj6gcohiuq
chess.fillament.i2p,tv6wbanei647yf5bie4dhg2wmybkjurezlpdfwftc5ajqlfswwya
chess.i2p,sbnoqznp5yzxals3vs6nzyqaj2fetvonys4e3b3x4ktmfeus54sa
china.i2p,wit6f2zx6dtuqqze6nhbykrds3idppfirxvhf2f7ydqoqf4xdzeq
chitanka.i2p,u4s3jneepk3akoez46kqiwikoezi6zyj2ibjkjyi4uuvsbcojzba
ciaran.i2p,2r3645eete6xwbfu62ogonudcrcgqq25sbnij5v4geru74yrscna
ciphercraft.i2p,7s5pkqbpbfdkxtwuu2e2iwstbikyewvvscy76lij4x5pfbygbjca
closedshop.i2p,6fg67mbw2okopzyonsck4bsy3cy7l2fame56uiysr2cezhjhzdbq
cneal.i2p,g4za73ffigv3ht4jnhzy4dae52djjq7lqcguqsfg3w5cxzqm7nba
co.i2p,3mvo5eifcwplcsoubtvqkzdahwo2sdhfygfdde7lj2glybk4q22q
codevoid.i2p,2mukrqwtinsw27uoejtrz74zxtilyhnnfdyso7j3yo6vaa6nzlaa
colombo-bt.i2p,cyr75zgiu2uuzap5zeosforbgvpfbqos2g6spe4qfulvzpyhnzxa
complication.i2p,x2av6rwj5e5tp64yhdmifdyleo4wblw4ncrrcrabxwscuevpdv7a
comwiz.i2p,6p7zqfotzbd66etl5xqy3p6xvr5ijucru3am2xqa7wmnj6vf3djq
confessions.i2p,lh5vitshufxpmyr44zgyymebo5elc42eda7pxvn5lmtes47c7rxa
connelly.i2p,5yrris3nigb3fapvzrlrcaew6cdmzdknzvgrc7y2jpn3ntqurweq
costeira.i2p,abhty5xlmnyab2kqdxcd56352kcescxoux3p6dbqdrghggyygnxa
cowsay.i2p,q4ghzfpah4ffvm3bhc6fdkrznk5f6jxfjm2daytlparznai5d54q
crstrack.i2p,mm3zx3besctrx6peq5wzzueil237jdgscuvn5ugwilxrwzyuajja
crypthost.i2p,zywhrxtnkjc3rxxvxbocom7ml4hnutomgtuvqrwyf3rhuupnq5ca
crypto.i2p,vffax5jzewwv6pfim55hvhqyynafkygdalvzoqd74lkib3hla3ta
cryptostorm.i2p,mlu7mswyirjf53usqq7gyamvqc6rqihezgdbevov3dkxmkfo57aq
curiosity.i2p,eomeif4xrykxlzhawc3icdilje5iammijos6tyizwhrfh3j7qdvq
cvs.i2p,yd6k7dzpsa2tnlzx4q7xqkmd4qsjk5xk5hbiqpiarwbeyvxaxgba
danwin1210.i2p,eoqdf4no5dxn4tw5n256kkd4lzz3uk4p47np4mepsykpsdzrnvba
darknetnow.i2p,gkx3o5fy7mv7l4psqqnhp35d5iun7rt3soci6ylf3rgb7a5a655q
darknut.i2p,2mk37gtvpk2i63o6vl7vna4dr46rqexxetupgn5efuuins7x3qya
darkrealm.i2p,gbh4eerxdsph7etxsxznfhvmuiz54trlkenakqep343u4xcoekzq
darrob.i2p,hz2xhtpeo6btgiwi6od4qj2575ml5o2246rd5orarruyjhd63zja
dashninja.i2p,dzjzoefy7fx57h5xkdknikvfv3ckbxu2bx5wryn6taud343g2jma
davidkra.i2p,nq7ca2egm563nir3xegfv52ocgmxstpz56droji4jgnzfoosk45a
dcherukhin.i2p,qa4boq364ndjdgow4kadycr5vvch7hofzblcqangh3nobzvyew7a
de-ebook-archiv.i2p,6mhurvyn6b6j6xa4a3wpuz7ovpsejbuncvyl6rnhepasfgdgmn7q
de-ebooks.i2p,epqdyuuhtydkg5muwwq47n7jvr66pq4jheve7ky5euls6klzwuyq
dead.i2p,7ko27dxvicr2sezvykkrfiktlghx5y5onup3f2bas5ipocy6ibvq
deadgod.i2p,63bveyh7wefb44hlia7wtxxb3jal3r67thd6jekmwrtq4ulaaksa
debian-multimedia.i2p,cylxxz2y35x6cvyrl57wu3brckurtexatyi2i5awz3eeamqwjspq
decadence.i2p,pw5ys7k2grjb5myydpv6ohikm6nna7y6u2dro44i4rucgulu3ikq
deepwebradio.i2p,2nait2gdeozkgf6gyhzjfij6mwldwkxxwcvtxobb4b5q5cvtm5la
def2.i2p,cepsrw27kdegwo7ihzouwvgcvw2obswwjs23ollgj7hk2yrce3da
def3.i2p,xbf3ots2purqun7orn72ypkpjmrzbfrkj3u654zfe77hbrbow6la
def4.i2p,yyzdq4fwwmnlojp23drfpfqujln2vcjozjrfzfeuriuqzdq7g4mq
deploy.i2p,ujzspsqkbz5z272eozsrdv4ukl434h3fuliwrfxxnab74jmd7e6a
det.i2p,y6d4fs3rpqrctuv77ltfajf5m4tl4kzcu7rtwhxgiohylfxxow4q
detonate.i2p,nykapdsjjswdkjov7x3jzslhg4ig3cpkhmshxqzijuhbisx25jja
dev.i2p,cfscxpnm3w3qxnlv3oikewxm4qrot4u6dwp52ec2iuo6m7xb5mna
di.i2p,3irnooyt5spqiem66upksabez4f3yyrvvjwkmwyzlbealg64mgxa
diasporg.i2p,edvccoobtjukjgw2os5eetywanbb2mpag5aknkrpia5qx2koksua
diftracker.i2p,m4mer767ipj7mq6l7gdrmrq37yzvsj3kzezd7n7nsfuctntjseka
dm.i2p,heysbdivyeugdbggpscco5wje3dsvwgcpp5ot4sopooebnmiqvtq
docs.i2p,ato242wckzs4eaawlr5matzxudt6t5enw73e4p6r3wajwkxsm3za
docs.i2p2.i2p,las5l45ulwwf5i72nht6vk33sfkidcpr2okpf5b6mvgbk3a2ujna
downloads.legion.i2p,xpmxdpuuptlekyhs7mmdwkvry7h2jbvpqpzsijqe3a5ctxgodesq
dox.i2p,vk27cjdrtegfdnrjqutebgxkpyrfj42trdfbsupl5zn2kp34wb3a
dropbox.i2p,omax2s5n4mzvymidpuxp2yqknf23asvu54uon6cxl6gdrlblnuiq
duck.i2p,3u2mqm3mvcyc27yliky3xnr4khpgfd4eeadhwwjneaqhj25a65ua
dumpteam.i2p,2fwlpuouwxlk2nj4xklvm43m52tqyhqnu2fcfiuv7clvf3wd5nwa
dust.i2p,u6xgh6zhhhvdvefbqksfljfs3nyjvqcrmyamp5bryz5f4injmniq
dvdr-core.i2p,fg6l2ej6qrk5rkyfzdptxx5xkcm4kvdla4gg2tun7z7fm5cxxw5q
dyad.i2p,7n2ljphvp2dep7imoujvydxp4myuxfld3axwfgcny5xc5x6jj6ka
e-reading.i2p,z54dnry6rxtmzcg7e6y3qtsig5yf5fmehuvakcg5wnuahx3iafuq
easygpg2.i2p,bwxry5alzx5ihgrd3glah4eotddblzhalvpheppnw4zcajzqoora
eboochka.i2p,ou7g64d5in4sugv5fgmmzwnunuw5hloixio7puthmrvrkwrp6egq
ebooks.i2p,bvpy6xf6ivyws6mshhqmdmr36pruh2hvoceznzeag52mpu647nzq
echelon.i2p,afvtspvugtd32rsalxircjglh3fhcjzk7gxrm3gw4s2yrpvzk6wq
echo.baffled.i2p,bfr3lyicr72psxvt2umqfb562rtex66w6q3hi3tktzkoyane2iha
eco.i2p,2dq2o5h6c6a674qaduipp55mid5iktumjbswuwmpsrcqaeowdvwa
eddysblog.i2p,ieac3ub4g5sy3wuhsbqfembnpp7f3a37xgcx537ytzsmgfzexnbq
edge.i2p,aknsl5wmzjmwyc4wxutfdwy2w5vgd3vcx52mqx647hcgvyurmqta
eepdot.i2p,t6edyotbxmxvy56fofdvmragvsj65te2gkhvzv5qnblicutyvgoa
eepshare-project.i2p,sn26kom4qyuzouppv4lwnk6bqabdydcegtrilybviibwiq2s4nfq
eepsites.i2p,isskhl4ak3g7qevrarlmblddgr4ugnn3ckalwpjcvxafk5rjgypq
elf.i2p,duz6ey27ohpcp3llylklzdb63lylolzcixad6bh7rt5tkq42qqpa
elgoog.i2p,z6hrgkg2ajmuzlrddjlffrgctx7x7fkipm6c4hdzmohyn5wkr4ya
ems.i2p,734zw4jsegdf55zl3z6s22tqkbxcghu4qvk6q2wevjfmx7xhbn6q
epub-eepsite.i2p,yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
es.hiddenanswers.i2p,cw7ge5ey4ekp5iep2kaw6j54boebtqytpcbnvio2bfpccd5ejzfa
eschaton.i2p,xe75f5hzmrq6rkhsef2geslmi2v2yfngdiysmlmxvh7b4pyyjk4q
esuwiki.i2p,cwxuiwcpymb72vm5vluba66ofhugyf5qeevvwo7e2fqrxl243coa
evil.i2p,ljfl7cujtmxfffcydq77pgkqfxhgbikbc6qxjgkvcpn4wzd73a4a
evilchat.i2p,s5b7l3hzs3ea535vqc5qe2ufnutyxzd63ke5hdvnhz24ltp3pjla
evilgit.i2p,mx5vyoqhg77yuhthwznsxrepjsemq4uwitx4lxdzetk36ryl5rla
exch.i2p,vsyjsbbf2pyggtilpqwqnhgcc7mymjxblamarmxe5hmbxaxvcndq
exchange.gostcoin.i2p,n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
exchanged.i2p,ylmulgfskl6uiwac4hw4ecwqdzd3oxtwaemzj25zc6k5q4rkexra
exitpoint.i2p,5zmjurq3enudcenegnxu5hqmfmayz4lxvnik6ulch4xssa2ithta
exotrack.i2p,blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva
explorer.gostcoin.i2p,ktoacmumifddtqdw6ewns3szxths2hq2fat2o7xnwq4y3auga3za
fa.i2p,6n6p3aj6xqhevfojj36dixwbl4reopkhymxmatz7ai5sroh75rka
falafel.i2p,djpn5cbcgmpumwcriuzqistbae66txca2j4apjd2xesfgb7r5zmq
false.i2p,77mpz4z6s4eenjexleclqb36uxvqjtztqikjfqa4sovojh6gwwha
false2.i2p,j5i2tfumh3ti5sdtafwzzbpupmlcbg5drysfay2kxbdpsaljrosa
fantasy-worlds.i2p,62a4xcyyhvfrcq2bkckb7ia37fmrssrgx467tlkxp32fjpq577wq
fcp.entropy.i2p,de6h6ti5z3mcbdcwucu45vplikqyoeddsu3rqy7s2zy5i47j3peq
fcp.i2p,ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
fedo.i2p,zoamh7e3k2vf2g6pfy46ho4taujk2f4mxqqsv3gbg554fxbvyfqq
feedspace.i2p,kvtnpx4jylgeyojfhix4x462sqn5uork3roml4sfzotkxx62i4wa
ferret.i2p,kkqie5qmja7bkf3iad4zxhrdarwj7kbrx2m3etn5kmba3shgwj4q
fido.r4sas.i2p,i522xmu63hfbaw2k54cthffcoqmeao6urjyq3jg4hddf6wf57p3q
fifi4all.i2p,v2stz6bsot7sbjzix5tky5dm5ej7gidmjnkvzqjju5xvz5sz6fwa
files.hypercubus.i2p,qfglq25jwieszgyt7muz6dambzqsrmjhhszygzzx2ttubc77sffa
files.i2p,w2sy74xe6oqnuz6sfh5fhkzu7boholgzd5f3anhj47srxwpj2vaa
files.nickster.i2p,yil7dp2hg5pbqyovsiwb2ig6zjsq4tize3fnwemmqdrr6j5itdtq
fillament.i2p,udj2kiino4cylstsj4edpz2jsls77e32jvffn2a4knjn4222s2oq
firerabbit.i2p,awqh7n3wskzl3epyvkdwgarmfybsncm7vye6psg4tpkmplh3mj2q
flibs.i2p,ocdm33e3h5tdml3yyholj4objdwsrhlugfqjnqgdkslmgdzb6b3a
flibusta.i2p,zmw2cyw2vj7f6obx3msmdvdepdhnw2ctc4okza2zjxlukkdfckhq
flipkick.i2p,aso5rzc4ym6g2bcbxjy2n573bmbenkjawva2jg7fhyqhwtwgu6lq
flock.i2p,hflpi33ko5bi2655lx6bpzstdnjqgzrz23inovqjx5zpntyzyb3q
floureszination.i2p,vitpvfb25sikuk3crgcvtcdi7hajxnnq2t6weay3no7ulur2wwwq
forum.fr.i2p,onvelkowkbuwrglhw2cnocggvbdudi75sll5mfirde3cbopjqivq
forum.i2p,33pebl3dijgihcdxxuxm27m3m4rgldi5didiqmjqjtg4q6fla6ya
forum.rus.i2p,zd37rfivydhkiyvau27qxwzmerlzbqtthsa5ohtcww62zrygjaga
forums.i2p,tmlxlzag7lmkgwf6g2msygby3qttxvm6ixlfkq6s6cpgwubp33ya
fproxy.i2p,keknios3gm6kh6onez6x2bm2t7stv54oanvltuagphgdfjdw5e2a
fproxy.tino.i2p,fpaituvuvyxp6xdjnv3i27alnj2ifzcvqdweqb6yj5uybotzvyha
fproxy2.i2p,r4lgw4wmza25g7j5fjocjbwzwthfg4ymcbm52ref3hh2hogskcza
fr.i2p,ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
freeciv.nightblade.i2p,rluupsgxbvw5t7jno3apyzlrdirjkljft4gdoy4mxxh4fmd4xzta
freedomarchives.i2p,4ck6oliqfjz3sccpya2q4rh5xkj5xdxkqs76ieml37537nfhwd2q
freedomforum.i2p,abzmusjcm3p3llj4z7b5kkkexpsxcnsylikokouk5txfim3evqua
freefallheavens.i2p,giqnkltyugfmsb4ot5ywpvf3ievuswfurk6bjie4hxi2hh2axajq
freenet.eco.i2p,2kf7ovb35ztqkrurkm76y34jfpwi6go25xj7peznnmxrl7aieo7a
freshcoffee.i2p,sscuukigp6alcb3ylhkcugoejjfw5jqgtqbsbafw4hyku42lgc3q
frooze.i2p,m6ofa5dmyse4b4jg7kfmluuuc4pw5jqu6zh4qnboin4vropxepja
frosk.i2p,63naq7zb3hvbcppj2ng7qwf6ztusp4kwpyrzbt4ptafcdbu4pfjq
frostmirror.i2p,ycz3imuz6yte2zhlapmsm3bsvc46senvc2jxzwsbfdct5c72qulq
fs.i2p,ah4r4vzunzfa67atljlbrdgtg3zak5esh7ablpm6xno6fhqij35q
fsoc.i2p,vaqc4jm2trq7lx2kkglve7rkzxhhaptcwwl32uicx4ehf5k3hx6q
galen.i2p,4weo7zkxscxbcouiqx4mlnb35uwl2lromikzk33er3fljktyvi2q
gaming.i2p,rfxberwod6st2zc6gblqswxjl57nucgc3xrbwss43pe3dvqqzj4q
garden.i2p,qkk2dqx6nocycgt3vinsoc76cxkb4jreybcpgz3fcps2dbe4rowq
gaytorrents.i2p,fnggbr2t2aulr6rvlo4aehotx6wecfob7u3k2nxsnvtm4xex424q
general.i2p,5fklrsztdqpl3hkkwwrrw2rdowrq7wwhwb6h7avvk4fhansp4vvq
gernika.i2p,wpzqv3lxpecdsvcaadvbmrhhwlc7kp4n2mijdv2qjw3zr3ye232a
ginnegappen.i2p,kbhfkzx5jeqhfgss4xixnf4cb3jpuo432l3hxc32feelcmnr3yja
git-ssh.crypthost.i2p,llcp7jvz3hgtt3yzkdgjolwobisgvhv4xqa5a4oddejllyozur5a
git.crypthost.i2p,7frihhdcisdcyrzdbax6jzvx5gvtgwsm7m6kcem2tlaw4jtahbqa
git.psi.i2p,em763732l4b7b7zhaolctpt6wewwr7zw3nsxfchr6qmceizzmgpa
git.repo.i2p,vsd2vtgtuua2vwqsal2mpmxm2b2cpn3qzmqjoeumrrw2p4aot7uq
git.volatile.i2p,gwqdodo2stgwgwusekxpkh3hbtph5jjc3kovmov2e2fbfdxg3woq
glog.i2p,ciaqmqmd2wnws3hcpyboqymauyz4dbwmkb3gm2eckklgvdca4rgq
gloinsblog.i2p,zqazjq6ttjtbf2psrtmmjthjeuxaubi742ujrk2eptcsaoam4k7a
go.i2p,ll6q4lsirhwkln4dqxwqkh2xu4mu3jiy546b4uhe4fypyb4vvx2q
gonzo2000.i2p,nogsv7okydhbvrewv6hb4xdojncvhkusnyib4lglluc4uw67a37a
google.i2p,4p3ajq4cotnflmuv7fhef3ptop5qpm3uzzgp5bahxif3nc4w3ffq
gostcoin.i2p,4gzcllfxktrqzv3uys5k4vgkzbth4gqednwhfpt755yivm3davuq
gott.i2p,dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
greenflog.i2p,zny5ftmhzxulxzyczmeat53qjnue2xtqv2clisc7dg76lwfceecq
gstbtc.i2p,n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
gusion.i2p,4qyfdhizjixe2psu7wcvqufix5wlijocehpb2futurcmlhlktrta
guttersnipe.i2p,kizkhzes2bzp45widihremo6geepfk7dl6juourkvzuvlc6y3spq
hack8.i2p,un63fgjgi3auvi7zscznwqfol7ka4johgthvqf635mg3fefsjgpq
hagen.i2p,e2t6rqd2ysbvs53t5nnaf7drllkgk6kfriq3lfuz6mip6xfg644q
heisenberg.i2p,jz4quyw7zt63tmw65jfp76fblwadjss4iyi4puqdg3dye7oaqlvq
heligoland.i2p,gzrjm62ektpqjfsem3r3kwvg6zpjvvhvpjvwfxkm2ay4zu7sp6oq
hidden.i2p,iqodhhqo473qv5gwhjcs2bsrbhlqtpzgpnuumpastfiyhuwb2kyq
hiddenanswers.i2p,kj2kbzt27naifij4ki6bklsa2qfewxnkzbkgvximr4ecm7y4ojdq
hiddenbooru.i2p,zma5du344hy2ip5xcu6xmt4c7dgibnlv5jm4c2fre5nxv44sln3q
hiddenchan.i2p,6y4tltjdgqwfdcz6tqwc7dxhhuradop2vejatisu64nwjzh5tuwa
hiddengate.i2p,rvblcu54jvkkfffp3fobhunsvpgfc6546crcgzielzwe2s5m5hbq
home.duck.i2p,jsh7yfvm2t5urdcnmfzdy4n6vegqskdtlwem53chgxli4ipfmuma
hopekiller.i2p,kcaelbgsvrkiwpx36b4wxofebrl3njx7rgm5amzfmqwbomt44cxa
hotline.i2p,6cczi27iuxkm3aivazaemzltdqgh42ljzurqp43uclbz2lid2uqq
hq.postman.i2p,27ivgyi2xhbwjyqmnx3ufjvc2slg6mv7767hxct74cfwzksjemaq
http.entropy.i2p,ytu7kz5bdoc26nkpw2hajwt3q7n5rcbg2eokyefhmkxmmslimbdq
human.i2p,nrtcelq3humyfvoxmzmngpka6tmyifweouku5mbi5av4lc43hzaa
i2host.i2p,awdf3nnmxxup5q2i6dobhozgcbir7fxpccejwruqcde2ptld443q
i2jump.i2p,633kqgmwzzu6vhkevwvbf2pfyejt3gkes34i6upa4og57fgdfcxa
i2p-bt.postman.i2p,jeudwnx7mekjcowpqo6xpkwn7263c57y5piurrjrdzinjziu4fla
i2p-epub-eepsite.i2p,yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
i2p-javadocs.i2p,icgmr6hhjudl4yxhtuq4pxvss2pzypwddzowajgs5rdz6f55novq
i2p-projekt.i2p,udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna
i2pbote.i2p,tjgidoycrw6s3guetge3kvrvynppqjmvqsosmtbmgqasa6vmsf6a
i2pbuggenie.i2p,bioq5jbcnfopqwvk7qssaxcl7avzeta6mu72jmxjeowflpcrhf6q
i2pchan.i2p,tduxyvfs7fzi26znvph3mu2d2ewaess7emomfci22wvownajphuq
i2pd.i2p,4bpcp4fmvyr46vb4kqjvtxlst6puz4r3dld24umooiy5mesxzspa
i2pdocs.str4d.i2p,yfvbtrhjac3jutdsqzugog6mbz3jtyhpwovrt2mqc5mzv534y7cq
i2peek-a-boo.i2p,qgv64klyy4tgk4ranaznet5sjgi7ccsrawtjx3j5tvekvvfl67aa
i2pforum.i2p,tmipbl5d7ctnz3cib4yd2yivlrssrtpmuuzyqdpqkelzmnqllhda
i2pjump.i2p,2mwcgdjvfvd3xwumzqzqntual3l57h3zo7lwdmkjboeraudpkyka
i2plugins.i2p,bb63kmnmbpitsdu45ez54kmogvvljn3yudksurcxiyq7dn5abt7a
i2pmetrics.i2p,v65p4czypwxrn35zlrfkar2w77vr42acd7gbszegsrqq4u7sip5a
i2pnews.i2p,tc73n4kivdroccekirco7rhgxdg5f3cjvbaapabupeyzrqwv5guq
i2podisy.i2p,3c2jzypzjpxuq2ncr3wn3swn5d4isxlulqgccb6oq5f6zylcrvcq
i2push.i2p,mabdiml4busx53hjh4el5wlyn4go5mgji2dxsfyelagi4v5mzjxq
i2pwiki.i2p,nrbnshsndzb6homcipymkkngngw4s6twediqottzqdfyvrvjw3pq
iamevil.i2p,au7jhslyt4cxkjp365bvqvend3hhykrrhbohtjqlgoqrlijbezja
icu812.i2p,bxgqwfsnr3bgnr6adn62anjcin5nuthqglotb3wn3dgynsfofeva
id3nt.i2p,ufuqdzsxltiz224vq5gnuslt3a3t72dhy5kq6i2xway53m6pzv6q
identiguy.i2p,3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva
ilcosmista.i2p,6u2rfuq3cyeb7ytjzjxgbfa73ipzpzen5wx3tihyast2f2oeo24q
ilita.i2p,isxls447iuumsb35pq5r3di6xrxr2igugvshqwhi5hj5gvhwvqba
illuminati.i2p,syi6jakreatlm2z22u76izyqvbm4yi4yj7hr7jb63lgru5yhwwla
imhotep.i2p,qegmmhy52bdes2wqot4kfyqyg7xnxm5jzbafdb42rfoafadj2q7a
in.i2p,r5vbv2akbp6txy5amkftia757klgdy44s6cglqhmstpg65xycyjq
infosecurity.i2p,v3gkh5kqzawn2l3uzhw6xnszsh6w3nztjmlwil7p4kyrwrsm2dba
infoserver.i2p,jd3agbakybnhfvkeoxrx7t33iln6suzomv3kxkxf77j7rkonch6q
inproxy.tino.i2p,ex5yf6eqqmjkrzxnkn6cgvefgne24qxsskqnpmarmajoit43pgma
inr.i2p,joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq
instantexchange.i2p,5wiyndm44bysev22kxvczxt37p6o6qroiqykytrvn2yzi55aqfxq
investigaciones.i2p,n7hqd4asxrdwf3zwo7rzv27y2qkcfmakmz6mjar6aw6hlc4c7mha
invisible-internet.i2p,jnpykdpp46zenz4p64eb3opadl5g42dls3rurk2cvq6a3g3rvbvq
io.i2p,tx22i6crnorzuti3x6va4mijsbhoqswy2cfdxjbvprgsq4eerg7q
irc.00.i2p,bvcja52pppgfspp2ueuipoysjnvvoyblz2h6smpxcmanjquogirq
irc.arcturus.i2p,5nywlbn35p2nwsymwpfmicu6fxono6g64vwusxbsvmm2qwz6vupq
irc.baffled.i2p,5zmtoopscym6qagkvpgyn7jnkp6dwnfai745xevkxlou77c2fsjq
irc.carambar.i2p,hxzbpivxqxy6nuae4t6fnkhcgnhs4c72vt6mmsqfmfhrkn2ca6gq
irc.cerapadus.i2p,e4ckznxcxvgyikzjmjsu72i2dbj2d76ogexyukklbjvpcnhp6zzq
irc.dg.i2p,fvp3pkcw4uvijqabwtekcdilklp73gyasuek67wdcs2mucep4caq
irc.duck.i2p,chdpmm4gxffyn24xx5dhxvfd5httu42i5gtoe6cctjlsf4mbofeq
irc.echelon.i2p,ez2czsvej5p3z5bquue5q3thujcodfze7ptybctqhnqc7hms5uzq
irc.freshcoffee.i2p,ubiu2ehtfnrleemgpzsqkahwnvzuaifqa3u4wmaz5maaisd5ycfa
irc.i2p,l3ohmm4ccxvyuxuajeaddiptci5lsrnxtvtyq7iohphrt3oj2evq
irc.ilita.i2p,5xeoyfvtddmo5k3kxzv7b3d5risil6333ntqrr3yvx3yubz5tk3a
irc.ircbnc.i2p,4rqcsqd7xif6r4v55blqvmqu5er6due4eyene3mjorfkts4o3rxa
irc.killyourtv.i2p,wre4majmg2vnbi6id27et7yw6lnpf56wkbm6ftnlwpvxnktq73hq
irc.nickster.i2p,dhq3fhd5scw3jqhj5ge7kqfpprfolcgxfjbaw24obohaiqjtdu7a
irc.orz.i2p,7gifacog4aoons3syybojbbnyqqaaqijhngrehn2xlq3eucuyjcq
irc.postman.i2p,mpvr7qmek2yz2ekegp5rur573z7e77vp3xqt2lfbco5i6nkfppcq
irc.r4sas.i2p,hodhusp73gltozgrnianlbploon3rrvhrzfn5mf2g46o7aaau5la
ircssl.cerapadus.i2p,4x2i745i4w52ss3he2kse6tzwt64pr62yvrcb72lgvrb63fup6ea
irongeeks.i2p,ecduxoion5uc5hnvzjxff6iiwhdwph6gse3dknyvlo7e6gaeho7a
iscofsi.i2p,enjgdxs4um2dmhdb2ajff2egrdijkjji3g47m6unb74swbrqsddq
isotoxin.i2p,wue3ycaccf4texikza3fh6p5yrmtgnooisuypnepo5mo67lmpcqq
itemname.i2p,o35ut7hgywy35okvgkjkv3ufzv2ejv4luap4oytwbyy2jqy6u4vq
ivorytower.i2p,fpwrfvidfexsz7dspofkwtkmmizm7lyralfz5kvykffk7gubvxsq
j.i2p,kjxvohlsf5sdrzxzfcrmvquccnoevi6ytbl63mstsru5wt2dx3ea
jabber-2.i2p,pvnmzgemetkwcuvt45omgowmeznwk5xw3nc3ygeoz7yekqxy57na
jabber.duck.i2p,rhdzvvzraqzzm67zpyegb7knpfrjeffitixqzeyymdoz56uh2rtq
jake.i2p,v2axvy6pqefnla7gun5fmqs4lqe4xfyqovgzcundhxrpcdvfd7cq
jar.i2p,2fthkmujup3xiiu3yple24n6g4emzdiiimbuqwvpdddtsr3c4nrq
jazzy.i2p,ha5c3zafwkt6mwqwjcf4oqwvbwz473652ljjadiwrj4gfkfkjofa
jdot.i2p,kw4jr5qw4bhnj33avkwankjdh3zi7wtahlmgkjwvsv2isskkzgpq
jhor.i2p,c6rnm7oemydhuwzmhwwwxphkzanez5rnn7fkcs3lpgu6gkgtssoa
jikx.i2p,aazr55itvyns4lwppvx5njyx5tjdwemw4w6jbmpegdunznod2ieq
jisko.i2p,jxgfvr663uhr6m65hrgkscshysfshkq32ywdubc4ed7zda3e2pca
jmg.i2p,oglpnq7zungdukmk6gk5fzj5jp6wibuoihqgks453wztrwos4ggq
jnymo.i2p,nbfplxgykyfutyadlfko2rmizdsxox2pee2ahboj5mju4s3putda
jrandom.dev.i2p,htynimemonyzqmn76gworxyfkmqtsa7zcprbrd3i5cxqqm75tuzq
jrandom.i2p,dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
jrrecology.i2p,qxi24gpbum3w3kesuxvheyu3p5u5o6tuvoypaolub2gnvbld57xq
jwebcache.i2p,xdffxnxtjd6ji2zig3cgva7igvl2tiapyjoc7ylbzwqhxudbmvfa
k1773r.i2p,zam7u6vslhemddz347uusuzjdk5wma4h5hcmcqlng4ybbpdbjhnq
kaji.i2p,z5ic7gvm2k4doczphtrnrspl2w5sfbss2de4z3ihjijhtjw67ydq
kaji2.i2p,4lscgc6napekfx7ay5fdcjofeja4fnl7tqcd3fek63t4saavur2a
keys.echelon.i2p,mwfpkdmjur5ytq4og36ym3ychinv36b2a57f4rmgqmtrwepq3fva
keys.i2p,6qv4x7ltaxckd4vbay5s4ntqqflq4efk6oke2d5yzicqrmk443ba
keyserver.sigterm.i2p,isoxvnflrdn7cm76yjlfg5tbcugoito2hur7eidbqmo33xmwz5ga
killyourtv.i2p,aululz24ugumppq56jsaw3d7mkbmcgo7dl2lgeanvpniyk2cbrda
knijka.i2p,knjkodsakcxihwk5w5new76hibywia5zqcgoqgjttzsausnd22oa
knotwork.i2p,2yocdbcjiyfaqgxb4l6oenrrrrie6nydgmbnbfulqg7cik6bozxq
kohaar.i2p,qchpjehbhqjbxdo7w3m55jbkrtsneb7oqoxcr24qttiq6j5g3z5q
krabs.i2p,3yamyk5bgfgovg6zpvtvpdjk37ivjj2wog2w7wha5agzgxxkqaca
kuroneko.i2p,wbit2huhhwlyqp2j4undccuyrodh6qcmzdeyuaoy5o4ym7g5gdgq
kycklingar.i2p,gctswdhp4447yibxfbqg3uq2bvx63qjeqnaoaux75zw73leakyva
lazyguy.i2p,ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
legion.i2p,5oirascyhwfy2tr2horw6mixozsre7z6s7jfq7qbnj523q3bkebq
legwork.i2p,cuss2sgthm5wfipnnztrjdvtaczb22hnmr2ohnaqqqz3jf6ubf3a
lenta.i2p,nevfjzoo3eeef3lbj2nqsuwj5qh3veiztiw6gzeu2eokcowns3ra
libertor.i2p,7gajvk4dnnob6wlkoo2zcws7nor3gunvoi7ofalcps5lc76wruuq
library.i2p,brqqaq44vbeagesj5o3sxcnkc5yivkwouafyxa77ciu7l644ei2a
lifebox.i2p,pyqjnycm55cuxow22voqj62qysrjdnb6nbyladaiaiirqi7vp2yq
linuxagent.i2p,ap5riaikrjq2uv5qvy7klzhhqywvqi7wqscyipsewcun7w2eynlq
lists.i2p2.i2p,vmfwbic2brek2ez223j6fc6bl5mmouzqvbsch45msvyyzih3iqua
lm.i2p,yeyar743vuwmm6fpgf3x6bzmj7fxb5uxhuoxx4ea76wqssdi4f3q
lodikon.i2p,u3f67staiwhqxpacya3clmvurdwd2kp7qcthzhstqnhrmlwc2g4a
lolicatgirls.i2p,a4lzmjyba7aq7hl6okqpds7znnwymolqnr7xhvno2wraqb7uhfla
lolifox.i2p,7fd2clkiotjnaoeigdtxlkkb24eik675ovezjf67x26ysham4zca
longhorn.i2p,pohcihzxzttjclrazhs3p76wt3ih737egb5bovqb6ym3du6z3o7a
lp.i2p,jiklbujn3cbfikf4pca526jgmorx6mxhil3twqmfoteaplx6ddwq
lucky.i2p,wx36m3wnpt2y6bngdpg3ifrarvtkpwnluarx377bllpgvkuhybaa
luckypunk.i2p,y4t6cujjxnnrtln3rgmfbgbh46hic7wkef57krd7opitbgngohka
lunokhod.i2p,3yc6sp7xic4grmpfecbwuij6z3dp5kdgoo362pszaco7io42mnwa
m16.i2p,ucsr3eveuc4mx5y6gxnoaywd4ojvbel5q3ynns6s5yfw3vusmfva
mac7.i2p,3yjowssqzydciwa5zx55kazgf7q7w6g7rkocr7bngy35ii44t34q
madman2003.i2p,a2sam2xbhxbzmeyobphbxrkdwlppoerewq5qvibbyk3ftsr643qq
magix.i2p,cgfnyxv62msfynsfbv3kju22j2mt6tfnopshhmrcmpcrxyts6xwq
magnets.i2p,snz46nez6hrrpg6336neinflw56l3vwatk6bzzytwu77xmsfsoca
manas.i2p,6qolj62ikkoq6wdn3hbvcbdmlvf2rcyv432kgi5uy7mvrczmjtba
manveru.i2p,pbmbofs76wpjnxi55eqtwg4y6ltyij72o4fm4sxfjol3y57ze5sq
marcos.i2p,vpo36bsil2voqaou53zshuegssqaroa5mbrzxfmhjywlbojckalq
marshmallow.i2p,svdqd6j3y3gwryufcl4fkzpmcujgvrvphvk2oy4r7m75xs327e2q
marxists.i2p,lepah55qyp2fhuwxlz7bwrhzckn4gkuofivnofoeuyfpmke5x2hq
mattermost.i2p,x5oovnhnuli5fnwtgkbd5z5jvrvdvprqyuofywx6uoxkk4bie6ya
me.i2p,dbpegthe42sx2yendpesxgispuohjixm4bds7ts5gjxzni5nu6na
meeh.i2p,4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa
mesh.firerabbit.i2p,3x5wokr4bjy5z3ynji4fyhvwzv4fvgry3xafi5df5h75doezjytq
messageinabottle.i2p,avfhe3kvrrv7utxn2vre65lg7damxzzsewq3vukwie4llitd254a
metrics.i2p,z45ieamhex2ihqv7oowk5fz4qq47rbvxhhhbaaiinpajbhuevtpq
mhatta.i2p,o4rsxdeepfrnncsnjq675xogp5v5qkbfgbt6ooqeyfvlifobrjxq
microbleu.i2p,mtapervgibruizniems2yyr47pin2wpysyh7m632rigl26vjc6qa
microsoft.i2p,hvaqr5idszdyrjph34amb4mjosqd3ynggoxlnj7ciqhnx7q6plza
mindisl0st.i2p,u7rnqhvsuyxd3fabm4kyzn7brgz3i3cporj2emk2jmbpcmltyf7a
mindspore.i2p,uuh5dd3y2rqa7x2jpggm4p2pg6znarm5uanwsvybe4tk36ymwr4q
modulus.i2p,ctz3o6hdefrzwt3hlg6rjhdcbjk6irppbndq32u6jnn4lz72f62a
monerotools.i2p,5bal7dngxde2ddmhuzbtfken6w5nmxmixtjlrlmxt3wbhnemv73q
monerujo.i2p,puri6y5dtwh6zr4u77ep6ozatun6iz7v4wai2dzxppz7654corlq
morph.i2p,iovyp2dao5rta6g5v6hke2s4ugx2btkpcljddak2yhxfrx3l4dqa
mosbot.i2p,5bhmrp43mjwlzf4x64xgdrkwmw4luvng6eq5waa663a7vnkp732a
mosfet.i2p,s5ynkgagndmpxpf2kmnenv4x72io664gzd2x3qef54ilammnte3q
moxonom.i2p,gcjdrvnlobgexh7ebv276pwmnoj3yoyaqm3w4vmmdha4lgxfinqq
mp3.aum.i2p,n7bmu5dwux7f6gedmdik6zrm77bnls4lkzo2vo3bf4bwegk7vkjq
mp3.tc.i2p,w3ied5s7ldjcvnhxu2gyofe3oogzbplkyxshzfkhspiy2526snsa
mpaa.i2p,m6cqnglo7xlytwxkdsmwf3d23d6lq5r446c3tktb2tdmuah36zya
mrbamboo.i2p,tmpmkx6wlbbrgsnexrqlrib7laoegpbfeop7bnyezegii7hecpxa
mrflibble.i2p,u7k2qcmkrril6yvudvwxjqz7k3dzgp3jdejjjeapej7liselj3eq
mrplod.i2p,fjn5hxtybxyfyvdf6u5v5seg2sjd47hb5by6sa6ais4w3xnrxwyq
mtn.i2p,xisk3h6sku3iqj52uriogaajmnku7pwjux7wa4omx2zloamuw6eq
mtn.i2p-projekt.i2p,f52x5fp6uhq53f5zle5d6rq5un34xgmxgazvilvmzcby37xcmsfa
mtn.i2p2.i2p,l6kuhtmgvbp57d7jwalj5nksi6nr4gfzbz4oit62lxgipb3llt5a
mtn.meeh.i2p,h7ylrsuzzynrxp3jql7anoozyqblavj7eqces6o3wngvuuxhs2la
mudgaard.i2p,yz32lk42gtoesknesfolq3tt4erxxcejcote5pontaeqev3bj2kq
mush.zeit.i2p,dk3sg23kljawxqp3cb6xz5mnzjlyckzvq5jhqs5gnvdsv7wqn6ha
music.i2p,akamh76yi6p7xxbvl3qv3yhaockne57yfuh77acogbgpjmwypvia
mysterious.i2p,p66g2a4nzfkvidd3l7nwphcnfa3ttyu5kiolcb4czec2rn2kvwsq
mywastedlife.i2p,ceumy3puvvsrru5bmfmtgsajsx5qyehqac7l7a23xpwtfs2bvcgq
nacl.i2p,bm2fib3tumer72lopjh4nmqomwvqu2sdfyb2hmr6lnk7jbw3vvia
nano.i2p,ex5ssv7s3hj6jp7hvadxfw3wvbjbvnczxr4pbk7qw26ihiorjmba
nassai.i2p,v653cocvn3i6bgjdm3ciwbdnu32supglv6gn4fh23bohemsp545q
neodome.i2p,5hkhjehj3ct2pvcah7dcylwef2oti3xij5myxbv3pd7rocio5vkq
news-i2pn.i2p,wwcqkwfo5yhe6uribv5tzylk25j5hkdk6gdnyftzd3k7dawlzwca
news.neodome.i2p,trhwcnygfkeqjj6g4xhmrdp4gsjqsye47lsxshbmwbten4ywt5oq
news.underscore.i2p,rl7t3kspoktuatjcu7gf7xleu7y6biibs4fspzo24kll6n7hbq4q
newsbyte.i2p,gsk3rgsejxxrfabjxu5w5plplxsu47aoeoke22vvhlwwllzosnxq
nibble.i2p,jmdxcpdzqafedn3clc4y7u6o56qocfiffrzbzncmtggqtio5qjpa
nic.i2p,vzu5ymab6klevpcdudv4ypisjqaznmt44e6lcg7dwiuza4saibxq
nickster.i2p,zkwsa6kvq2wdhovw5g5wqakpb7rlaylyhfriwmurots5pvwbqauq
nickster2.i2p,eofzi7npzpk4p5gb4qper4hmwgxo6kepo3dheeblakewedxj2bwq
nickyb.i2p,gmpxk4tje7mnud32kg2kjmf36f6cpwqakzc2dxuzjnnz4qr5w4sa
nightblade.i2p,p4gkon7ytswxrbwkl7vruw6mg7kfw5aofovqjgt4c7tnqmbq6lha
ninja.i2p,q6dg6hlb3egzdqz352ri5rc4fx4gcrdeu3tpiyfxlv73yfjgrhya
nm.i2p,3itdpqzyn3ii7sivppo4sxxwhvgtpskzkbokrdibim6gqpvlw5ya
nntp.baffled.i2p,kc6muo2tih5mttbpzecteegvtonuysjidk3emcy4cm4yifzild2a
nntp.duck.i2p,gvzzor4utsqxswvf6jaglfks7yxudlz2s326ftrk56i4lpd2s47q
nntp.fr.i2p,npoztnqadfnu4vrokoh6rusoi3yne47s6jurc3lzhcrzzia5eqva
nntp.i2p,wwdzmeyler4djegvyt2bxmkwrckfgg3epkkwowyb75s47he6df6q
no.i2p,lpsg4x4gdrf7antxcdy47cl6abcqei5ommgzt55retq7go5ku3ba
noname56.i2p,oiyoslismzyxuw7ehxoigmtkdj35idim6flmlplddxuiiif6msfa
nop.i2p,ssag45lathm4gqp46si7c4w4tioyvjpcza5uvz5x2zuljnplylca
normal.i2p,j5fex634r2altzb3kjvu35qekt2r3hgsqzg5qxoy7dp53heu5pma
normanabcd.i2p,si2vh43gvxjnw2shwr24j76xyanow4oa6gbu4idookbraoxl3s3a
nothingburger.i2p,tesfpn757ysc7nih7mxher2b3jstkc3l5fhfcyb5kxhzhvv52trq
nothingspecial.i2p,wzrwqrp52bilqijrlboclynuev4kzpjzfzlvzl5aqxqt5fdnpbga
novospice.i2p,ukqap24nwac4gns77s4zy7j5cagt7l7syb5zo7eukfg3zn5gg5qq
nsa.i2p,nsetvbclpomqxfcit4mghn6z7vdhnza6jdzczby4crnto32uykga
nvspc.i2p,anlncoi2fzbsadbujidqmtji7hshfw3nrkqvbgdleepbxx3d5xra
nxt-wallet.i2p,33pp74k4ivy67z332qpyl3qlcqmi6gxqumrow4bldkblxxlxqq5a
obmen.i2p,vodkv54jaetjw7q2t2iethc4cbi4gjdrmw2ovfmr43mcybt7ekxa
obscuratus.i2p,i4j37hcmfssokfb6w3npup77v6v4awdxzxa65ranu34urjs4cota
ogg.aum.i2p,wchgsx6d6p3czloeqvna2db5jr7odw4v4kqrn4gr4qiipfyrbh5q
ogg.baffled.i2p,tfbvj2xal6lcuxv3hzuw7cw4g3whguombcv2zuotzvul4qtrimgq
ol.i2p,bnb46culzbssz6aipcjkuytanflz6dtndyhmlaxn3pfiv6zqrohq
onboard.i2p,qwlgxrmv62mhdu6bgkh4ufnxowxsatfb6tbs2zr666qyunwqnecq
onelon.i2p,irkvgdnlc6tidoqomre4qr7q4w4qcjfyvbovatgyolk6d4uvcyha
onhere.i2p,vwjowg5exhxxsmt4uhjeumuecf5tvticndq2qilfnhzrdumcnuva
oniichan.i2p,nnkikjorplul4dlytwfovkne66lwo7ln26xzuq33isvixw3wu3yq
onionforum.i2p,yadam2bp6hccgy7uvcigf5cabknovj5hrplcqxnufcu4ey33pu5q
ooo.i2p,iqp5wt326fyai5jajsa3vkkk5uk56ofn4anocgpe5iwlpisq6l7a
opal.i2p,li5kue3hfaqhhvaoxiw2ollhhkw765myhwcijgock5rs4erdqdaa
open4you.i2p,ice6ax5qrzwfwzsy64bctffj6zlzpuzdr5np65zsxlbt7hztyc6a
opendiftracker.i2p,bikpeyxci4zuyy36eau5ycw665dplun4yxamn7vmsastejdqtfoq
openforums.i2p,lho7cvuuzddql24utu7x6mzfsdmxqq7virxp5bcqsxzry2vmwj5q
opentracker.dg2.i2p,w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa
orion.i2p,5vntdqqckjex274sma3uqckwqep2czxs5zew25zlntwoofxk3sga
orz.i2p,oxomqkekybmyk6befjlouesit5mhstonzvzd2xnvsk7i6uyrqsfq
os3.i2p,s7x4ww5osrrfein3xgwyq67wnk6lgliw4mzt7shtu66wrb2zdojq
osiristomb.i2p,t3slf77axkv3qm7c3gzpv3jgmkraoqqe2bojr6h66eipibofsyzq
ot.knotwork.i2p,cxhvvfkbp2qbv5qojph7zb46molpe2ffanghnerjag3xdmy6ltxq
outproxy-tor.meeh.i2p,77igjr2pbg73ox5ngqy5ohzvrnur3ezqcogtl4vpuqtrcl3irsqq
outproxy.h2ik.i2p,nwgvfpfarpnyjjl4pwsxr2zdsppcx5we3kos2vlwicbiukopgaza
outproxyng.h2ik.i2p,v32zse2zczzgegelwxbx7n5i2lm2xhh2avltg76h6fz5tb53sfxq
overchan.oniichan.i2p,g7c54d4b7yva4ktpbaabqeu2yx6axalh4gevb44afpbwm23xuuya
p4bl0.i2p,lkgdfm4w6e2kkjhcdzr4ahhz26s3aunhrn6t2or436o73qh4z7ga
pants.i2p,xez3clscjfafkqwk6f473ccp3yvac4kh6rdp6dptwxa2lhixizgq
papel.i2p,mxskjqntn2d34q4ovsnd5mud7cgde734tdjldd3lt4hczh2645zq
pasta-nojs.i2p,dkkl3ab6iovxfqnp44wsjgqaabznvu7u3hugpzyagbeqlxgvx3la
paste.crypthost.i2p,2zaj4u4s4l3lgas2h5p6c6pvzr2dckylkrh5ngabursj4oh25ozq
paste.i2p2.i2p,b2gizskfea4sjxlw6ru2tb6kdrj47dsjc77cijsf5mzh4ogbmfvq
paste.r4sas.i2p,csen43keji3qiw6uobsgzysxyjd225g6446ylq5uuz6ur2glkzaa
pastebin.i2p,mnicncxrg2qqi55qftigiitaheugnj4rpysbk7zabdrirgktelqa
pastethis.i2p,erkqiwnjl7vtysqd3wvddv6tfvnhswarqkbn4blhdlhfxn7cf2ha
pdforge.i2p,wzeg3ehf6d2mqjqji3sd3rns776thvhe2vam2r6gjlmsqis2dctq
perv.i2p,f3k3wm4ae7t7ottfjd4hu6is7zsls73izl2gm2qynzficxcdsiwq
pgp.duck.i2p,wujajyxj3cgsfsbtr3g7g7npv5ft3de6pcstxlav26zq6cxdjmha
pharos.i2p,vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
pharoz.i2p,vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
phonebooth.i2p,noxia7rv6uvamoy2fkcgyj4ssjpdt4io6lzgx6jl6wujpufxedrq
photo.i2p,fqhuy77ugd5htnubzkyy5guvwboqn6goahtmn2g7feewvdj7k3iq
piespy.i2p,vzusfjzcu5ntnvobcvyzc4dcu4j6ommtnpmba2puk3kexgdzrl7a
pisekot.i2p,7yzdwhy723fodqz4onp6k3nyvixra2sa6dl45tcblhmyoa7i36nq
pizdabol.i2p,5vik2232yfwyltuwzq7ht2yocla46q76ioacin2bfofgy63hz6wa
planet.i2p,y45f23mb2apgywmftrjmfg35oynzfwjed7rxs2mh76pbdeh4fatq
plugins.i2p,wwgtflbaa7od2fxbw4u7q7uugmdclxf56alddvizugwcz5edjgia
polecat.i2p,het5jrdn35nhkanxmom5mjyggyvmn2wdj2agyqlrv4mhzhtmavwq
politguy.i2p,6dkkh3wnlwlr6k7wnlp4dbtf7pebjrph5afra2vqgfjnbihdglkq
pomoyka.i2p,omt56v4jxa4hurbwk44vqbbcwn3eavuynyc24c25cy7grucjh24q
pool.gostcoin.i2p,m4f4k3eeaj7otbc254ccj7d5hivguqgnohwelkibr4ddk43qhywa
pop.mail.i2p,bup6pmac7adgzkb5r6eknk2juczkxigolkwqkbmenawkes5s5qfq
pop.postman.i2p,ipkiowj7x4yjj7jc35yay3c6gauynkkl64gzzyxra3wmyhtfxlya
pravtor.i2p,2sr27o5x2v2pyqro7wl5nl6krrsbizwrzsky5y7pkohwh24gn6xq
pris.i2p,ahiwycgzuutdxvfqu3wseqffdnhy675nes57s4it2uysy5pxmz6a
project-future.i2p,ivqynpfwxzl746gxf376lxqvgktql2lqshzwnwjk2twut6xq7xta
projectmayhem2012-086.i2p,ehkjj4ptsagxlo27wpv4a5dk4zxqf4kg4p6fh35xrlz4y6mhe4eq
protokol.i2p,f4xre35ehc5l6ianjvt3zcktxkjlyp2iwdje65qnu2j6vurhy6nq
proxynet.i2p,7gar5a3n4hzvsgi73iizo65mjza4kujf7feopfxuwu5p6wtwog5a
psi.i2p,avviiexdngd32ccoy4kuckvc3mkf53ycvzbz6vz75vzhv4tbpk5a
psy.i2p,s3elzoj3wo6v6wqu5ehd56vevpz2vrhhjc5m6mxoazicrl43y62q
psyco.i2p,eoilbrgyaiikxzdtmk2zeoalteupjrvcu3ui23p4wvfqo25bb73q
pt.hiddenanswers.i2p,o5jlxbbnx3byzgmihqye3kysop5jgl3unsrkmurbtr2nrnl2y74a
ptm.i2p,7dna5745ynxgogpjermnq26hwrqyjdlsibpjfmjxlwig247bjisa
ptt.i2p,q7r32j7lc3xgrcw2ym33wv4lfgqbez7vtm4lts7n34qfe3iygeha
pull.git.repo.i2p,3so7htzxzz6h46qvjm3fbd735zl3lrblerlj2xxybhobublcv67q
push.git.repo.i2p,jef4g5vxnqybm4zpouum3lzbl6ti6456q57nbyj5kfyldkempm3a
pycache.awup.i2p,w45lkxdnqhil4sgzanmxce62sv3q4szeowcjb2e72a5y5vbhm4ra
r4sas.i2p,2gafixvoztrndawkmhfxamci5lgd3urwnilxqmlo6ittu552cndq
radio.r4sas.i2p,cv72xsje5ihg6e24atitmhyk2cbml6eggi6b6fjfh2vgw62gdpla
ragnarok.i2p,jpzw6kbuzz3ll2mfi3emcaan4gidyt7ysdhu62r5k5xawrva7kca
ransack.i2p,mqamk4cfykdvhw5kjez2gnvse56gmnqxn7vkvvbuor4k4j2lbbnq
rasputin-sucks.i2p,fdozdbyak4rul4jwpqfisbkcx4xbrkuvf2o5r6fd3xryyrjgvjiq
rebel.i2p,nch2arl45crkyk6bklyk2hrdwjf5nztyxdtoshy6llhwqgxho5jq
red.i2p,fzbdltgsg7jrpz7gmjfvhpcdnw5yrglwspnxqp4zoym3bglntzfa
redpanda.i2p,3wcnp6afz4cikqzdu2ktb5wfz7hb3ejdbpn7ocpy7fmeqyzbaiea
redzara.i2p,ty7bt62rw5ryvk44dd3v5sua6c7wnbpxxqb6v4dohajmwmezi7va
reefer.i2p,4cde25mrrnt5n4nvp5tl62gej33nekfvq2viubmx4xdakhm5pfaa
relatelist.i2p,utrer5zgnou72hs4eztmk37pmzdtfw3d6s23wwl7nk3lkqpzbdiq
repo.i2p,uxe3lqueuuyklel23sf5h25zwgqgjwsofrqchhnptd5y6pedzbxa
repo.r4sas.i2p,ymzx5zgt6qzdg6nhxnecdgbqjd34ery6mpqolnbyo5kcwxadnodq
reseed.i2p,j7xszhsjy7orrnbdys7yykrssv5imkn4eid7n5ikcnxuhpaaw6cq
retrobbs-nntp.i2p,fkyzl24oxcxvjzkx74t3533x7qjketzmvzk6bwn3d6hj5t7hlw6q
retrobbs.i2p,mnn77stihntxdoade3ca2vcf456w6vhhvdsfepdvq5qggikvprxq
retrobbs2.i2p,ejff7jtyaus37slkwgeqrrcmyhpj26carp7n27f5h6s5vlbeiy6q
revo-ua.i2p,hpojpumki22xjwhmhe6zkiy44oanyn7u4ctcfe3in2ibwm5l32hq
riaa.i2p,lfbezn7amkzhswnx7lb4lxihyggl2kuqo5c7vwkcv6bwqmr4cuoa
rideronthestorm.i2p,xrdc2qc7quhumhglpbcuiqxr42nuffv4xj4a73jbr4ygepitibqq
romster.i2p,eaf2stdqdbepylt53egvixdi34g2usvgi7a4oixsja6atkran43a
rootd.i2p,mzbe5wofwn7eaqq4yefrmxizqaxoslwqxrv5qcv2opx5lnhg64dq
rospravosudie.i2p,z55khrnlj6bzhs5zielutm6ae6t2bbhfuiujwlrp3teubqyc4w7q
rotten.i2p,j4bm3rvezlejnb44elniagi5v2gazh7jaqrzhbod2pbxmgeb2frq
rpi.i2p,56p5qxsrvo5ereibevetw2qbj5bronmos7wxunku27g2s4kpbnlq
rslight.i2p,bitag46q3465nylvzuikfwjcj7ewi4gjkjtvuxhn73f6vsxffyiq
rsync.thetower.i2p,w4brpcdod7wnfqhwqrxyt4sbf2acouqfk5wyosfpq4mxq4s35kqa
ru.hiddenanswers.i2p,o6rmndvggfwnuvxwyq54y667fmmurgveerlzufyrhub6w3vkagva
ru.i2p,m7fqktjgtmsb3x7bvfrdx4tf7htnhytnz5qi2ujjcnph33u3hnja
rufurus.i2p,7msryymfdta3ssyz34qur6gi4jyfkvca5iyfmnceviipwu7g2wca
rus.i2p,gh6655arkncnbrzq5tmq4xpn36734d4tdza6flbw5xppye2dt6ga
ruslibgen.i2p,kk566cv37hivbjafiij5ryoui2ebxnm7b25gb3troniixopaj6nq
rutor.i2p,tro5tvvtd2qg34naxhvqp4236it36jjaipbda5vnjmggp55navdq
salt.i2p,6aflphlze6btsbez5cm4x53ydrmwhqrkxsud535d3qjh4wq62rxq
sasquotch.i2p,p6535uyfk2y6etc3t47vd3oqxydznqior5jxcvq5bdxe5kw5th6q
schwarzwald.i2p,4gokilzy73mmudufy3pohgatm42fcstx7uzg5hjvnfyphxpnphuq
sciencebooks.i2p,ypftjpgck75swz3bnsu4nw7rmrlr2vqsn4mwivwt3zcc3rxln5cq
scp.duck.i2p,ghbpsolpnveizxu4wbs7jbs2vj3kntnsexfcdleyhpqdhfpxleda
search.i2p,nz4qj6xaw5fda3rsmsax6yjthqy4c7uak2j3dzcehtkgyso4q46q
secretchat.i2p,cl3j2zxhpw6u6jevny45i557ojhwfxn4g375nnuqhy6lp27mry2q
secure.thetinhat.i2p,4q3qyzgz3ub5npbmt3vqqege5lg4zy62rhbgage4lpvnujwfpala
seeker.i2p,ipll7sit24oyhnwawpvokz5u7dabq6klveuqpx3sbi6o5qemy2bq
seomon.i2p,5mvpsy4h45w4fx7upen7ay3vkrs5klphz5nptmtcqvc3fsajsm4q
septu.i2p,5lqvih7yzbqacfi63hwnmih57dxopu5g2o5o4e2aorq7bt4ooyra
serien.i2p,3z5k3anbbk32thinvwcy4g5al7dmb75fagcm3zgh4rzrt3maphda
ses.i2p,5qfoz6qfgbo7z5sdi26naxstpi2xiltamkcdbhmj6y6q2bo4inja
shiftfox.i2p,wpvnuzslu7hjy4gujvnphtyckchdoxccrlhbyomsmjizykczyseq
shoieq3.i2p,3fjk4nfk3mccch4hdreghnyijcvovsi3yucjz3qzj5sxngqk5j6q
shoronil.i2p,7shqzgmb6tabiwrnwlasruq7pswy2d3emvfhaitehkqgod7i62sa
short.i2p,z5mt5rvnanlex6r3x3jnjhzzfqpv36r4ylesynigytegjmebauba
sion.i2p,lcbmmw2tvplvqh2dq5lmpxl3vnd5o4j3bdul5moa23deakjrso5q
sirup.i2p,aohdp4yajnkitrtw7v2mo3sp7swuqhjfwlsi5xwd7dudzftumsma
site.games.i2p,zeuczucfxeev3k7tvqlfcdpfbnqggheiknyyb5r2q4utn3d2auja
skank.i2p,qiii4iqrj3fwv4ucaji2oykcvsob75jviycv3ghw7dhzxg2kq53q
slack.i2p,gfcsh2yrb2tx7hyvmobriv52skz7qoobn7n7y7n6xaehhh4rpbja
slacker.i2p,wq7m2wdguzweleb666ygv3bmfhha63zj74rub76vfesbyhsyk6iq
smeghead.i2p,ojf4czveeuekxqkjvkszvv7eiop5dg7x2p6rgfzl4ng4xrjk6lja
smtp.mail.i2p,kdn7zx7fgoe4bn5abaaj5cb3e4ql22fklb5veui5yajpj4cxapya
smtp.postman.i2p,jj7pt6chsziz6oxxnzpqj7mzhxm2xfhcrbh7dl3tegifb577vx5q
socks1.tor.i2p,sifawcdexgdmoc3krv46pvvz74nzd6fkju2vzykjxsx3egqsb6wq
sonax.i2p,jmuxdhlok5ggojehesfjlit2e2q3fhzwwfxjndts7vzdshucbjjq
sponge.i2p,o5hu7phy7udffuhts6w5wn5mw3sepwe3hyvw6kthti33wa2xn5tq
squid.i2p,r4ll5zkbokgxlttqc2lrojvvey5yar4xr5prnndvnmggnqzjaeoq
squid2.i2p,hum4wlwizbsckbudcklflei66qxhpxsdkyo4l2rn256smmjleila
sqz.i2p,3jvbwc7sy4lnhj25nj7yepx7omli4ulqirnawv3mz6qlhgokjgzq
ssh.i2p,xpvdadaouc4qr75pteymyozc7mcsynjfkuqqkkla542lpcsqionq
stasher.i2p,6ilgpudnba4kroleunc2weh5txgoxys5yucij5gla6pjyki4oewa
stats.i2p,7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq
status.str4d.i2p,ycyyjo3psqbo45nuz243xvgvwnmzlanzqbzxv3kh6gyjztv7425q
sto-man.i2p,rg4eilfpe24ws6nctix63qw2dlvd2tqgwdcgdxzji6l5bc4dc7aa
str4d.i2p,wrrwzdgsppwl2g2bdohhajz3dh45ui6u3y7yuop5ivvfzxtwnipa
stream.i2p,prmbv3xm63ksoetnhbzqg4nzu2lhqdnqytgsydb7u3quxfrg7rna
streams.darkrealm.i2p,ud3gcmvysjch4lbjr2khmhqpf7r2x5if4q43xkqdptl4k7lc4muq
striker.i2p,4gswsrfpbd44hwjoj33jbqfbwzxfkwpuplb3ydq5zm7nfu2pxvdq
subrosa.i2p,g3lnglrnoual7wyabnwwv37uwhadgbxiqz36pf3f5cwfuxsx4mxq
subterra.i2p,vdmhe4u26unzgd7ysq6w36ubjncms5wzbhzr2gq576sq4xut5zwq
sugadude.i2p,yzjn76iyqard64wgggfrnywkxi7tbfkw7mjhpviqz3p2dguey4yq
suicidal.i2p,yfamynllow5xiqbbca7eh5xn733wtnuti5bi4ovc7dwycntqmiuq
sungo.i2p,h67s3jw56rwfyoxqxj3fngrluybsgxc2meendngkehzqowxnpj3q
surrender.adab.i2p,jgz7xglgfgnjfklrytyn427np2ubipztlm5bxrtbiucayglukrta
susi.i2p,qc6g2qfi2ccw7vjwpst6rwuofgzbeoewsb2usv7rubutf4gzqveq
syncline.i2p,5kcqmhislu3lmr7llgmdl72yu3efhyriljdc6wp774ftpwlcs5ra
syndie-project.i2p,xa63tpfoaqt3zru2ehxjjfbpadwj4ha6qsdvtcqtyr3b7hmt4iaq
syndie.echelon.i2p,vwrl2qmcif722fdkn3ldxcgz76df5cq4qypbndzthxwgmykyewta
syndie.i2p,7lm3yzpuejhpl4tt4l7o4ndqlu7hgijohofh7oaydx7q7kelenbq
syndiemedia.i2p,4lrbbblclodhobn3jadt5bf2yab2pxzoz4ey4a2cvrl44tdv3jma
tabak.i2p,y5o2vwb6kart7ivpnbpk4yte3i7kf2dsx7fy3i6w7htqtxhmbzia
tahoeserve.i2p,yhs7tsjeznxdenmdho5gjmk755wtredfzipb5t272oi5otipfkoa
tc.i2p,qkv2yk6rof3rh7n3eelg5niujae6cmdzcpqbv3wsttedxtqqqj7a
telegram.i2p,i6jow7hymogz2s42xq62gqgej2zdm4xtnmpc6vjcwktdxpdoupja
templar.i2p,zxeralsujowfpyi2ynyjooxy222pzz4apc2qcwrfx5ikhf64et7q
terror.i2p,wsijm6aqz4qtuyn2jedpx6imar5uq4yuhjdgtfqumxbqww47vbnq
thebland.i2p,oiviukgwapzxsrwxsoucpqa47s3wt6nfuhfjxvgbqsyrze2mwrda
thebreton.i2p,woutbsflcrlgppx4y7ag2kawlqijyenvlwrhbbvbkoaksuhf2hkq
thedarkside.i2p,fxt3z33nzkrg5kjrk7bp5vvmu7w2vsn4i6jo6cily3hsm6u664ca
theland.i2p,26ppxbseda6xmim37ksarccdb4q5ctdagfmt2u5aba6xjh452zsa
thetower.i2p,3xqa5nype64y6fxgqjq6r5w2qpiqftoraj2niebumseat4cj654a
thornworld.i2p,vinz4ygmodxarocntyjlfwk2wjpvzndlf4hxss2w2t3fk52oplva
tino.i2p,e4bfnhvaofu4s67ztcgiskos2mqyhskid64dvlqexxs2c2bno3iq
tinyurl.i2p,mc4oxv3v7dnyzpvok7v5qxkwtgjprgyz6w7x3tag4fipsen6rdwa
tome.i2p,qktkxwawgixrm5lzofnj5n24zspbnzxy4pvjm7uvaxvmgwrsuvgq
tor-gw.meeh.i2p,ounrqi7cfemnt66yhnhigt2u27fkctbvct527cp2522ozy3btjza
tor-www-proxy.i2p,xov45rvjks5fe4ofmpblkj23bnwxgslbypbgvchbr7yul2ujej2q
torapa.i2p,eejqjtpko6mdd4opvntbpsuandstrebxpbymfhix7avp5obrw5ta
torrentfinder.i2p,mpc73okj7wq2xl6clofl64cn6v7vrvhpmi6d524nrsvbeuvjxalq
torrfreedom.i2p,nfrjvknwcw47itotkzmk6mdlxmxfxsxhbhlr5ozhlsuavcogv4hq
trac.i2p,kyioa2lgdi2za2fwfwajnb3ljz6zwlx7yzjdpnxnch5uw3iqn6ca
trac.i2p2.i2p,i43xzkihpdq34f2jlmtgiyyay5quafg5rebog7tk7xil2c6kbyoa
tracker-fr.i2p,qfrvqrfoqkistgzo2oxpfduz4ktkhtqopleozs3emblmm36fepea
tracker.awup.i2p,dl47cno335ltvqm6noi5zcij5hpvbj7vjkzuofu262efvu6yp6cq
tracker.crypthost.i2p,ri5a27ioqd4vkik72fawbcryglkmwyy4726uu5j3eg6zqh2jswfq
tracker.fr.i2p,rzwqr7pfibq5wlcq4a7akm6ohfyhz7hchmy4wz5t55lhd7dwao5q
tracker.i2p,lsjcplya2b4hhmezz2jy5gqh6zlk3nskisjkhhwapy3jjly4ds5q
tracker.lodikon.i2p,q2a7tqlyddbyhxhtuia4bmtqpohpp266wsnrkm6cgoahdqrjo3ra
tracker.mastertracker.i2p,tiwurhqvaaguwpz2shdahqmcfze5ejre52ed2rmoadnjkkilskda
tracker.postman.i2p,jfcylf4j3gfmqogkltwy7v5m47wp4h7ffrnfsva6grfdavdn7ueq
tracker.psi.i2p,vmow3h54yljn7zvzbqepdddt5fmygijujycod2q6yznpy2rrzuwa
tracker.thebland.i2p,s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq
tracker.welterde.i2p,cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa
tracker2.postman.i2p,ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna
traditio.i2p,wkpjjloylf6jopu2itgpktr45t2xvpjijxilxd5tq4i7wkqgwhhq
trevorreznik.i2p,wc2z6o5fxm2saqzpfcawr63lejwccvzkysmgtfudkrigqopzfdma
true.i2p,pdilhl5vmefyzrrnmak5bnmxqxk2pmw7rpy4f7wbaeppqu2vvugq
trwcln.i2p,evml6jiiujhulsgxkdu3wcmkwbokxlv4is6w5qj46tp3ajz3hqzq
trypanom.i2p,tgv5acj4khwvr6t44cmryohybd2e5o2kndysnzae6qwcr4hzda3q
ts.i2p,nebcjgfx3f7q4wzihqmguwcdeopaf7f6wyk2dojw4bcuku472zxq
ttc.i2p,wb4tsfyvfv4idgrultsq6o7inza4fxkc7dijsfpncbx7zko4cdlq
ttp.i2p,uuczclxejmetohwf2vqewovx3qcumdfh5zecjb3xkcdmk6e5j72a
tumbach.i2p,u6pciacxnpbsq7nwc3tgutywochfd6aysgayijr7jxzoysgxklvq
tutorials.i2p,zy37tq6ynucp3ufoyeegswqjaeofmj57cpm5ecd7nbanh2h6f2ja
ugha.i2p,z3f3owc72awbywk4p6qb5l2mxgitvs6ejztggbpn2a3ddmymfjda
uk.i2p,vydbychnep3mzkzhg43ptewp242issy47whamfbxodc4ma6wc63a
underground.i2p,dlnuthb6tpw3kchlb7xoztyspy4ehlggjhl44l64vbcrulrfeica
underscore.i2p,3gmezyig6gvsjbpkq2kihoskpuqpkfrajmhhm7hpyrjuvtasgepa
unqueued.i2p,3gvn4kwd7z74jxc2sn4ucx52dpvpscxbzjluux3ul4t3eu5g64xq
up.i2p,25it5olgdo7pht25z6buzd32sw7jvc65oziqeuocfozfhgua655q
update.dg.i2p,iqj6ysfh3wl26m4buvyna73yhduifv523l7bwuexxak4mgldexja
update.killyourtv.i2p,gqdfg25jlqtm35qnmt4b7r53d6u2vep4ob23fwd42iyy4j6cvdqq
update.postman.i2p,u5rbu6yohfafplp6lgbbmmcuip34s7g3zqdd63cp27dl3nbd7gtq
utansans.i2p,u2oyre7ygqv4qs5xjjijfg3x7ddwtod6nqwgbomuuzljzvnq4rda
v2mail.i2p,4gg7fykcqe7oaqt4w5fmlarnia7vtmwkv3h45zzgoj6o6crryg5a
vadino.i2p,aalttzlt3z25ktokesceweabm5yyhhvml2z3rfotndgpfyh6myra
visibility.i2p,pwgma3snbsgkddxgb54mrxxkt3l4jzchrtp52vxmw7rbkjygylxq
volatile.i2p,q6rve733tvhgyys57jfw4fymqf3xsnza6dqailcdjcq7w4fa5m3a
vpnbest.i2p,ov5f74ndsy5rfkuyps56waf42vxncufqu5rzm3vsnxkdtogccaea
vudu.i2p,3zlwci7pvgep2igygzyjej24ue7mjsktlhaff6crpsr75yquak2q
w.i2p,j2xorlcb3qxubnthzqu7lt4fvxqn63it4ikwmze55yjkzeeampuq
wa11ed.city.i2p,7mxwtmala3ycg2sybjwwfil7s6dqck2fbemeutghhwu73rznmqoa
wahoo.i2p,vqe5vkpe5wbda7lwekcd2jaj44ar3rawgv54u5rcolezbg5f5vwa
wallet.gostcoin.i2p,reuvum7lgetglafn72chypesvto773oy53zumagrpigkckybrwda
wallsgetbombed.i2p,tzhea5d65fllm4263wztghgw4ijdgibsca5xsecp6lk4xlsbdeuq
web.telegram.i2p,re6cgwg2yrkgaixlqvt5ufajbb3w42fsldlq7k5brpvnd5gp6x5a
wiht.i2p,yojmpj3sh76g3i6ogzgsf7eouipdgdij5o2blcpdgmu5oyjk5xca
wiki.fr.i2p,lrqa7hw52uxjb5q3pedmjs6hzos5zrod4y6a4e25hu7vcjhohvxq
wiki.ilita.i2p,r233yskmowqe4od4he4b37wydr5fqzvj3z77v5fdei2etp2kg34a
wintermute.i2p,4gvlfrdy2rkmem33c342tjntpvqik65wekcvm4275qbkuwotoila
wspucktracker.i2p,ubd2txda3kllumx7ftg4unzgqy536cn6dd2ax6mlhodczfas7rgq
www.aum.i2p,3xolizygkzkqrldncjqsb734szznw2u36lliceuacqnbs2n65aeq
www.baffled.i2p,lqrsfslwu4xnubkk2hofhmuvvr4dia2zevxefinbzdsjurvehtqq
www.fr.i2p,rmkgvlfwo3vkb3xrr6epoypxasdzzuilv3sckcqbo6c4os5jo2ea
www.i2p,ojxyenivrrqvycgbxbm3phgisu5abspzq4g2us4fjlwz4tx222va
www.i2p2.i2p,rjxwbsw4zjhv4zsplma6jmf5nr24e4ymvvbycd3swgiinbvg7oga
www.imule.i2p,657xcllunctawyjtar5kgh3wpt6z4l7ba6mmam5rf7hev5w2lsvq
www.infoserver.i2p,fq7xhxkdcauhwn4loufcadiiy24zbei25elnup33a3gfrdzrtlyq
www.janonymous.i2p,vosqx5qw22hwrzcgsm4ib7hymf5ryovsbtaexqrzmnzshy5bhakq
www.mail.i2p,nctas6ioo7aaekfstv3o45yh6ywzwa3vznrdae52ouupzke5pyba
www.nntp.i2p,kly3o7zmetuwyz7xonnhttw4lj2244pkbibjz26uflyfte3b3dka
www.postman.i2p,rb3srw2gaooyw63q62cp4udrxxa6molr2irbkgrloveylpkkblhq
www.syndie.i2p,vojgy5ep4wffmtpjmpnbpa4gq64bgn4yicuw6qmhbm6nqa2ysrva
www1.squid.i2p,vbh3bltd2duwbukafgj6f6vfi6aigwso7snucp5zohnf66a2hkpa
xc.i2p,mt45a2z3sb2iyy2mwauj4rwa2lwu4peanfy6gx6ybidwnbasusyq
xeha.i2p,oartgetziabrdemxctowp7bbeggc7ktmj7tr4qgk5y5jcz4prbtq
xilog.i2p,eoc5i5q52hutnmsmq56edvooulutaxfikddgdz27otmgtsxmiloq
xmpp.crypthost.i2p,ittkqpjuliwsdewdugkhvgzstejr2jp5tzou7p332lxx4xw7srba
xmpp.rpi.i2p,3yv65pfwiwfuv4ciwtx34clqps6o2mc3vtyltcbqdkcki6untbca
xn--l2bl5aw.i2p,d2epikjh5crt2l5xjmtceqw2ho44hzp6x3u7hgjrd4mi4wywikwa
xolotl.i2p,rwr6rrlmrotxfkxt22mah42cycliy2g5k7hgxyxkpcyyxkd2bgwq
xotc.i2p,gqgvzum3xdgtaahkjfw3layb33vjrucmw5btyhrppm463cz3c5oq
z-lab.i2p,s6g2pz3mrwzsl4ts65ox3scqawfj7mzvd7hn2ekiiycawopkriba
zab.i2p,n4xen5sohufgjhv327ex4qra77f4tpqohlcyoa3atoboknzqazeq
zcash.i2p,zcashmliuw3yd2ptfyd5sadatcpyxj4ldiqahtjzg73cgoevxp4q
zener.i2p,mcbyglflte3dhwhqyafsfpnqtcapqkv2sepqd62wzd7fo2dzz4ca
zerobin.i2p,3564erslxzaoucqasxsjerk4jz2xril7j2cbzd4p7flpb4ut67hq
zeroman.i2p,gq77fmto535koofcd53f6yzcc5y57ccrxg3pb6twhcodc7v5dutq
zeronet.i2p,fe6pk5sibhkr64veqxkfochdfptehyxrrbs3edwjs5ckjbjn4bna
znc.i2p,uw2yt6njjl676fupd72hiezwmd4ouuywowrph6fvhkzhlnvp7jwa
znc.str4d.i2p,ufkajv3stxpxlwgwwb2ae6oixdjircnbwog77qxpxv7nt67rpcxq
zzz.i2p,ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq
1 00.i2p zmzpltxslembpaupg3srh4bbhv5txgh5jmms6sfj4hzsvlv3xugq
2 0ipfs.i2p cdii3ou5mve5sfxyirs6kogt4tbvivk2d6o25awbcbazjrlhjeza
3 0xcc.i2p gawouxh2sg32cluwlqsnpy3dwedvoqtfroi4evvdvm2pfv7tdadq
4 1.fcp.freenet.i2p cuxbeputgxn75ak4nr7ltp7fjktnzl5sul3wstwnsoytbbpb4ixq
5 102chan.i2p xxu3lso4h2rh6wmrxiou3ax7r7la7x6dhoepnku3jvrlwp35pefq
6 1st.i2p rduua7bhest6rwsmmyttzssfdw3p4eu6bgl3mb4hin32qo3x5zfq
7 2.fcp.freenet.i2p ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
8 333.i2p ctvfe2fimcsdfxmzmd42brnbf7ceenwrbroyjx3wzah5eudjyyza
9 55cancri.i2p b4iqenefh2fr4xtuq6civfc6nhnia6e2yo36pf7vcgdvrwmh7xua
10 adab.i2p pxjr6f2cig6v7v7ekam3smdnkqgmgseyy5cdwrozdyejm7jknkha
11 alice.i2p iq26r2ls2qlkhbn62cvgb6a4iib7m5lkoulohdua5z6uvzlovjtq
12 always.i2p wp43sdtuxum6gxbjvyeor35r5yvgtkp3dcu7dv47lx22zeb3relq
13 amazone.i2p e6kq73lsxaeyiwpmykdbdo3uy4ppj64bl7y3viegp6mqrilqybqa
14 amiga.i2p edy2xappzjjh7bxqounevji4wd2binqkv7gft4usrkan45xhbk5q
15 amobius.i2p rj6432agdprun5baai2hj62xfhb4l75uvzl55dhj6z5zzoxv3htq
16 anarchistfaq.i2p xosberjz2geveh5dcstztq5kwew6xx2brrqaorkjf2323bjzcd3q
17 animal.i2p 5iedafy32swqq4t2wcmjb4fvg3onscng7ct7wb237jkvrclaftla
18 anodex.i2p 25cb5kixhxm6i6c6wequrhi65mez4duc4l5qk6ictbik3tnxlu6a
19 anoncoin.i2p nmi3loretkk4zbili32t2e5wyznwoxcsgzmd2z4ll3msgndyqpfa
20 anongw.i2p owrnciwubb3f3dctvlmnaknb6tjdxtlzvv7klocb45mmhievdjhq
21 anonsfw.i2p ir6hzi66izmvqx3usjl6br3nndkpazonlckrzt3gtltqcy5ralyq
22 anonymnet.i2p 77ouyl2ane7ffgydosd4ye42g67aomtc4jrusmi76lds5qonlffa
23 anonynanny.i2p l2lnhq2dynnmf3m46tcbpcmbbn4kifjgt26go6n2hlapy4drhyja
24 anonyradio.i2p cbobsax3rhoyjbk7ii2nd2fnl5bxh3x7bbearokyxgvmudn7o5bq
25 antipiracyagency.i2p by4kcmklz7xnkai6ndfio47kts3rndm6wwleegtxghllimikdapq
26 antipiratbyran.i2p y2qbhrvuciifbszaqqwxd5t75bomp7kzdqx4yxsrkaq542t75k3a
27 aosp.i2p ly7raldsh2na2cgw5yvueyvqqjgx3vbqinecjrqdldgya76i2p2q
28 arc2.i2p rnmosuwvtftfcrk5sk7zoyhyadh2g4dhe2mif5ml7qjisgkyw2na
29 archaicbinarybbs.i2p t7o2tw36cffedgfr6kahewpkrntofnliuapji2e4rucl3os55epa
30 archiv.tutorials.i2p lldr2miowq6353fxy44pnxfk37d6yn2f6kaivzecbmvvnnf5exyq
31 archive.i2p x54d5st3dl6mwgfxj6raiekqkypo5pdvuex3n62szwju7hgefiyq
32 archive.syndie.i2p abbyu5n3mh3nj7pe3b6byldrxswvva5ttxcafsnnseidanurq3kq
33 ardor-wallet.i2p tm23k5ny3umhf6vf3kghnnwacli5zywq5wrr3xcqowbcofuyr4gq
34 ardvark.i2p jcmw2sol3hruwc6rfinonx4e23pjkukkg7lg7xt7xb2gpiyyraiq
35 arf.i2p o46lsq4u7udxg3qqlidrmpj4lb4nr7ldxmbb2x53nftndaeyxqeq
36 arkan.i2p 7o5y2lyyrjx5tf6l4fyumywui7msjv5azaaheatvw5sqj7mxbuvq
37 asciiwhite.i2p itbzny5ktuenhjwjfqx3jravolhlj5wullhhr2m4qr6k2emnm5dq
38 aspnet.i2p tsb7zqru57p4q2a7cto2lko4w5cg4lieglwm6t27c44fkphqmf2a
39 asylum.i2p p45ejjw4p2q6nq3mzi6cm6ep35grtzshboidj2lojmrmic22noha
40 auchan.i2p 6vxz4yp3vhjwbkmxajj7wiikxafwujig63gkhjknbq6xh4rqpm5a
41 aum.i2p ohdfneqxapfd3fwfbum4tut7z6k3rnr7rrguoxdrrfe2tln2kpbq
42 awup.i2p v6g32duzrkacnrezfbll3pza5u37h7lnukr2wbsk6rqen6prhbga
43 b.i2p 272kt3gcx6wjurunzaiiwld7s5p4mpjewfubzmlcvw2vie62ckpq
44 bacardi.i2p hivhnx2v47vh234c7coi2urj5cyvbl4bu3ypjr7snklortyqeljq
45 backup.i2p kepphem42whle3rkfv26wcksmnegdbg6rdp6t3oobdkc2fmzrdkq
46 badfish.i2p f6v26gyr4eipy3a7pi2voulw5qvob6dg7zij6xpo2ywbi5tvbu6a
47 badtoyz.i2p 3qz6ubtwlt2c4iasofjirkckq43u5fgkzyg7mlutcsym5gzhijna
48 barry.i2p 4kyahq53ol52n23l44tefgeaxqpp3cbb632t5k3umdvqcooevdzq
49 bash.i2p s3wouoilbl3mrefxjhp4qoyujgok34e7y6vmpbu6hx4342ivqo4q
50 bdl.i2p kp6fnuulenbjm7r26pfbmjcq3u7c7kvxeajodvgr5flcnskdgi5a
51 bdsm.i2p pa7fxql5jljegg7j5tglhnnaod2sptq3gxvdn3ji6muqyhgn3poq
52 betaguru.i2p d7cduwwhrcc2voameqfkvd66u3advu4jw2p6pysgax35vq6ovriq
53 beyond.i2p uaicfqlrpjtitqbqkpfujanj5dollzfzee5glsuls67ekw6hlpoa
54 bible.i2p pypz7ca24n3lyp4tm3kvncg3ltp3gd5pgnacc6zltoeffiyyegda
55 bible4u.i2p xs6lr2g5jiaajtb3nkno2zmy34eipitrggooxb7wtey7uko7bqmq
56 bigbrother.i2p tnxiifs6uticzyg6ac4lhv2l5luwi6xra7yngocro56ive5e4jsq
57 bitlox.i2p lqw5khxcdntlv3u4vhn53upcqirplvnc4etjlmoytrzs66ytettq
58 bittorrent.i2p pgax2vz572i4zsp6u6paox5xubmjrkqohq6g4hvlp6ruzzy56l5q
59 bk1k.i2p nlyegmtyfffo5jfgg5h4dxxnlmqko2g36gpaye5a7vd3is35xxfq
60 bl.i2p e73d6uhnfbylza6wqkhxejmqeyfb7thkzw35gn5ojmna64jzyk2a
61 black.i2p sjwueu62qpe6dtv5b322k3f23fl4uz3w6qe6wcrwauiwpnymypfq
62 blackbox.i2p 7josyf7zjieoib3ovmr5a4dh5w64kmfh45lv5h436eljtgfegtqa
63 blackexchange.i2p ztgr5kghkyn43fhhkuycroxgfti6cojo3vg4wdd3usqonyvrla5q
64 blog.curiosity.i2p yiz6jec5k7ccxdgnh7msqa4ze52bqqmf6rpq6bqdyojra2erd4ta
65 blog.polecat.i2p orlccceubewvxo3fbdyydq6e4uuidbs4xd5u2gyqbculnowo3ehq
66 blog.tinlans.i2p ylkch2nkrwehakx4z6wiyjbeqwlgasknukdkex6r6yq4xusrjnda
67 bluebeam.i2p lvxp3cbcfwtol57d5pmrsck32t7ndutlxubjb4smaf32bynhlk6a
68 blueheron.i2p anfb5jrhixjmvkyxctqwkezqer7dbob22wge2bh6wsewbhgnftfa
69 bnc.i2p fr4zbcygmx2vdct6nrabakfys4b4derm6jqu2ovppkgqillvlqxa
70 bob.i2p i76m7dwm5hnapljendbie6fc5y3mjlkdlduo3tvbwiwmvhxbpyaa
71 bobcat.i2p ftuukjtcquuvppt726w37boit7gp5hf2yxwfop35prx3grzzzxlq
72 bobthebuilder.i2p qlahgthqhr4uojkkwahnper2cl3ro5f5gtzy5t4lzapbzo4osy6q
73 boerse.i2p 7633w56hd53sesr6b532r5qlbdnvyl5bnvama6ign6xryaxol4rq
74 bofh.i2p auvuinzogu6gc4pwsgbjijuszxgcjygciu2wy53pfz7mo5nfpc5a
75 boing.i2p bgsq33bh74j66hn4oh7oovlvuhhdyw22lq2qi2fnv3jyh2ryap3a
76 books.manveru.i2p eb2tisc2vr5jvjqrixrozcujiucwxg4m722stxwho5666ipl67zq
77 bote.i2p bhjhc3lsdqzoyhxwzyrd63kvyg4br6n2337d74blyintae66mr2a
78 bozo.i2p 7a2d23h6htprhzrol36vgwgklsbqrnuya4tbaaaspmaeaodt57iq
79 brittanyworld.i2p e76umhhic3474sdxiuax25ixyfg7y3z7oojj4fmxvhgv3ruet6aa
80 bt.i2p uhkuu54pg47zey76h45tnvsdtpkf5bthbtrjgnaloi5m54h4hlaq
81 bugfuzz.i2p ubszn4gsf22vga67rvzzlg4qj2bfcq6o52fmxz46xruawqm6z7rq
82 burntout.i2p lkep3fd7tjvxrs25crr2c3jy7xm4s7bqiua5r327zgpw37sgyerq
83 bytepay.i2p 7amc4ztwkzu3cgsaaaw3223ohuihn5hlsqc6gpf2rxdyptdkyugq
84 ca.i2pd.i2p u5safmawcxj5vlrdtqrsqbsndkr5cfenpicgg5euu4xqm73yicba
85 cases.i2p kmpmk2fmineaiwublteqlifg4fkmewnhmxqlcgg7qwecz6daj43a
86 cathugger.i2p vq43xjjcnejqpzfprws5qzrea2siieshu4tglpdepql2w3w3bpba
87 cbs.i2p u3lp7wazvq6opodzwjg5sc5w5kwxehmxd4wcdpt4s4j2k4dx4apq
88 cerapadus.i2p zroed2cxga5zeuu6rcvmp2yfi77nzduw7yhdplbeuqkuyxwbrzaq
89 cerebrum.i2p u5gtsfn267udwfh2uq35jiabkufifvcbgv456zz34cydutsiw2eq
90 cgan.i2p 43z65gdr52xe3fxmkumwp3dzhedu4tu4rdtzr24hz5b4awcpfbqa
91 chat.i2p ollpwnp6yidc3obbb3famgt6rw5jg5w3k3a6z7hhaegj6gcohiuq
92 chess.fillament.i2p tv6wbanei647yf5bie4dhg2wmybkjurezlpdfwftc5ajqlfswwya
93 chess.i2p sbnoqznp5yzxals3vs6nzyqaj2fetvonys4e3b3x4ktmfeus54sa
94 china.i2p wit6f2zx6dtuqqze6nhbykrds3idppfirxvhf2f7ydqoqf4xdzeq
95 chitanka.i2p u4s3jneepk3akoez46kqiwikoezi6zyj2ibjkjyi4uuvsbcojzba
96 ciaran.i2p 2r3645eete6xwbfu62ogonudcrcgqq25sbnij5v4geru74yrscna
97 ciphercraft.i2p 7s5pkqbpbfdkxtwuu2e2iwstbikyewvvscy76lij4x5pfbygbjca
98 closedshop.i2p 6fg67mbw2okopzyonsck4bsy3cy7l2fame56uiysr2cezhjhzdbq
99 cneal.i2p g4za73ffigv3ht4jnhzy4dae52djjq7lqcguqsfg3w5cxzqm7nba
100 co.i2p 3mvo5eifcwplcsoubtvqkzdahwo2sdhfygfdde7lj2glybk4q22q
101 codevoid.i2p 2mukrqwtinsw27uoejtrz74zxtilyhnnfdyso7j3yo6vaa6nzlaa
102 colombo-bt.i2p cyr75zgiu2uuzap5zeosforbgvpfbqos2g6spe4qfulvzpyhnzxa
103 complication.i2p x2av6rwj5e5tp64yhdmifdyleo4wblw4ncrrcrabxwscuevpdv7a
104 comwiz.i2p 6p7zqfotzbd66etl5xqy3p6xvr5ijucru3am2xqa7wmnj6vf3djq
105 confessions.i2p lh5vitshufxpmyr44zgyymebo5elc42eda7pxvn5lmtes47c7rxa
106 connelly.i2p 5yrris3nigb3fapvzrlrcaew6cdmzdknzvgrc7y2jpn3ntqurweq
107 costeira.i2p abhty5xlmnyab2kqdxcd56352kcescxoux3p6dbqdrghggyygnxa
108 cowsay.i2p q4ghzfpah4ffvm3bhc6fdkrznk5f6jxfjm2daytlparznai5d54q
109 crstrack.i2p mm3zx3besctrx6peq5wzzueil237jdgscuvn5ugwilxrwzyuajja
110 crypthost.i2p zywhrxtnkjc3rxxvxbocom7ml4hnutomgtuvqrwyf3rhuupnq5ca
111 crypto.i2p vffax5jzewwv6pfim55hvhqyynafkygdalvzoqd74lkib3hla3ta
112 cryptostorm.i2p mlu7mswyirjf53usqq7gyamvqc6rqihezgdbevov3dkxmkfo57aq
113 curiosity.i2p eomeif4xrykxlzhawc3icdilje5iammijos6tyizwhrfh3j7qdvq
114 cvs.i2p yd6k7dzpsa2tnlzx4q7xqkmd4qsjk5xk5hbiqpiarwbeyvxaxgba
115 danwin1210.i2p eoqdf4no5dxn4tw5n256kkd4lzz3uk4p47np4mepsykpsdzrnvba
116 darknetnow.i2p gkx3o5fy7mv7l4psqqnhp35d5iun7rt3soci6ylf3rgb7a5a655q
117 darknut.i2p 2mk37gtvpk2i63o6vl7vna4dr46rqexxetupgn5efuuins7x3qya
118 darkrealm.i2p gbh4eerxdsph7etxsxznfhvmuiz54trlkenakqep343u4xcoekzq
119 darrob.i2p hz2xhtpeo6btgiwi6od4qj2575ml5o2246rd5orarruyjhd63zja
120 dashninja.i2p dzjzoefy7fx57h5xkdknikvfv3ckbxu2bx5wryn6taud343g2jma
121 davidkra.i2p nq7ca2egm563nir3xegfv52ocgmxstpz56droji4jgnzfoosk45a
122 dcherukhin.i2p qa4boq364ndjdgow4kadycr5vvch7hofzblcqangh3nobzvyew7a
123 de-ebook-archiv.i2p 6mhurvyn6b6j6xa4a3wpuz7ovpsejbuncvyl6rnhepasfgdgmn7q
124 de-ebooks.i2p epqdyuuhtydkg5muwwq47n7jvr66pq4jheve7ky5euls6klzwuyq
125 dead.i2p 7ko27dxvicr2sezvykkrfiktlghx5y5onup3f2bas5ipocy6ibvq
126 deadgod.i2p 63bveyh7wefb44hlia7wtxxb3jal3r67thd6jekmwrtq4ulaaksa
127 debian-multimedia.i2p cylxxz2y35x6cvyrl57wu3brckurtexatyi2i5awz3eeamqwjspq
128 decadence.i2p pw5ys7k2grjb5myydpv6ohikm6nna7y6u2dro44i4rucgulu3ikq
129 deepwebradio.i2p 2nait2gdeozkgf6gyhzjfij6mwldwkxxwcvtxobb4b5q5cvtm5la
130 def2.i2p cepsrw27kdegwo7ihzouwvgcvw2obswwjs23ollgj7hk2yrce3da
131 def3.i2p xbf3ots2purqun7orn72ypkpjmrzbfrkj3u654zfe77hbrbow6la
132 def4.i2p yyzdq4fwwmnlojp23drfpfqujln2vcjozjrfzfeuriuqzdq7g4mq
133 deploy.i2p ujzspsqkbz5z272eozsrdv4ukl434h3fuliwrfxxnab74jmd7e6a
134 det.i2p y6d4fs3rpqrctuv77ltfajf5m4tl4kzcu7rtwhxgiohylfxxow4q
135 detonate.i2p nykapdsjjswdkjov7x3jzslhg4ig3cpkhmshxqzijuhbisx25jja
136 dev.i2p cfscxpnm3w3qxnlv3oikewxm4qrot4u6dwp52ec2iuo6m7xb5mna
137 di.i2p 3irnooyt5spqiem66upksabez4f3yyrvvjwkmwyzlbealg64mgxa
138 diasporg.i2p edvccoobtjukjgw2os5eetywanbb2mpag5aknkrpia5qx2koksua
139 diftracker.i2p m4mer767ipj7mq6l7gdrmrq37yzvsj3kzezd7n7nsfuctntjseka
140 dm.i2p heysbdivyeugdbggpscco5wje3dsvwgcpp5ot4sopooebnmiqvtq
141 docs.i2p ato242wckzs4eaawlr5matzxudt6t5enw73e4p6r3wajwkxsm3za
142 docs.i2p2.i2p las5l45ulwwf5i72nht6vk33sfkidcpr2okpf5b6mvgbk3a2ujna
143 downloads.legion.i2p xpmxdpuuptlekyhs7mmdwkvry7h2jbvpqpzsijqe3a5ctxgodesq
144 dox.i2p vk27cjdrtegfdnrjqutebgxkpyrfj42trdfbsupl5zn2kp34wb3a
145 dropbox.i2p omax2s5n4mzvymidpuxp2yqknf23asvu54uon6cxl6gdrlblnuiq
146 duck.i2p 3u2mqm3mvcyc27yliky3xnr4khpgfd4eeadhwwjneaqhj25a65ua
147 dumpteam.i2p 2fwlpuouwxlk2nj4xklvm43m52tqyhqnu2fcfiuv7clvf3wd5nwa
148 dust.i2p u6xgh6zhhhvdvefbqksfljfs3nyjvqcrmyamp5bryz5f4injmniq
149 dvdr-core.i2p fg6l2ej6qrk5rkyfzdptxx5xkcm4kvdla4gg2tun7z7fm5cxxw5q
150 dyad.i2p 7n2ljphvp2dep7imoujvydxp4myuxfld3axwfgcny5xc5x6jj6ka
151 e-reading.i2p z54dnry6rxtmzcg7e6y3qtsig5yf5fmehuvakcg5wnuahx3iafuq
152 easygpg2.i2p bwxry5alzx5ihgrd3glah4eotddblzhalvpheppnw4zcajzqoora
153 eboochka.i2p ou7g64d5in4sugv5fgmmzwnunuw5hloixio7puthmrvrkwrp6egq
154 ebooks.i2p bvpy6xf6ivyws6mshhqmdmr36pruh2hvoceznzeag52mpu647nzq
155 echelon.i2p afvtspvugtd32rsalxircjglh3fhcjzk7gxrm3gw4s2yrpvzk6wq
156 echo.baffled.i2p bfr3lyicr72psxvt2umqfb562rtex66w6q3hi3tktzkoyane2iha
157 eco.i2p 2dq2o5h6c6a674qaduipp55mid5iktumjbswuwmpsrcqaeowdvwa
158 eddysblog.i2p ieac3ub4g5sy3wuhsbqfembnpp7f3a37xgcx537ytzsmgfzexnbq
159 edge.i2p aknsl5wmzjmwyc4wxutfdwy2w5vgd3vcx52mqx647hcgvyurmqta
160 eepdot.i2p t6edyotbxmxvy56fofdvmragvsj65te2gkhvzv5qnblicutyvgoa
161 eepshare-project.i2p sn26kom4qyuzouppv4lwnk6bqabdydcegtrilybviibwiq2s4nfq
162 eepsites.i2p isskhl4ak3g7qevrarlmblddgr4ugnn3ckalwpjcvxafk5rjgypq
163 elf.i2p duz6ey27ohpcp3llylklzdb63lylolzcixad6bh7rt5tkq42qqpa
164 elgoog.i2p z6hrgkg2ajmuzlrddjlffrgctx7x7fkipm6c4hdzmohyn5wkr4ya
165 ems.i2p 734zw4jsegdf55zl3z6s22tqkbxcghu4qvk6q2wevjfmx7xhbn6q
166 epub-eepsite.i2p yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
167 es.hiddenanswers.i2p cw7ge5ey4ekp5iep2kaw6j54boebtqytpcbnvio2bfpccd5ejzfa
168 eschaton.i2p xe75f5hzmrq6rkhsef2geslmi2v2yfngdiysmlmxvh7b4pyyjk4q
169 esuwiki.i2p cwxuiwcpymb72vm5vluba66ofhugyf5qeevvwo7e2fqrxl243coa
170 evil.i2p ljfl7cujtmxfffcydq77pgkqfxhgbikbc6qxjgkvcpn4wzd73a4a
171 evilchat.i2p s5b7l3hzs3ea535vqc5qe2ufnutyxzd63ke5hdvnhz24ltp3pjla
172 evilgit.i2p mx5vyoqhg77yuhthwznsxrepjsemq4uwitx4lxdzetk36ryl5rla
173 exch.i2p vsyjsbbf2pyggtilpqwqnhgcc7mymjxblamarmxe5hmbxaxvcndq
174 exchange.gostcoin.i2p n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
175 exchanged.i2p ylmulgfskl6uiwac4hw4ecwqdzd3oxtwaemzj25zc6k5q4rkexra
176 exitpoint.i2p 5zmjurq3enudcenegnxu5hqmfmayz4lxvnik6ulch4xssa2ithta
177 exotrack.i2p blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva
178 explorer.gostcoin.i2p ktoacmumifddtqdw6ewns3szxths2hq2fat2o7xnwq4y3auga3za
179 fa.i2p 6n6p3aj6xqhevfojj36dixwbl4reopkhymxmatz7ai5sroh75rka
180 falafel.i2p djpn5cbcgmpumwcriuzqistbae66txca2j4apjd2xesfgb7r5zmq
181 false.i2p 77mpz4z6s4eenjexleclqb36uxvqjtztqikjfqa4sovojh6gwwha
182 false2.i2p j5i2tfumh3ti5sdtafwzzbpupmlcbg5drysfay2kxbdpsaljrosa
183 fantasy-worlds.i2p 62a4xcyyhvfrcq2bkckb7ia37fmrssrgx467tlkxp32fjpq577wq
184 fcp.entropy.i2p de6h6ti5z3mcbdcwucu45vplikqyoeddsu3rqy7s2zy5i47j3peq
185 fcp.i2p ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
186 fedo.i2p zoamh7e3k2vf2g6pfy46ho4taujk2f4mxqqsv3gbg554fxbvyfqq
187 feedspace.i2p kvtnpx4jylgeyojfhix4x462sqn5uork3roml4sfzotkxx62i4wa
188 ferret.i2p kkqie5qmja7bkf3iad4zxhrdarwj7kbrx2m3etn5kmba3shgwj4q
189 fido.r4sas.i2p i522xmu63hfbaw2k54cthffcoqmeao6urjyq3jg4hddf6wf57p3q
190 fifi4all.i2p v2stz6bsot7sbjzix5tky5dm5ej7gidmjnkvzqjju5xvz5sz6fwa
191 files.hypercubus.i2p qfglq25jwieszgyt7muz6dambzqsrmjhhszygzzx2ttubc77sffa
192 files.i2p w2sy74xe6oqnuz6sfh5fhkzu7boholgzd5f3anhj47srxwpj2vaa
193 files.nickster.i2p yil7dp2hg5pbqyovsiwb2ig6zjsq4tize3fnwemmqdrr6j5itdtq
194 fillament.i2p udj2kiino4cylstsj4edpz2jsls77e32jvffn2a4knjn4222s2oq
195 firerabbit.i2p awqh7n3wskzl3epyvkdwgarmfybsncm7vye6psg4tpkmplh3mj2q
196 flibs.i2p ocdm33e3h5tdml3yyholj4objdwsrhlugfqjnqgdkslmgdzb6b3a
197 flibusta.i2p zmw2cyw2vj7f6obx3msmdvdepdhnw2ctc4okza2zjxlukkdfckhq
198 flipkick.i2p aso5rzc4ym6g2bcbxjy2n573bmbenkjawva2jg7fhyqhwtwgu6lq
199 flock.i2p hflpi33ko5bi2655lx6bpzstdnjqgzrz23inovqjx5zpntyzyb3q
200 floureszination.i2p vitpvfb25sikuk3crgcvtcdi7hajxnnq2t6weay3no7ulur2wwwq
201 forum.fr.i2p onvelkowkbuwrglhw2cnocggvbdudi75sll5mfirde3cbopjqivq
202 forum.i2p 33pebl3dijgihcdxxuxm27m3m4rgldi5didiqmjqjtg4q6fla6ya
203 forum.rus.i2p zd37rfivydhkiyvau27qxwzmerlzbqtthsa5ohtcww62zrygjaga
204 forums.i2p tmlxlzag7lmkgwf6g2msygby3qttxvm6ixlfkq6s6cpgwubp33ya
205 fproxy.i2p keknios3gm6kh6onez6x2bm2t7stv54oanvltuagphgdfjdw5e2a
206 fproxy.tino.i2p fpaituvuvyxp6xdjnv3i27alnj2ifzcvqdweqb6yj5uybotzvyha
207 fproxy2.i2p r4lgw4wmza25g7j5fjocjbwzwthfg4ymcbm52ref3hh2hogskcza
208 fr.i2p ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
209 freeciv.nightblade.i2p rluupsgxbvw5t7jno3apyzlrdirjkljft4gdoy4mxxh4fmd4xzta
210 freedomarchives.i2p 4ck6oliqfjz3sccpya2q4rh5xkj5xdxkqs76ieml37537nfhwd2q
211 freedomforum.i2p abzmusjcm3p3llj4z7b5kkkexpsxcnsylikokouk5txfim3evqua
212 freefallheavens.i2p giqnkltyugfmsb4ot5ywpvf3ievuswfurk6bjie4hxi2hh2axajq
213 freenet.eco.i2p 2kf7ovb35ztqkrurkm76y34jfpwi6go25xj7peznnmxrl7aieo7a
214 freshcoffee.i2p sscuukigp6alcb3ylhkcugoejjfw5jqgtqbsbafw4hyku42lgc3q
215 frooze.i2p m6ofa5dmyse4b4jg7kfmluuuc4pw5jqu6zh4qnboin4vropxepja
216 frosk.i2p 63naq7zb3hvbcppj2ng7qwf6ztusp4kwpyrzbt4ptafcdbu4pfjq
217 frostmirror.i2p ycz3imuz6yte2zhlapmsm3bsvc46senvc2jxzwsbfdct5c72qulq
218 fs.i2p ah4r4vzunzfa67atljlbrdgtg3zak5esh7ablpm6xno6fhqij35q
219 fsoc.i2p vaqc4jm2trq7lx2kkglve7rkzxhhaptcwwl32uicx4ehf5k3hx6q
220 galen.i2p 4weo7zkxscxbcouiqx4mlnb35uwl2lromikzk33er3fljktyvi2q
221 gaming.i2p rfxberwod6st2zc6gblqswxjl57nucgc3xrbwss43pe3dvqqzj4q
222 garden.i2p qkk2dqx6nocycgt3vinsoc76cxkb4jreybcpgz3fcps2dbe4rowq
223 gaytorrents.i2p fnggbr2t2aulr6rvlo4aehotx6wecfob7u3k2nxsnvtm4xex424q
224 general.i2p 5fklrsztdqpl3hkkwwrrw2rdowrq7wwhwb6h7avvk4fhansp4vvq
225 gernika.i2p wpzqv3lxpecdsvcaadvbmrhhwlc7kp4n2mijdv2qjw3zr3ye232a
226 ginnegappen.i2p kbhfkzx5jeqhfgss4xixnf4cb3jpuo432l3hxc32feelcmnr3yja
227 git-ssh.crypthost.i2p llcp7jvz3hgtt3yzkdgjolwobisgvhv4xqa5a4oddejllyozur5a
228 git.crypthost.i2p 7frihhdcisdcyrzdbax6jzvx5gvtgwsm7m6kcem2tlaw4jtahbqa
229 git.psi.i2p em763732l4b7b7zhaolctpt6wewwr7zw3nsxfchr6qmceizzmgpa
230 git.repo.i2p vsd2vtgtuua2vwqsal2mpmxm2b2cpn3qzmqjoeumrrw2p4aot7uq
231 git.volatile.i2p gwqdodo2stgwgwusekxpkh3hbtph5jjc3kovmov2e2fbfdxg3woq
232 glog.i2p ciaqmqmd2wnws3hcpyboqymauyz4dbwmkb3gm2eckklgvdca4rgq
233 gloinsblog.i2p zqazjq6ttjtbf2psrtmmjthjeuxaubi742ujrk2eptcsaoam4k7a
234 go.i2p ll6q4lsirhwkln4dqxwqkh2xu4mu3jiy546b4uhe4fypyb4vvx2q
235 gonzo2000.i2p nogsv7okydhbvrewv6hb4xdojncvhkusnyib4lglluc4uw67a37a
236 google.i2p 4p3ajq4cotnflmuv7fhef3ptop5qpm3uzzgp5bahxif3nc4w3ffq
237 gostcoin.i2p 4gzcllfxktrqzv3uys5k4vgkzbth4gqednwhfpt755yivm3davuq
238 gott.i2p dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
239 greenflog.i2p zny5ftmhzxulxzyczmeat53qjnue2xtqv2clisc7dg76lwfceecq
240 gstbtc.i2p n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
241 gusion.i2p 4qyfdhizjixe2psu7wcvqufix5wlijocehpb2futurcmlhlktrta
242 guttersnipe.i2p kizkhzes2bzp45widihremo6geepfk7dl6juourkvzuvlc6y3spq
243 hack8.i2p un63fgjgi3auvi7zscznwqfol7ka4johgthvqf635mg3fefsjgpq
244 hagen.i2p e2t6rqd2ysbvs53t5nnaf7drllkgk6kfriq3lfuz6mip6xfg644q
245 heisenberg.i2p jz4quyw7zt63tmw65jfp76fblwadjss4iyi4puqdg3dye7oaqlvq
246 heligoland.i2p gzrjm62ektpqjfsem3r3kwvg6zpjvvhvpjvwfxkm2ay4zu7sp6oq
247 hidden.i2p iqodhhqo473qv5gwhjcs2bsrbhlqtpzgpnuumpastfiyhuwb2kyq
248 hiddenanswers.i2p kj2kbzt27naifij4ki6bklsa2qfewxnkzbkgvximr4ecm7y4ojdq
249 hiddenbooru.i2p zma5du344hy2ip5xcu6xmt4c7dgibnlv5jm4c2fre5nxv44sln3q
250 hiddenchan.i2p 6y4tltjdgqwfdcz6tqwc7dxhhuradop2vejatisu64nwjzh5tuwa
251 hiddengate.i2p rvblcu54jvkkfffp3fobhunsvpgfc6546crcgzielzwe2s5m5hbq
252 home.duck.i2p jsh7yfvm2t5urdcnmfzdy4n6vegqskdtlwem53chgxli4ipfmuma
253 hopekiller.i2p kcaelbgsvrkiwpx36b4wxofebrl3njx7rgm5amzfmqwbomt44cxa
254 hotline.i2p 6cczi27iuxkm3aivazaemzltdqgh42ljzurqp43uclbz2lid2uqq
255 hq.postman.i2p 27ivgyi2xhbwjyqmnx3ufjvc2slg6mv7767hxct74cfwzksjemaq
256 http.entropy.i2p ytu7kz5bdoc26nkpw2hajwt3q7n5rcbg2eokyefhmkxmmslimbdq
257 human.i2p nrtcelq3humyfvoxmzmngpka6tmyifweouku5mbi5av4lc43hzaa
258 i2host.i2p awdf3nnmxxup5q2i6dobhozgcbir7fxpccejwruqcde2ptld443q
259 i2jump.i2p 633kqgmwzzu6vhkevwvbf2pfyejt3gkes34i6upa4og57fgdfcxa
260 i2p-bt.postman.i2p jeudwnx7mekjcowpqo6xpkwn7263c57y5piurrjrdzinjziu4fla
261 i2p-epub-eepsite.i2p yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
262 i2p-javadocs.i2p icgmr6hhjudl4yxhtuq4pxvss2pzypwddzowajgs5rdz6f55novq
263 i2p-projekt.i2p udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna
264 i2pbote.i2p tjgidoycrw6s3guetge3kvrvynppqjmvqsosmtbmgqasa6vmsf6a
265 i2pbuggenie.i2p bioq5jbcnfopqwvk7qssaxcl7avzeta6mu72jmxjeowflpcrhf6q
266 i2pchan.i2p tduxyvfs7fzi26znvph3mu2d2ewaess7emomfci22wvownajphuq
267 i2pd.i2p 4bpcp4fmvyr46vb4kqjvtxlst6puz4r3dld24umooiy5mesxzspa
268 i2pdocs.str4d.i2p yfvbtrhjac3jutdsqzugog6mbz3jtyhpwovrt2mqc5mzv534y7cq
269 i2peek-a-boo.i2p qgv64klyy4tgk4ranaznet5sjgi7ccsrawtjx3j5tvekvvfl67aa
270 i2pforum.i2p tmipbl5d7ctnz3cib4yd2yivlrssrtpmuuzyqdpqkelzmnqllhda
271 i2pjump.i2p 2mwcgdjvfvd3xwumzqzqntual3l57h3zo7lwdmkjboeraudpkyka
272 i2plugins.i2p bb63kmnmbpitsdu45ez54kmogvvljn3yudksurcxiyq7dn5abt7a
273 i2pmetrics.i2p v65p4czypwxrn35zlrfkar2w77vr42acd7gbszegsrqq4u7sip5a
274 i2pnews.i2p tc73n4kivdroccekirco7rhgxdg5f3cjvbaapabupeyzrqwv5guq
275 i2podisy.i2p 3c2jzypzjpxuq2ncr3wn3swn5d4isxlulqgccb6oq5f6zylcrvcq
276 i2push.i2p mabdiml4busx53hjh4el5wlyn4go5mgji2dxsfyelagi4v5mzjxq
277 i2pwiki.i2p nrbnshsndzb6homcipymkkngngw4s6twediqottzqdfyvrvjw3pq
278 iamevil.i2p au7jhslyt4cxkjp365bvqvend3hhykrrhbohtjqlgoqrlijbezja
279 icu812.i2p bxgqwfsnr3bgnr6adn62anjcin5nuthqglotb3wn3dgynsfofeva
280 id3nt.i2p ufuqdzsxltiz224vq5gnuslt3a3t72dhy5kq6i2xway53m6pzv6q
281 identiguy.i2p 3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva
282 ilcosmista.i2p 6u2rfuq3cyeb7ytjzjxgbfa73ipzpzen5wx3tihyast2f2oeo24q
283 ilita.i2p isxls447iuumsb35pq5r3di6xrxr2igugvshqwhi5hj5gvhwvqba
284 illuminati.i2p syi6jakreatlm2z22u76izyqvbm4yi4yj7hr7jb63lgru5yhwwla
285 imhotep.i2p qegmmhy52bdes2wqot4kfyqyg7xnxm5jzbafdb42rfoafadj2q7a
286 in.i2p r5vbv2akbp6txy5amkftia757klgdy44s6cglqhmstpg65xycyjq
287 infosecurity.i2p v3gkh5kqzawn2l3uzhw6xnszsh6w3nztjmlwil7p4kyrwrsm2dba
288 infoserver.i2p jd3agbakybnhfvkeoxrx7t33iln6suzomv3kxkxf77j7rkonch6q
289 inproxy.tino.i2p ex5yf6eqqmjkrzxnkn6cgvefgne24qxsskqnpmarmajoit43pgma
290 inr.i2p joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq
291 instantexchange.i2p 5wiyndm44bysev22kxvczxt37p6o6qroiqykytrvn2yzi55aqfxq
292 investigaciones.i2p n7hqd4asxrdwf3zwo7rzv27y2qkcfmakmz6mjar6aw6hlc4c7mha
293 invisible-internet.i2p jnpykdpp46zenz4p64eb3opadl5g42dls3rurk2cvq6a3g3rvbvq
294 io.i2p tx22i6crnorzuti3x6va4mijsbhoqswy2cfdxjbvprgsq4eerg7q
295 irc.00.i2p bvcja52pppgfspp2ueuipoysjnvvoyblz2h6smpxcmanjquogirq
296 irc.arcturus.i2p 5nywlbn35p2nwsymwpfmicu6fxono6g64vwusxbsvmm2qwz6vupq
297 irc.baffled.i2p 5zmtoopscym6qagkvpgyn7jnkp6dwnfai745xevkxlou77c2fsjq
298 irc.carambar.i2p hxzbpivxqxy6nuae4t6fnkhcgnhs4c72vt6mmsqfmfhrkn2ca6gq
299 irc.cerapadus.i2p e4ckznxcxvgyikzjmjsu72i2dbj2d76ogexyukklbjvpcnhp6zzq
300 irc.dg.i2p fvp3pkcw4uvijqabwtekcdilklp73gyasuek67wdcs2mucep4caq
301 irc.duck.i2p chdpmm4gxffyn24xx5dhxvfd5httu42i5gtoe6cctjlsf4mbofeq
302 irc.echelon.i2p ez2czsvej5p3z5bquue5q3thujcodfze7ptybctqhnqc7hms5uzq
303 irc.freshcoffee.i2p ubiu2ehtfnrleemgpzsqkahwnvzuaifqa3u4wmaz5maaisd5ycfa
304 irc.i2p l3ohmm4ccxvyuxuajeaddiptci5lsrnxtvtyq7iohphrt3oj2evq
305 irc.ilita.i2p 5xeoyfvtddmo5k3kxzv7b3d5risil6333ntqrr3yvx3yubz5tk3a
306 irc.ircbnc.i2p 4rqcsqd7xif6r4v55blqvmqu5er6due4eyene3mjorfkts4o3rxa
307 irc.killyourtv.i2p wre4majmg2vnbi6id27et7yw6lnpf56wkbm6ftnlwpvxnktq73hq
308 irc.nickster.i2p dhq3fhd5scw3jqhj5ge7kqfpprfolcgxfjbaw24obohaiqjtdu7a
309 irc.orz.i2p 7gifacog4aoons3syybojbbnyqqaaqijhngrehn2xlq3eucuyjcq
310 irc.postman.i2p mpvr7qmek2yz2ekegp5rur573z7e77vp3xqt2lfbco5i6nkfppcq
311 irc.r4sas.i2p hodhusp73gltozgrnianlbploon3rrvhrzfn5mf2g46o7aaau5la
312 ircssl.cerapadus.i2p 4x2i745i4w52ss3he2kse6tzwt64pr62yvrcb72lgvrb63fup6ea
313 irongeeks.i2p ecduxoion5uc5hnvzjxff6iiwhdwph6gse3dknyvlo7e6gaeho7a
314 iscofsi.i2p enjgdxs4um2dmhdb2ajff2egrdijkjji3g47m6unb74swbrqsddq
315 isotoxin.i2p wue3ycaccf4texikza3fh6p5yrmtgnooisuypnepo5mo67lmpcqq
316 itemname.i2p o35ut7hgywy35okvgkjkv3ufzv2ejv4luap4oytwbyy2jqy6u4vq
317 ivorytower.i2p fpwrfvidfexsz7dspofkwtkmmizm7lyralfz5kvykffk7gubvxsq
318 j.i2p kjxvohlsf5sdrzxzfcrmvquccnoevi6ytbl63mstsru5wt2dx3ea
319 jabber-2.i2p pvnmzgemetkwcuvt45omgowmeznwk5xw3nc3ygeoz7yekqxy57na
320 jabber.duck.i2p rhdzvvzraqzzm67zpyegb7knpfrjeffitixqzeyymdoz56uh2rtq
321 jake.i2p v2axvy6pqefnla7gun5fmqs4lqe4xfyqovgzcundhxrpcdvfd7cq
322 jar.i2p 2fthkmujup3xiiu3yple24n6g4emzdiiimbuqwvpdddtsr3c4nrq
323 jazzy.i2p ha5c3zafwkt6mwqwjcf4oqwvbwz473652ljjadiwrj4gfkfkjofa
324 jdot.i2p kw4jr5qw4bhnj33avkwankjdh3zi7wtahlmgkjwvsv2isskkzgpq
325 jhor.i2p c6rnm7oemydhuwzmhwwwxphkzanez5rnn7fkcs3lpgu6gkgtssoa
326 jikx.i2p aazr55itvyns4lwppvx5njyx5tjdwemw4w6jbmpegdunznod2ieq
327 jisko.i2p jxgfvr663uhr6m65hrgkscshysfshkq32ywdubc4ed7zda3e2pca
328 jmg.i2p oglpnq7zungdukmk6gk5fzj5jp6wibuoihqgks453wztrwos4ggq
329 jnymo.i2p nbfplxgykyfutyadlfko2rmizdsxox2pee2ahboj5mju4s3putda
330 jrandom.dev.i2p htynimemonyzqmn76gworxyfkmqtsa7zcprbrd3i5cxqqm75tuzq
331 jrandom.i2p dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
332 jrrecology.i2p qxi24gpbum3w3kesuxvheyu3p5u5o6tuvoypaolub2gnvbld57xq
333 jwebcache.i2p xdffxnxtjd6ji2zig3cgva7igvl2tiapyjoc7ylbzwqhxudbmvfa
334 k1773r.i2p zam7u6vslhemddz347uusuzjdk5wma4h5hcmcqlng4ybbpdbjhnq
335 kaji.i2p z5ic7gvm2k4doczphtrnrspl2w5sfbss2de4z3ihjijhtjw67ydq
336 kaji2.i2p 4lscgc6napekfx7ay5fdcjofeja4fnl7tqcd3fek63t4saavur2a
337 keys.echelon.i2p mwfpkdmjur5ytq4og36ym3ychinv36b2a57f4rmgqmtrwepq3fva
338 keys.i2p 6qv4x7ltaxckd4vbay5s4ntqqflq4efk6oke2d5yzicqrmk443ba
339 keyserver.sigterm.i2p isoxvnflrdn7cm76yjlfg5tbcugoito2hur7eidbqmo33xmwz5ga
340 killyourtv.i2p aululz24ugumppq56jsaw3d7mkbmcgo7dl2lgeanvpniyk2cbrda
341 knijka.i2p knjkodsakcxihwk5w5new76hibywia5zqcgoqgjttzsausnd22oa
342 knotwork.i2p 2yocdbcjiyfaqgxb4l6oenrrrrie6nydgmbnbfulqg7cik6bozxq
343 kohaar.i2p qchpjehbhqjbxdo7w3m55jbkrtsneb7oqoxcr24qttiq6j5g3z5q
344 krabs.i2p 3yamyk5bgfgovg6zpvtvpdjk37ivjj2wog2w7wha5agzgxxkqaca
345 kuroneko.i2p wbit2huhhwlyqp2j4undccuyrodh6qcmzdeyuaoy5o4ym7g5gdgq
346 kycklingar.i2p gctswdhp4447yibxfbqg3uq2bvx63qjeqnaoaux75zw73leakyva
347 lazyguy.i2p ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
348 legion.i2p 5oirascyhwfy2tr2horw6mixozsre7z6s7jfq7qbnj523q3bkebq
349 legwork.i2p cuss2sgthm5wfipnnztrjdvtaczb22hnmr2ohnaqqqz3jf6ubf3a
350 lenta.i2p nevfjzoo3eeef3lbj2nqsuwj5qh3veiztiw6gzeu2eokcowns3ra
351 libertor.i2p 7gajvk4dnnob6wlkoo2zcws7nor3gunvoi7ofalcps5lc76wruuq
352 library.i2p brqqaq44vbeagesj5o3sxcnkc5yivkwouafyxa77ciu7l644ei2a
353 lifebox.i2p pyqjnycm55cuxow22voqj62qysrjdnb6nbyladaiaiirqi7vp2yq
354 linuxagent.i2p ap5riaikrjq2uv5qvy7klzhhqywvqi7wqscyipsewcun7w2eynlq
355 lists.i2p2.i2p vmfwbic2brek2ez223j6fc6bl5mmouzqvbsch45msvyyzih3iqua
356 lm.i2p yeyar743vuwmm6fpgf3x6bzmj7fxb5uxhuoxx4ea76wqssdi4f3q
357 lodikon.i2p u3f67staiwhqxpacya3clmvurdwd2kp7qcthzhstqnhrmlwc2g4a
358 lolicatgirls.i2p a4lzmjyba7aq7hl6okqpds7znnwymolqnr7xhvno2wraqb7uhfla
359 lolifox.i2p 7fd2clkiotjnaoeigdtxlkkb24eik675ovezjf67x26ysham4zca
360 longhorn.i2p pohcihzxzttjclrazhs3p76wt3ih737egb5bovqb6ym3du6z3o7a
361 lp.i2p jiklbujn3cbfikf4pca526jgmorx6mxhil3twqmfoteaplx6ddwq
362 lucky.i2p wx36m3wnpt2y6bngdpg3ifrarvtkpwnluarx377bllpgvkuhybaa
363 luckypunk.i2p y4t6cujjxnnrtln3rgmfbgbh46hic7wkef57krd7opitbgngohka
364 lunokhod.i2p 3yc6sp7xic4grmpfecbwuij6z3dp5kdgoo362pszaco7io42mnwa
365 m16.i2p ucsr3eveuc4mx5y6gxnoaywd4ojvbel5q3ynns6s5yfw3vusmfva
366 mac7.i2p 3yjowssqzydciwa5zx55kazgf7q7w6g7rkocr7bngy35ii44t34q
367 madman2003.i2p a2sam2xbhxbzmeyobphbxrkdwlppoerewq5qvibbyk3ftsr643qq
368 magix.i2p cgfnyxv62msfynsfbv3kju22j2mt6tfnopshhmrcmpcrxyts6xwq
369 magnets.i2p snz46nez6hrrpg6336neinflw56l3vwatk6bzzytwu77xmsfsoca
370 manas.i2p 6qolj62ikkoq6wdn3hbvcbdmlvf2rcyv432kgi5uy7mvrczmjtba
371 manveru.i2p pbmbofs76wpjnxi55eqtwg4y6ltyij72o4fm4sxfjol3y57ze5sq
372 marcos.i2p vpo36bsil2voqaou53zshuegssqaroa5mbrzxfmhjywlbojckalq
373 marshmallow.i2p svdqd6j3y3gwryufcl4fkzpmcujgvrvphvk2oy4r7m75xs327e2q
374 marxists.i2p lepah55qyp2fhuwxlz7bwrhzckn4gkuofivnofoeuyfpmke5x2hq
375 mattermost.i2p x5oovnhnuli5fnwtgkbd5z5jvrvdvprqyuofywx6uoxkk4bie6ya
376 me.i2p dbpegthe42sx2yendpesxgispuohjixm4bds7ts5gjxzni5nu6na
377 meeh.i2p 4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa
378 mesh.firerabbit.i2p 3x5wokr4bjy5z3ynji4fyhvwzv4fvgry3xafi5df5h75doezjytq
379 messageinabottle.i2p avfhe3kvrrv7utxn2vre65lg7damxzzsewq3vukwie4llitd254a
380 metrics.i2p z45ieamhex2ihqv7oowk5fz4qq47rbvxhhhbaaiinpajbhuevtpq
381 mhatta.i2p o4rsxdeepfrnncsnjq675xogp5v5qkbfgbt6ooqeyfvlifobrjxq
382 microbleu.i2p mtapervgibruizniems2yyr47pin2wpysyh7m632rigl26vjc6qa
383 microsoft.i2p hvaqr5idszdyrjph34amb4mjosqd3ynggoxlnj7ciqhnx7q6plza
384 mindisl0st.i2p u7rnqhvsuyxd3fabm4kyzn7brgz3i3cporj2emk2jmbpcmltyf7a
385 mindspore.i2p uuh5dd3y2rqa7x2jpggm4p2pg6znarm5uanwsvybe4tk36ymwr4q
386 modulus.i2p ctz3o6hdefrzwt3hlg6rjhdcbjk6irppbndq32u6jnn4lz72f62a
387 monerotools.i2p 5bal7dngxde2ddmhuzbtfken6w5nmxmixtjlrlmxt3wbhnemv73q
388 monerujo.i2p puri6y5dtwh6zr4u77ep6ozatun6iz7v4wai2dzxppz7654corlq
389 morph.i2p iovyp2dao5rta6g5v6hke2s4ugx2btkpcljddak2yhxfrx3l4dqa
390 mosbot.i2p 5bhmrp43mjwlzf4x64xgdrkwmw4luvng6eq5waa663a7vnkp732a
391 mosfet.i2p s5ynkgagndmpxpf2kmnenv4x72io664gzd2x3qef54ilammnte3q
392 moxonom.i2p gcjdrvnlobgexh7ebv276pwmnoj3yoyaqm3w4vmmdha4lgxfinqq
393 mp3.aum.i2p n7bmu5dwux7f6gedmdik6zrm77bnls4lkzo2vo3bf4bwegk7vkjq
394 mp3.tc.i2p w3ied5s7ldjcvnhxu2gyofe3oogzbplkyxshzfkhspiy2526snsa
395 mpaa.i2p m6cqnglo7xlytwxkdsmwf3d23d6lq5r446c3tktb2tdmuah36zya
396 mrbamboo.i2p tmpmkx6wlbbrgsnexrqlrib7laoegpbfeop7bnyezegii7hecpxa
397 mrflibble.i2p u7k2qcmkrril6yvudvwxjqz7k3dzgp3jdejjjeapej7liselj3eq
398 mrplod.i2p fjn5hxtybxyfyvdf6u5v5seg2sjd47hb5by6sa6ais4w3xnrxwyq
399 mtn.i2p xisk3h6sku3iqj52uriogaajmnku7pwjux7wa4omx2zloamuw6eq
400 mtn.i2p-projekt.i2p f52x5fp6uhq53f5zle5d6rq5un34xgmxgazvilvmzcby37xcmsfa
401 mtn.i2p2.i2p l6kuhtmgvbp57d7jwalj5nksi6nr4gfzbz4oit62lxgipb3llt5a
402 mtn.meeh.i2p h7ylrsuzzynrxp3jql7anoozyqblavj7eqces6o3wngvuuxhs2la
403 mudgaard.i2p yz32lk42gtoesknesfolq3tt4erxxcejcote5pontaeqev3bj2kq
404 mush.zeit.i2p dk3sg23kljawxqp3cb6xz5mnzjlyckzvq5jhqs5gnvdsv7wqn6ha
405 music.i2p akamh76yi6p7xxbvl3qv3yhaockne57yfuh77acogbgpjmwypvia
406 mysterious.i2p p66g2a4nzfkvidd3l7nwphcnfa3ttyu5kiolcb4czec2rn2kvwsq
407 mywastedlife.i2p ceumy3puvvsrru5bmfmtgsajsx5qyehqac7l7a23xpwtfs2bvcgq
408 nacl.i2p bm2fib3tumer72lopjh4nmqomwvqu2sdfyb2hmr6lnk7jbw3vvia
409 nano.i2p ex5ssv7s3hj6jp7hvadxfw3wvbjbvnczxr4pbk7qw26ihiorjmba
410 nassai.i2p v653cocvn3i6bgjdm3ciwbdnu32supglv6gn4fh23bohemsp545q
411 neodome.i2p 5hkhjehj3ct2pvcah7dcylwef2oti3xij5myxbv3pd7rocio5vkq
412 news-i2pn.i2p wwcqkwfo5yhe6uribv5tzylk25j5hkdk6gdnyftzd3k7dawlzwca
413 news.neodome.i2p trhwcnygfkeqjj6g4xhmrdp4gsjqsye47lsxshbmwbten4ywt5oq
414 news.underscore.i2p rl7t3kspoktuatjcu7gf7xleu7y6biibs4fspzo24kll6n7hbq4q
415 newsbyte.i2p gsk3rgsejxxrfabjxu5w5plplxsu47aoeoke22vvhlwwllzosnxq
416 nibble.i2p jmdxcpdzqafedn3clc4y7u6o56qocfiffrzbzncmtggqtio5qjpa
417 nic.i2p vzu5ymab6klevpcdudv4ypisjqaznmt44e6lcg7dwiuza4saibxq
418 nickster.i2p zkwsa6kvq2wdhovw5g5wqakpb7rlaylyhfriwmurots5pvwbqauq
419 nickster2.i2p eofzi7npzpk4p5gb4qper4hmwgxo6kepo3dheeblakewedxj2bwq
420 nickyb.i2p gmpxk4tje7mnud32kg2kjmf36f6cpwqakzc2dxuzjnnz4qr5w4sa
421 nightblade.i2p p4gkon7ytswxrbwkl7vruw6mg7kfw5aofovqjgt4c7tnqmbq6lha
422 ninja.i2p q6dg6hlb3egzdqz352ri5rc4fx4gcrdeu3tpiyfxlv73yfjgrhya
423 nm.i2p 3itdpqzyn3ii7sivppo4sxxwhvgtpskzkbokrdibim6gqpvlw5ya
424 nntp.baffled.i2p kc6muo2tih5mttbpzecteegvtonuysjidk3emcy4cm4yifzild2a
425 nntp.duck.i2p gvzzor4utsqxswvf6jaglfks7yxudlz2s326ftrk56i4lpd2s47q
426 nntp.fr.i2p npoztnqadfnu4vrokoh6rusoi3yne47s6jurc3lzhcrzzia5eqva
427 nntp.i2p wwdzmeyler4djegvyt2bxmkwrckfgg3epkkwowyb75s47he6df6q
428 no.i2p lpsg4x4gdrf7antxcdy47cl6abcqei5ommgzt55retq7go5ku3ba
429 noname56.i2p oiyoslismzyxuw7ehxoigmtkdj35idim6flmlplddxuiiif6msfa
430 nop.i2p ssag45lathm4gqp46si7c4w4tioyvjpcza5uvz5x2zuljnplylca
431 normal.i2p j5fex634r2altzb3kjvu35qekt2r3hgsqzg5qxoy7dp53heu5pma
432 normanabcd.i2p si2vh43gvxjnw2shwr24j76xyanow4oa6gbu4idookbraoxl3s3a
433 nothingburger.i2p tesfpn757ysc7nih7mxher2b3jstkc3l5fhfcyb5kxhzhvv52trq
434 nothingspecial.i2p wzrwqrp52bilqijrlboclynuev4kzpjzfzlvzl5aqxqt5fdnpbga
435 novospice.i2p ukqap24nwac4gns77s4zy7j5cagt7l7syb5zo7eukfg3zn5gg5qq
436 nsa.i2p nsetvbclpomqxfcit4mghn6z7vdhnza6jdzczby4crnto32uykga
437 nvspc.i2p anlncoi2fzbsadbujidqmtji7hshfw3nrkqvbgdleepbxx3d5xra
438 nxt-wallet.i2p 33pp74k4ivy67z332qpyl3qlcqmi6gxqumrow4bldkblxxlxqq5a
439 obmen.i2p vodkv54jaetjw7q2t2iethc4cbi4gjdrmw2ovfmr43mcybt7ekxa
440 obscuratus.i2p i4j37hcmfssokfb6w3npup77v6v4awdxzxa65ranu34urjs4cota
441 ogg.aum.i2p wchgsx6d6p3czloeqvna2db5jr7odw4v4kqrn4gr4qiipfyrbh5q
442 ogg.baffled.i2p tfbvj2xal6lcuxv3hzuw7cw4g3whguombcv2zuotzvul4qtrimgq
443 ol.i2p bnb46culzbssz6aipcjkuytanflz6dtndyhmlaxn3pfiv6zqrohq
444 onboard.i2p qwlgxrmv62mhdu6bgkh4ufnxowxsatfb6tbs2zr666qyunwqnecq
445 onelon.i2p irkvgdnlc6tidoqomre4qr7q4w4qcjfyvbovatgyolk6d4uvcyha
446 onhere.i2p vwjowg5exhxxsmt4uhjeumuecf5tvticndq2qilfnhzrdumcnuva
447 oniichan.i2p nnkikjorplul4dlytwfovkne66lwo7ln26xzuq33isvixw3wu3yq
448 onionforum.i2p yadam2bp6hccgy7uvcigf5cabknovj5hrplcqxnufcu4ey33pu5q
449 ooo.i2p iqp5wt326fyai5jajsa3vkkk5uk56ofn4anocgpe5iwlpisq6l7a
450 opal.i2p li5kue3hfaqhhvaoxiw2ollhhkw765myhwcijgock5rs4erdqdaa
451 open4you.i2p ice6ax5qrzwfwzsy64bctffj6zlzpuzdr5np65zsxlbt7hztyc6a
452 opendiftracker.i2p bikpeyxci4zuyy36eau5ycw665dplun4yxamn7vmsastejdqtfoq
453 openforums.i2p lho7cvuuzddql24utu7x6mzfsdmxqq7virxp5bcqsxzry2vmwj5q
454 opentracker.dg2.i2p w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa
455 orion.i2p 5vntdqqckjex274sma3uqckwqep2czxs5zew25zlntwoofxk3sga
456 orz.i2p oxomqkekybmyk6befjlouesit5mhstonzvzd2xnvsk7i6uyrqsfq
457 os3.i2p s7x4ww5osrrfein3xgwyq67wnk6lgliw4mzt7shtu66wrb2zdojq
458 osiristomb.i2p t3slf77axkv3qm7c3gzpv3jgmkraoqqe2bojr6h66eipibofsyzq
459 ot.knotwork.i2p cxhvvfkbp2qbv5qojph7zb46molpe2ffanghnerjag3xdmy6ltxq
460 outproxy-tor.meeh.i2p 77igjr2pbg73ox5ngqy5ohzvrnur3ezqcogtl4vpuqtrcl3irsqq
461 outproxy.h2ik.i2p nwgvfpfarpnyjjl4pwsxr2zdsppcx5we3kos2vlwicbiukopgaza
462 outproxyng.h2ik.i2p v32zse2zczzgegelwxbx7n5i2lm2xhh2avltg76h6fz5tb53sfxq
463 overchan.oniichan.i2p g7c54d4b7yva4ktpbaabqeu2yx6axalh4gevb44afpbwm23xuuya
464 p4bl0.i2p lkgdfm4w6e2kkjhcdzr4ahhz26s3aunhrn6t2or436o73qh4z7ga
465 pants.i2p xez3clscjfafkqwk6f473ccp3yvac4kh6rdp6dptwxa2lhixizgq
466 papel.i2p mxskjqntn2d34q4ovsnd5mud7cgde734tdjldd3lt4hczh2645zq
467 pasta-nojs.i2p dkkl3ab6iovxfqnp44wsjgqaabznvu7u3hugpzyagbeqlxgvx3la
468 paste.crypthost.i2p 2zaj4u4s4l3lgas2h5p6c6pvzr2dckylkrh5ngabursj4oh25ozq
469 paste.i2p2.i2p b2gizskfea4sjxlw6ru2tb6kdrj47dsjc77cijsf5mzh4ogbmfvq
470 paste.r4sas.i2p csen43keji3qiw6uobsgzysxyjd225g6446ylq5uuz6ur2glkzaa
471 pastebin.i2p mnicncxrg2qqi55qftigiitaheugnj4rpysbk7zabdrirgktelqa
472 pastethis.i2p erkqiwnjl7vtysqd3wvddv6tfvnhswarqkbn4blhdlhfxn7cf2ha
473 pdforge.i2p wzeg3ehf6d2mqjqji3sd3rns776thvhe2vam2r6gjlmsqis2dctq
474 perv.i2p f3k3wm4ae7t7ottfjd4hu6is7zsls73izl2gm2qynzficxcdsiwq
475 pgp.duck.i2p wujajyxj3cgsfsbtr3g7g7npv5ft3de6pcstxlav26zq6cxdjmha
476 pharos.i2p vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
477 pharoz.i2p vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
478 phonebooth.i2p noxia7rv6uvamoy2fkcgyj4ssjpdt4io6lzgx6jl6wujpufxedrq
479 photo.i2p fqhuy77ugd5htnubzkyy5guvwboqn6goahtmn2g7feewvdj7k3iq
480 piespy.i2p vzusfjzcu5ntnvobcvyzc4dcu4j6ommtnpmba2puk3kexgdzrl7a
481 pisekot.i2p 7yzdwhy723fodqz4onp6k3nyvixra2sa6dl45tcblhmyoa7i36nq
482 pizdabol.i2p 5vik2232yfwyltuwzq7ht2yocla46q76ioacin2bfofgy63hz6wa
483 planet.i2p y45f23mb2apgywmftrjmfg35oynzfwjed7rxs2mh76pbdeh4fatq
484 plugins.i2p wwgtflbaa7od2fxbw4u7q7uugmdclxf56alddvizugwcz5edjgia
485 polecat.i2p het5jrdn35nhkanxmom5mjyggyvmn2wdj2agyqlrv4mhzhtmavwq
486 politguy.i2p 6dkkh3wnlwlr6k7wnlp4dbtf7pebjrph5afra2vqgfjnbihdglkq
487 pomoyka.i2p omt56v4jxa4hurbwk44vqbbcwn3eavuynyc24c25cy7grucjh24q
488 pool.gostcoin.i2p m4f4k3eeaj7otbc254ccj7d5hivguqgnohwelkibr4ddk43qhywa
489 pop.mail.i2p bup6pmac7adgzkb5r6eknk2juczkxigolkwqkbmenawkes5s5qfq
490 pop.postman.i2p ipkiowj7x4yjj7jc35yay3c6gauynkkl64gzzyxra3wmyhtfxlya
491 pravtor.i2p 2sr27o5x2v2pyqro7wl5nl6krrsbizwrzsky5y7pkohwh24gn6xq
492 pris.i2p ahiwycgzuutdxvfqu3wseqffdnhy675nes57s4it2uysy5pxmz6a
493 project-future.i2p ivqynpfwxzl746gxf376lxqvgktql2lqshzwnwjk2twut6xq7xta
494 projectmayhem2012-086.i2p ehkjj4ptsagxlo27wpv4a5dk4zxqf4kg4p6fh35xrlz4y6mhe4eq
495 protokol.i2p f4xre35ehc5l6ianjvt3zcktxkjlyp2iwdje65qnu2j6vurhy6nq
496 proxynet.i2p 7gar5a3n4hzvsgi73iizo65mjza4kujf7feopfxuwu5p6wtwog5a
497 psi.i2p avviiexdngd32ccoy4kuckvc3mkf53ycvzbz6vz75vzhv4tbpk5a
498 psy.i2p s3elzoj3wo6v6wqu5ehd56vevpz2vrhhjc5m6mxoazicrl43y62q
499 psyco.i2p eoilbrgyaiikxzdtmk2zeoalteupjrvcu3ui23p4wvfqo25bb73q
500 pt.hiddenanswers.i2p o5jlxbbnx3byzgmihqye3kysop5jgl3unsrkmurbtr2nrnl2y74a
501 ptm.i2p 7dna5745ynxgogpjermnq26hwrqyjdlsibpjfmjxlwig247bjisa
502 ptt.i2p q7r32j7lc3xgrcw2ym33wv4lfgqbez7vtm4lts7n34qfe3iygeha
503 pull.git.repo.i2p 3so7htzxzz6h46qvjm3fbd735zl3lrblerlj2xxybhobublcv67q
504 push.git.repo.i2p jef4g5vxnqybm4zpouum3lzbl6ti6456q57nbyj5kfyldkempm3a
505 pycache.awup.i2p w45lkxdnqhil4sgzanmxce62sv3q4szeowcjb2e72a5y5vbhm4ra
506 r4sas.i2p 2gafixvoztrndawkmhfxamci5lgd3urwnilxqmlo6ittu552cndq
507 radio.r4sas.i2p cv72xsje5ihg6e24atitmhyk2cbml6eggi6b6fjfh2vgw62gdpla
508 ragnarok.i2p jpzw6kbuzz3ll2mfi3emcaan4gidyt7ysdhu62r5k5xawrva7kca
509 ransack.i2p mqamk4cfykdvhw5kjez2gnvse56gmnqxn7vkvvbuor4k4j2lbbnq
510 rasputin-sucks.i2p fdozdbyak4rul4jwpqfisbkcx4xbrkuvf2o5r6fd3xryyrjgvjiq
511 rebel.i2p nch2arl45crkyk6bklyk2hrdwjf5nztyxdtoshy6llhwqgxho5jq
512 red.i2p fzbdltgsg7jrpz7gmjfvhpcdnw5yrglwspnxqp4zoym3bglntzfa
513 redpanda.i2p 3wcnp6afz4cikqzdu2ktb5wfz7hb3ejdbpn7ocpy7fmeqyzbaiea
514 redzara.i2p ty7bt62rw5ryvk44dd3v5sua6c7wnbpxxqb6v4dohajmwmezi7va
515 reefer.i2p 4cde25mrrnt5n4nvp5tl62gej33nekfvq2viubmx4xdakhm5pfaa
516 relatelist.i2p utrer5zgnou72hs4eztmk37pmzdtfw3d6s23wwl7nk3lkqpzbdiq
517 repo.i2p uxe3lqueuuyklel23sf5h25zwgqgjwsofrqchhnptd5y6pedzbxa
518 repo.r4sas.i2p ymzx5zgt6qzdg6nhxnecdgbqjd34ery6mpqolnbyo5kcwxadnodq
519 reseed.i2p j7xszhsjy7orrnbdys7yykrssv5imkn4eid7n5ikcnxuhpaaw6cq
520 retrobbs-nntp.i2p fkyzl24oxcxvjzkx74t3533x7qjketzmvzk6bwn3d6hj5t7hlw6q
521 retrobbs.i2p mnn77stihntxdoade3ca2vcf456w6vhhvdsfepdvq5qggikvprxq
522 retrobbs2.i2p ejff7jtyaus37slkwgeqrrcmyhpj26carp7n27f5h6s5vlbeiy6q
523 revo-ua.i2p hpojpumki22xjwhmhe6zkiy44oanyn7u4ctcfe3in2ibwm5l32hq
524 riaa.i2p lfbezn7amkzhswnx7lb4lxihyggl2kuqo5c7vwkcv6bwqmr4cuoa
525 rideronthestorm.i2p xrdc2qc7quhumhglpbcuiqxr42nuffv4xj4a73jbr4ygepitibqq
526 romster.i2p eaf2stdqdbepylt53egvixdi34g2usvgi7a4oixsja6atkran43a
527 rootd.i2p mzbe5wofwn7eaqq4yefrmxizqaxoslwqxrv5qcv2opx5lnhg64dq
528 rospravosudie.i2p z55khrnlj6bzhs5zielutm6ae6t2bbhfuiujwlrp3teubqyc4w7q
529 rotten.i2p j4bm3rvezlejnb44elniagi5v2gazh7jaqrzhbod2pbxmgeb2frq
530 rpi.i2p 56p5qxsrvo5ereibevetw2qbj5bronmos7wxunku27g2s4kpbnlq
531 rslight.i2p bitag46q3465nylvzuikfwjcj7ewi4gjkjtvuxhn73f6vsxffyiq
532 rsync.thetower.i2p w4brpcdod7wnfqhwqrxyt4sbf2acouqfk5wyosfpq4mxq4s35kqa
533 ru.hiddenanswers.i2p o6rmndvggfwnuvxwyq54y667fmmurgveerlzufyrhub6w3vkagva
534 ru.i2p m7fqktjgtmsb3x7bvfrdx4tf7htnhytnz5qi2ujjcnph33u3hnja
535 rufurus.i2p 7msryymfdta3ssyz34qur6gi4jyfkvca5iyfmnceviipwu7g2wca
536 rus.i2p gh6655arkncnbrzq5tmq4xpn36734d4tdza6flbw5xppye2dt6ga
537 ruslibgen.i2p kk566cv37hivbjafiij5ryoui2ebxnm7b25gb3troniixopaj6nq
538 rutor.i2p tro5tvvtd2qg34naxhvqp4236it36jjaipbda5vnjmggp55navdq
539 salt.i2p 6aflphlze6btsbez5cm4x53ydrmwhqrkxsud535d3qjh4wq62rxq
540 sasquotch.i2p p6535uyfk2y6etc3t47vd3oqxydznqior5jxcvq5bdxe5kw5th6q
541 schwarzwald.i2p 4gokilzy73mmudufy3pohgatm42fcstx7uzg5hjvnfyphxpnphuq
542 sciencebooks.i2p ypftjpgck75swz3bnsu4nw7rmrlr2vqsn4mwivwt3zcc3rxln5cq
543 scp.duck.i2p ghbpsolpnveizxu4wbs7jbs2vj3kntnsexfcdleyhpqdhfpxleda
544 search.i2p nz4qj6xaw5fda3rsmsax6yjthqy4c7uak2j3dzcehtkgyso4q46q
545 secretchat.i2p cl3j2zxhpw6u6jevny45i557ojhwfxn4g375nnuqhy6lp27mry2q
546 secure.thetinhat.i2p 4q3qyzgz3ub5npbmt3vqqege5lg4zy62rhbgage4lpvnujwfpala
547 seeker.i2p ipll7sit24oyhnwawpvokz5u7dabq6klveuqpx3sbi6o5qemy2bq
548 seomon.i2p 5mvpsy4h45w4fx7upen7ay3vkrs5klphz5nptmtcqvc3fsajsm4q
549 septu.i2p 5lqvih7yzbqacfi63hwnmih57dxopu5g2o5o4e2aorq7bt4ooyra
550 serien.i2p 3z5k3anbbk32thinvwcy4g5al7dmb75fagcm3zgh4rzrt3maphda
551 ses.i2p 5qfoz6qfgbo7z5sdi26naxstpi2xiltamkcdbhmj6y6q2bo4inja
552 shiftfox.i2p wpvnuzslu7hjy4gujvnphtyckchdoxccrlhbyomsmjizykczyseq
553 shoieq3.i2p 3fjk4nfk3mccch4hdreghnyijcvovsi3yucjz3qzj5sxngqk5j6q
554 shoronil.i2p 7shqzgmb6tabiwrnwlasruq7pswy2d3emvfhaitehkqgod7i62sa
555 short.i2p z5mt5rvnanlex6r3x3jnjhzzfqpv36r4ylesynigytegjmebauba
556 sion.i2p lcbmmw2tvplvqh2dq5lmpxl3vnd5o4j3bdul5moa23deakjrso5q
557 sirup.i2p aohdp4yajnkitrtw7v2mo3sp7swuqhjfwlsi5xwd7dudzftumsma
558 site.games.i2p zeuczucfxeev3k7tvqlfcdpfbnqggheiknyyb5r2q4utn3d2auja
559 skank.i2p qiii4iqrj3fwv4ucaji2oykcvsob75jviycv3ghw7dhzxg2kq53q
560 slack.i2p gfcsh2yrb2tx7hyvmobriv52skz7qoobn7n7y7n6xaehhh4rpbja
561 slacker.i2p wq7m2wdguzweleb666ygv3bmfhha63zj74rub76vfesbyhsyk6iq
562 smeghead.i2p ojf4czveeuekxqkjvkszvv7eiop5dg7x2p6rgfzl4ng4xrjk6lja
563 smtp.mail.i2p kdn7zx7fgoe4bn5abaaj5cb3e4ql22fklb5veui5yajpj4cxapya
564 smtp.postman.i2p jj7pt6chsziz6oxxnzpqj7mzhxm2xfhcrbh7dl3tegifb577vx5q
565 socks1.tor.i2p sifawcdexgdmoc3krv46pvvz74nzd6fkju2vzykjxsx3egqsb6wq
566 sonax.i2p jmuxdhlok5ggojehesfjlit2e2q3fhzwwfxjndts7vzdshucbjjq
567 sponge.i2p o5hu7phy7udffuhts6w5wn5mw3sepwe3hyvw6kthti33wa2xn5tq
568 squid.i2p r4ll5zkbokgxlttqc2lrojvvey5yar4xr5prnndvnmggnqzjaeoq
569 squid2.i2p hum4wlwizbsckbudcklflei66qxhpxsdkyo4l2rn256smmjleila
570 sqz.i2p 3jvbwc7sy4lnhj25nj7yepx7omli4ulqirnawv3mz6qlhgokjgzq
571 ssh.i2p xpvdadaouc4qr75pteymyozc7mcsynjfkuqqkkla542lpcsqionq
572 stasher.i2p 6ilgpudnba4kroleunc2weh5txgoxys5yucij5gla6pjyki4oewa
573 stats.i2p 7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq
574 status.str4d.i2p ycyyjo3psqbo45nuz243xvgvwnmzlanzqbzxv3kh6gyjztv7425q
575 sto-man.i2p rg4eilfpe24ws6nctix63qw2dlvd2tqgwdcgdxzji6l5bc4dc7aa
576 str4d.i2p wrrwzdgsppwl2g2bdohhajz3dh45ui6u3y7yuop5ivvfzxtwnipa
577 stream.i2p prmbv3xm63ksoetnhbzqg4nzu2lhqdnqytgsydb7u3quxfrg7rna
578 streams.darkrealm.i2p ud3gcmvysjch4lbjr2khmhqpf7r2x5if4q43xkqdptl4k7lc4muq
579 striker.i2p 4gswsrfpbd44hwjoj33jbqfbwzxfkwpuplb3ydq5zm7nfu2pxvdq
580 subrosa.i2p g3lnglrnoual7wyabnwwv37uwhadgbxiqz36pf3f5cwfuxsx4mxq
581 subterra.i2p vdmhe4u26unzgd7ysq6w36ubjncms5wzbhzr2gq576sq4xut5zwq
582 sugadude.i2p yzjn76iyqard64wgggfrnywkxi7tbfkw7mjhpviqz3p2dguey4yq
583 suicidal.i2p yfamynllow5xiqbbca7eh5xn733wtnuti5bi4ovc7dwycntqmiuq
584 sungo.i2p h67s3jw56rwfyoxqxj3fngrluybsgxc2meendngkehzqowxnpj3q
585 surrender.adab.i2p jgz7xglgfgnjfklrytyn427np2ubipztlm5bxrtbiucayglukrta
586 susi.i2p qc6g2qfi2ccw7vjwpst6rwuofgzbeoewsb2usv7rubutf4gzqveq
587 syncline.i2p 5kcqmhislu3lmr7llgmdl72yu3efhyriljdc6wp774ftpwlcs5ra
588 syndie-project.i2p xa63tpfoaqt3zru2ehxjjfbpadwj4ha6qsdvtcqtyr3b7hmt4iaq
589 syndie.echelon.i2p vwrl2qmcif722fdkn3ldxcgz76df5cq4qypbndzthxwgmykyewta
590 syndie.i2p 7lm3yzpuejhpl4tt4l7o4ndqlu7hgijohofh7oaydx7q7kelenbq
591 syndiemedia.i2p 4lrbbblclodhobn3jadt5bf2yab2pxzoz4ey4a2cvrl44tdv3jma
592 tabak.i2p y5o2vwb6kart7ivpnbpk4yte3i7kf2dsx7fy3i6w7htqtxhmbzia
593 tahoeserve.i2p yhs7tsjeznxdenmdho5gjmk755wtredfzipb5t272oi5otipfkoa
594 tc.i2p qkv2yk6rof3rh7n3eelg5niujae6cmdzcpqbv3wsttedxtqqqj7a
595 telegram.i2p i6jow7hymogz2s42xq62gqgej2zdm4xtnmpc6vjcwktdxpdoupja
596 templar.i2p zxeralsujowfpyi2ynyjooxy222pzz4apc2qcwrfx5ikhf64et7q
597 terror.i2p wsijm6aqz4qtuyn2jedpx6imar5uq4yuhjdgtfqumxbqww47vbnq
598 thebland.i2p oiviukgwapzxsrwxsoucpqa47s3wt6nfuhfjxvgbqsyrze2mwrda
599 thebreton.i2p woutbsflcrlgppx4y7ag2kawlqijyenvlwrhbbvbkoaksuhf2hkq
600 thedarkside.i2p fxt3z33nzkrg5kjrk7bp5vvmu7w2vsn4i6jo6cily3hsm6u664ca
601 theland.i2p 26ppxbseda6xmim37ksarccdb4q5ctdagfmt2u5aba6xjh452zsa
602 thetower.i2p 3xqa5nype64y6fxgqjq6r5w2qpiqftoraj2niebumseat4cj654a
603 thornworld.i2p vinz4ygmodxarocntyjlfwk2wjpvzndlf4hxss2w2t3fk52oplva
604 tino.i2p e4bfnhvaofu4s67ztcgiskos2mqyhskid64dvlqexxs2c2bno3iq
605 tinyurl.i2p mc4oxv3v7dnyzpvok7v5qxkwtgjprgyz6w7x3tag4fipsen6rdwa
606 tome.i2p qktkxwawgixrm5lzofnj5n24zspbnzxy4pvjm7uvaxvmgwrsuvgq
607 tor-gw.meeh.i2p ounrqi7cfemnt66yhnhigt2u27fkctbvct527cp2522ozy3btjza
608 tor-www-proxy.i2p xov45rvjks5fe4ofmpblkj23bnwxgslbypbgvchbr7yul2ujej2q
609 torapa.i2p eejqjtpko6mdd4opvntbpsuandstrebxpbymfhix7avp5obrw5ta
610 torrentfinder.i2p mpc73okj7wq2xl6clofl64cn6v7vrvhpmi6d524nrsvbeuvjxalq
611 torrfreedom.i2p nfrjvknwcw47itotkzmk6mdlxmxfxsxhbhlr5ozhlsuavcogv4hq
612 trac.i2p kyioa2lgdi2za2fwfwajnb3ljz6zwlx7yzjdpnxnch5uw3iqn6ca
613 trac.i2p2.i2p i43xzkihpdq34f2jlmtgiyyay5quafg5rebog7tk7xil2c6kbyoa
614 tracker-fr.i2p qfrvqrfoqkistgzo2oxpfduz4ktkhtqopleozs3emblmm36fepea
615 tracker.awup.i2p dl47cno335ltvqm6noi5zcij5hpvbj7vjkzuofu262efvu6yp6cq
616 tracker.crypthost.i2p ri5a27ioqd4vkik72fawbcryglkmwyy4726uu5j3eg6zqh2jswfq
617 tracker.fr.i2p rzwqr7pfibq5wlcq4a7akm6ohfyhz7hchmy4wz5t55lhd7dwao5q
618 tracker.i2p lsjcplya2b4hhmezz2jy5gqh6zlk3nskisjkhhwapy3jjly4ds5q
619 tracker.lodikon.i2p q2a7tqlyddbyhxhtuia4bmtqpohpp266wsnrkm6cgoahdqrjo3ra
620 tracker.mastertracker.i2p tiwurhqvaaguwpz2shdahqmcfze5ejre52ed2rmoadnjkkilskda
621 tracker.postman.i2p jfcylf4j3gfmqogkltwy7v5m47wp4h7ffrnfsva6grfdavdn7ueq
622 tracker.psi.i2p vmow3h54yljn7zvzbqepdddt5fmygijujycod2q6yznpy2rrzuwa
623 tracker.thebland.i2p s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq
624 tracker.welterde.i2p cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa
625 tracker2.postman.i2p ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna
626 traditio.i2p wkpjjloylf6jopu2itgpktr45t2xvpjijxilxd5tq4i7wkqgwhhq
627 trevorreznik.i2p wc2z6o5fxm2saqzpfcawr63lejwccvzkysmgtfudkrigqopzfdma
628 true.i2p pdilhl5vmefyzrrnmak5bnmxqxk2pmw7rpy4f7wbaeppqu2vvugq
629 trwcln.i2p evml6jiiujhulsgxkdu3wcmkwbokxlv4is6w5qj46tp3ajz3hqzq
630 trypanom.i2p tgv5acj4khwvr6t44cmryohybd2e5o2kndysnzae6qwcr4hzda3q
631 ts.i2p nebcjgfx3f7q4wzihqmguwcdeopaf7f6wyk2dojw4bcuku472zxq
632 ttc.i2p wb4tsfyvfv4idgrultsq6o7inza4fxkc7dijsfpncbx7zko4cdlq
633 ttp.i2p uuczclxejmetohwf2vqewovx3qcumdfh5zecjb3xkcdmk6e5j72a
634 tumbach.i2p u6pciacxnpbsq7nwc3tgutywochfd6aysgayijr7jxzoysgxklvq
635 tutorials.i2p zy37tq6ynucp3ufoyeegswqjaeofmj57cpm5ecd7nbanh2h6f2ja
636 ugha.i2p z3f3owc72awbywk4p6qb5l2mxgitvs6ejztggbpn2a3ddmymfjda
637 uk.i2p vydbychnep3mzkzhg43ptewp242issy47whamfbxodc4ma6wc63a
638 underground.i2p dlnuthb6tpw3kchlb7xoztyspy4ehlggjhl44l64vbcrulrfeica
639 underscore.i2p 3gmezyig6gvsjbpkq2kihoskpuqpkfrajmhhm7hpyrjuvtasgepa
640 unqueued.i2p 3gvn4kwd7z74jxc2sn4ucx52dpvpscxbzjluux3ul4t3eu5g64xq
641 up.i2p 25it5olgdo7pht25z6buzd32sw7jvc65oziqeuocfozfhgua655q
642 update.dg.i2p iqj6ysfh3wl26m4buvyna73yhduifv523l7bwuexxak4mgldexja
643 update.killyourtv.i2p gqdfg25jlqtm35qnmt4b7r53d6u2vep4ob23fwd42iyy4j6cvdqq
644 update.postman.i2p u5rbu6yohfafplp6lgbbmmcuip34s7g3zqdd63cp27dl3nbd7gtq
645 utansans.i2p u2oyre7ygqv4qs5xjjijfg3x7ddwtod6nqwgbomuuzljzvnq4rda
646 v2mail.i2p 4gg7fykcqe7oaqt4w5fmlarnia7vtmwkv3h45zzgoj6o6crryg5a
647 vadino.i2p aalttzlt3z25ktokesceweabm5yyhhvml2z3rfotndgpfyh6myra
648 visibility.i2p pwgma3snbsgkddxgb54mrxxkt3l4jzchrtp52vxmw7rbkjygylxq
649 volatile.i2p q6rve733tvhgyys57jfw4fymqf3xsnza6dqailcdjcq7w4fa5m3a
650 vpnbest.i2p ov5f74ndsy5rfkuyps56waf42vxncufqu5rzm3vsnxkdtogccaea
651 vudu.i2p 3zlwci7pvgep2igygzyjej24ue7mjsktlhaff6crpsr75yquak2q
652 w.i2p j2xorlcb3qxubnthzqu7lt4fvxqn63it4ikwmze55yjkzeeampuq
653 wa11ed.city.i2p 7mxwtmala3ycg2sybjwwfil7s6dqck2fbemeutghhwu73rznmqoa
654 wahoo.i2p vqe5vkpe5wbda7lwekcd2jaj44ar3rawgv54u5rcolezbg5f5vwa
655 wallet.gostcoin.i2p reuvum7lgetglafn72chypesvto773oy53zumagrpigkckybrwda
656 wallsgetbombed.i2p tzhea5d65fllm4263wztghgw4ijdgibsca5xsecp6lk4xlsbdeuq
657 web.telegram.i2p re6cgwg2yrkgaixlqvt5ufajbb3w42fsldlq7k5brpvnd5gp6x5a
658 wiht.i2p yojmpj3sh76g3i6ogzgsf7eouipdgdij5o2blcpdgmu5oyjk5xca
659 wiki.fr.i2p lrqa7hw52uxjb5q3pedmjs6hzos5zrod4y6a4e25hu7vcjhohvxq
660 wiki.ilita.i2p r233yskmowqe4od4he4b37wydr5fqzvj3z77v5fdei2etp2kg34a
661 wintermute.i2p 4gvlfrdy2rkmem33c342tjntpvqik65wekcvm4275qbkuwotoila
662 wspucktracker.i2p ubd2txda3kllumx7ftg4unzgqy536cn6dd2ax6mlhodczfas7rgq
663 www.aum.i2p 3xolizygkzkqrldncjqsb734szznw2u36lliceuacqnbs2n65aeq
664 www.baffled.i2p lqrsfslwu4xnubkk2hofhmuvvr4dia2zevxefinbzdsjurvehtqq
665 www.fr.i2p rmkgvlfwo3vkb3xrr6epoypxasdzzuilv3sckcqbo6c4os5jo2ea
666 www.i2p ojxyenivrrqvycgbxbm3phgisu5abspzq4g2us4fjlwz4tx222va
667 www.i2p2.i2p rjxwbsw4zjhv4zsplma6jmf5nr24e4ymvvbycd3swgiinbvg7oga
668 www.imule.i2p 657xcllunctawyjtar5kgh3wpt6z4l7ba6mmam5rf7hev5w2lsvq
669 www.infoserver.i2p fq7xhxkdcauhwn4loufcadiiy24zbei25elnup33a3gfrdzrtlyq
670 www.janonymous.i2p vosqx5qw22hwrzcgsm4ib7hymf5ryovsbtaexqrzmnzshy5bhakq
671 www.mail.i2p nctas6ioo7aaekfstv3o45yh6ywzwa3vznrdae52ouupzke5pyba
672 www.nntp.i2p kly3o7zmetuwyz7xonnhttw4lj2244pkbibjz26uflyfte3b3dka
673 www.postman.i2p rb3srw2gaooyw63q62cp4udrxxa6molr2irbkgrloveylpkkblhq
674 www.syndie.i2p vojgy5ep4wffmtpjmpnbpa4gq64bgn4yicuw6qmhbm6nqa2ysrva
675 www1.squid.i2p vbh3bltd2duwbukafgj6f6vfi6aigwso7snucp5zohnf66a2hkpa
676 xc.i2p mt45a2z3sb2iyy2mwauj4rwa2lwu4peanfy6gx6ybidwnbasusyq
677 xeha.i2p oartgetziabrdemxctowp7bbeggc7ktmj7tr4qgk5y5jcz4prbtq
678 xilog.i2p eoc5i5q52hutnmsmq56edvooulutaxfikddgdz27otmgtsxmiloq
679 xmpp.crypthost.i2p ittkqpjuliwsdewdugkhvgzstejr2jp5tzou7p332lxx4xw7srba
680 xmpp.rpi.i2p 3yv65pfwiwfuv4ciwtx34clqps6o2mc3vtyltcbqdkcki6untbca
681 xn--l2bl5aw.i2p d2epikjh5crt2l5xjmtceqw2ho44hzp6x3u7hgjrd4mi4wywikwa
682 xolotl.i2p rwr6rrlmrotxfkxt22mah42cycliy2g5k7hgxyxkpcyyxkd2bgwq
683 xotc.i2p gqgvzum3xdgtaahkjfw3layb33vjrucmw5btyhrppm463cz3c5oq
684 z-lab.i2p s6g2pz3mrwzsl4ts65ox3scqawfj7mzvd7hn2ekiiycawopkriba
685 zab.i2p n4xen5sohufgjhv327ex4qra77f4tpqohlcyoa3atoboknzqazeq
686 zcash.i2p zcashmliuw3yd2ptfyd5sadatcpyxj4ldiqahtjzg73cgoevxp4q
687 zener.i2p mcbyglflte3dhwhqyafsfpnqtcapqkv2sepqd62wzd7fo2dzz4ca
688 zerobin.i2p 3564erslxzaoucqasxsjerk4jz2xril7j2cbzd4p7flpb4ut67hq
689 zeroman.i2p gq77fmto535koofcd53f6yzcc5y57ccrxg3pb6twhcodc7v5dutq
690 zeronet.i2p fe6pk5sibhkr64veqxkfochdfptehyxrrbs3edwjs5ckjbjn4bna
691 znc.i2p uw2yt6njjl676fupd72hiezwmd4ouuywowrph6fvhkzhlnvp7jwa
692 znc.str4d.i2p ufkajv3stxpxlwgwwb2ae6oixdjircnbwog77qxpxv7nt67rpcxq
693 zzz.i2p ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq

View File

@ -4,6 +4,7 @@
#logfile = /sdcard/i2pd/i2pd.log
loglevel = none
#tunnelsdir = /sdcard/i2pd/tunnels.d
# host = 1.2.3.4
# port = 4567
@ -36,7 +37,12 @@ port = 7070
enabled = true
address = 127.0.0.1
port = 4444
# keys = http-proxy-keys.dat
inbound.length = 1
inbound.quantity = 5
outbound.length = 1
outbound.quantity = 5
signaturetype=7
keys = proxy-keys.dat
# addresshelper = true
# outproxy = http://false.i2p
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
@ -45,7 +51,7 @@ port = 4444
enabled = true
address = 127.0.0.1
port = 4447
# keys = socks-proxy-keys.dat
keys = proxy-keys.dat
# outproxy.enabled = false
# outproxy = 127.0.0.1
# outproxyport = 9050
@ -79,3 +85,6 @@ verify = true
[limits]
transittunnels = 50
[persist]
profiles = false

1
android/assets/tunnels.d Symbolic link
View File

@ -0,0 +1 @@
../../contrib/tunnels.d

View File

@ -2,9 +2,10 @@ buildscript {
repositories {
mavenCentral()
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.android.tools.build:gradle:3.4.2'
}
}
@ -15,28 +16,32 @@ repositories {
maven {
url 'https://maven.google.com'
}
google()
}
dependencies {
compile 'com.android.support:support-compat:28.0.0'
implementation 'androidx.core:core:1.0.2'
}
android {
compileSdkVersion 28
buildToolsVersion "28.0.1"
compileSdkVersion 29
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "org.purplei2p.i2pd"
targetSdkVersion 28
targetSdkVersion 29
minSdkVersion 14
versionCode 1
versionName "2.21.1"
versionCode 2310
versionName "2.31.0"
setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
ndk {
abiFilters 'armeabi-v7a'
abiFilters 'x86'
//abiFilters 'arm64-v8a'
//abiFilters 'x86_64'
}
externalNativeBuild {
ndkBuild {
arguments "-j4"
arguments "-j3"
}
}
}
@ -49,6 +54,16 @@ android {
assets.srcDirs = ['assets']
}
}
splits {
abi {
// change that to true if you need splitted apk
enable true
reset()
//include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
include "armeabi-v7a", "x86"
universalApk true
}
}
signingConfigs {
orignal {
storeFile file("i2pdapk.jks")
@ -59,7 +74,7 @@ android {
}
buildTypes {
release {
minifyEnabled true
minifyEnabled false
signingConfig signingConfigs.orignal
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
@ -69,6 +84,21 @@ android {
path './jni/Android.mk'
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
}
ext.abiCodes = ['armeabi-v7a':1, 'x86':2, 'arm64-v8a':3, 'x86_64':4]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
if (baseAbiVersionCode != null) {
output.versionCodeOverride = baseAbiVersionCode + variant.versionCode
}
}
}

View File

@ -1 +1,3 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.parallel=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Tue Aug 20 14:39:08 MSK 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

172
android/gradlew vendored Executable file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -25,43 +25,43 @@ include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_system
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_date_time
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_filesystem
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_program_options
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
LOCAL_STATIC_LIBRARIES := crypto
include $(PREBUILT_STATIC_LIBRARY)

View File

@ -1,28 +1,23 @@
#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
#APP_ABI := armeabi-v7a x86
#APP_PLATFORM := android-14
# http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
NDK_TOOLCHAIN_VERSION := 4.9
# APP_STL := stlport_shared --> does not seem to contain C++11 features
APP_STL := gnustl_shared
# ABI arm64-v8a and x86_64 supported only from platform-21
#APP_ABI := arm64-v8a x86_64
#APP_PLATFORM := android-21
# Enable c++11 extensions in source code
APP_CPPFLAGS += -std=c++11
NDK_TOOLCHAIN_VERSION := clang
#APP_STL := c++_shared
APP_STL := c++_static
# Enable c++17 extensions in source code
APP_CPPFLAGS += -std=c++17 -fexceptions -frtti
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_CPPFLAGS += -DANDROID_ARM7A
endif
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
#APP_OPTIM := debug
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/android-ifaddrs.git

View File

@ -39,7 +39,7 @@ namespace android
emit resultReady();
}
Controller::Controller(DaemonAndroidImpl& daemon):
Controller::Controller(DaemonAndroidImpl& daemon):
m_Daemon (daemon)
{
Worker *worker = new Worker (m_Daemon);
@ -57,19 +57,21 @@ namespace android
workerThread.quit();
workerThread.wait();
Log.d(TAG"Waiting for daemon worker thread finished.");
if(m_Daemon.isRunning())
{
Log.d(TAG"Stopping the daemon...");
m_Daemon.stop();
Log.d(TAG"Stopped the daemon.");
if(m_Daemon.isRunning())
{
Log.d(TAG"Stopping the daemon...");
m_Daemon.stop();
Log.d(TAG"Stopped the daemon.");
}
}
*/
std::string dataDir = "";
DaemonAndroidImpl::DaemonAndroidImpl ()
//:
/*mutex(nullptr), */
//m_IsRunning(false),
//m_RunningChangedCallback(nullptr)
/*mutex(nullptr), */
//m_IsRunning(false),
//m_RunningChangedCallback(nullptr)
{
}
@ -82,10 +84,10 @@ namespace android
{
//mutex=new QMutex(QMutex::Recursive);
//setRunningCallback(0);
//m_IsRunning=false;
// make sure assets are ready before proceed
i2p::fs::DetectDataDir("", false);
//m_IsRunning=false;
// make sure assets are ready before proceed
i2p::fs::DetectDataDir(dataDir, false);
int numAttempts = 0;
do
{
@ -93,7 +95,7 @@ namespace android
numAttempts++;
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
}
while (numAttempts <= 10); // 10 seconds max
while (numAttempts <= 10); // 10 seconds max
return Daemon.init(argc,argv);
}
@ -125,16 +127,16 @@ namespace android
bool DaemonAndroidImpl::isRunning()
{
return m_IsRunning;
return m_IsRunning;
}
void DaemonAndroidImpl::setRunning(bool newValue)
{
bool oldValue = m_IsRunning;
bool oldValue = m_IsRunning;
if(oldValue!=newValue)
{
m_IsRunning = newValue;
if(m_RunningChangedCallback)
m_IsRunning = newValue;
if(m_RunningChangedCallback)
m_RunningChangedCallback();
}
}
@ -183,14 +185,14 @@ namespace android
catch (boost::exception& ex)
{
std::stringstream ss;
ss << boost::diagnostic_information(ex);
return ss.str();
ss << boost::diagnostic_information(ex);
return ss.str();
}
catch (std::exception& ex)
{
std::stringstream ss;
ss << ex.what();
return ss.str();
ss << ex.what();
return ss.str();
}
catch(...)
{
@ -203,5 +205,10 @@ namespace android
{
daemon.stop();
}
void SetDataDir(std::string jdataDir)
{
dataDir = jdataDir;
}
}
}

View File

@ -7,45 +7,47 @@ namespace i2p
{
namespace android
{
class DaemonAndroidImpl
{
public:
class DaemonAndroidImpl
{
public:
DaemonAndroidImpl ();
~DaemonAndroidImpl ();
//typedef void (*runningChangedCallback)();
//typedef void (*runningChangedCallback)();
/**
* @return success
*/
bool init(int argc, char* argv[]);
void start();
void stop();
void restart();
//void setRunningCallback(runningChangedCallback cb);
//bool isRunning();
private:
//void setRunning(bool running);
/**
* @return success
*/
bool init(int argc, char* argv[]);
void start();
void stop();
void restart();
//void setRunningCallback(runningChangedCallback cb);
//bool isRunning();
private:
//void setRunning(bool running);
private:
//QMutex* mutex;
//bool m_IsRunning;
//bool m_IsRunning;
//runningChangedCallback m_RunningChangedCallback;
};
};
/**
* returns "ok" if daemon init failed
* returns errinfo if daemon initialized and started okay
*/
std::string start();
std::string start();
// stops the daemon
void stop();
// stops the daemon
void stop();
/*
// set datadir received from jni
void SetDataDir(std::string jdataDir);
/*
class Worker : public QObject
{
Q_OBJECT
{
Q_OBJECT
public:
Worker (DaemonAndroidImpl& daemon);
@ -54,33 +56,33 @@ namespace android
DaemonAndroidImpl& m_Daemon;
public slots:
void startDaemon();
void restartDaemon();
void stopDaemon();
public slots:
void startDaemon();
void restartDaemon();
void stopDaemon();
signals:
void resultReady();
};
signals:
void resultReady();
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(DaemonAndroidImpl& daemon);
~Controller();
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(DaemonAndroidImpl& daemon);
~Controller();
private:
DaemonAndroidImpl& m_Daemon;
public slots:
void handleResults(){}
signals:
void startDaemon();
void stopDaemon();
void restartDaemon();
};
*/
public slots:
void handleResults(){}
signals:
void startDaemon();
void stopDaemon();
void restartDaemon();
};
*/
}
}

View File

@ -1,5 +1,3 @@
//#include <string.h>
#include <jni.h>
#include "org_purplei2p_i2pd_I2PD_JNI.h"
#include "DaemonAndroid.h"
@ -7,60 +5,90 @@
#include "Transports.h"
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
(JNIEnv * env, jclass clazz) {
(JNIEnv *env, jclass clazz) {
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a/NEON (hard-float)"
#else
#define ABI "armeabi-v7a/NEON"
#endif
#else
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a (hard-float)"
#else
#define ABI "armeabi-v7a"
#endif
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__x86_64__)
#define ABI "x86_64"
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
#define ABI "mips64"
#elif defined(__mips__)
#define ABI "mips"
#elif defined(__aarch64__)
#define ABI "arm64-v8a"
#else
#define ABI "unknown"
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a/NEON (hard-float)"
#else
#define ABI "armeabi-v7a/NEON"
#endif
#else
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a (hard-float)"
#else
#define ABI "armeabi-v7a"
#endif
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__x86_64__)
#define ABI "x86_64"
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
#define ABI "mips64"
#elif defined(__mips__)
#define ABI "mips"
#elif defined(__aarch64__)
#define ABI "arm64-v8a"
#else
#define ABI "unknown"
#endif
return env->NewStringUTF(ABI);
return env->NewStringUTF(ABI);
}
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
(JNIEnv * env, jclass clazz) {
(JNIEnv *env, jclass clazz) {
return env->NewStringUTF(i2p::android::start().c_str());
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
(JNIEnv * env, jclass clazz) {
(JNIEnv *env, jclass clazz) {
i2p::android::stop();
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
(JNIEnv * env, jclass clazz) {
(JNIEnv *env, jclass clazz) {
i2p::context.SetAcceptsTunnels (false);
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
(JNIEnv *env, jclass clazz) {
i2p::context.SetAcceptsTunnels (true);
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv * env, jclass clazz, jboolean isConnected)
{
(JNIEnv *env, jclass clazz, jboolean isConnected) {
bool isConnectedBool = (bool) isConnected;
i2p::transport::transports.SetOnline (isConnectedBool);
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
(JNIEnv *env, jclass clazz, jstring jdataDir) {
/*
// Method 1: convert UTF-16 jstring to std::string (https://stackoverflow.com/a/41820336)
const jclass stringClass = env->GetObjectClass(jdataDir);
const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jdataDir, getBytes, env->NewStringUTF("UTF-8"));
size_t length = (size_t) env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
std::string dataDir = std::string((char *)pBytes, length);
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(stringJbytes);
env->DeleteLocalRef(stringClass); */
// Method 2: get string chars and make char array.
auto dataDir = env->GetStringUTFChars(jdataDir, NULL);
env->ReleaseStringUTFChars(jdataDir, dataDir);
// Set DataDir
i2p::android::SetDataDir(dataDir);
}

View File

@ -13,19 +13,25 @@ extern "C" {
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
(JNIEnv *, jclass);
(JNIEnv *, jclass);
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
(JNIEnv *, jclass);
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
(JNIEnv *, jclass);
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
(JNIEnv *, jclass);
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv * env, jclass clazz, jboolean isConnected);
(JNIEnv * env, jclass clazz, jboolean isConnected);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
(JNIEnv *env, jclass clazz, jstring jdataDir);
#ifdef __cplusplus
}

View File

@ -11,4 +11,4 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-28
target=android-29

View File

@ -0,0 +1,13 @@
<LinearLayout android:id="@+id/layout_prompt"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".I2PDActivity">
<WebView
android:id="@+id/webview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>

View File

@ -3,14 +3,23 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".I2PDActivity">
<item
android:id="@+id/action_graceful_stop"
android:title="@string/action_graceful_stop"
android:orderInCategory="98"
/>
<item
android:id="@+id/action_stop"
android:title="@string/action_stop"
android:orderInCategory="99"
/>
<group android:id="@+id/group_i2pd_control" >
<item
android:id="@+id/action_stop"
android:orderInCategory="99"
android:title="@string/action_stop" />
<item
android:id="@+id/action_graceful_stop"
android:orderInCategory="98"
android:title="@string/action_graceful_stop" />
<item
android:id="@+id/action_start_webview"
android:orderInCategory="97"
android:title="@string/action_start_webview" />
</group>
<group android:id="@+id/group_various" >
<item
android:id="@+id/action_battery_otimizations"
android:title="@string/menu_item_battery_optimizations_str" />
</group>
</menu>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">i2pd</string>
<string name="action_stop">Остановить</string>
<string name="action_graceful_stop">Корректная остановка</string>
<string name="action_cancel_graceful_stop">Отменить корректную остановку</string>
<string name="graceful_stop_is_already_in_progress">Корректная остановка уже запущена</string>
<string name="graceful_stop_is_in_progress">Корректная остановка запущена</string>
<string name="already_stopped">Уже остановлено</string>
<string name="uninitialized">Приложение инициализируется</string>
<string name="starting">Приложение запускается</string>
<string name="jniLibraryLoaded">Загружены JNI библиотеки</string>
<string name="startedOkay">Приложение запущено</string>
<string name="startFailed">Запуск не удался</string>
<string name="gracefulShutdownInProgress">Корректная остановка запущена</string>
<string name="stopped">Приложение было остановлено</string>
<string name="remaining">осталось</string>
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
<string name="permDenied">Права для записи на SD карту отклонены, вам необходимо предоставить их для продолжения</string>
<string name="menu_item_battery_optimizations_str">Оптимизации аккумулятора</string>
<string name="battery_optimizations_enabled">Оптимизации аккумулятора включены</string>
<string name="device_does_not_support_disabling_battery_optimizations">Ваша версия Андроид не поддерживает отключение оптимизаций аккумулятора</string>
<string name="battery_optimizations_enabled_explained">Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\nРекомендуется отключить эти оптимизации.</string>
<string name="battery_optimizations_enabled_dialog" >Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\n\nВам сейчас будет предложено разрешить отключение этих оптимизаций.</string>
<string name="continue_str">Продолжить</string>
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Ваша версия Андроид не поддерживает показ диалога об оптимизациях аккумулятора для приложений.</string>
<string name="shutdown_canceled">Плановая остановка отменена</string>
</resources>

View File

@ -1,18 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="app_name">i2pd</string>
<string name="action_stop">Stop</string>
<string name="action_graceful_stop">Graceful Stop</string>
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
<string name="already_stopped">Already stopped</string>
<string name="uninitialized">i2pd initializing</string>
<string name="starting">i2pd is starting</string>
<string name="jniLibraryLoaded">i2pd: loaded JNI libraries</string>
<string name="startedOkay">i2pd started</string>
<string name="startFailed">i2pd start failed</string>
<string name="gracefulShutdownInProgress">i2pd: graceful shutdown in progress</string>
<string name="stopped">i2pd has stopped</string>
<string name="uninitialized">Application initializing</string>
<string name="starting">Application starting</string>
<string name="jniLibraryLoaded">Loaded JNI libraries</string>
<string name="startedOkay">Application Started</string>
<string name="startFailed">Start failed</string>
<string name="gracefulShutdownInProgress">Graceful shutdown in progress</string>
<string name="stopped">Application stopped</string>
<string name="remaining">remaining</string>
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
<string name="permDenied">SD card write permission denied, you need to allow this to continue</string>
<string name="battery_optimizations_enabled">Battery optimizations enabled</string>
<string name="battery_optimizations_enabled_explained">Your Android is doing some heavy battery optimizations on I2PD that might lead to daemon closing with no other reason.\nIt is recommended to allow disabling those battery optimizations.</string>
<string name="battery_optimizations_enabled_dialog" >Your Android is doing some heavy battery optimizations on I2PD that might lead to daemon closing with no other reason.\n\nYou will now be asked to allow to disable those.</string>
<string name="continue_str">Continue</string>
<string name="device_does_not_support_disabling_battery_optimizations">Your Android version does not support opting out of battery optimizations</string>
<string name="menu_item_battery_optimizations_str">Battery Optimizations</string>
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Your Android OS version does not support showing the dialog for battery optimizations for applications.</string>
<string name="shutdown_canceled">Planned shutdown canceled</string>
<string name="action_start_webview">Start webview</string>
</resources>

View File

@ -2,18 +2,18 @@ package org.purplei2p.i2pd;
import java.util.HashSet;
import java.util.Set;
import android.os.Environment;
import android.util.Log;
import org.purplei2p.i2pd.R;
public class DaemonSingleton {
private static final String TAG="i2pd";
private static final String TAG = "i2pd";
private static final DaemonSingleton instance = new DaemonSingleton();
public interface StateUpdateListener { void daemonStateUpdate(); }
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
public static DaemonSingleton getInstance() {
return instance;
}
public static DaemonSingleton getInstance() { return instance; }
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
@ -33,27 +33,34 @@ public class DaemonSingleton {
}
}
public synchronized void startAcceptingTunnels() {
if(isStartedOkay()){
setState(State.startedOkay);
I2PD_JNI.startAcceptingTunnels();
}
}
private volatile boolean startedOkay;
public enum State {
uninitialized(R.string.uninitialized),
starting(R.string.starting),
jniLibraryLoaded(R.string.jniLibraryLoaded),
startedOkay(R.string.startedOkay),
startFailed(R.string.startFailed),
gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
stopped(R.string.stopped);
uninitialized(R.string.uninitialized),
starting(R.string.starting),
jniLibraryLoaded(R.string.jniLibraryLoaded),
startedOkay(R.string.startedOkay),
startFailed(R.string.startFailed),
gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
stopped(R.string.stopped);
State(int statusStringResourceId) {
this.statusStringResourceId = statusStringResourceId;
}
State(int statusStringResourceId) {
this.statusStringResourceId = statusStringResourceId;
}
private final int statusStringResourceId;
private final int statusStringResourceId;
public int getStatusStringResourceId() {
return statusStringResourceId;
}
};
public int getStatusStringResourceId() {
return statusStringResourceId;
}
};
private volatile State state = State.uninitialized;
@ -75,6 +82,7 @@ public class DaemonSingleton {
}
try {
synchronized (DaemonSingleton.this) {
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
daemonStartResult = I2PD_JNI.startDaemon();
if("ok".equals(daemonStartResult)){
setState(State.startedOkay);
@ -84,7 +92,6 @@ public class DaemonSingleton {
} catch (Throwable tr) {
lastThrowable=tr;
setState(State.startFailed);
return;
}
}

View File

@ -10,140 +10,140 @@ import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class ForegroundService extends Service {
private static final String TAG="FgService";
private static final String TAG="FgService";
private volatile boolean shown;
private volatile boolean shown;
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
new DaemonSingleton.StateUpdateListener() {
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
new DaemonSingleton.StateUpdateListener() {
@Override
public void daemonStateUpdate() {
try {
synchronized (ForegroundService.this) {
if (shown) cancelNotification();
showNotification();
}
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
}
};
@Override
public void daemonStateUpdate() {
try {
synchronized (ForegroundService.this) {
if (shown) cancelNotification();
showNotification();
}
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
}
};
private NotificationManager notificationManager;
private NotificationManager notificationManager;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
private int NOTIFICATION = 1;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
private int NOTIFICATION = 1;
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder {
ForegroundService getService() {
return ForegroundService.this;
}
}
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder {
ForegroundService getService() {
return ForegroundService.this;
}
}
@Override
public void onCreate() {
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
@Override
public void onCreate() {
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
synchronized (this) {
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
if (!shown) daemonStateUpdatedListener.daemonStateUpdate();
}
// Tell the user we started.
// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
}
synchronized (this) {
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
if (!shown) daemonStateUpdatedListener.daemonStateUpdate();
}
// Tell the user we started.
// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
@Override
public void onDestroy() {
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
cancelNotification();
}
@Override
public void onDestroy() {
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
cancelNotification();
}
private synchronized void cancelNotification() {
// Cancel the persistent notification.
notificationManager.cancel(NOTIFICATION);
private synchronized void cancelNotification() {
// Cancel the persistent notification.
notificationManager.cancel(NOTIFICATION);
stopForeground(true);
stopForeground(true);
// Tell the user we stopped.
// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
shown=false;
}
// Tell the user we stopped.
//Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
shown=false;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
/**
* Show a notification while this service is running.
*/
private synchronized void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId());
/**
* Show a notification while this service is running.
*/
private synchronized void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, I2PDActivity.class), 0);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, I2PDActivity.class), 0);
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
String channelId = Build.VERSION.SDK_INT >= 26 ? createNotificationChannel() : "";
// Set the info for the views that show in the notification panel.
Notification notification = new NotificationCompat.Builder(this, channelId)
.setOngoing(true)
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
.setPriority(Notification.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_SERVICE)
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.app_name)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
// Set the info for the views that show in the notification panel.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setOngoing(true)
.setSmallIcon(R.drawable.itoopie_notification_icon); // the status icon
if(Build.VERSION.SDK_INT >= 16) builder = builder.setPriority(Notification.PRIORITY_DEFAULT);
if(Build.VERSION.SDK_INT >= 21) builder = builder.setCategory(Notification.CATEGORY_SERVICE);
Notification notification = builder
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.app_name)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
// Send the notification.
//mNM.notify(NOTIFICATION, notification);
startForeground(NOTIFICATION, notification);
shown = true;
}
// Send the notification.
//mNM.notify(NOTIFICATION, notification);
startForeground(NOTIFICATION, notification);
shown = true;
}
@RequiresApi(Build.VERSION_CODES.O)
private synchronized String createNotificationChannel() {
String channelId = getString(R.string.app_name);
CharSequence channelName = "I2Pd service";
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
//chan.setLightColor(Color.PURPLE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
@RequiresApi(Build.VERSION_CODES.O)
private synchronized String createNotificationChannel() {
String channelId = getString(R.string.app_name);
CharSequence channelName = "I2Pd service";
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
//chan.setLightColor(Color.PURPLE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
if(service!=null)service.createNotificationChannel(chan);
else Log.e(TAG, "error: NOTIFICATION_SERVICE is null");
return channelId;
}
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
}

View File

@ -13,31 +13,58 @@ import java.io.StringWriter;
import java.util.Timer;
import java.util.TimerTask;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
// For future package update checking
import org.purplei2p.i2pd.BuildConfig;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS;
public class I2PDActivity extends Activity {
private WebView webView;
private static final String TAG = "i2pdActvt";
private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
public static final String PACKAGE_URI_SCHEME = "package:";
private TextView textView;
private boolean assetsCopied;
private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/";
//private ConfigParser parser = new ConfigParser(i2pdpath); // TODO:
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
@ -47,32 +74,27 @@ public class I2PDActivity extends Activity {
public void daemonStateUpdate()
{
processAssets();
runOnUiThread(new Runnable(){
@Override
public void run() {
try {
if(textView==null) return;
Throwable tr = daemon.getLastThrowable();
if(tr!=null) {
textView.setText(throwableToString(tr));
return;
}
DaemonSingleton.State state = daemon.getState();
textView.setText(
String.valueOf(state)+
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
);
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
}
});
runOnUiThread(() -> {
try {
if(textView==null) return;
Throwable tr = daemon.getLastThrowable();
if(tr!=null) {
textView.setText(throwableToString(tr));
return;
}
DaemonSingleton.State state = daemon.getState();
String startResultStr = DaemonSingleton.State.startFailed.equals(state) ? String.format(": %s", daemon.getDaemonStartResult()) : "";
String graceStr = DaemonSingleton.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
});
}
};
private static volatile long graceStartedMillis;
private static final Object graceStartedMillis_LOCK=new Object();
private Menu optionsMenu;
private static String formatGraceTimeRemaining() {
long remainingSeconds;
@ -86,6 +108,7 @@ public class I2PDActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
textView = new TextView(this);
@ -93,6 +116,17 @@ public class I2PDActivity extends Activity {
daemon.addStateChangeListener(daemonStateUpdatedListener);
daemonStateUpdatedListener.daemonStateUpdate();
// request permissions
if (Build.VERSION.SDK_INT >= 23)
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
// set the app be foreground
doBindService();
@ -104,6 +138,8 @@ public class I2PDActivity extends Activity {
}
rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
}
openBatteryOptimizationDialogIfNeeded();
}
@Override
@ -111,7 +147,7 @@ public class I2PDActivity extends Activity {
super.onDestroy();
textView = null;
daemon.removeStateChangeListener(daemonStateUpdatedListener);
//cancelGracefulStop();
//cancelGracefulStop0();
try{
doUnbindService();
}catch(Throwable tr){
@ -119,7 +155,21 @@ public class I2PDActivity extends Activity {
}
}
private static void cancelGracefulStop() {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Log.e(TAG, "WR_EXT_STORAGE perm granted");
else {
Log.e(TAG, "WR_EXT_STORAGE perm declined, stopping i2pd");
i2pdStop();
//TODO must work w/o this perm, ask orignal
}
}
}
private void cancelGracefulStop0() {
Timer gracefulQuitTimer = getGracefulQuitTimer();
if(gracefulQuitTimer!=null) {
gracefulQuitTimer.cancel();
@ -190,11 +240,17 @@ public class I2PDActivity extends Activity {
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.options_main, menu);
menu.findItem(R.id.action_battery_otimizations).setVisible(isBatteryOptimizationsOpenOsDialogApiAvailable());
this.optionsMenu = menu;
return true;
}
private boolean isBatteryOptimizationsOpenOsDialogApiAvailable() {
return android.os.Build.VERSION.SDK_INT >= 23;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
@ -205,28 +261,53 @@ public class I2PDActivity extends Activity {
i2pdStop();
return true;
case R.id.action_graceful_stop:
i2pdGracefulStop();
return true;
synchronized (graceStartedMillis_LOCK) {
if (getGracefulQuitTimer() != null)
cancelGracefulStop();
else
i2pdGracefulStop();
}
return true;
case R.id.action_battery_otimizations:
onActionBatteryOptimizations();
return true;
case R.id.action_start_webview:
setContentView(R.layout.webview);
this.webView = (WebView) findViewById(R.id.webview1);
this.webView.setWebViewClient(new WebViewClient());
WebSettings webSettings = this.webView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptEnabled(false);
this.webView.loadUrl("http://127.0.0.1:7070"); // TODO: instead 7070 I2Pd....HttpPort
break;
}
return super.onOptionsItemSelected(item);
}
private void i2pdStop() {
cancelGracefulStop();
new Thread(new Runnable(){
@Override
public void run() {
Log.d(TAG, "stopping");
try{
daemon.stopDaemon();
}catch (Throwable tr) {
Log.e(TAG, "", tr);
}
private void onActionBatteryOptimizations() {
if (isBatteryOptimizationsOpenOsDialogApiAvailable()) {
try {
startActivity(new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
} catch (ActivityNotFoundException e) {
Log.e(TAG,"BATT_OPTIM_DIALOG_ActvtNotFound", e);
Toast.makeText(this, R.string.os_version_does_not_support_battery_optimizations_show_os_dialog_api, Toast.LENGTH_SHORT).show();
}
}
}
},"stop").start();
private void i2pdStop() {
cancelGracefulStop0();
new Thread(() -> {
Log.d(TAG, "stopping");
try {
daemon.stopDaemon();
} catch (Throwable tr) {
Log.e(TAG, "", tr);
}
quit(); //TODO make menu items for starting i2pd. On my Android, I need to reboot the OS to restart i2pd.
},"stop").start();
}
private static volatile Timer gracefulQuitTimer;
@ -244,29 +325,45 @@ public class I2PDActivity extends Activity {
}
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
Toast.LENGTH_SHORT).show();
new Thread(new Runnable(){
@Override
public void run() {
try{
Log.d(TAG, "grac stopping");
if(daemon.isStartedOkay()) {
daemon.stopAcceptingTunnels();
long gracefulStopAtMillis;
synchronized (graceStartedMillis_LOCK) {
graceStartedMillis = System.currentTimeMillis();
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
}
rescheduleGraceStop(null,gracefulStopAtMillis);
}else{
i2pdStop();
}
} catch(Throwable tr) {
Log.e(TAG,"",tr);
new Thread(() -> {
try {
Log.d(TAG, "grac stopping");
if(daemon.isStartedOkay()) {
daemon.stopAcceptingTunnels();
long gracefulStopAtMillis;
synchronized (graceStartedMillis_LOCK) {
graceStartedMillis = System.currentTimeMillis();
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
}
rescheduleGraceStop(null,gracefulStopAtMillis);
} else {
i2pdStop();
}
} catch(Throwable tr) {
Log.e(TAG,"",tr);
}
},"gracInit").start();
}
private void cancelGracefulStop()
{
cancelGracefulStop0();
new Thread(() -> {
try
{
Log.d(TAG, "canceling grac stop");
if(daemon.isStartedOkay()) {
daemon.startAcceptingTunnels();
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
}
}
},"gracInit").start();
else
i2pdStop();
}
catch(Throwable tr)
{
Log.e(TAG,"",tr);
}
},"gracCancel").start();
}
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
@ -294,8 +391,19 @@ public class I2PDActivity extends Activity {
return gracefulQuitTimer;
}
private static void setGracefulQuitTimer(Timer gracefulQuitTimer) {
private void setGracefulQuitTimer(Timer gracefulQuitTimer) {
I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
runOnUiThread(()-> {
Menu menu = optionsMenu;
if (menu != null) {
MenuItem item = menu.findItem(R.id.action_graceful_stop);
if (item != null) {
synchronized (graceStartedMillis_LOCK) {
item.setTitle(getGracefulQuitTimer() != null ? R.string.action_cancel_graceful_stop : R.string.action_graceful_stop);
}
}
}
});
}
/**
@ -318,19 +426,22 @@ public class I2PDActivity extends Activity {
// to a file. That doesn't appear to be the case. If the returned array is
// null or has 0 length, we assume the path is to a file. This means empty
// directories will get turned into files.
if (contents == null || contents.length == 0)
throw new IOException();
if (contents == null || contents.length == 0) {
copyFileAsset(path);
return;
}
// Make the directory.
File dir = new File(i2pdpath, path);
dir.mkdirs();
boolean result = dir.mkdirs();
Log.d(TAG, "dir.mkdirs() returned " + result);
// Recurse on the contents.
for (String entry : contents) {
copyAsset(path + "/" + entry);
copyAsset(path + '/' + entry);
}
} catch (IOException e) {
copyFileAsset(path);
Log.e(TAG, "ex ignored for path='" + path + "'", e);
}
}
@ -343,77 +454,186 @@ public class I2PDActivity extends Activity {
*/
private void copyFileAsset(String path) {
File file = new File(i2pdpath, path);
if(!file.exists()) try {
InputStream in = getAssets().open(path);
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int read = in.read(buffer);
while (read != -1) {
out.write(buffer, 0, read);
read = in.read(buffer);
if(!file.exists()) {
try {
try (InputStream in = getAssets().open(path) ) {
try (OutputStream out = new FileOutputStream(file)) {
byte[] buffer = new byte[1024];
int read = in.read(buffer);
while (read != -1) {
out.write(buffer, 0, read);
read = in.read(buffer);
}
}
}
} catch (IOException e) {
Log.e(TAG, "", e);
}
out.close();
in.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
private void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
for (File child : fileOrDirectory.listFiles()) {
deleteRecursive(child);
File[] files = fileOrDirectory.listFiles();
if(files!=null) {
for (File child : files) {
deleteRecursive(child);
}
}
}
fileOrDirectory.delete();
boolean deleteResult = fileOrDirectory.delete();
if(!deleteResult)Log.e(TAG, "fileOrDirectory.delete() returned "+deleteResult+", absolute path='"+fileOrDirectory.getAbsolutePath()+"'");
}
private void processAssets() {
if (!assetsCopied) try {
assetsCopied = true; // prevent from running on every state update
File holderfile = new File(i2pdpath, "assets.ready");
File holderFile = new File(i2pdpath, "assets.ready");
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
StringBuilder text = new StringBuilder();
if (holderfile.exists()) try { // if holder file exists, read assets version string
BufferedReader br = new BufferedReader(new FileReader(holderfile));
String line;
if (holderFile.exists()) {
try { // if holder file exists, read assets version string
FileReader fileReader = new FileReader(holderFile);
while ((line = br.readLine()) != null) {
text.append(line);
}
br.close();
}
catch (IOException e) {
Log.e(TAG, "", e);
}
try {
BufferedReader br = new BufferedReader(fileReader);
try {
String line;
while ((line = br.readLine()) != null) {
text.append(line);
}
}finally {
try{
br.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} finally {
try{
fileReader.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
// if version differs from current app version or null, try to delete certificates folder
if (!text.toString().contains(versionName)) try {
holderfile.delete();
File certpath = new File(i2pdpath, "certificates");
deleteRecursive(certpath);
boolean deleteResult = holderFile.delete();
if(!deleteResult)Log.e(TAG, "holderFile.delete() returned "+deleteResult+", absolute path='"+holderFile.getAbsolutePath()+"'");
File certPath = new File(i2pdpath, "certificates");
deleteRecursive(certPath);
}
catch (Throwable tr) {
Log.e(TAG, "", tr);
}
// copy assets. If processed file exists, it won't be overwrited
// copy assets. If processed file exists, it won't be overwritten
copyAsset("addressbook");
copyAsset("certificates");
copyAsset("tunnels.d");
copyAsset("i2pd.conf");
copyAsset("subscriptions.txt");
copyAsset("tunnels.conf");
// update holder file about successful copying
FileWriter writer = new FileWriter(holderfile);
writer.append(versionName);
writer.flush();
writer.close();
FileWriter writer = new FileWriter(holderFile);
try {
writer.append(versionName);
} finally {
try{
writer.close();
}catch (IOException e){
Log.e(TAG,"on writer close", e);
}
}
}
catch (Throwable tr)
{
Log.e(TAG,"copy assets",tr);
Log.e(TAG,"on assets copying", tr);
}
}
@SuppressLint("BatteryLife")
private void openBatteryOptimizationDialogIfNeeded() {
boolean questionEnabled = getPreferences().getBoolean(getBatteryOptimizationPreferenceKey(), true);
Log.i(TAG,"BATT_OPTIM_questionEnabled=="+questionEnabled);
if (!isKnownIgnoringBatteryOptimizations()
&& android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
&& questionEnabled) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.battery_optimizations_enabled);
builder.setMessage(R.string.battery_optimizations_enabled_dialog);
builder.setPositiveButton(R.string.continue_str, (dialog, which) -> {
try {
startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse(PACKAGE_URI_SCHEME + getPackageName())));
} catch (ActivityNotFoundException e) {
Log.e(TAG,"BATT_OPTIM_ActvtNotFound", e);
Toast.makeText(this, R.string.device_does_not_support_disabling_battery_optimizations, Toast.LENGTH_SHORT).show();
}
});
builder.setOnDismissListener(dialog -> setNeverAskForBatteryOptimizationsAgain());
final AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
}
private void setNeverAskForBatteryOptimizationsAgain() {
getPreferences().edit().putBoolean(getBatteryOptimizationPreferenceKey(), false).apply();
}
protected boolean isKnownIgnoringBatteryOptimizations() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (pm == null) {
Log.i(TAG, "BATT_OPTIM: POWER_SERVICE==null");
return false;
}
boolean ignoring = pm.isIgnoringBatteryOptimizations(getPackageName());
Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
return ignoring;
} else {
Log.i(TAG, "BATT_OPTIM: old sdk version=="+Build.VERSION.SDK_INT);
return false;
}
}
protected SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
}
private String getBatteryOptimizationPreferenceKey() {
@SuppressLint("HardwareIds") String device = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
return "show_battery_optimization" + (device == null ? "" : device);
}
private void quit() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
finishAffinity();
} else {
//moveTaskToBack(true);
finish();
}
}catch (Throwable tr) {
Log.e(TAG, "", tr);
}
try{
daemon.stopDaemon();
}catch (Throwable tr) {
Log.e(TAG, "", tr);
}
System.exit(0);
}
}

View File

@ -15,157 +15,156 @@ import java.lang.reflect.Method;
//android.permission.WRITE_EXTERNAL_STORAGE
public class I2PDPermsAskerActivity extends Activity {
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
private Button button_request_write_ext_storage_perms;
private TextView textview_retry;
private Button button_request_write_ext_storage_perms;
private TextView textview_retry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//if less than Android 6, no runtime perms req system present
if (android.os.Build.VERSION.SDK_INT < 23) {
startMainActivity();
return;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//if less than Android 6, no runtime perms req system present
if (android.os.Build.VERSION.SDK_INT < 23) {
startMainActivity();
return;
}
setContentView(R.layout.activity_perms_asker);
button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
textview_retry = (TextView) findViewById(R.id.textview_retry);
setContentView(R.layout.activity_perms_asker);
button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
textview_retry = (TextView) findViewById(R.id.textview_retry);
button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
request_write_ext_storage_perms();
}
});
request_write_ext_storage_perms();
}
button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
request_write_ext_storage_perms();
}
});
request_write_ext_storage_perms();
}
private void request_write_ext_storage_perms() {
private void request_write_ext_storage_perms() {
textview_retry.setVisibility(TextView.GONE);
button_request_write_ext_storage_perms.setVisibility(Button.GONE);
textview_retry.setVisibility(TextView.GONE);
button_request_write_ext_storage_perms.setVisibility(Button.GONE);
Method methodCheckPermission;
Method method_shouldShowRequestPermissionRationale;
Method method_requestPermissions;
try {
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
method_shouldShowRequestPermissionRationale =
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
Integer resultObj;
try {
resultObj = (Integer) methodCheckPermission.invoke(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Throwable e) {
throw new RuntimeException(e);
}
Method methodCheckPermission;
Method method_shouldShowRequestPermissionRationale;
Method method_requestPermissions;
try {
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
method_shouldShowRequestPermissionRationale =
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
Integer resultObj;
try {
resultObj = (Integer) methodCheckPermission.invoke(
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Throwable e) {
throw new RuntimeException(e);
}
if (resultObj != PackageManager.PERMISSION_GRANTED) {
if (resultObj != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
Boolean aBoolean;
try {
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (aBoolean) {
// Should we show an explanation?
Boolean aBoolean;
try {
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (aBoolean) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
showExplanation();
showExplanation();
} else {
} else {
// No explanation needed, we can request the permission.
// No explanation needed, we can request the permission.
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else startMainActivity();
}
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else startMainActivity();
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_WRITE_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_WRITE_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
// permission was granted, yay! Do the
// contacts-related task you need to do.
startMainActivity();
startMainActivity();
} else {
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
textview_retry.setText("SD card write permission denied, you need to allow this to continue");
textview_retry.setVisibility(TextView.VISIBLE);
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
}
return;
}
// permission denied, boo! Disable the
// functionality that depends on this permission.
textview_retry.setText(R.string.permDenied);
textview_retry.setVisibility(TextView.VISIBLE);
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
}
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
private void startMainActivity() {
startActivity(new Intent(this, I2PDActivity.class));
finish();
}
private void startMainActivity() {
startActivity(new Intent(this, I2PDActivity.class));
finish();
}
private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
private void showExplanation() {
Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
startActivityForResult(intent, SHOW_EXPLANATION_REQUEST);
}
private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
private void showExplanation() {
Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
startActivityForResult(intent, SHOW_EXPLANATION_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == SHOW_EXPLANATION_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Request the permission
Method method_requestPermissions;
try {
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
finish(); //close the app
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == SHOW_EXPLANATION_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Request the permission
Method method_requestPermissions;
try {
method_requestPermissions =
getClass().getMethod("requestPermissions", String[].class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
try {
method_requestPermissions.invoke(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_WRITE_EXTERNAL_STORAGE);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
finish(); //close the app
}
}
}
}

View File

@ -9,30 +9,30 @@ import android.widget.Button;
public class I2PDPermsExplanationActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perms_explanation);
ActionBar actionBar = getActionBar();
if(actionBar!=null)actionBar.setHomeButtonEnabled(false);
Button button_ok = (Button) findViewById(R.id.button_ok);
button_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
returnFromActivity();
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perms_explanation);
ActionBar actionBar = getActionBar();
if(actionBar!=null)actionBar.setHomeButtonEnabled(false);
Button button_ok = (Button) findViewById(R.id.button_ok);
button_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
returnFromActivity();
}
});
}
private void returnFromActivity() {
Intent data = new Intent();
Activity parent = getParent();
if (parent == null) {
setResult(Activity.RESULT_OK, data);
} else {
parent.setResult(Activity.RESULT_OK, data);
}
finish();
}
private void returnFromActivity() {
Intent data = new Intent();
Activity parent = getParent();
if (parent == null) {
setResult(Activity.RESULT_OK, data);
} else {
parent.setResult(Activity.RESULT_OK, data);
}
finish();
}
}

View File

@ -1,21 +1,27 @@
package org.purplei2p.i2pd;
public class I2PD_JNI {
public static native String getABICompiledWith();
public static native String getABICompiledWith();
/**
* returns error info if failed
* returns "ok" if daemon initialized and started okay
*/
public static native String startDaemon();
//should only be called after startDaemon() success
public static native void stopDaemon();
public static native String startDaemon();
public static native void stopAcceptingTunnels();
//should only be called after startDaemon() success
public static native void stopDaemon();
public static native void stopAcceptingTunnels();
public static native void startAcceptingTunnels();
public static native void onNetworkStateChanged(boolean isConnected);
public static native void setDataDir(String jdataDir);
public static void loadLibraries() {
System.loadLibrary("gnustl_shared");
System.loadLibrary("i2pd");
}
//System.loadLibrary("c++_shared");
System.loadLibrary("i2pd");
}
}

View File

@ -9,12 +9,12 @@ import android.net.NetworkInfo;
public class NetworkStateChangeReceiver extends BroadcastReceiver {
private static final String TAG = "i2pd";
private static final String TAG = "i2pd";
//api level 1
@Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG,"Network state change");
@Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG,"Network state change");
try {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
@ -26,5 +26,5 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver {
} catch (Throwable tr) {
Log.d(TAG,"",tr);
}
}
}
}

View File

@ -26,43 +26,43 @@ include $(BUILD_EXECUTABLE)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_system
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_date_time
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_filesystem
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_program_options
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
LOCAL_STATIC_LIBRARIES := crypto
include $(PREBUILT_STATIC_LIBRARY)

View File

@ -1,19 +1,16 @@
#APP_ABI := all
#APP_ABI := armeabi-v7a x86
#APP_ABI := x86
#APP_ABI := x86_64
APP_ABI := armeabi-v7a
APP_ABI := all
#APP_ABI += x86
#APP_ABI += x86_64
#APP_ABI += armeabi-v7a
#APP_ABI += arm64-v8a
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
APP_PLATFORM := android-14
# http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
NDK_TOOLCHAIN_VERSION := 4.9
# APP_STL := stlport_shared --> does not seem to contain C++11 features
#APP_STL := gnustl_shared
APP_STL := gnustl_static
NDK_TOOLCHAIN_VERSION := clang
APP_STL := c++_static
# Enable c++11 extensions in source code
APP_CPPFLAGS += -std=c++11 -fvisibility=default -fPIE
# Enable c++17 extensions in source code
APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE
APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP
APP_LDFLAGS += -rdynamic -fPIE -pie
@ -24,7 +21,7 @@ endif
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
#APP_OPTIM := debug
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/android-ifaddrs.git

View File

@ -1,4 +1,4 @@
version: 2.21.1.{build}
version: 2.31.0.{build}
pull_requests:
do_not_increment_build_number: true
branches:
@ -17,10 +17,10 @@ environment:
- MSYSTEM: MINGW32
install:
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
- if "%MSYSTEM%" == "MINGW64" (
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"

View File

@ -19,8 +19,6 @@ option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
option(WITH_MESHNET "Build for cjdns test network" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
option(WITH_I2LUA "Build for i2lua" OFF)
option(WITH_WEBSOCKETS "Build with websocket ui" OFF)
# paths
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
@ -75,27 +73,20 @@ set (LIBI2PD_SRC
"${LIBI2PD_SRC_DIR}/Signature.cpp"
"${LIBI2PD_SRC_DIR}/Timestamp.cpp"
"${LIBI2PD_SRC_DIR}/api.cpp"
"${LIBI2PD_SRC_DIR}/Event.cpp"
"${LIBI2PD_SRC_DIR}/Gost.cpp"
"${LIBI2PD_SRC_DIR}/ChaCha20.cpp"
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
"${LIBI2PD_SRC_DIR}/Ed25519.cpp"
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
"${LIBI2PD_SRC_DIR}/Blinding.cpp"
"${LIBI2PD_SRC_DIR}/Elligator.cpp"
"${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"
)
if (WITH_WEBSOCKETS)
add_definitions(-DWITH_EVENTS)
find_package(websocketpp REQUIRED)
endif ()
if (WIN32 OR MSYS)
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
endif ()
if (WITH_I2LUA)
add_definitions(-DI2LUA)
endif()
add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "")
@ -121,13 +112,8 @@ set (CLIENT_SRC
"${LIBI2PD_CLIENT_SRC_DIR}/SOCKS.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/HTTPProxy.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/I2CP.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/WebSocks.cpp"
)
if(WITH_WEBSOCKETS)
list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp")
endif ()
add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
@ -181,17 +167,17 @@ else()
set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections" ) # -flto is added from above
endif ()
# check for c++11 support
# check for c++17 & c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" CXX0X_SUPPORTED)
if (CXX11_SUPPORTED)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
elseif (CXX0X_SUPPORTED) # gcc 4.6
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
elseif (NOT MSVC)
message(SEND_ERROR "C++11 standard not seems to be supported by compiler. Too old version?")
endif ()
if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
@ -364,8 +350,8 @@ if (NOT ZLIB_FOUND )
set( ZLIB_EXTRA -DASM686=ON "-DCMAKE_ASM_MASM_FLAGS=/W0 /safeseh" )
endif()
ExternalProject_Add(zlib-project
URL http://zlib.net/zlib-1.2.8.tar.gz
URL_MD5 44d667c142d7cda120332623eab69f40
URL https://zlib.net/zlib-1.2.11.tar.gz
URL_HASH SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/zlib
PATCH_COMMAND "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-static.patch
&& "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-amd64.patch
@ -423,8 +409,6 @@ message(STATUS " PCH : ${WITH_PCH}")
message(STATUS " MESHNET : ${WITH_MESHNET}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS " I2LUA : ${WITH_I2LUA}")
message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}")
message(STATUS "---------------------------------------")
#Handle paths nicely
@ -469,6 +453,7 @@ if (WITH_BINARY)
if (WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS})
endif()
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
target_link_libraries( "${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)

View File

@ -21,6 +21,8 @@ set MSYSTEM=MINGW32
set "xSH=%WD%bash -lc"
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
REM detecting number of processors and subtract 1.
set /a threads=%NUMBER_OF_PROCESSORS%-1
@ -52,6 +54,14 @@ set bitness=64
call :BUILDING
echo.
REM building for WinXP
set "WD=C:\msys64-xp\usr\bin\"
set MSYSTEM=MINGW32
set bitness=32
set "xSH=%WD%bash -lc"
call :BUILDING_XP
echo.
del README.txt >> nul
echo Build complete...
@ -62,12 +72,18 @@ exit /b 0
%xSH% "make clean" >> nul
echo Building i2pd %tag% for win%bitness%:
echo Build AVX+AESNI...
%xSH% "make DEBUG=no 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 DEBUG=no USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_aesni_%tag%.log 2>&1
echo Build AVX...
%xSH% "make DEBUG=no 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 DEBUG=no USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_%tag%.log 2>&1
echo Build AESNI...
%xSH% "make DEBUG=no 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 DEBUG=no USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_aesni_%tag%.log 2>&1
echo Build without extensions...
%xSH% "make DEBUG=no 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 DEBUG=no USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build/build_win%bitness%_%tag%.log 2>&1
goto EOF
:BUILDING_XP
%xSH% "make clean" >> nul
echo Building i2pd %tag% for winxp...
%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads% && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST% && make clean" > build/build_winxp_%tag%.log 2>&1
:EOF

View File

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

View File

@ -0,0 +1,45 @@
#!/bin/bash
# Copyright (c) 2013-2017, The PurpleI2P Project
#
# This file is part of Purple i2pd project and licensed under BSD3
#
# See full license text in LICENSE file at top of project tree
GITDESC=$(git describe --tags)
declare -A ABILIST=(
["armeabi-v7a"]="armv7l"
["arm64-v8a"]="aarch64"
["x86"]="x86"
["x86_64"]="x86_64"
)
# Remove old files and archives
if [ -d archive ]; then
rm -r archive
fi
if [ -f i2pd_*_android_binary.zip ]; then
rm i2pd_*_android_binary.zip
fi
# Prepare files for package
mkdir archive
for ABI in "${!ABILIST[@]}"; do
if [ -f ../../android_binary_only/libs/${ABI}/i2pd ]; then
cp ../../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
fi
done
cp i2pd archive/i2pd
cp -rH ../../android/assets/* archive/
# Compress files
cd archive
zip -r6 ../i2pd_${GITDESC}_android_binary.zip .
# Remove temporary folder
cd ..
rm -r archive

View File

@ -0,0 +1,33 @@
#!/bin/sh
# Copyright (c) 2013-2019, The PurpleI2P Project
#
# This file is part of Purple i2pd project and licensed under BSD3
#
# See full license text in LICENSE file at top of project tree
#
# That script written for use with Termux.
# https://stackoverflow.com/a/246128
SOURCE="${0}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
arch=$(uname -m)
screenfind=$(which screen)
if [ -z $screenfind ]; then
echo "Can't find 'screen' installed. That script needs it!";
exit 1;
fi
if [ -z i2pd-$arch ]; then
echo "Can't find i2pd binary for your archtecture.";
exit 1;
fi
screen -AmdS i2pd ./i2pd-$arch --datadir=$DIR

View File

@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF5TCCA82gAwIBAgIRANFIiHpTaRY2Z30TQOiuqFcwDQYJKoZIhvcNAQELBQAw
cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM
EGF0b21pa2VAbWFpbC5pMnAwHhcNMTYwODAyMTQyNDEyWhcNMjYwODAyMTQyNDEy
WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD
VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE
AwwQYXRvbWlrZUBtYWlsLmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBAMLRmxclaAvm405JLHNNiniUi0aZaBoLJ+afwn2LGfTDUhTD5Y8lW6V9o90n
eTNOCaiid7bWpVBkA1M4gZ9TdUnP0POa99jXZbj4PHFRl1l8k4Ap12PUO3hgwtH7
7j7j+UPaIuE2y+U7hJbmyQ0v7r8yjGWSTtSqs+exNhyr4Mh7DvacZySZ+oqQdXYA
vnfDpBX1dKlN1Nb4XloG0uE1OK1YfJoC+p+v8qXjKagIdZgThdmsWcQ82EGI+Q9u
VfrE4m3CNwJy0X86wMNYqHej88wBHnJMmTm+cZtFLVmZsRqnuLAQL1wrfCbGSltR
zhVQHTysLwMz9+llTXtzMf+R2kcEAYWiPc5IRVU+LvkN/610r5fuHW+OcQ9ZgRVn
PMqlv5PDG2ZxdIOAQQsOd7fH0r5q3MhqlVstVE45Rl33uA+M7wjJK2cvnOoSioxp
szn2GIZliXQXo4dJczgfN2U4PLBGRBGmrB1R2S1YsG6CrSJuMCX14VKJP69Nfm8a
EDA5GKNke+ZpXCszPLaNMB70LVFQc9FmMhsOgLIIoJBgd61uMgokMJJMLaWN0RaK
w1ZduxYGUmg2T2pi/clIkVzZmlcHKViUn0sMcKD+ibEPOvQIB/3HPEEt6iIkanc/
da5IFzikkaykt/Tu6o8rreeEu65HkIxFaCHegSXLHSyxj00BAgMBAAGjejB4MA4G
A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQYXRvbWlrZUBtYWlsLmkycDAbBgNVHSME
FDASgBBhdG9taWtlQG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAA0MdWfN/N
1q5CdJqDyw4JQwzdYkA27Wr02qIcmwnqjcCEDPl4uDTyqN9gbEpJ48AcsdXRa6GE
lLh/qJ67I6YDe63LuhndzRULNgxGHVMGS8kBJIssQehb2rOFnbUTp0gMR+0QpXXe
omase4kL90c9uuYX1vXaO/ADssY2/QX49prwJO+UY/jGhcX4YheFI/teA85u6Qko
ero437Shqhl0kbdK+eBkOFf9a7mGxpMT73KE1jFS6433W4fFOkybQ1dcS0qStaUM
3qKC0EQCbAl1seAp3AGuG46swHZB0rZ1WCKVAr5yqCWSWMYO+fL6FosNg9z/VDVh
g6FFfoGrv19yaVFa9AvQsk1ATZ+bwtHProNx2Xet9pnAI30dT16+C5wCctoR6RVf
iOHl6CGqadjOycbMDVvOfJhypNDgWW3gBaCfXiAocJTLpR7hKNZ2bnvcP2xyXH1j
Qz/kiMJoZ3+TV1yC/x/maAHsUIQHqqd6ZRj7x5MgJq0UBdITo2ZQVfXYI0ZGIeNm
fMu+P5448+NdpASa9QoqS8kPFeUaHJMzMFHBKhrr8lTJeZ82hKBXt5jD3Tbef5Ck
n5auKu2D0IjvrzsdIpNMQAhuBPT06TW/LzN/MvardZcaLcBmcutefw6Z7RsedHvj
cGpnw4a2u9sHZIUNHzoGq32+7UWXsBI5Ow==
-----END CERTIFICATE-----

View File

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFfTCCA2WgAwIBAgIEOprmhjANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEYMBYGA1UEAwwPYmFja3VwQG1haWwu
aTJwMB4XDTEzMTAxMzEzNDQ1NVoXDTIzMTAxMzEzNDQ1NVowbzELMAkGA1UEBhMC
WFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255
bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2JhY2t1cEBtYWls
LmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIoAkobXwk/Enf1d
roHyqCyvcJfZJVTwb/LgYWAvCBMCr+RGqlSgtk3g69Y3I0xU08fD2kGt3r5Pwsbr
omXIbJAcccyLqmQ5QX6QgL+X9VpMDp9C4h2RogCrqLBAWw4cuZ4RS9VCpP1Yis7H
uejYqENP86p7BsRnuW/4cYnfunAdMpss4LpRGQXt1nTX+kfgCYgnKFbFqwAHt7yV
Ds+Pe6FuBHPlp+sc1amKRcUnSvhXLsv43VicnT7xYL/kUsN83wrtHA3B4aGDx3aA
3/EzuRmIXQB0BlTZILMEyYwG/nc4OsW82QYrvEZ9BIg9A4lF/wS/KZCICPxLF2zo
dGjnmlgkiA4s8eO+va/ElHyELjckVXqmG1eXHhSkEsDvOQJy01IUuwLinvq7cUbJ
HfJBZJllEg+sLDCv3FkEqN+XjBNFfQN4oNew4w6IPY6YH1INVB9LL0Cmdu4DudLv
TY8OcI8eSfez3hmm+pYQ23PJRYYnvRDnRECyIWBegkckWRh8U/WvZUYUvETK6EDl
/0KpTtfzX6MqHA5D6bTAB8Y3ijGMLrZ/B5vj5yCoZbLiGme9X2moR2k1LEhdhtzV
exsqezCpg6dn48FTX7mHjvR5/r4kz2jqBGmdPUWIIxnjFUzDUK3llVQiHihleHpe
jL4LqnhBGKWFRTaVwaIkBG4zAfIzAgMBAAGjITAfMB0GA1UdDgQWBBQNkfW7bSMl
1/4KDbgwrkf9x1Zu/TANBgkqhkiG9w0BAQ0FAAOCAgEAGg3a3rTf0EznQocmio0T
5gCoL0n8h6yKW/PyPAIELrd9wiYjhJFcWvMTcJJJnVqmAL5vpvhaAFVtAfx70MGa
0DZ7FvytK5hEfF4IqOFDyEEVGJR5rIpVK4MeI1nmwEsxdbW+FhODjtRzgYO8XBME
Xj4aY1FWg9vxc3reUj6PSFsZtsB0aLiRgL9JDovJIiRw0Uqr1v2wXBte5yVCxDge
vTREZtpK4cKetoOa68pwSXI32JwKE18j6bfdKVBCcYQKlKP/3gHGduaDrQv3w32S
DRym5s6MREeTUOtAw4wq46KpdOX8yyAqJPrCfMwS6ORd3t+egqOw0PUnsqb97w4O
lUtrRYvb2cOj60SmRx4vJvItyuHbKqIK7o2e1RcUZPXYoAVx2ww4XB2Wk4D7LSAs
cS7nLj8yAqzJ2qqtBzxu+zILJtkVa12dKF0xmS0BxBp4sCYiBtmAVE8AWQqEuSHA
FrMWqoXcjcfdvvyX487FFWWUE7ZBIn0hee2sK9J9+SPtqczJaN7TF3K3nzo65WJG
1epltmq2Ugjb67Gz7v4y7H23DJ/qhm8yLtCHTj69HTta5I08j6Kut924WLZaiMO/
4YoEL5AE63X0sxYibKFQiq7FW5nUJA280GRlY3xSMFzlB2ggazrUV3YAWVDhfdnI
flpzWXkFM2D36OUaubfe9YY=
-----END CERTIFICATE-----

View File

@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF1TCCA72gAwIBAgIRAJBHySZnvNg3lU00//fwny4wDQYJKoZIhvcNAQELBQAw
bDELMAkGA1UEBhMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEM
MAoGA1UECxMDSTJQMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxFTATBgNVBAMM
DHpteEBtYWlsLmkycDAeFw0xNjAxMDExNzE5MTlaFw0yNjAxMDExNzE5MTlaMGwx
CzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAK
BgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMRUwEwYDVQQDDAx6
bXhAbWFpbC5pMnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnDGVU
iC6pNJ3mfqZRQYACUbQ6SQI05yh3PawHqQrmiW3rD05SXBCF+6b2EpA4U0ThFhtm
cGyUObtBL749x03SUYcWhknZNq+zrvb9AypaKFpIx2DjFT8vQadn0l71cNaiwxX1
Wzk1Au6mh9SFPvH5gDF9SQol7dYYKnn9L61V7hvH9fDiZyoi9Cz3ifE3SAWoM2PJ
lBzbu16tyQE94HvIdZhp8cE/6/kiW1wjSqvT9dfZ4gMuZHOF5E8lkq/bg8tPa/oj
rglY7ozT/9/IWtJ7ERcDyepmKjq7+Xx4sNXTvc+B7D4XfMjhaxFLtV/kLQ9mqx8R
UPvPy+atw7mlfUf822YFSft2jBAxNJwCPdhXuuFkTUTIk9YXcChUCSPyv17gej/P
A++/hdhYI/kIs8AVsaJjytTqwU3A2Pt1QogM8VLsSJ2NY7gSzj868nzIZ4OuoWbz
KzpnS/3bQkYHrqMtDIjRr1bOudxbu2/ben5v8Qg9wE9uV/8YNhhaKAcfJOV6OXfF
MYec9DOEVVvECOfYUX35Vtn/w7E6SSL7Gu6QEWviA4Bf2XBh1YFX0ZpBUMY9awNz
7PDf+z+YGkrQ6ifvLPW9vHW3lmouRWzo5NgJIIvLYBJKmxkf08p94s8YailjiGzA
dJWXg3HDWgwMe7BY7AJQbU/o35Vv+0CroUsR3wIDAQABo3IwcDAOBgNVHQ8BAf8E
BAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA8GA1UdEwEB/wQF
MAMBAf8wFQYDVR0OBA4EDHpteEBtYWlsLmkycDAXBgNVHSMEEDAOgAx6bXhAbWFp
bC5pMnAwDQYJKoZIhvcNAQELBQADggIBAATXH/PNdF40DjD9DcF4W5Ot7CWGskDY
cR4ywtvU2EcDNEwv4q0FPEpxy5LPaUmTKQ6fsRXUZizjaPLpgCLbv9qYc5xRLrSi
yk9mrAbJ1iEU+DfHHBcS1VQWtc7+9LA0W3ZIA+pygjPjTxwQqQAcjn4BdfaIQpVa
VJ2kl5JtbTuYHL80GAQFYnzCCa5GKM7zgcLsyO1mQwnpDvFeSlKJJ6rx1QjhlJu+
90Ig8IOBCIgokfUv9OdYBl6rmDq9i9pvqJU+H4VepqE1jnDAO+YqQ4laZj7LVVM8
I9uia+8RKntUOBkUkLB3ouGdVJUmp3kGrkExxUdDHYP9VNJG6ZMwyKO8HXGtoTsR
TFWIEIbq/biBL9obM/d8fRV5xpfZNbPi6cRzw8REY9UIKECKr7B2B6PnDVVQIQw0
7SCVjmSYWexOqoJPZ1L7/AZDP/tFvx32cWwCszj5jqUaPo9ZNPb6DxQJDdNaZrFH
3CA+PbiaeEz9IH0yBY/6wQgO0k3qOyFQrlkC+YRoYUQNc+6xS38l5ZnYUtBAy8ms
N43eODQ/OhsLzy6PwwXdzvR/0g18SrQyTLfbn2b/kwvbC8Qe40QFfkOf5lPXjdnP
Ii/lcMuvDMlMhoWGFwWm5bkkXE81TKnFXu2/IMsW6HYb3oiTjkaCap22fCr9l0jj
fNr8P7NIRyZ8
-----END CERTIFICATE-----

View File

@ -24,7 +24,7 @@ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
# 1. install deps, clone and build.
# 2. strip binaries.
# 3. Purge all dependencies and other unrelated packages, including build directory.
RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \
RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl git \
&& mkdir -p /tmp/build \
&& cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \
&& cd i2pd \
@ -36,8 +36,8 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boos
&& cd /usr/local/bin \
&& strip i2pd \
&& rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \
boost-python3 python3 gdbm boost-unit_test_framework boost-python linux-headers boost-prg_exec_monitor \
boost-serialization boost-signals boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \
boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \
boost-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \
libtool g++ gcc pkgconfig
# 2. Adding required libraries to run i2pd to ensure it will run.

View File

@ -10,6 +10,11 @@
## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf
# tunconf = /var/lib/i2pd/tunnels.conf
## Tunnels config files path
## Use that path to store separated tunnels in different config files.
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
# tunnelsdir = /var/lib/i2pd/tunnels.conf.d
## Where to write pidfile (don't write by default)
# pidfile = /var/run/i2pd.pid
@ -88,6 +93,8 @@ ipv6 = false
## Address and port service will listen on
address = 127.0.0.1
port = 7070
## Path to web console, default "/"
# webroot = /
## Uncomment following lines to enable Web Console authentication
# auth = true
# user = i2pd
@ -218,3 +225,7 @@ verify = true
# inbound.quantity = 3
# outbound.length = 2
# outbound.quantity = 3
[persist]
## Save peer profiles on disk (default: true)
# profiles = true

View File

@ -11,7 +11,7 @@ RuntimeDirectoryMode=0700
LogsDirectory=i2pd
LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/var/run/i2pd/i2pd.pid
### Uncomment, if auto restart needed
@ -23,8 +23,10 @@ KillSignal=SIGQUIT
#KillSignal=SIGINT
#TimeoutStopSec=10m
# If you have problems with hanging i2pd, you can try enable this
# If you have problems with hanging i2pd, you can try increase this
LimitNOFILE=4096
# To enable write of coredump uncomment this
#LimitCORE=infinity
PrivateDevices=yes
[Install]

View File

@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.21.1
Version: 2.31.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@ -47,23 +47,42 @@ cd build
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%if 0%{?mageia} > 7
pushd build
make %{?_smp_mflags}
popd
%else
make %{?_smp_mflags}
%endif
%install
cd build
pushd build
%if 0%{?mageia}
pushd build
%endif
chrpath -d i2pd
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
install -d -m 755 %{buildroot}%{_datadir}/i2pd
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.d/README %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d/README
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name}
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
@ -87,16 +106,47 @@ getent passwd i2pd >/dev/null || \
%files
%doc LICENSE README.md
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
%{_sbindir}/i2pd
%{_datadir}/i2pd/certificates
%config(noreplace) %{_sysconfdir}/i2pd/*
/%{_unitdir}/i2pd.service
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
%{_unitdir}/i2pd.service
%{_mandir}/man1/i2pd.1*
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
%{_datadir}/%{name}/certificates
%{_sharedstatedir}/i2pd/certificates
%changelog
* Fri Apr 10 2020 orignal <i2porignal@yandex.ru> - 2.31.0
- update to 2.31.0
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
- update to 2.30.0
* Mon Oct 21 2019 orignal <i2porignal@yandex.ru> - 2.29.0
- update to 2.29.0
* Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0
- update to 2.28.0
* Wed Jul 3 2019 orignal <i2porignal@yandex.ru> - 2.27.0
- update to 2.27.0
* Fri Jun 7 2019 orignal <i2porignal@yandex.ru> - 2.26.0
- update to 2.26.0
* Thu May 9 2019 orignal <i2porignal@yandex.ru> - 2.25.0
- update to 2.25.0
* Thu Mar 21 2019 orignal <i2porignal@yandex.ru> - 2.24.0
- update to 2.24.0
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
- update to 2.23.0
* Fri Nov 09 2018 r4sas <r4sas@i2pmail.org> - 2.22.0
- add support of tunnelsdir option
* Thu Feb 01 2018 r4sas <r4sas@i2pmail.org> - 2.18.0
- Initial i2pd-git based on i2pd 2.18.0-1 spec

View File

@ -1,5 +1,5 @@
Name: i2pd
Version: 2.21.1
Version: 2.31.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@ -45,24 +45,43 @@ cd build
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%if 0%{?mageia} > 7
pushd build
make %{?_smp_mflags}
popd
%else
make %{?_smp_mflags}
%endif
%install
cd build
pushd build
%if 0%{?mageia}
pushd build
%endif
chrpath -d i2pd
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
install -d -m 755 %{buildroot}%{_datadir}/i2pd
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
%pre
@ -89,6 +108,7 @@ getent passwd i2pd >/dev/null || \
%{_sbindir}/i2pd
%{_datadir}/i2pd/certificates
%config(noreplace) %{_sysconfdir}/i2pd/*
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
/%{_unitdir}/i2pd.service
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
@ -96,7 +116,38 @@ getent passwd i2pd >/dev/null || \
%changelog
* Thu Oct 22 2018 orignal <i2porignal@yandex.ru> - 2.21.1
* Fri Apr 10 2020 orignal <i2porignal@yandex.ru> - 2.31.0
- update to 2.31.0
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
- update to 2.30.0
* Mon Oct 21 2019 orignal <i2porignal@yandex.ru> - 2.29.0
- update to 2.29.0
* Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0
- update to 2.28.0
* Wed Jul 3 2019 orignal <i2porignal@yandex.ru> - 2.27.0
- update to 2.27.0
* Fri Jun 7 2019 orignal <i2porignal@yandex.ru> - 2.26.0
- update to 2.26.0
* Thu May 9 2019 orignal <i2porignal@yandex.ru> - 2.25.0
- update to 2.25.0
* Thu Mar 21 2019 orignal <i2porignal@yandex.ru> - 2.24.0
- update to 2.24.0
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
- update to 2.23.0
* Fri Nov 09 2018 r4sas <r4sas@i2pmail.org> - 2.22.0
- update to 2.22.0
- add support of tunnelsdir option
* Mon Oct 22 2018 orignal <i2porignal@yandex.ru> - 2.21.1
- update to 2.21.1
* Thu Oct 4 2018 orignal <i2porignal@yandex.ru> - 2.21.0

View File

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

View File

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

4
contrib/tunnels.d/README Normal file
View File

@ -0,0 +1,4 @@
# In that directory you can store separated config files for every tunnel.
# Please read documentation for more info.
#
# You can find examples in /usr/share/doc/i2pd/tunnels.d directory

View File

@ -23,11 +23,9 @@
#include "ClientContext.h"
#include "Crypto.h"
#include "UPnP.h"
#include "Timestamp.h"
#include "util.h"
#include "Event.h"
#include "Websocket.h"
namespace i2p
{
namespace util
@ -41,9 +39,7 @@ namespace i2p
std::unique_ptr<i2p::http::HTTPServer> httpServer;
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
std::unique_ptr<i2p::transport::UPnP> UPnP;
#ifdef WITH_EVENTS
std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
#endif
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
};
Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
@ -60,12 +56,12 @@ namespace i2p
return service;
}
bool Daemon_Singleton::init(int argc, char* argv[]) {
return init(argc, argv, nullptr);
}
bool Daemon_Singleton::init(int argc, char* argv[]) {
return init(argc, argv, nullptr);
}
bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
{
bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
{
i2p::config::Init();
i2p::config::ParseCmdline(argc, argv);
@ -108,10 +104,10 @@ namespace i2p
logs = "file";
i2p::log::Logger().SetLogLevel(loglevel);
if (logstream) {
LogPrint(eLogInfo, "Log: will send messages to std::ostream");
i2p::log::Logger().SendTo (logstream);
} else if (logs == "file") {
if (logstream) {
LogPrint(eLogInfo, "Log: will send messages to std::ostream");
i2p::log::Logger().SendTo (logstream);
} else if (logs == "file") {
if (logfile == "")
logfile = i2p::fs::DataDirPath("i2pd.log");
LogPrint(eLogInfo, "Log: will send messages to ", logfile);
@ -125,7 +121,7 @@ namespace i2p
// use stdout -- default
}
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
LogPrint(eLogDebug, "FS: main config file: ", config);
LogPrint(eLogDebug, "FS: data directory: ", datadir);
@ -149,17 +145,27 @@ namespace i2p
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
i2p::context.UpdatePort (port);
}
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2)
{
bool published; i2p::config::GetOption("ntcp2.published", published);
if (published)
{
uint16_t port; i2p::config::GetOption("ntcp2.port", port);
i2p::context.PublishNTCP2Address (port, true); // publish
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
if (!ntcp && !ntcp2port) ntcp2port = port; // use standard port
i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
if (ipv6)
{
std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
}
}
else
i2p::context.PublishNTCP2Address (port, false); // unpublish
@ -221,15 +227,15 @@ namespace i2p
if (family.length () > 0)
LogPrint(eLogInfo, "Daemon: family set to ", family);
bool trust; i2p::config::GetOption("trust.enabled", trust);
if (trust)
{
LogPrint(eLogInfo, "Daemon: explicit trust enabled");
std::string fam; i2p::config::GetOption("trust.family", fam);
bool trust; i2p::config::GetOption("trust.enabled", trust);
if (trust)
{
LogPrint(eLogInfo, "Daemon: explicit trust enabled");
std::string fam; i2p::config::GetOption("trust.family", fam);
std::string routers; i2p::config::GetOption("trust.routers", routers);
bool restricted = false;
if (fam.length() > 0)
{
if (fam.length() > 0)
{
std::set<std::string> fams;
size_t pos = 0, comma;
do
@ -241,7 +247,7 @@ namespace i2p
while (comma != std::string::npos);
i2p::transport::transports.RestrictRoutesToFamilies(fams);
restricted = fams.size() > 0;
}
}
if (routers.length() > 0) {
std::set<i2p::data::IdentHash> idents;
size_t pos = 0, comma;
@ -254,20 +260,21 @@ namespace i2p
pos = comma + 1;
}
while (comma != std::string::npos);
LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routesrs");
LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers");
i2p::transport::transports.RestrictRoutesToRouters(idents);
restricted = idents.size() > 0;
}
if(!restricted)
LogPrint(eLogError, "Daemon: no trusted routers of families specififed");
}
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
if (hidden)
{
LogPrint(eLogInfo, "Daemon: using hidden mode");
i2p::data::netdb.SetHidden(true);
}
return true;
}
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
if (hidden)
{
LogPrint(eLogInfo, "Daemon: using hidden mode");
i2p::data::netdb.SetHidden(true);
}
return true;
}
bool Daemon_Singleton::start()
@ -282,6 +289,13 @@ namespace i2p
d.UPnP->Start ();
}
bool nettime; i2p::config::GetOption("nettime.enabled", nettime);
if (nettime)
{
d.m_NTPSync = std::unique_ptr<i2p::util::NTPTimeSync>(new i2p::util::NTPTimeSync);
d.m_NTPSync->Start ();
}
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports");
@ -303,7 +317,7 @@ namespace i2p
bool http; i2p::config::GetOption("http.enabled", http);
if (http) {
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
d.httpServer->Start();
@ -325,37 +339,29 @@ namespace i2p
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
d.m_I2PControlService->Start ();
}
#ifdef WITH_EVENTS
bool websocket; i2p::config::GetOption("websockets.enabled", websocket);
if(websocket) {
std::string websocketAddr; i2p::config::GetOption("websockets.address", websocketAddr);
uint16_t websocketPort; i2p::config::GetOption("websockets.port", websocketPort);
LogPrint(eLogInfo, "Daemon: starting Websocket server at ", websocketAddr, ":", websocketPort);
d.m_WebsocketServer = std::unique_ptr<i2p::event::WebsocketServer>(new i2p::event::WebsocketServer (websocketAddr, websocketPort));
d.m_WebsocketServer->Start();
i2p::event::core.SetListener(d.m_WebsocketServer->ToListener());
}
#endif
return true;
}
bool Daemon_Singleton::stop()
{
#ifdef WITH_EVENTS
i2p::event::core.SetListener(nullptr);
#endif
LogPrint(eLogInfo, "Daemon: shutting down");
LogPrint(eLogInfo, "Daemon: stopping Client");
i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
i2p::tunnel::tunnels.Stop();
if (d.UPnP) {
if (d.UPnP)
{
d.UPnP->Stop ();
d.UPnP = nullptr;
}
if (d.m_NTPSync)
{
d.m_NTPSync->Stop ();
d.m_NTPSync = nullptr;
}
LogPrint(eLogInfo, "Daemon: stopping Transports");
i2p::transport::transports.Stop();
LogPrint(eLogInfo, "Daemon: stopping NetDB");
@ -371,13 +377,6 @@ namespace i2p
d.m_I2PControlService->Stop ();
d.m_I2PControlService = nullptr;
}
#ifdef WITH_EVENTS
if (d.m_WebsocketServer) {
LogPrint(eLogInfo, "Daemon: stopping Websocket server");
d.m_WebsocketServer->Stop();
d.m_WebsocketServer = nullptr;
}
#endif
i2p::crypto::TerminateCrypto ();
i2p::log::Logger().Stop();

View File

@ -54,6 +54,7 @@ namespace http {
" body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n"
" a, .slide label { text-decoration: none; color: #894C84; }\r\n"
" a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n"
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial; width: 1.5em;}\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"
@ -63,9 +64,11 @@ namespace http {
" .tunnel.failed { color: #D33F3F; }\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"
" .slide p, .slide [type='checkbox']{ display:none; }\r\n"
" .slide [type='checkbox']:checked ~ p { display:block; margin-top: 0; padding: 0; }\r\n"
" table { display: table; border-collapse: collapse; text-align: center; }\r\n"
" table.extaddr { text-align: left; }\r\n table.services { width: 100%; }"
" .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n"
" .slide div.content, .slide [type='checkbox'] { display: none; }\r\n"
" .slide [type='checkbox']:checked ~ div.content { 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";
@ -89,10 +92,12 @@ namespace http {
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_COMMAND_KILLSTREAM[] = "closestream";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
static std::string ConvertTime (uint64_t time);
std::map<uint32_t, uint32_t> HTTPConnection::m_Tokens;
static void ShowUptime (std::stringstream& s, int seconds)
{
@ -155,6 +160,8 @@ namespace http {
static void ShowPageHead (std::stringstream& s)
{
std::string webroot;
i2p::config::GetOption("http.webroot", webroot);
s <<
"<!DOCTYPE html>\r\n"
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
@ -173,16 +180,18 @@ namespace http {
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
"<div class=wrapper>\r\n"
"<div class=left>\r\n"
" <a href=\"/\">Main page</a><br>\r\n<br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
" <a href=\"" << webroot << "\">Main page</a><br>\r\n<br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n";
if (i2p::context.IsFloodfill ())
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n";
s <<
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
s <<
"</div>\r\n"
"<div class=right>";
@ -201,10 +210,7 @@ namespace http {
s << "<b>ERROR:</b>&nbsp;" << string << "<br>\r\n";
}
void ShowStatus (
std::stringstream& s,
bool includeHiddenContent,
i2p::http::OutputFormatEnum outputFormat)
void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat)
{
s << "<b>Uptime:</b> ";
ShowUptime(s, i2p::context.GetUptime ());
@ -231,11 +237,8 @@ namespace http {
}
s << "<br>\r\n";
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
if (auto remains = Daemon.gracefulShutdownInterval) {
s << "<b>Stopping in:</b> ";
s << remains << " seconds";
s << "<br>\r\n";
}
if (auto remains = Daemon.gracefulShutdownInterval)
s << "<b>Stopping in:</b> " << remains << " seconds<br>\r\n";
#endif
auto family = i2p::context.GetFamily ();
if (family.length () > 0)
@ -251,51 +254,56 @@ namespace http {
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
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'>";
if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) {
s << "<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 << "<div class='slide'>";
if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) {
s << "<label for='slide-info'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide-info'/>\r\n<div class='content'>\r\n";
}
if(includeHiddenContent) {
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
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" ;
s << "<b>Our external address:</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
{
s << "<tr>\r\n";
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
{
s << "NTCP2";
s << "<td>NTCP2";
if (address->host.is_v6 ()) s << "v6";
s << "&nbsp;&nbsp; supported <br>\r\n";
s << "</td><td>supported</td>\r\n</tr>\r\n";
continue;
}
switch (address->transportStyle)
{
case i2p::data::RouterInfo::eTransportNTCP:
{
s << "NTCP";
s << "<td>NTCP";
if (address->IsPublishedNTCP2 ()) s << "2";
if (address->host.is_v6 ()) s << "v6";
s << "&nbsp;&nbsp;";
s << "</td>\r\n";
break;
}
case i2p::data::RouterInfo::eTransportSSU:
{
s << "<td>SSU";
if (address->host.is_v6 ())
s << "SSUv6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
else
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
break;
s << "v6";
s << "</td>\r\n";
break;
}
default:
s << "Unknown&nbsp;&nbsp;";
s << "<td>Unknown</td>\r\n";
}
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n</tr>\r\n";
}
}
s << "</p>\r\n</div>\r\n";
if(outputFormat==OutputFormatEnum::forQtUi) {
s << "<br>";
}
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
s << "</tbody></table>\r\n";
}
s << "</div>\r\n</div>\r\n";
if(outputFormat==OutputFormatEnum::forQtUi) {
s << "<br>";
}
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
s << "<b>LeaseSets:</b> " << i2p::data::netdb.GetNumLeaseSets () << "<br>\r\n";
@ -306,26 +314,27 @@ namespace http {
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n<br>\r\n";
if(outputFormat==OutputFormatEnum::forWebConsole) {
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";
}
if(outputFormat==OutputFormatEnum::forWebConsole) {
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
s << "<table class=\"services\"><caption>Services</caption><tbody>\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";
s << "<tr><td>" << "I2PControl" << "</td><td><div class='" << ((i2pcontrol) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "</tbody></table>\r\n";
}
}
void ShowLocalDestinations (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
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 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
}
@ -340,7 +349,7 @@ namespace http {
{
auto ident = dest->GetIdentHash ();
auto& name = dest->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
s << name << " ]</a> &#8660; " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"<br>\r\n" << std::endl;
}
}
@ -349,16 +358,25 @@ namespace http {
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest)
{
s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"11\" wrap=\"on\">";
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"11\" wrap=\"on\">";
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
if (dest->IsEncryptedLeaseSet ())
{
i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
s << "<div class='slide'><label for='slide-b33'><b>Encrypted B33 address:</b></label>\r\n<input type='checkbox' id='slide-b33'/>\r\n<div class='content'>\r\n";
s << blinded.ToB33 () << ".b32.i2p<br>\r\n";
s << "</div>\r\n</div>\r\n";
}
if(dest->GetNumRemoteLeaseSets())
{
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";
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<div class='content'>\r\n<table><thead><th>Address</th><th>Type</th><th>EncType</th></thead><tbody>";
for(auto& it: dest->GetLeaseSets ())
s << it.second->GetIdentHash ().ToBase32 () << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
s << "<tr><td>" << it.first.ToBase32 () << "</td><td>" << (int)it.second->GetStoreType () << "</td><td>" << (int)it.second->GetEncryptionType () <<"</td></tr>\r\n";
s << "</tbody></table>\r\n</div>\r\n</div>\r\n<br>\r\n";
} else
s << "<b>LeaseSets:</b> <i>0</i><br>\r\n";
s << "<b>LeaseSets:</b> <i>0</i><br>\r\n<br>\r\n";
auto pool = dest->GetTunnelPool ();
if (pool)
{
@ -383,28 +401,31 @@ namespace http {
if (!dest->GetSessions ().empty ()) {
std::stringstream tmp_s; uint32_t out_tags = 0;
for (const auto& it: dest->GetSessions ()) {
tmp_s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
out_tags = out_tags + it.second->GetNumOutgoingTags ();
}
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n" << tmp_s.str () << "</p>\r\n</div>\r\n";
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n"
<< "<div class='content'>\r\n<table><tbody><thead><th>Destination</th><th>Amount</th></thead>\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
} else
s << "Outgoing: <i>0</i><br>\r\n";
s << "<br>\r\n";
}
void ShowLocalDestination (std::stringstream& s, const std::string& b32)
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token)
{
s << "<b>Local Destination:</b><br>\r\n<br>\r\n";
i2p::data::IdentHash ident;
ident.FromBase32 (b32);
auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest)
{
ShowLeaseSetDestination (s, dest);
// show streams
s << "<table><caption>Streams</caption>\r\n<tr>";
s << "<th>StreamID</th>";
s << "<th>Destination</th>";
s << "<table>\r\n<caption>Streams</caption>\r\n<thead>\r\n<tr>";
s << "<th style=\"width:25px;\">StreamID</th>";
s << "<th style=\"width:5px;\" \\>"; // Stream closing button column
s << "<th class=\"streamdest\">Destination</th>";
s << "<th>Sent</th>";
s << "<th>Received</th>";
s << "<th>Out</th>";
@ -413,13 +434,20 @@ namespace http {
s << "<th>RTT</th>";
s << "<th>Window</th>";
s << "<th>Status</th>";
s << "</tr>\r\n";
s << "</tr>\r\n</thead>\r\n<tbody>\r\n";
for (const auto& it: dest->GetAllStreams ())
{
auto streamDest = i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ());
s << "<tr>";
s << "<td>" << it->GetSendStreamID () << "</td>";
s << "<td>" << i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()) << "</td>";
s << "<td>" << it->GetRecvStreamID () << "</td>";
if (it->GetRecvStreamID ()) {
s << "<td><a class=\"button\" href=\"/?cmd=" << HTTP_COMMAND_KILLSTREAM << "&b32=" << b32 << "&streamID="
<< it->GetRecvStreamID () << "&token=" << token << "\" title=\"Close stream\"> &#10008; </a></td>";
} else {
s << "<td \\>";
}
s << "<td class=\"streamdest\" title=\"" << streamDest << "\">" << streamDest << "</td>";
s << "<td>" << it->GetNumSentBytes () << "</td>";
s << "<td>" << it->GetNumReceivedBytes () << "</td>";
s << "<td>" << it->GetSendQueueSize () << "</td>";
@ -430,7 +458,7 @@ namespace http {
s << "<td>" << (int)it->GetStatus () << "</td>";
s << "</tr>\r\n";
}
s << "</table>";
s << "</tbody>\r\n</table>";
}
}
@ -452,35 +480,57 @@ namespace http {
void ShowLeasesSets(std::stringstream& s)
{
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)
{
// create copy of lease set so we extract leases
i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen());
s << "<div class='leaseset";
if (ls.IsExpired())
s << " expired"; // additional css class for expired
s << "'>\r\n";
if (!ls.IsValid())
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\r\n";
s << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<p class='content'>\r\n";
s << "<b>Expires:</b> " << ConvertTime(ls.GetExpirationTime()) << "<br>\r\n";
auto leases = ls.GetNonExpiredLeases();
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
for ( auto & l : leases )
if (i2p::data::netdb.GetNumLeaseSets ())
{
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 << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
s << "<b>EndDate:</b> " << ConvertTime(l->endDate) << "<br>\r\n";
// create copy of lease set so we extract leases
auto storeType = leaseSet->GetStoreType ();
std::unique_ptr<i2p::data::LeaseSet> ls;
if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET)
ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
else
ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
if (!ls) return;
s << "<div class='leaseset";
if (ls->IsExpired())
s << " expired"; // additional css class for expired
s << "'>\r\n";
if (!ls->IsValid())
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\r\n";
s << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<div class='content'>\r\n";
s << "<b>Store type:</b> " << (int)storeType << "<br>\r\n";
s << "<b>Expires:</b> " << ConvertTime(ls->GetExpirationTime()) << "<br>\r\n";
if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET || storeType == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2)
{
// leases information is available
auto leases = ls->GetNonExpiredLeases();
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
for ( auto & l : leases )
{
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
s << "<b>EndDate:</b> " << ConvertTime(l->endDate) << "<br>\r\n";
}
}
s << "</div>\r\n</div>\r\n</div>\r\n";
}
s << "</p>\r\n</div>\r\n</div>\r\n";
}
);
// end for each lease set
);
// end for each lease set
}
else if (!i2p::context.IsFloodfill ())
{
s << "<b>LeaseSets:</b> not floodfill.<br>\r\n";
}
else
{
s << "<b>LeaseSets:</b> 0<br>\r\n";
}
}
void ShowTunnels (std::stringstream& s)
@ -510,47 +560,55 @@ namespace http {
static void ShowCommands (std::stringstream& s, uint32_t token)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
/* commands */
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=\"" << webroot << "?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 ())
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
if (Daemon.gracefulShutdownInterval)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start 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>";
s << " <a href=\"" << webroot << "?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";
s << " <a href=\"" << webroot << "?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 << " <a href=\"" << webroot << "?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";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
}
void ShowTransitTunnels (std::stringstream& s)
{
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
if(i2p::tunnel::tunnels.CountTransitTunnels())
{
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
s << it->GetTunnelID () << " &#8658; ";
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
s << " &#8658; " << it->GetTunnelID ();
else
s << " &#8658; " << it->GetTunnelID () << " &#8658; ";
s << " " << it->GetNumTransmittedBytes () << "<br>\r\n";
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
{
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
s << it->GetTunnelID () << " &#8658; ";
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
s << " &#8658; " << it->GetTunnelID ();
else
s << " &#8658; " << it->GetTunnelID () << " &#8658; ";
s << " " << it->GetNumTransmittedBytes () << "<br>\r\n";
}
}
else
{
s << "<b>Transit tunnels:</b> no transit tunnels currently built.<br>\r\n";
}
}
@ -584,13 +642,15 @@ namespace http {
}
if (!tmp_s.str ().empty ())
{
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "'><b>" << name << "</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "'/>\r\n<p class='content'>";
s << tmp_s.str () << "</p>\r\n</div>\r\n";
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "'><b>" << name
<< "</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "'/>\r\n<div class='content'>"
<< tmp_s.str () << "</div>\r\n</div>\r\n";
}
if (!tmp_s6.str ().empty ())
{
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "v6'><b>" << name << "v6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "v6'/>\r\n<p class='content'>";
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "v6'><b>" << name
<< "v6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "v6'/>\r\n<div class='content'>"
<< tmp_s6.str () << "</div>\r\n</div>\r\n";
}
}
@ -617,7 +677,7 @@ namespace http {
auto sessions = ssuServer->GetSessions ();
if (!sessions.empty ())
{
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'>";
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<div class='content'>";
for (const auto& it: sessions)
{
auto endpoint = it.second->GetRemoteEndpoint ();
@ -629,12 +689,12 @@ namespace http {
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "</p>\r\n</div>\r\n";
s << "</div>\r\n</div>\r\n";
}
auto sessions6 = ssuServer->GetSessionsV6 ();
if (!sessions6.empty ())
{
s << "<div class='slide'><label for='slide_ssuv6'><b>SSUv6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssuv6'/>\r\n<p class='content'>";
s << "<div class='slide'><label for='slide_ssuv6'><b>SSUv6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssuv6'/>\r\n<div class='content'>";
for (const auto& it: sessions6)
{
auto endpoint = it.second->GetRemoteEndpoint ();
@ -646,29 +706,38 @@ namespace http {
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "</p>\r\n</div>\r\n";
s << "</div>\r\n</div>\r\n";
}
}
}
void ShowSAMSessions (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) {
if (!sam)
{
ShowError(s, "SAM disabled");
return;
}
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
for (auto& it: sam->GetSessions ())
if(sam->GetSessions ().size ())
{
auto& name = it.second->localDestination->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
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=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
}
}
else
s << "<b>SAM Sessions:</b> no sessions currently running.<br>\r\n";
}
static void ShowSAMSession (std::stringstream& s, const std::string& id)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
s << "<b>SAM Session:</b><br>\r\n<br>\r\n";
auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) {
@ -681,7 +750,7 @@ namespace http {
return;
}
auto& ident = session->localDestination->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
s << "<br>\r\n";
s << "<b>Streams:</b><br>\r\n";
@ -701,11 +770,12 @@ namespace http {
void ShowI2PTunnels (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
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=\"" << webroot << "?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;
@ -714,7 +784,7 @@ namespace http {
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?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;
@ -723,7 +793,7 @@ namespace http {
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?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;
@ -734,7 +804,7 @@ namespace http {
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?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 ();
@ -748,7 +818,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=\"" << webroot << "?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;
@ -761,7 +831,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=\"" << webroot << "?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;
@ -780,8 +850,7 @@ namespace http {
}
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0),
expected_host(hostname)
m_Socket (socket), m_BufferLen (0), expected_host(hostname)
{
/* cache options */
i2p::config::GetOption("http.auth", needAuth);
@ -833,7 +902,8 @@ namespace http {
m_Socket->close ();
}
bool HTTPConnection::CheckAuth (const HTTPReq & req) {
bool HTTPConnection::CheckAuth (const HTTPReq & req)
{
/* method #1: http://user:pass@127.0.0.1:7070/ */
if (req.uri.find('@') != std::string::npos) {
URL url;
@ -844,22 +914,8 @@ namespace http {
auto provided = req.GetHeader ("Authorization");
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];
std::size_t len = 0;
len = i2p::data::ByteStreamToBase64((unsigned char *)expected.c_str(), expected.length(), b64_creds, b64_sz);
/* if we decoded properly then check credentials */
if(len) {
b64_creds[len] = '\0';
expected = "Basic ";
expected += b64_creds;
result = expected == provided;
}
delete [] b64_creds;
return result;
std::string expected = "Basic " + i2p::data::ToBase64Standard (user + ":" + pass);
if (expected == provided) return true;
}
LogPrint(eLogWarning, "HTTPServer: auth failure from ", m_Socket->remote_endpoint().address ());
@ -909,7 +965,7 @@ namespace http {
} else if (req.uri.find("cmd=") != std::string::npos) {
HandleCommand (req, res, s);
} else {
ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole);
ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole);
res.add_header("Refresh", "10");
}
ShowPageTail (s);
@ -919,7 +975,23 @@ namespace http {
SendReply (res, content);
}
std::map<uint32_t, uint32_t> HTTPConnection::m_Tokens;
uint32_t HTTPConnection::CreateToken ()
{
uint32_t token;
RAND_bytes ((uint8_t *)&token, 4);
token &= 0x7FFFFFFF; // clear first bit
auto ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = m_Tokens.begin (); it != m_Tokens.end (); )
{
if (ts > it->second + TOKEN_EXPIRATION_TIMEOUT)
it = m_Tokens.erase (it);
else
++it;
}
m_Tokens[token] = ts;
return token;
}
void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{
std::map<std::string, std::string> params;
@ -936,18 +1008,7 @@ namespace http {
ShowTunnels (s);
else if (page == HTTP_PAGE_COMMANDS)
{
uint32_t token;
RAND_bytes ((uint8_t *)&token, 4);
token &= 0x7FFFFFFF; // clear first bit
auto ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = m_Tokens.begin (); it != m_Tokens.end (); )
{
if (ts > it->second + TOKEN_EXPIRATION_TIMEOUT)
it = m_Tokens.erase (it);
else
++it;
}
m_Tokens[token] = ts;
uint32_t token = CreateToken ();
ShowCommands (s, token);
}
else if (page == HTTP_PAGE_TRANSIT_TUNNELS)
@ -955,7 +1016,10 @@ namespace http {
else if (page == HTTP_PAGE_LOCAL_DESTINATIONS)
ShowLocalDestinations (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATION)
ShowLocalDestination (s, params["b32"]);
{
uint32_t token = CreateToken ();
ShowLocalDestination (s, params["b32"], token);
}
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
ShowI2CPLocalDestination (s, params["i2cp_id"]);
else if (page == HTTP_PAGE_SAM_SESSIONS)
@ -981,7 +1045,10 @@ namespace http {
url.parse(req.uri);
url.parse_query(params);
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
std::string redirect = "5; url=" + webroot + "?page=commands";
std::string token = params["token"];
if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ())
{
ShowError(s, "Invalid token");
@ -997,43 +1064,85 @@ namespace http {
i2p::context.SetAcceptsTunnels (true);
else if (cmd == HTTP_COMMAND_DISABLE_TRANSIT)
i2p::context.SetAcceptsTunnels (false);
else if (cmd == HTTP_COMMAND_SHUTDOWN_START) {
else if (cmd == HTTP_COMMAND_SHUTDOWN_START)
{
i2p::context.SetAcceptsTunnels (false);
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
Daemon.gracefulShutdownInterval = 10*60;
#elif defined(WIN32_APP)
i2p::win32::GracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
}
else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL)
{
i2p::context.SetAcceptsTunnels (true);
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
Daemon.gracefulShutdownInterval = 0;
#elif defined(WIN32_APP)
i2p::win32::StopGracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
}
else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW)
{
#ifndef WIN32_APP
Daemon.running = false;
#else
i2p::win32::StopWin32App ();
#endif
} else if (cmd == HTTP_COMMAND_LOGLEVEL){
}
else if (cmd == HTTP_COMMAND_LOGLEVEL)
{
std::string level = params["level"];
SetLogLevel (level);
} else {
}
else if (cmd == HTTP_COMMAND_KILLSTREAM)
{
std::string b32 = params["b32"];
uint32_t streamID = std::stoul(params["streamID"], nullptr);
i2p::data::IdentHash ident;
ident.FromBase32 (b32);
auto dest = i2p::client::context.FindLocalDestination (ident);
if (streamID)
{
if (dest)
{
if(dest->DeleteStream (streamID))
s << "<b>SUCCESS</b>:&nbsp;Stream closed<br><br>\r\n";
else
s << "<b>ERROR</b>:&nbsp;Stream not found or already was closed<br><br>\r\n";
}
else
s << "<b>ERROR</b>:&nbsp;Destination not found<br><br>\r\n";
}
else
s << "<b>ERROR</b>:&nbsp;StreamID can be null<br><br>\r\n";
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">Return to destination page</a><br>\r\n";
s << "<p>You will be redirected back in 5 seconds</b>";
redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32;
res.add_header("Refresh", redirect.c_str());
return;
}
else
{
res.code = 400;
ShowError(s, "Unknown command: " + cmd);
return;
}
s << "<b>SUCCESS</b>:&nbsp;Command accepted<br><br>\r\n";
s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a><br>\r\n";
s << "<p>You will be redirected in 5 seconds</b>";
res.add_header("Refresh", "5; url=/?page=commands");
res.add_header("Refresh", redirect.c_str());
}
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
{
reply.add_header("X-Frame-Options", "SAMEORIGIN");
reply.add_header("X-Content-Type-Options", "nosniff");
reply.add_header("X-XSS-Protection", "1; mode=block");
reply.add_header("Content-Type", "text/html");
reply.body = content;

View File

@ -35,11 +35,11 @@ namespace http
void HandlePage (const HTTPReq & req, HTTPRes & res, std::stringstream& data);
void HandleCommand (const HTTPReq & req, HTTPRes & res, std::stringstream& data);
void SendReply (HTTPRes & res, std::string & content);
uint32_t CreateToken ();
private:
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
boost::asio::deadline_timer m_Timer;
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
size_t m_BufferLen;
std::string m_SendBuffer;
@ -89,7 +89,7 @@ namespace http
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
} // http
} // i2p

View File

@ -394,13 +394,15 @@ namespace client
void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
bool first = true;
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
auto it1 = m_RouterInfoHandlers.find (it->first);
if (it1 != m_RouterInfoHandlers.end ())
{
if (it != params.begin ()) results << ",";
if (!first) results << ",";
else first = false;
(this->*(it1->second))(results);
}
else
@ -569,8 +571,8 @@ namespace client
EVP_PKEY_assign_RSA (pkey, rsa);
X509 * x509 = X509_new ();
ASN1_INTEGER_set (X509_get_serialNumber (x509), 1);
X509_gmtime_adj (X509_get_notBefore (x509), 0);
X509_gmtime_adj (X509_get_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration
X509_gmtime_adj (X509_getm_notBefore (x509), 0);
X509_gmtime_adj (X509_getm_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration
X509_set_pubkey (x509, pkey); // public key
X509_NAME * name = X509_get_subject_name (x509);
X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *)"A1", -1, -1, 0); // country (Anonymous proxy)

View File

@ -79,43 +79,59 @@ namespace transport
void UPnP::Discover ()
{
#if MINIUPNPC_API_VERSION >= 14
int nerror = 0;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror);
#elif ( MINIUPNPC_API_VERSION >= 8 || defined(UPNPDISCOVER_SUCCESS) )
int nerror = 0;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
bool isError;
int err;
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNPDISCOVER_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 14)
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
#else
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0);
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, &err);
#endif
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;
#endif // MINIUPNPC_API_VERSION >= 8
{
// notify satrting thread
// notify starting thread
std::unique_lock<std::mutex> l(m_StartedMutex);
m_Started.notify_all ();
}
int r;
r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
if (r == 1)
if (isError)
{
r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
return;
}
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
m_upnpUrlsInitialized=err!=0;
if (err == UPNP_IGD_VALID_CONNECTED)
{
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress() returned ", r);
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
return;
}
else
{
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0])
{
LogPrint (eLogError, "UPnP: GetExternalIPAddress() failed.");
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
return;
}
}
}
else
{
LogPrint (eLogError, "UPnP: GetValidIGD() failed.");
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
return;
}
@ -126,6 +142,20 @@ namespace transport
PortMapping ();
}
int UPnP::CheckMapping (const char* port, const char* type)
{
int err = UPNPCOMMAND_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 10)
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL, NULL, NULL, NULL, NULL);
#elif ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL, NULL, NULL, NULL);
#else
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL);
#endif
return err;
}
void UPnP::PortMapping ()
{
const auto& a = context.GetRouterInfo().GetAddresses();
@ -134,13 +164,47 @@ namespace transport
if (!address->host.is_v6 () && address->port)
TryPortMapping (address);
}
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
PortMapping ();
});
}
void UPnP::TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
std::string strDesc; i2p::config::GetOption("upnp.name", strDesc);
int err = UPNPCOMMAND_SUCCESS;
// check for existing mapping
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
#else
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL);
#endif
if (err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
return;
}
else
{
LogPrint (eLogInfo, "UPnP: port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
return;
}
}
else
{
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return;
}
}
void UPnP::CloseMapping ()
@ -153,53 +217,42 @@ namespace transport
}
}
void UPnP::TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
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);
return;
}
else
{
LogPrint (eLogDebug, "UPnP: Port Mapping successful. (", m_NetworkAddr ,":", strPort, " type ", strType, " -> ", m_externalIPAddress ,":", strPort ,")");
return;
}
}
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
if(!m_upnpUrlsInitialized) {
return;
}
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int r = 0;
r = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r);
int err = UPNPCOMMAND_SUCCESS;
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS)
{
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
}
}
void UPnP::Close ()
{
freeUPNPDevlist (m_Devlist);
m_Devlist = 0;
FreeUPNPUrls (&m_upnpUrls);
}
if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
switch (address->transportStyle)
{
case i2p::data::RouterInfo::eTransportNTCP:
return "TCP";
break;
return "TCP";
break;
case i2p::data::RouterInfo::eTransportSSU:
default:
return "UDP";
return "UDP";
}
}
}

View File

@ -19,20 +19,31 @@ namespace i2p
{
namespace transport
{
const int UPNP_RESPONSE_TIMEOUT = 2000; // in milliseconds
enum
{
UPNP_IGD_NONE = 0,
UPNP_IGD_VALID_CONNECTED = 1,
UPNP_IGD_VALID_NOT_CONNECTED = 2,
UPNP_IGD_INVALID = 3
};
class UPnP
{
public:
public:
UPnP ();
~UPnP ();
void Close ();
void Close ();
void Start ();
void Stop ();
void Start ();
void Stop ();
private:
private:
void Discover ();
int CheckMapping (const char* port, const char* type);
void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping ();
@ -41,23 +52,22 @@ namespace transport
void Run ();
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
private:
private:
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started;
std::mutex m_StartedMutex;
boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer;
struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData;
bool m_upnpUrlsInitialized=false;
struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData;
// For miniupnpc
char * m_MulticastIf = 0;
char * m_Minissdpdpath = 0;
struct UPNPDev * m_Devlist = 0;
char m_NetworkAddr[64];
char m_externalIPAddress[40];
// For miniupnpc
struct UPNPDev * m_Devlist = 0;
char m_NetworkAddr[64];
char m_externalIPAddress[40];
};
}
}
@ -65,14 +75,15 @@ namespace transport
#else // USE_UPNP
namespace i2p {
namespace transport {
/* class stub */
class UPnP {
public:
UPnP () {};
~UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
void Stop () {};
};
/* class stub */
class UPnP {
public:
UPnP () {};
~UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
void Stop () {};
};
}
}
#endif // USE_UPNP

4
debian/.gitignore vendored
View File

@ -1,9 +1,9 @@
debhelper-build-stamp
files
i2pd-dbg.substvars
i2pd-dbg/
i2pd.postinst.debhelper
i2pd.postrm.debhelper
i2pd.prerm.debhelper
i2pd.substvars
i2pd/
i2pd-dbg/

66
debian/changelog vendored
View File

@ -1,8 +1,72 @@
i2pd (2.31.0-1) unstable; urgency=medium
* updated to version 2.31.0
-- orignal <orignal@i2pmail.org> Fri, 10 Apr 2020 16:00:00 +0000
i2pd (2.30.0-1) unstable; urgency=medium
* updated to version 2.30.0/0.9.45
-- orignal <orignal@i2pmail.org> Tue, 25 Feb 2020 16:00:00 +0000
i2pd (2.29.0-1) unstable; urgency=medium
* updated to version 2.29.0/0.9.43
-- orignal <orignal@i2pmail.org> Mon, 21 Oct 2019 16:00:00 +0000
i2pd (2.28.0-1) unstable; urgency=medium
* updated to version 2.28.0/0.9.42
-- orignal <orignal@i2pmail.org> Tue, 27 Aug 2019 16:00:00 +0000
i2pd (2.27.0-1) unstable; urgency=medium
* updated to version 2.27.0/0.9.41
-- orignal <orignal@i2pmail.org> Wed, 3 Jul 2019 16:00:00 +0000
i2pd (2.26.0-1) unstable; urgency=medium
* updated to version 2.26.0
-- orignal <orignal@i2pmail.org> Fri, 7 Jun 2019 16:00:00 +0000
i2pd (2.25.0-1) unstable; urgency=medium
* updated to version 2.25.0/0.9.40
-- orignal <orignal@i2pmail.org> Thu, 9 May 2019 16:00:00 +0000
i2pd (2.24.0-1) unstable; urgency=medium
* updated to version 2.24.0/0.9.39
-- orignal <orignal@i2pmail.org> Thu, 21 Mar 2019 16:00:00 +0000
i2pd (2.23.0-1) unstable; urgency=medium
* updated to version 2.23.0/0.9.38
* update docs, dirs, install, links files
-- orignal <orignal@i2pmail.org> Mon, 21 Jan 2019 16:00:00 +0000
i2pd (2.22.0-1) unstable; urgency=medium
* updated to version 2.22.0/0.9.37
* update manpage (1)
* update links, install files to support tunnelsdir option
* renamed and updated patch (#1210)
-- r4sas <r4sas@i2pmail.org> Fri, 09 Nov 2018 02:00:00 +0000
i2pd (2.21.1-1) unstable; urgency=medium
* updated to version 2.21.1
-- orignal <orignal@i2pmail.org> Thu, 22 Oct 2018 16:00:00 +0000
-- orignal <orignal@i2pmail.org> Mon, 22 Oct 2018 16:00:00 +0000
i2pd (2.21.0-1) unstable; urgency=medium

1
debian/docs vendored
View File

@ -2,3 +2,4 @@ README.md
contrib/i2pd.conf
contrib/subscriptions.txt
contrib/tunnels.conf
contrib/tunnels.d

3
debian/i2pd.1 vendored
View File

@ -45,6 +45,9 @@ Log messages with full CLF-formatted date and time (\fIdisabled\fR by default)
\fB\-\-datadir=\fR
Path to storage of i2pd data (RI, keys, peer profiles, ...)
.TP
\fB\-\-tunnelsdir=\fR
Path to tunnels configuration files (default: \fI~/.i2pd/tunnels.d\fR or \fI/var/lib/i2pd/tunnels.d\fR)
.TP
\fB\-\-host=\fR
The external IP address
.TP

3
debian/i2pd.init vendored
View File

@ -18,6 +18,7 @@ DAEMON_OPTS="" # Arguments to run the daemon with
PIDFILE=/var/run/$NAME/$NAME.pid
I2PCONF=/etc/$NAME/i2pd.conf
TUNCONF=/etc/$NAME/tunnels.conf
TUNDIR=/etc/$NAME/tunnels.conf.d
LOGFILE=/var/log/$NAME/$NAME.log
USER="i2pd"
@ -53,7 +54,7 @@ do_start()
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
--pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \
--tunnelsdir=$TUNDIR --pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \
|| return 2
return $?
}

1
debian/i2pd.install vendored
View File

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

1
debian/i2pd.links vendored
View File

@ -1,4 +1,5 @@
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d
usr/share/i2pd/certificates var/lib/i2pd/certificates

3
debian/i2pd.openrc vendored
View File

@ -4,10 +4,11 @@ pidfile="/var/run/i2pd/i2pd.pid"
logfile="/var/log/i2pd/i2pd.log"
mainconf="/etc/i2pd/i2pd.conf"
tunconf="/etc/i2pd/tunnels.conf"
tundir="/etc/i2pd/tunnels.conf.d"
name="i2pd"
command="/usr/sbin/i2pd"
command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --pidfile=$pidfile"
command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --tunnelsdir=$tundir --pidfile=$pidfile"
description="i2p router written in C++"
required_dirs="/var/lib/i2pd"
required_files="$mainconf"

View File

@ -6,8 +6,8 @@ Bug: https://github.com/PurpleI2P/i2pd/issues/1210
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2018-08-25
--- i2pd-2.20.0.orig/contrib/i2pd.service
+++ i2pd-2.20.0/contrib/i2pd.service
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
@@ -6,10 +6,10 @@ After=network.target
[Service]
User=i2pd
@ -21,5 +21,5 @@ Last-Update: 2018-08-25
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/kill -HUP $MAINPID

View File

@ -1,2 +1,2 @@
01-tune-build-opts.patch
fix-#1210
02-fix-1210.patch

View File

@ -5,13 +5,13 @@
# SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
# Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
# Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \
# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp
# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Gost.cpp
LIB_SRC = $(wildcard $(LIB_SRC_DIR)/*.cpp)
#LIB_CLIENT_SRC = \
# AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \
# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp WebSocks.cpp
# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp
LIB_CLIENT_SRC = $(wildcard $(LIB_CLIENT_SRC_DIR)/*.cpp)

317
libi2pd/Blinding.cpp Normal file
View File

@ -0,0 +1,317 @@
#include <zlib.h> // for crc32
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include "Base.h"
#include "Crypto.h"
#include "Log.h"
#include "Timestamp.h"
#include "I2PEndian.h"
#include "Ed25519.h"
#include "Signature.h"
#include "Blinding.h"
namespace i2p
{
namespace data
{
static EC_POINT * BlindPublicKeyECDSA (const EC_GROUP * group, const EC_POINT * pub, const uint8_t * seed)
{
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order (group, q, ctx);
// calculate alpha = seed mod q
BIGNUM * alpha = BN_CTX_get (ctx);
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
BN_mod (alpha, alpha, q, ctx); // % q
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
auto p = EC_POINT_new (group);
EC_POINT_mul (group, p, alpha, nullptr, nullptr, ctx); // B*alpha
EC_POINT_add (group, p, pub, p, ctx); // pub + B*alpha
BN_CTX_end (ctx);
BN_CTX_free (ctx);
return p;
}
static void BlindPrivateKeyECDSA (const EC_GROUP * group, const BIGNUM * priv, const uint8_t * seed, BIGNUM * blindedPriv)
{
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order (group, q, ctx);
// calculate alpha = seed mod q
BIGNUM * alpha = BN_CTX_get (ctx);
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
BN_mod (alpha, alpha, q, ctx); // % q
BN_add (alpha, alpha, priv); // alpha = alpha + priv
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q
BN_mod (blindedPriv, alpha, q, ctx); // % q
BN_CTX_end (ctx);
BN_CTX_free (ctx);
}
static void BlindEncodedPublicKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * pub, const uint8_t * seed, uint8_t * blindedPub)
{
BIGNUM * x = BN_bin2bn (pub, publicKeyLen/2, NULL);
BIGNUM * y = BN_bin2bn (pub + publicKeyLen/2, publicKeyLen/2, NULL);
EC_POINT * p = EC_POINT_new (group);
EC_POINT_set_affine_coordinates_GFp (group, p, x, y, NULL);
EC_POINT * p1 = BlindPublicKeyECDSA (group, p, seed);
EC_POINT_free (p);
EC_POINT_get_affine_coordinates_GFp (group, p1, x, y, NULL);
EC_POINT_free (p1);
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
BN_free (x); BN_free (y);
}
static void BlindEncodedPrivateKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub)
{
BIGNUM * a = BN_bin2bn (priv, publicKeyLen/2, NULL);
BIGNUM * a1 = BN_new ();
BlindPrivateKeyECDSA (group, a, seed, a1);
BN_free (a);
i2p::crypto::bn2buf (a1, blindedPriv, publicKeyLen/2);
auto p = EC_POINT_new (group);
BN_CTX * ctx = BN_CTX_new ();
EC_POINT_mul (group, p, a1, nullptr, nullptr, ctx); // B*a1
BN_CTX_free (ctx);
BN_free (a1);
BIGNUM * x = BN_new(), * y = BN_new();
EC_POINT_get_affine_coordinates_GFp (group, p, x, y, NULL);
EC_POINT_free (p);
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
BN_free (x); BN_free (y);
}
template<typename Fn, typename...Args>
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
{
size_t publicKeyLength = 0;
EC_GROUP * group = nullptr;
switch (sigType)
{
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
{
publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH;
group = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
break;
}
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
{
publicKeyLength = i2p::crypto::ECDSAP384_KEY_LENGTH;
group = EC_GROUP_new_by_curve_name (NID_secp384r1);
break;
}
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
{
publicKeyLength = i2p::crypto::ECDSAP521_KEY_LENGTH;
group = EC_GROUP_new_by_curve_name (NID_secp521r1);
break;
}
default:
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA");
}
if (group)
{
blind (publicKeyLength, group, key, seed, std::forward<Args>(args)...);
EC_GROUP_free (group);
}
return publicKeyLength;
}
//----------------------------------------------------------
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
m_IsClientAuth (clientAuth)
{
if (!identity) return;
auto len = identity->GetSigningPublicKeyLen ();
m_PublicKey.resize (len);
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
m_SigType = identity->GetSigningKeyType ();
m_BlindedSigType = m_SigType;
}
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
m_SigType (0) // 0 means invalid, we can't blind DSA, set it later
{
uint8_t addr[40]; // TODO: define length from b33
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
if (l < 32)
{
LogPrint (eLogError, "Blinding: malformed b33 ", b33);
return;
}
uint32_t checksum = crc32 (0, addr + 3, l - 3);
// checksum is Little Endian
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
uint8_t flags = addr[0];
size_t offset = 1;
if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
{
m_SigType = bufbe16toh (addr + offset); offset += 2;
m_BlindedSigType = bufbe16toh (addr + offset); offset += 2;
}
else // one byte sig
{
m_SigType = addr[offset]; offset++;
m_BlindedSigType = addr[offset]; offset++;
}
m_IsClientAuth = flags & B33_PER_CLIENT_AUTH_FLAG;
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (m_SigType));
if (blindedVerifier)
{
auto len = blindedVerifier->GetPublicKeyLen ();
if (offset + len <= l)
{
m_PublicKey.resize (len);
memcpy (m_PublicKey.data (), addr + offset, len);
}
else
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType);
}
else
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33");
}
std::string BlindedPublicKey::ToB33 () const
{
if (m_PublicKey.size () > 32) return ""; // assume 25519
uint8_t addr[35]; char str[60]; // TODO: define actual length
uint8_t flags = 0;
if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
addr[0] = flags; // flags
addr[1] = m_SigType; // sig type
addr[2] = m_BlindedSigType; // blinded sig type
memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());
uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ());
// checksum is Little Endian
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
auto l = ByteStreamToBase32 (addr, m_PublicKey.size () + 3, str, 60);
return std::string (str, str + l);
}
void BlindedPublicKey::GetCredential (uint8_t * credential) const
{
// A = destination's signing public key
// stA = signature type of A, 2 bytes big endian
uint16_t stA = htobe16 (GetSigType ());
// stA1 = signature type of blinded A, 2 bytes big endian
uint16_t stA1 = htobe16 (GetBlindedSigType ());
// credential = H("credential", A || stA || stA1)
H ("credential", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, credential);
}
void BlindedPublicKey::GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const
{
uint8_t credential[32];
GetCredential (credential);
// subcredential = H("subcredential", credential || blindedPublicKey)
H ("subcredential", { {credential, 32}, {blinded, len} }, subcredential);
}
void BlindedPublicKey::GenerateAlpha (const char * date, uint8_t * seed) const
{
uint16_t stA = htobe16 (GetSigType ()), stA1 = htobe16 (GetBlindedSigType ());
uint8_t salt[32];
//seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64)
H ("I2PGenerateAlpha", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt);
i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed);
}
size_t BlindedPublicKey::GetBlindedKey (const char * date, uint8_t * blindedKey) const
{
uint8_t seed[64];
GenerateAlpha (date, seed);
size_t publicKeyLength = 0;
switch (m_SigType)
{
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
publicKeyLength = BlindECDSA (m_SigType, GetPublicKey (), seed, BlindEncodedPublicKeyECDSA, blindedKey);
break;
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break;
default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
}
return publicKeyLength;
}
size_t BlindedPublicKey::BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const
{
uint8_t seed[64];
GenerateAlpha (date, seed);
size_t publicKeyLength = 0;
switch (m_SigType)
{
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub);
break;
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break;
default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
}
return publicKeyLength;
}
void BlindedPublicKey::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const
{
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, p.c_str (), p.length ());
for (const auto& it: bufs)
SHA256_Update (&ctx, it.first, it.second);
SHA256_Final (hash, &ctx);
}
i2p::data::IdentHash BlindedPublicKey::GetStoreHash (const char * date) const
{
i2p::data::IdentHash hash;
uint8_t blinded[128];
size_t publicKeyLength = 0;
if (date)
publicKeyLength = GetBlindedKey (date, blinded);
else
{
char currentDate[9];
i2p::util::GetCurrentDate (currentDate);
publicKeyLength = GetBlindedKey (currentDate, blinded);
}
if (publicKeyLength)
{
auto stA1 = htobe16 (m_BlindedSigType);
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, (const uint8_t *)&stA1, 2);
SHA256_Update (&ctx, blinded, publicKeyLength);
SHA256_Final ((uint8_t *)hash, &ctx);
}
else
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported");
return hash;
}
}
}

47
libi2pd/Blinding.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef BLINDING_H__
#define BLINDING_H__
#include <inttypes.h>
#include <string>
#include <vector>
#include "Identity.h"
namespace i2p
{
namespace data
{
class BlindedPublicKey // for encrypted LS2
{
public:
BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p
std::string ToB33 () const;
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length
size_t BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const; // date is 8 chars "YYYYMMDD", return public key length
i2p::data::IdentHash GetStoreHash (const char * date = nullptr) const; // date is 8 chars "YYYYMMDD", use current if null
private:
void GetCredential (uint8_t * credential) const; // 32 bytes
void GenerateAlpha (const char * date, uint8_t * seed) const; // 64 bytes, date is 8 chars "YYYYMMDD"
void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const;
private:
std::vector<uint8_t> m_PublicKey;
i2p::data::SigningKeyType m_SigType, m_BlindedSigType;
bool m_IsClientAuth = false;
};
}
}
#endif

View File

@ -1,21 +1,24 @@
/*
* Copyright (c) 2013-2018, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
* Kovri go write your own code
*
*/
#include "I2PEndian.h"
#include "ChaCha20.h"
/**
This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker
Kovri go write your own code
*/
#if !OPENSSL_AEAD_CHACHA20_POLY1305
namespace i2p
{
namespace crypto
{
namespace chacha
{
constexpr int rounds = 20;
constexpr std::size_t blocksize = 64;
void u32t8le(uint32_t v, uint8_t * p)
{
p[0] = v & 0xff;
@ -48,44 +51,18 @@ void quarterround(uint32_t *x, int a, int b, int c, int d)
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
}
struct State_t
{
State_t() {};
State_t(State_t &&) = delete;
State_t & operator += (const State_t & other)
{
for(int i = 0; i < 16; i++)
data[i] += other.data[i];
return *this;
}
void Copy(const State_t & other)
{
memcpy(data, other.data, sizeof(uint32_t) * 16);
}
uint32_t data[16];
};
void Chacha20Block::operator << (const Chacha20State & st)
{
int i;
for (i = 0; i < 16; i++)
u32t8le(st.data[i], data + (i << 2));
}
struct Block_t
{
Block_t() {};
Block_t(Block_t &&) = delete;
uint8_t data[blocksize];
void operator << (const State_t & st)
{
int i;
for (i = 0; i < 16; i++)
u32t8le(st.data[i], data + (i << 2));
}
};
void block(const State_t &input, Block_t & block, int rounds)
void block (Chacha20State &input, int rounds)
{
int i;
State_t x;
Chacha20State x;
x.Copy(input);
for (i = rounds; i > 0; i -= 2)
@ -100,48 +77,62 @@ void block(const State_t &input, Block_t & block, int rounds)
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
block << x;
input.block << x;
}
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
{
state.data[0] = 0x61707865;
state.data[1] = 0x3320646e;
state.data[2] = 0x79622d32;
state.data[3] = 0x6b206574;
for (size_t i = 0; i < 8; i++)
state.data[4 + i] = chacha::u8t32le(key + i * 4);
state.data[12] = htole32 (counter);
for (size_t i = 0; i < 3; i++)
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
}
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
{
state.data[12] = htole32 (counter);
state.offset = 0;
}
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
{
if (state.offset > 0)
{
// previous block if any
auto s = chacha::blocksize - state.offset;
if (sz < s) s = sz;
for (size_t i = 0; i < s; i++)
buf[i] ^= state.block.data[state.offset + i];
buf += s;
sz -= s;
state.offset += s;
if (state.offset >= chacha::blocksize) state.offset = 0;
}
for (size_t i = 0; i < sz; i += chacha::blocksize)
{
chacha::block(state, chacha::rounds);
state.data[12]++;
for (size_t j = i; j < i + chacha::blocksize; j++)
{
if (j >= sz)
{
state.offset = j & 0x3F; // % 64
break;
}
buf[j] ^= state.block.data[j - i];
}
}
}
} // namespace chacha
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
{
chacha::State_t state;
chacha::Block_t block;
size_t i, j;
state.data[0] = 0x61707865;
state.data[1] = 0x3320646e;
state.data[2] = 0x79622d32;
state.data[3] = 0x6b206574;
for (i = 0; i < 8; i++)
state.data[4 + i] = chacha::u8t32le(key + i * 4);
state.data[12] = counter;
for (i = 0; i < 3; i++)
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
for (i = 0; i < sz; i += chacha::blocksize)
{
chacha::block(state, block, chacha::rounds);
state.data[12]++;
for (j = i; j < i + chacha::blocksize; j++)
{
if (j >= sz) break;
buf[j] ^= block.data[j - i];
}
}
}
}
}
#endif

View File

@ -1,26 +1,72 @@
/**
This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker
Kovri go write your own code
*/
/*
* Copyright (c) 2013-2018, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
* Kovri go write your own code
*
*/
#ifndef LIBI2PD_CHACHA20_H
#define LIBI2PD_CHACHA20_H
#include <cstdint>
#include <cstring>
#include <inttypes.h>
#include <string.h>
#include "Crypto.h"
#if !OPENSSL_AEAD_CHACHA20_POLY1305
namespace i2p
{
namespace crypto
{
const std::size_t CHACHA20_KEY_BYTES = 32;
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
const std::size_t CHACHA20_KEY_BYTES = 32;
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
namespace chacha
{
constexpr std::size_t blocksize = 64;
constexpr int rounds = 20;
/** encrypt buf in place with chacha20 */
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1);
struct Chacha20State;
struct Chacha20Block
{
Chacha20Block () {};
Chacha20Block (Chacha20Block &&) = delete;
uint8_t data[blocksize];
void operator << (const Chacha20State & st);
};
struct Chacha20State
{
Chacha20State (): offset (0) {};
Chacha20State (Chacha20State &&) = delete;
Chacha20State & operator += (const Chacha20State & other)
{
for(int i = 0; i < 16; i++)
data[i] += other.data[i];
return *this;
}
void Copy(const Chacha20State & other)
{
memcpy(data, other.data, sizeof(uint32_t) * 16);
}
uint32_t data[16];
Chacha20Block block;
size_t offset;
};
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
}
}
}
#endif
#endif

View File

@ -32,6 +32,7 @@ namespace config {
options_description general("General options");
general.add_options()
("help", "Show this message")
("version", "Show i2pd version")
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
@ -57,9 +58,9 @@ namespace config {
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
("ntcp", value<bool>()->default_value(true), "Enable NTCP transport (default: enabled)")
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
#ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
@ -72,7 +73,7 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(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.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
;
@ -87,6 +88,7 @@ namespace config {
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
;
options_description httpproxy("HTTP Proxy options");
@ -129,6 +131,7 @@ namespace config {
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
;
options_description bob("BOB options");
@ -151,8 +154,8 @@ namespace config {
("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address")
("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port")
("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password")
("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate")
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key")
("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection certificate")
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection certificate key")
;
bool upnp_default = false;
@ -162,7 +165,7 @@ namespace config {
options_description upnp("UPnP options");
upnp.add_options()
("upnp.enabled", value<bool>()->default_value(upnp_default), "Enable or disable UPnP: automatic port forwarding")
("upnp.name", value<std::string>()->default_value("I2Pd"), "Name i2pd appears in UPnP forwardings list")
("upnp.name", value<std::string>()->default_value("I2Pd"), "Name i2pd appears in UPnP forwarding list")
;
options_description precomputation("Precomputation options");
@ -188,15 +191,13 @@ namespace config {
"https://reseed.i2p-projekt.de/,"
"https://i2p.mooo.com/netDb/,"
"https://netdb.i2p2.no/,"
"https://reseed.i2p2.no/,"
"https://reseed2.i2p2.no/,"
// "https://us.reseed.i2p2.no:444/," // mamoth's shit
// "https://uk.reseed.i2p2.no:444/," // mamoth's shit
"https://i2p-0.manas.ca:8443/,"
"https://download.xxlspeed.com/,"
"https://reseed-fr.i2pd.xyz/,"
"https://reseed.atomike.ninja/,"
"https://reseed.memcpy.io/,"
"https://reseed.onion.im/,"
"https://itoopie.atomike.ninja/,"
"https://i2pseed.creativecowpat.net:8443/,"
"https://i2p.novg.net/"
), "Reseed URLs, separated by comma")
@ -217,13 +218,6 @@ namespace config {
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
;
options_description websocket("Websocket Options");
websocket.add_options()
("websockets.enabled", value<bool>()->default_value(false), "Enable websocket server")
("websockets.address", value<std::string>()->default_value("127.0.0.1"), "Address to bind websocket server on")
("websockets.port", value<uint16_t>()->default_value(7666), "Port to bind websocket server on")
;
options_description exploratory("Exploratory Options");
exploratory.add_options()
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
@ -235,8 +229,28 @@ namespace config {
options_description ntcp2("NTCP2 Options");
ntcp2.add_options()
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
("ntcp2.published", value<bool>()->default_value(true), "Publish NTCP2 (default: enabled)")
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to bind NTCP2 on")
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
;
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.ntpservers", value<std::string>()->default_value(
"0.pool.ntp.org,"
"1.pool.ntp.org,"
"2.pool.ntp.org,"
"3.pool.ntp.org"
), "Comma separated list of NTCP servers")
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
;
options_description persist("Network information persisting options");
persist.add_options()
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
("persist.addressbook", value<bool>()->default_value(true), "Persist full addresses (default: true)")
;
m_OptionsDesc
@ -254,9 +268,10 @@ namespace config {
.add(reseed)
.add(addressbook)
.add(trust)
.add(websocket)
.add(exploratory)
.add(ntcp2)
.add(nettime)
.add(persist)
;
}
@ -284,6 +299,23 @@ namespace config {
std::cout << m_OptionsDesc;
exit(EXIT_SUCCESS);
}
else if (m_Options.count("version"))
{
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
std::cout << "Boost version "
<< BOOST_VERSION / 100000 << "." // maj. version
<< BOOST_VERSION / 100 % 1000 << "." // min. version
<< BOOST_VERSION % 100 // patch version
<< std::endl;
#if defined(OPENSSL_VERSION_TEXT)
std::cout << OPENSSL_VERSION_TEXT << std::endl;
#endif
#if defined(LIBRESSL_VERSION_TEXT)
std::cout << LIBRESSL_VERSION_TEXT << std::endl;
#endif
exit(EXIT_SUCCESS);
}
}
void ParseConfig(const std::string& path)

View File

@ -32,12 +32,12 @@ namespace config {
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
*
* If --help is given in parameters, shows it's list with description
* terminates the program with exitcode 0.
* If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0.
*
* In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option,
* and then terminate program with exitcode 1.
* and then terminate the program with exitcode 1.
*
* Other exceptions will be passed to higher level.
*/
@ -107,7 +107,7 @@ namespace config {
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false othervise
* @return true if value set to default, false otherwise
*/
bool IsDefault(const char *name);
}

View File

@ -8,11 +8,14 @@
#include <openssl/crypto.h>
#include "TunnelBase.h"
#include <openssl/ssl.h>
#include "Crypto.h"
#if LEGACY_OPENSSL
#if OPENSSL_HKDF
#include <openssl/kdf.h>
#endif
#if !OPENSSL_AEAD_CHACHA20_POLY1305
#include "ChaCha20.h"
#include "Poly1305.h"
#endif
#include "Crypto.h"
#include "Ed25519.h"
#include "I2PEndian.h"
#include "Log.h"
@ -282,6 +285,7 @@ namespace crypto
{
#if OPENSSL_X25519
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
m_Pkey = nullptr;
#else
m_Ctx = BN_CTX_new ();
#endif
@ -292,11 +296,20 @@ namespace crypto
#if OPENSSL_X25519
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
if (pub)
memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
else
{
size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
}
#else
m_Ctx = BN_CTX_new ();
memcpy (m_PrivateKey, priv, 32);
memcpy (m_PublicKey, pub, 32);
m_Ctx = BN_CTX_new ();
if (pub)
memcpy (m_PublicKey, pub, 32);
else
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
#endif
}
@ -304,8 +317,7 @@ namespace crypto
{
#if OPENSSL_X25519
EVP_PKEY_CTX_free (m_Ctx);
if (m_Pkey)
EVP_PKEY_free (m_Pkey);
if (m_Pkey) EVP_PKEY_free (m_Pkey);
#else
BN_CTX_free (m_Ctx);
#endif
@ -314,7 +326,11 @@ namespace crypto
void X25519Keys::GenerateKeys ()
{
#if OPENSSL_X25519
m_Pkey = nullptr;
if (m_Pkey)
{
EVP_PKEY_free (m_Pkey);
m_Pkey = nullptr;
}
EVP_PKEY_keygen_init (m_Ctx);
EVP_PKEY_keygen (m_Ctx, &m_Pkey);
EVP_PKEY_CTX_free (m_Ctx);
@ -341,6 +357,28 @@ namespace crypto
#endif
}
void X25519Keys::GetPrivateKey (uint8_t * priv) const
{
#if OPENSSL_X25519
size_t len = 32;
EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
#else
memcpy (priv, m_PrivateKey, 32);
#endif
}
void X25519Keys::SetPrivateKey (const uint8_t * priv)
{
#if OPENSSL_X25519
if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
if (m_Pkey) EVP_PKEY_free (m_Pkey);
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
#else
memcpy (m_PrivateKey, priv, 32);
#endif
}
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
{
@ -1076,66 +1114,7 @@ namespace crypto
if (len < msgLen) return false;
if (encrypt && len < msgLen + 16) return false;
bool ret = true;
#if LEGACY_OPENSSL
// generate one time poly key
uint8_t polyKey[64];
memset(polyKey, 0, sizeof(polyKey));
chacha20 (polyKey, 64, nonce, key, 0);
// create Poly1305 message
if (!ad) adLen = 0;
std::vector<uint8_t> polyMsg(adLen + msgLen + 3*16);
size_t offset = 0;
uint8_t padding[16]; memset (padding, 0, 16);
if (ad)
{
memcpy (polyMsg.data (), ad, adLen); offset += adLen; // additional authenticated data
auto rem = adLen & 0x0F; // %16
if (rem)
{
// padding1
rem = 16 - rem;
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
}
}
// encrypt/decrypt data and add to hash
if (buf != msg)
memcpy (buf, msg, msgLen);
if (encrypt)
{
chacha20 (buf, msgLen, nonce, key, 1); // encrypt
memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption
}
else
{
memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption
chacha20 (buf, msgLen, nonce, key, 1); // decrypt
}
offset += msgLen; // encrypted data
auto rem = msgLen & 0x0F; // %16
if (rem)
{
// padding2
rem = 16 - rem;
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
}
htole64buf (polyMsg.data () + offset, adLen); offset += 8;
htole64buf (polyMsg.data () + offset, msgLen); offset += 8;
if (encrypt)
{
// calculate Poly1305 tag and write in after encrypted data
Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)polyKey, polyMsg.data (), offset);
}
else
{
uint32_t tag[8];
// calculate Poly1305 tag
Poly1305HMAC (tag, (uint32_t *)polyKey, polyMsg.data (), offset);
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
}
#else
#if OPENSSL_AEAD_CHACHA20_POLY1305
int outlen = 0;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
if (encrypt)
@ -1160,10 +1139,176 @@ namespace crypto
}
EVP_CIPHER_CTX_free (ctx);
#else
chacha::Chacha20State state;
// generate one time poly key
chacha::Chacha20Init (state, nonce, key, 0);
uint64_t polyKey[8];
memset(polyKey, 0, sizeof(polyKey));
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
// create Poly1305 hash
Poly1305 polyHash (polyKey);
if (!ad) adLen = 0;
uint8_t padding[16]; memset (padding, 0, 16);
if (ad)
{
polyHash.Update (ad, adLen);// additional authenticated data
auto rem = adLen & 0x0F; // %16
if (rem)
{
// padding1
rem = 16 - rem;
polyHash.Update (padding, rem);
}
}
// encrypt/decrypt data and add to hash
Chacha20SetCounter (state, 1);
if (buf != msg)
memcpy (buf, msg, msgLen);
if (encrypt)
{
chacha::Chacha20Encrypt (state, buf, msgLen); // encrypt
polyHash.Update (buf, msgLen); // after encryption
}
else
{
polyHash.Update (buf, msgLen); // before decryption
chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt
}
auto rem = msgLen & 0x0F; // %16
if (rem)
{
// padding2
rem = 16 - rem;
polyHash.Update (padding, rem);
}
// adLen and msgLen
htole64buf (padding, adLen);
htole64buf (padding + 8, msgLen);
polyHash.Update (padding, 16);
if (encrypt)
// calculate Poly1305 tag and write in after encrypted data
polyHash.Finish ((uint64_t *)(buf + msgLen));
else
{
uint64_t tag[4];
// calculate Poly1305 tag
polyHash.Finish (tag);
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
}
#endif
return ret;
}
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
{
if (bufs.empty ()) return;
#if OPENSSL_AEAD_CHACHA20_POLY1305
int outlen = 0;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
for (const auto& it: bufs)
EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second);
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
EVP_CIPHER_CTX_free (ctx);
#else
chacha::Chacha20State state;
// generate one time poly key
chacha::Chacha20Init (state, nonce, key, 0);
uint64_t polyKey[8];
memset(polyKey, 0, sizeof(polyKey));
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
Poly1305 polyHash (polyKey);
// encrypt buffers
Chacha20SetCounter (state, 1);
size_t size = 0;
for (const auto& it: bufs)
{
chacha::Chacha20Encrypt (state, it.first, it.second);
polyHash.Update (it.first, it.second); // after encryption
size += it.second;
}
// padding
uint8_t padding[16];
memset (padding, 0, 16);
auto rem = size & 0x0F; // %16
if (rem)
{
// padding2
rem = 16 - rem;
polyHash.Update (padding, rem);
}
// adLen and msgLen
// adLen is always zero
htole64buf (padding + 8, size);
polyHash.Update (padding, 16);
// MAC
polyHash.Finish ((uint64_t *)mac);
#endif
}
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
{
#if OPENSSL_AEAD_CHACHA20_POLY1305
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
uint32_t iv[4];
iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
int outlen = 0;
EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
EVP_CIPHER_CTX_free (ctx);
#else
chacha::Chacha20State state;
chacha::Chacha20Init (state, nonce, key, 1);
if (out != msg) memcpy (out, msg, msgLen);
chacha::Chacha20Encrypt (state, out, msgLen);
#endif
}
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
uint8_t * out, size_t outLen)
{
#if OPENSSL_HKDF
EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr);
EVP_PKEY_derive_init (pctx);
EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
if (key && keyLen)
{
EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
}
else
{
// zerolen
EVP_PKEY_CTX_hkdf_mode (pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
uint8_t tempKey[32]; unsigned int len;
HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len);
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
}
if (info.length () > 0)
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
EVP_PKEY_derive (pctx, out, &outLen);
EVP_PKEY_CTX_free (pctx);
#else
uint8_t prk[32]; unsigned int len;
HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len);
auto l = info.length ();
memcpy (out, info.c_str (), l); out[l] = 0x01;
HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
if (outLen > 32) // 64
{
memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len);
}
#endif
}
// init and terminate
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
@ -1178,11 +1323,13 @@ namespace crypto
}
}*/
void InitCrypto (bool precomputation)
{
i2p::cpu::Detect ();
i2p::cpu::Detect ();
#if LEGACY_OPENSSL
SSL_library_init ();
#endif
/* auto numLocks = CRYPTO_num_locks();
for (int i = 0; i < numLocks; i++)
m_OpenSSLMutexes.emplace_back (new std::mutex);
@ -1217,3 +1364,4 @@ namespace crypto
}
}
}

View File

@ -3,6 +3,7 @@
#include <inttypes.h>
#include <string>
#include <vector>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/aes.h>
@ -22,13 +23,19 @@
// recognize openssl version and features
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif
#endif
namespace i2p
@ -67,11 +74,13 @@ namespace crypto
public:
X25519Keys ();
X25519Keys (const uint8_t * priv, const uint8_t * pub); // for RouterContext
X25519Keys (const uint8_t * priv, const uint8_t * pub); // if pub is null, derive from priv
~X25519Keys ();
void GenerateKeys ();
const uint8_t * GetPublicKey () const { return m_PublicKey; };
void GetPrivateKey (uint8_t * priv) const;
void SetPrivateKey (const uint8_t * priv); // wihout calculating public
void Agree (const uint8_t * pub, uint8_t * shared);
private:
@ -107,27 +116,16 @@ namespace crypto
void operator^=(const ChipherBlock& other) // XOR
{
#ifdef __AVX__
if (i2p::cpu::avx)
{
__asm__
(
"vmovups (%[buf]), %%xmm0 \n"
"vmovups (%[other]), %%xmm1 \n"
"vxorps %%xmm0, %%xmm1, %%xmm0 \n"
"vmovups %%xmm0, (%[buf]) \n"
:
: [buf]"r"(buf), [other]"r"(other.buf)
: "%xmm0", "%xmm1", "memory"
);
}
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
{
for (int i = 0; i < 4; i++)
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
}
else
#endif
{
// TODO: implement it better
{
for (int i = 0; i < 16; i++)
buf[i] ^= other.buf[i];
}
}
}
};
@ -292,6 +290,15 @@ namespace crypto
// AEAD/ChaCha20/Poly1305
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
// ChaCha20
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
// HKDF
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
// init and terminate
void InitCrypto (bool precomputation);
void TerminateCrypto ();

View File

@ -14,6 +14,7 @@ namespace crypto
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
{
if (!ctx) return;
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, zeroPadding);
}
@ -24,6 +25,7 @@ namespace crypto
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
{
if (!ctx) return false;
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, zeroPadding);
}
@ -146,6 +148,34 @@ namespace crypto
BN_free (x); BN_free (y);
}
ECIESX25519AEADRatchetEncryptor::ECIESX25519AEADRatchetEncryptor (const uint8_t * pub)
{
memcpy (m_PublicKey, pub, 32);
}
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool)
{
memcpy (pub, m_PublicKey, 32);
}
ECIESX25519AEADRatchetDecryptor::ECIESX25519AEADRatchetDecryptor (const uint8_t * priv)
{
m_StaticKeys.SetPrivateKey (priv);
}
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding)
{
m_StaticKeys.Agree (epub, sharedSecret);
return true;
}
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub)
{
X25519Keys k;
k.GenerateKeys ();
k.GetPrivateKey (priv);
memcpy (pub, k.GetPublicKey (), 32);
}
}
}

View File

@ -22,6 +22,7 @@ namespace crypto
virtual ~CryptoKeyDecryptor () {};
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data
virtual size_t GetPublicKeyLen () const = 0; // we need it to set key in LS2
};
// ElGamal
@ -43,7 +44,8 @@ namespace crypto
ElGamalDecryptor (const uint8_t * priv);
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 256; };
private:
uint8_t m_PrivateKey[256];
@ -73,7 +75,8 @@ namespace crypto
ECIESP256Decryptor (const uint8_t * priv);
~ECIESP256Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 64; };
private:
EC_GROUP * m_Curve;
@ -105,13 +108,47 @@ namespace crypto
ECIESGOSTR3410Decryptor (const uint8_t * priv);
~ECIESGOSTR3410Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 64; };
private:
BIGNUM * m_PrivateKey;
};
void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub);
// ECIES-X25519-AEAD-Ratchet
class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor
{
public:
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
~ECIESX25519AEADRatchetEncryptor () {};
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
// copies m_PublicKey to pub
private:
uint8_t m_PublicKey[32];
};
class ECIESX25519AEADRatchetDecryptor: public CryptoKeyDecryptor
{
public:
ECIESX25519AEADRatchetDecryptor (const uint8_t * priv);
~ECIESX25519AEADRatchetDecryptor () {};
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding);
// agree with static and return in sharedSecret (32 bytes)
size_t GetPublicKeyLen () const { return 32; };
private:
X25519Keys m_StaticKeys;
};
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub);
}
}

View File

@ -12,10 +12,8 @@ namespace i2p
namespace datagram
{
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner):
m_Owner (owner.get()),
m_Receiver (nullptr)
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr)
{
m_Identity.FromBase64 (owner->GetIdentity()->ToBase64());
}
DatagramDestination::~DatagramDestination ()
@ -28,14 +26,15 @@ namespace datagram
auto owner = m_Owner;
std::vector<uint8_t> v(MAX_DATAGRAM_SIZE);
uint8_t * buf = v.data();
auto identityLen = m_Identity.ToBuffer (buf, MAX_DATAGRAM_SIZE);
auto localIdentity = m_Owner->GetIdentity ();
auto identityLen = localIdentity->ToBuffer (buf, MAX_DATAGRAM_SIZE);
uint8_t * signature = buf + identityLen;
auto signatureLen = m_Identity.GetSignatureLen ();
auto signatureLen = localIdentity->GetSignatureLen ();
uint8_t * buf1 = signature + signatureLen;
size_t headerLen = identityLen + signatureLen;
memcpy (buf1, payload, len);
if (m_Identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
if (localIdentity->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
{
uint8_t hash[32];
SHA256(buf1, len, hash);
@ -49,7 +48,13 @@ namespace datagram
session->SendMsg(msg);
}
void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
{
auto msg = CreateDataMessage (payload, len, fromPort, toPort, true); // raw
auto session = ObtainSession(identity);
session->SendMsg(msg);
}
void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len)
{
i2p::data::IdentityEx identity;
@ -82,6 +87,14 @@ namespace datagram
LogPrint (eLogWarning, "Datagram signature verification failed");
}
void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
if (m_RawReceiver)
m_RawReceiver (fromPort, toPort, buf, len);
else
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
}
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
@ -92,18 +105,24 @@ namespace datagram
return r;
}
void DatagramDestination::HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
void DatagramDestination::HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw)
{
// unzip it
uint8_t uncompressed[MAX_DATAGRAM_SIZE];
size_t uncompressedLen = m_Inflator.Inflate (buf, len, uncompressed, MAX_DATAGRAM_SIZE);
if (uncompressedLen)
HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen);
{
if (isRaw)
HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen);
else
HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen);
}
else
LogPrint (eLogWarning, "Datagram: decompression failed");
}
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort)
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw)
{
auto msg = NewI2NPMessage ();
uint8_t * buf = msg->GetPayload ();
@ -114,7 +133,7 @@ namespace datagram
htobe32buf (msg->GetPayload (), size); // length
htobe16buf (buf + 4, fromPort); // source port
htobe16buf (buf + 6, toPort); // destination port
buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol
buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol
msg->len += size + 4;
msg->FillI2NPMessageHeader (eI2NPData);
}
@ -170,7 +189,7 @@ namespace datagram
return nullptr;
}
DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination,
DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
const i2p::data::IdentHash & remoteIdent) :
m_LocalDestination(localDestination),
m_RemoteIdent(remoteIdent),

View File

@ -37,7 +37,7 @@ namespace datagram
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
{
public:
DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent);
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
void Start ();
void Stop ();
@ -81,7 +81,7 @@ namespace datagram
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
private:
i2p::client::ClientDestination * m_LocalDestination;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
@ -99,22 +99,28 @@ namespace datagram
class DatagramDestination
{
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
public:
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
~DatagramDestination ();
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
void ResetReceiver () { m_Receiver = nullptr; };
void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; };
void ResetReceiver (uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); };
void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
void ResetRawReceiver () { m_RawReceiver = nullptr; };
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
// clean up stale sessions
@ -124,17 +130,19 @@ namespace datagram
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw = false);
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
Receiver FindReceiver(uint16_t port);
private:
i2p::client::ClientDestination * m_Owner;
i2p::data::IdentityEx m_Identity;
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
Receiver m_Receiver; // default
RawReceiver m_RawReceiver; // default
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
std::mutex m_ReceiversMutex;

View File

@ -7,16 +7,17 @@
#include "Timestamp.h"
#include "NetDb.hpp"
#include "Destination.h"
#include "util.h"
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_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service)
LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
bool isPublic, const std::map<std::string, std::string> * params):
m_Service (service), 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),
m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
{
int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
@ -66,6 +67,32 @@ namespace client
if (it != params->end ()) m_Nickname = it->second;
// otherwise we set default nickname in Start when we know local address
}
it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ())
m_LeaseSetType = std::stoi(it->second);
if (m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
// authentication for encrypted LeaseSet
it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE);
if (it != params->end ())
{
auto authType = std::stoi (it->second);
if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
m_AuthType = authType;
else
LogPrint (eLogError, "Destination: Unknown auth type ", authType);
}
}
it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
if (it != params->end ())
{
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{
LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr);
}
}
}
}
catch (std::exception & ex)
@ -96,77 +123,36 @@ namespace client
LeaseSetDestination::~LeaseSetDestination ()
{
if (m_IsRunning)
Stop ();
if (m_Pool)
i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
for (auto& it: m_LeaseSetRequests)
it.second->Complete (nullptr);
}
void LeaseSetDestination::Run ()
void LeaseSetDestination::Start ()
{
while (m_IsRunning)
{
try
{
m_Service.run ();
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Destination: runtime exception: ", ex.what ());
}
}
if (m_Nickname.empty ())
m_Nickname = i2p::data::GetIdentHashAbbreviation (GetIdentHash ()); // set default nickname
LoadTags ();
m_Pool->SetLocalDestination (shared_from_this ());
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));
}
bool LeaseSetDestination::Start ()
void LeaseSetDestination::Stop ()
{
if (!m_IsRunning)
m_CleanupTimer.cancel ();
m_PublishConfirmationTimer.cancel ();
m_PublishVerificationTimer.cancel ();
if (m_Pool)
{
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_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));
m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ()));
return true;
m_Pool->SetLocalDestination (nullptr);
i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
}
else
return false;
}
bool LeaseSetDestination::Stop ()
{
if (m_IsRunning)
{
m_CleanupTimer.cancel ();
m_PublishConfirmationTimer.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 ();
delete m_Thread;
m_Thread = 0;
}
SaveTags ();
CleanUp (); // GarlicDestination
return true;
}
else
return false;
SaveTags ();
CleanUp (); // GarlicDestination
}
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
@ -209,7 +195,7 @@ namespace client
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
}
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
std::shared_ptr<i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
{
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
{
@ -268,15 +254,21 @@ namespace client
if (!m_Pool) return nullptr;
if (!m_LeaseSet)
UpdateLeaseSet ();
auto ls = GetLeaseSetMt ();
return (ls && ls->GetInnerLeaseSet ()) ? ls->GetInnerLeaseSet () : ls; // always non-encrypted
}
std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSetMt ()
{
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
return m_LeaseSet;
}
void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet)
void LeaseSetDestination::SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet)
{
{
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
m_LeaseSet.reset (newLeaseSet);
m_LeaseSet = newLeaseSet;
}
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
if (m_IsPublic)
@ -320,30 +312,38 @@ namespace client
void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
{
m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msgID));
}
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len)
{
I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]);
LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
}
bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len)
{
uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
switch (typeID)
{
case eI2NPData:
HandleDataMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
HandleDataMessage (payload, len);
break;
case eI2NPDeliveryStatus:
// we assume tunnel tests non-encrypted
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
break;
case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
HandleDatabaseStoreMessage (payload, len);
break;
case eI2NPDatabaseSearchReply:
HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
HandleDatabaseSearchReplyMessage (payload, len);
break;
default:
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID);
return false;
}
return true;
}
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
@ -357,51 +357,76 @@ namespace client
}
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet
switch (buf[DATABASE_STORE_TYPE_OFFSET])
{
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end ())
case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
case i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2: // 3
{
leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end ())
{
leaseSet->Update (buf + offset, len - offset);
leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
{
leaseSet->Update (buf + offset, len - offset);
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
else
{
LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed");
m_RemoteLeaseSets.erase (it);
leaseSet = nullptr;
}
}
else
LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
}
else
{
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
else
leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetPreferredCryptoType () ); // LeaseSet2
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
{
if (leaseSet->GetIdentHash () != GetIdentHash ())
{
LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
m_RemoteLeaseSets[key] = leaseSet;
}
else
LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
}
else
{
LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed");
m_RemoteLeaseSets.erase (it);
LogPrint (eLogError, "Destination: New remote LeaseSet failed");
leaseSet = nullptr;
}
}
else
LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
break;
}
else
case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
{
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset);
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
auto it2 = m_LeaseSetRequests.find (key);
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
{
if (leaseSet->GetIdentHash () != GetIdentHash ())
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr, GetPreferredCryptoType ());
if (ls2->IsValid ())
{
LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
m_RemoteLeaseSets[key] = leaseSet;
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
leaseSet = ls2;
}
else
LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
}
else
{
LogPrint (eLogError, "Destination: New remote LeaseSet failed");
leaseSet = nullptr;
}
LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
break;
}
default:
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
}
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 ())
@ -453,9 +478,8 @@ namespace client
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
}
void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID)
{
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
if (msgID == m_PublishReplyToken)
{
LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed for ", GetIdentHash().ToBase32());
@ -467,7 +491,7 @@ namespace client
shared_from_this (), std::placeholders::_1));
}
else
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msgID);
}
void LeaseSetDestination::SetLeaseSetUpdated ()
@ -477,7 +501,8 @@ namespace client
void LeaseSetDestination::Publish ()
{
if (!m_LeaseSet || !m_Pool)
auto leaseSet = GetLeaseSetMt ();
if (!leaseSet || !m_Pool)
{
LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet");
return;
@ -509,7 +534,7 @@ 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 (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
if (!floodfill)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
@ -519,7 +544,7 @@ namespace client
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 (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));
@ -542,7 +567,7 @@ namespace client
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
// Java floodfill never sends confirmation 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,
@ -557,26 +582,32 @@ namespace client
{
if (ecode != boost::asio::error::operation_aborted)
{
auto ls = GetLeaseSetMt ();
if (!ls)
{
LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
return;
}
auto s = shared_from_this ();
RequestLeaseSet (GetIdentHash (),
// "this" added due to bug in gcc 4.7-4.8
[s,this](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
// we must capture this for gcc 4.7 due the bug
RequestLeaseSet (ls->GetStoreHash (),
[s, ls, this](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
{
if (leaseSet)
{
if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet)
if (*ls == *leaseSet)
{
// we got latest LeasetSet
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", s->GetIdentHash().ToBase32());
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
return;
}
else
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32());
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", s->GetIdentHash().ToBase32());
}
else
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32());
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
// we have to publish again
s->Publish ();
});
@ -597,7 +628,27 @@ namespace client
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
return false;
}
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete, nullptr));
return true;
}
bool LeaseSetDestination::RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete)
{
if (!dest || !m_Pool || !IsReady ())
{
if (requestComplete)
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
return false;
}
auto storeHash = dest->GetStoreHash ();
auto leaseSet = FindLeaseSet (storeHash);
if (leaseSet)
{
if (requestComplete)
m_Service.post ([requestComplete, leaseSet](void){requestComplete (leaseSet);});
return true;
}
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), storeHash, requestComplete, dest));
return true;
}
@ -616,13 +667,20 @@ namespace client
});
}
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
void LeaseSetDestination::CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify)
{
if (dest)
CancelDestinationRequest (dest->GetStoreHash (), notify);
}
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey)
{
std::set<i2p::data::IdentHash> excluded;
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
if (floodfill)
{
auto request = std::make_shared<LeaseSetRequest> (m_Service);
request->requestedBlindedKey = requestedBlindedKey; // for encrypted LeaseSet2
if (requestComplete)
request->requestComplete.push_back (requestComplete);
auto ts = i2p::util::GetSecondsSinceEpoch ();
@ -764,26 +822,79 @@ namespace client
}
}
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(GetService())
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
{
if (isPublic)
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET;
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
}
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service)
{
if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType ();
// extract encryption type params for LS2
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params)
{
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
if (it != params->end ())
m_EncryptionKeyType = std::stoi(it->second);
}
memset (m_EncryptionPrivateKey, 0, 256);
memset (m_EncryptionPublicKey, 0, 256);
if (isPublic)
PersistTemporaryKeys ();
else
i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (),
m_EncryptionPrivateKey, m_EncryptionPublicKey);
m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey);
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey);
if (isPublic)
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
// extract streaming params
if (params)
try
{
if (params)
{
// extract streaming params
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
if (it != params->end ())
m_StreamingAckDelay = std::stoi(it->second);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
// authentication for encrypted LeaseSet
auto authType = GetAuthType ();
if (authType > 0)
{
m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
else
LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
if (m_AuthKeys->size ())
LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
else
{
LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
m_AuthKeys = nullptr;
}
}
}
}
}
catch (std::exception & ex)
{
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
if (it != params->end ())
m_StreamingAckDelay = std::stoi(it->second);
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
}
}
@ -791,71 +902,35 @@ namespace client
{
}
bool ClientDestination::Start ()
void ClientDestination::Start ()
{
if (LeaseSetDestination::Start ())
LeaseSetDestination::Start ();
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
m_StreamingDestination->Start ();
for (auto& it: m_StreamingDestinationsByPorts)
it.second->Start ();
}
void ClientDestination::Stop ()
{
LeaseSetDestination::Stop ();
m_ReadyChecker.cancel();
m_StreamingDestination->Stop ();
//m_StreamingDestination->SetOwner (nullptr);
m_StreamingDestination = nullptr;
for (auto& it: m_StreamingDestinationsByPorts)
{
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
m_StreamingDestination->Start ();
for (auto& it: m_StreamingDestinationsByPorts)
it.second->Start ();
return true;
it.second->Stop ();
//it.second->SetOwner (nullptr);
}
else
return false;
}
bool ClientDestination::Stop ()
{
if (LeaseSetDestination::Stop ())
m_StreamingDestinationsByPorts.clear ();
if (m_DatagramDestination)
{
m_ReadyChecker.cancel();
m_StreamingDestination->Stop ();
//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;
delete m_DatagramDestination;
m_DatagramDestination = nullptr;
}
else
return false;
}
#ifdef I2LUA
void ClientDestination::Ready(ReadyPromise & p)
{
ScheduleCheckForReady(&p);
}
void ClientDestination::ScheduleCheckForReady(ReadyPromise * p)
{
// tick every 100ms
m_ReadyChecker.expires_from_now(boost::posix_time::milliseconds(100));
m_ReadyChecker.async_wait([&, p] (const boost::system::error_code & ecode) {
HandleCheckForReady(ecode, p);
});
}
void ClientDestination::HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p)
{
if(ecode) // error happened
p->set_value(nullptr);
else if(IsReady()) // we are ready
p->set_value(std::shared_ptr<ClientDestination>(this));
else // we are not ready
ScheduleCheckForReady(p);
}
#endif
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
{
uint32_t length = bufbe32toh (buf);
@ -887,6 +962,13 @@ namespace client
else
LogPrint (eLogError, "Destination: Missing datagram destination");
break;
case PROTOCOL_TYPE_RAW:
// raw datagram
if (m_DatagramDestination)
m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true);
else
LogPrint (eLogError, "Destination: Missing raw datagram destination");
break;
default:
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
}
@ -906,7 +988,7 @@ namespace client
{
auto s = GetSharedFromThis ();
RequestDestination (dest,
[s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
[s, streamRequestComplete, port](std::shared_ptr<const i2p::data::LeaseSet> ls)
{
if (ls)
streamRequestComplete(s->CreateStream (ls, port));
@ -916,6 +998,24 @@ namespace client
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
{
if (!streamRequestComplete)
{
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
return;
}
auto s = GetSharedFromThis ();
RequestDestinationWithEncryptedLeaseSet (dest,
[s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
{
if (ls)
streamRequestComplete(s->CreateStream (ls, port));
else
streamRequestComplete (nullptr);
});
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
{
if (m_StreamingDestination)
@ -1004,10 +1104,11 @@ namespace client
return;
}
LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p");
i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (),
m_EncryptionPrivateKey, m_EncryptionPublicKey);
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
memset (m_EncryptionPrivateKey, 0, 256);
memset (m_EncryptionPublicKey, 0, 256);
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
// TODO:: persist crypto key type
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
if (f1) {
f1.write ((char *)m_EncryptionPublicKey, 256);
@ -1019,9 +1120,25 @@ namespace client
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
{
auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels);
// sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
{
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_EncryptionPublicKey, tunnels);
// sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
}
else
{
// standard LS2 (type 3) first
uint16_t keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256;
bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
m_Keys, i2p::data::LocalLeaseSet2::KeySections { {m_EncryptionKeyType, keyLen, m_EncryptionPublicKey} },
tunnels, IsPublic (), isPublishedEncrypted);
if (isPublishedEncrypted) // encrypt if type 5
ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
leaseSet = ls2;
}
SetLeaseSet (leaseSet);
}
@ -1030,7 +1147,7 @@ namespace client
if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
}
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
{
if (m_Decryptor)
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
@ -1038,5 +1155,63 @@ namespace client
LogPrint (eLogError, "Destinations: decryptor is not set");
return false;
}
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
{
for (auto it: *params)
if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group))
{
auto pos = it.second.find (':');
if (pos != std::string::npos)
{
i2p::data::AuthPublicKey pubKey;
if (pubKey.FromBase64 (it.second.substr (pos+1)))
m_AuthKeys->push_back (pubKey);
else
LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
}
}
}
bool ClientDestination::DeleteStream (uint32_t recvStreamID)
{
if (m_StreamingDestination->DeleteStream (recvStreamID))
return true;
for (auto it: m_StreamingDestinationsByPorts)
if (it.second->DeleteStream (recvStreamID))
return true;
return false;
}
RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
RunnableService ("Destination"),
ClientDestination (GetIOService (), keys, isPublic, params)
{
}
RunnableClientDestination::~RunnableClientDestination ()
{
if (IsRunning ())
Stop ();
}
void RunnableClientDestination::Start ()
{
if (!IsRunning ())
{
ClientDestination::Start ();
StartIOService ();
}
}
void RunnableClientDestination::Stop ()
{
if (IsRunning ())
{
ClientDestination::Stop ();
StopIOService ();
}
}
}
}

View File

@ -8,9 +8,6 @@
#include <set>
#include <string>
#include <functional>
#ifdef I2LUA
#include <future>
#endif
#include <boost/asio.hpp>
#include "Identity.h"
#include "TunnelPool.h"
@ -20,6 +17,7 @@
#include "NetDb.hpp"
#include "Streaming.h"
#include "Datagram.h"
#include "util.h"
namespace i2p
{
@ -52,7 +50,14 @@ namespace client
const int DEFAULT_TAGS_TO_SEND = 40;
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname";
const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType";
const int DEFAULT_LEASESET_TYPE = 1;
const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType";
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
// latency
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
@ -79,6 +84,7 @@ namespace client
std::list<RequestComplete> requestComplete;
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
std::shared_ptr<i2p::tunnel::InboundTunnel> replyTunnel;
std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey; // for encrypted LeaseSet2 only
void Complete (std::shared_ptr<i2p::data::LeaseSet> ls)
{
@ -90,28 +96,28 @@ namespace client
public:
LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr);
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~LeaseSetDestination ();
const std::string& GetNickname () const { return m_Nickname; };
boost::asio::io_service& GetService () { return m_Service; };
virtual bool Start ();
virtual bool Stop ();
virtual void Start ();
virtual void Stop ();
/** i2cp reconfigure */
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
bool IsRunning () const { return m_IsRunning; };
boost::asio::io_service& GetService () { return m_Service; };
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
// implements GarlicDestination
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const { return m_Pool; }
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
// override GarlicDestination
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
@ -121,7 +127,15 @@ namespace client
protected:
void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet);
// implements GarlicDestination
void HandleI2NPMessage (const uint8_t * buf, size_t len);
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len);
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
int GetLeaseSetType () const { return m_LeaseSetType; };
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
int GetAuthType () const { return m_AuthType; };
bool IsPublic () const { return m_IsPublic; };
virtual void CleanupDestination () {}; // additional clean up in derived classes
// I2CP
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
@ -129,34 +143,33 @@ namespace client
private:
void Run ();
void UpdateLeaseSet ();
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSetMt ();
void Publish ();
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
void HandlePublishDelayTimer (const boost::system::error_code& ecode);
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
void HandleDeliveryStatusMessage (uint32_t msgID);
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete);
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets ();
i2p::data::CryptoKeyType GetPreferredCryptoType () const;
private:
volatile bool m_IsRunning;
std::thread * m_Thread;
boost::asio::io_service m_Service;
boost::asio::io_service& m_Service;
mutable std::mutex m_RemoteLeaseSetsMutex;
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
std::mutex m_LeaseSetMutex;
std::shared_ptr<i2p::data::LocalLeaseSet> m_LeaseSet;
std::shared_ptr<const i2p::data::LocalLeaseSet> m_LeaseSet;
bool m_IsPublic;
uint32_t m_PublishReplyToken;
uint64_t m_LastSubmissionTime; // in seconds
@ -165,30 +178,28 @@ namespace client
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer;
std::string m_Nickname;
int m_LeaseSetType, m_AuthType;
std::unique_ptr<i2p::data::Tag<32> > m_LeaseSetPrivKey; // non-null if presented
public:
// for HTTP only
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; };
bool IsEncryptedLeaseSet () const { return m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; };
bool IsPerClientAuth () const { return m_AuthType > 0; };
};
class ClientDestination: public LeaseSetDestination
{
public:
#ifdef I2LUA
// type for informing that a client destination is ready
typedef std::promise<std::shared_ptr<ClientDestination> > ReadyPromise;
// informs promise with shared_from_this() when this destination is ready to use
// if cancelled before ready, informs promise with nullptr
void Ready(ReadyPromise & p);
#endif
ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~ClientDestination ();
virtual bool Start ();
virtual bool Stop ();
void Start ();
void Stop ();
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
@ -203,6 +214,7 @@ namespace client
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
// following methods operate with default streaming destination
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
void StopAcceptingStreams ();
@ -211,12 +223,14 @@ namespace client
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
// implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
protected:
@ -227,17 +241,17 @@ namespace client
private:
std::shared_ptr<ClientDestination> GetSharedFromThis ()
{ return std::static_pointer_cast<ClientDestination>(shared_from_this ()); }
std::shared_ptr<ClientDestination> GetSharedFromThis () {
return std::static_pointer_cast<ClientDestination>(shared_from_this ());
}
void PersistTemporaryKeys ();
#ifdef I2LUA
void ScheduleCheckForReady(ReadyPromise * p);
void HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p);
#endif
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
private:
i2p::data::PrivateKeys m_Keys;
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
i2p::data::CryptoKeyType m_EncryptionKeyType;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
int m_StreamingAckDelay;
@ -248,11 +262,26 @@ namespace client
boost::asio::deadline_timer m_ReadyChecker;
std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP
public:
// for HTTP only
std::vector<std::shared_ptr<const i2p::stream::Stream> > GetAllStreams () const;
bool DeleteStream (uint32_t recvStreamID);
};
class RunnableClientDestination: private i2p::util::RunnableService, public ClientDestination
{
public:
RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~RunnableClientDestination ();
void Start ();
void Stop ();
};
}
}

View File

@ -0,0 +1,664 @@
#include <string.h>
#include <openssl/sha.h>
#include "Log.h"
#include "Crypto.h"
#include "Elligator.h"
#include "Tag.h"
#include "I2PEndian.h"
#include "Timestamp.h"
#include "Tunnel.h"
#include "TunnelPool.h"
#include "ECIESX25519AEADRatchetSession.h"
namespace i2p
{
namespace garlic
{
void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k)
{
// DH_INITIALIZE(rootKey, k)
uint8_t keydata[64];
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
// nextRootKey = keydata[0:31]
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
m_NextSymmKeyIndex = 0;
}
void RatchetTagSet::NextSessionTagRatchet ()
{
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32);
m_NextIndex = 0;
}
uint64_t RatchetTagSet::GetNextSessionTag ()
{
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
m_NextIndex++;
if (m_NextIndex >= 65535) m_NextIndex = 0; // TODO: dirty hack, should create new tagset
return m_KeyData.GetTag ();
}
void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
{
if (m_NextSymmKeyIndex > 0 && index >= m_NextSymmKeyIndex)
{
auto num = index + 1 - m_NextSymmKeyIndex;
for (int i = 0; i < num; i++)
i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK);
m_NextSymmKeyIndex += num;
memcpy (key, m_CurrentSymmKeyCK + 32, 32);
}
else
CalculateSymmKeyCK (index, key);
}
void RatchetTagSet::CalculateSymmKeyCK (int index, uint8_t * key)
{
// TODO: store intermediate keys
uint8_t currentSymmKeyCK[64];
i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64)
for (int i = 0; i < index; i++)
i2p::crypto::HKDF (currentSymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_n = HKDF(symmKey_chainKey_(n-1), SYMMKEY_CONSTANT, "SymmetricRatchet", 64)
memcpy (key, currentSymmKeyCK + 32, 32);
}
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner):
GarlicRoutingSession (owner, true)
{
ResetKeys ();
}
ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
{
}
void ECIESX25519AEADRatchetSession::ResetKeys ()
{
// TODO : use precalculated hashes
static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes
SHA256 ((const uint8_t *)protocolName, 40, m_H);
memcpy (m_CK, m_H, 32);
SHA256 (m_H, 32, m_H);
}
void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
{
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, m_H, 32);
SHA256_Update (&ctx, buf, len);
SHA256_Final (m_H, &ctx);
}
void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce)
{
memset (nonce, 0, 4);
htole64buf (nonce + 4, seqn);
}
bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf)
{
for (int i = 0; i < 10; i++)
{
m_EphemeralKeys.GenerateKeys ();
if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf))
return true; // success
}
return false;
}
uint64_t ECIESX25519AEADRatchetSession::CreateNewSessionTag () const
{
uint8_t tagsetKey[32];
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
// Session Tag Ratchet
RatchetTagSet tagsetNsr;
tagsetNsr.DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
tagsetNsr.NextSessionTagRatchet ();
return tagsetNsr.GetNextSessionTag ();
}
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
{
if (!GetOwner ()) return false;
// we are Bob
// KDF1
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32); // h = SHA256(h || bpk)
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{
LogPrint (eLogError, "Garlic: Can't decode elligator");
return false;
}
buf += 32; len -= 32;
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// decrypt flags/static
uint8_t nonce[12], fs[32];
CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
return false;
}
MixHash (buf, 48); // h = SHA256(h || ciphertext)
buf += 48; len -= 48; // 32 data + 16 poly
// decrypt payload
std::vector<uint8_t> payload (len - 16);
// KDF2 for payload
bool isStatic = !i2p::data::Tag<32> (fs).IsZero ();
if (isStatic)
{
// static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32);
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
}
else // all zeros flags
CreateNonce (1, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false;
}
if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext)
m_State = eSessionStateNewSessionReceived;
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
HandlePayload (payload.data (), len - 16);
return true;
}
void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, int index)
{
size_t offset = 0;
while (offset < len)
{
uint8_t blk = buf[offset];
offset++;
auto size = bufbe16toh (buf + offset);
offset += 2;
LogPrint (eLogDebug, "Garlic: Block type ", (int)blk, " of size ", size);
if (size > len)
{
LogPrint (eLogError, "Garlic: Unexpected block length ", size);
break;
}
switch (blk)
{
case eECIESx25519BlkGalicClove:
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
break;
case eECIESx25519BlkDateTime:
LogPrint (eLogDebug, "Garlic: datetime");
break;
case eECIESx25519BlkOptions:
LogPrint (eLogDebug, "Garlic: options");
break;
case eECIESx25519BlkPadding:
LogPrint (eLogDebug, "Garlic: padding");
break;
case eECIESx25519BlkAckRequest:
{
LogPrint (eLogDebug, "Garlic: ack request");
m_AckRequests.push_back ({0, index}); // TODO: use actual tagsetid
break;
}
default:
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
}
offset += size;
}
}
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
ResetKeys ();
// we are Alice, bpk is m_RemoteStaticKey
size_t offset = 0;
if (!GenerateEphemeralKeysAndEncode (out + offset))
{
LogPrint (eLogError, "Garlic: Can't encode elligator");
return false;
}
offset += 32;
// KDF1
MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt static key section
uint8_t nonce[12];
CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
return false;
}
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48;
// KDF2
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false;
}
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
m_State = eSessionStateNewSessionSent;
if (GetOwner ())
GetOwner ()->AddECIESx25519SessionTag (0, CreateNewSessionTag (), shared_from_this ());
return true;
}
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob
uint64_t tag = CreateNewSessionTag ();
size_t offset = 0;
memcpy (out + offset, &tag, 8);
offset += 8;
if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk
{
LogPrint (eLogError, "Garlic: Can't encode elligator");
return false;
}
offset += 32;
// KDF for Reply Key Section
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
uint8_t nonce[12];
CreateNonce (0, nonce);
// calulate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (sharedSecret /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false;
}
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
offset += 16;
memcpy (m_NSRHeader, out, 56); // for possible next NSR
// KDF for payload
uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
// k_ab = keydata[0:31], k_ba = keydata[32:63]
m_ReceiveTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
m_ReceiveTagset.NextSessionTagRatchet ();
m_SendTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
m_SendTagset.NextSessionTagRatchet ();
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed");
return false;
}
m_State = eSessionStateNewSessionReplySent;
return true;
}
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob and sent NSR already
memcpy (out, m_NSRHeader, 56);
uint8_t nonce[12];
CreateNonce (0, nonce);
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed");
return false;
}
return true;
}
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len)
{
// we are Alice
LogPrint (eLogDebug, "Garlic: reply received");
const uint8_t * tag = buf;
buf += 8; len -= 8; // tag
uint8_t bepk[32]; // Bob's ephemeral key
if (!i2p::crypto::GetElligator ()->Decode (buf, bepk))
{
LogPrint (eLogError, "Garlic: Can't decode elligator");
return false;
}
buf += 32; len -= 32;
// KDF for Reply Key Section
MixHash (tag, 8); // h = SHA256(h || tag)
MixHash (bepk, 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
uint8_t nonce[12];
CreateNonce (0, nonce);
// calulate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
{
LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
return false;
}
MixHash (buf, 16); // h = SHA256(h || ciphertext)
buf += 16; len -= 16;
// KDF for payload
uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
// k_ab = keydata[0:31], k_ba = keydata[32:63]
m_SendTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
m_SendTagset.NextSessionTagRatchet ();
m_ReceiveTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
m_ReceiveTagset.NextSessionTagRatchet ();
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// decrypt payload
std::vector<uint8_t> payload (len - 16);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
return false;
}
m_State = eSessionStateEstablished;
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
HandlePayload (payload.data (), len - 16);
return true;
}
bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
uint8_t nonce[12];
auto index = m_SendTagset.GetNextIndex ();
CreateNonce (index, nonce); // tag's index
uint64_t tag = m_SendTagset.GetNextSessionTag ();
memcpy (out, &tag, 8);
// ad = The session tag, 8 bytes
// ciphertext = ENCRYPT(k, n, payload, ad)
uint8_t key[32];
m_SendTagset.GetSymmKey (index, key);
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false;
}
return true;
}
bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index)
{
uint8_t nonce[12];
CreateNonce (index, nonce); // tag's index
len -= 8; // tag
std::vector<uint8_t> payload (len - 16);
uint8_t key[32];
m_ReceiveTagset.GetSymmKey (index, key);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 8, len - 16, buf, 8, key, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
return false;
}
HandlePayload (payload.data (), len - 16, index);
if (m_ReceiveTagset.GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3)
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
return true;
}
bool ECIESX25519AEADRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len, int index)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
switch (m_State)
{
case eSessionStateNewSessionReplySent:
m_State = eSessionStateEstablished;
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
#endif
case eSessionStateEstablished:
return HandleExistingSessionMessage (buf, len, index);
case eSessionStateNew:
return HandleNewIncomingSession (buf, len);
case eSessionStateNewSessionSent:
return HandleNewOutgoingSessionReply (buf, len);
default:
return false;
}
return true;
}
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
auto payload = CreatePayload (msg);
size_t len = payload.size ();
switch (m_State)
{
case eSessionStateEstablished:
if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 24;
break;
case eSessionStateNew:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 96;
break;
case eSessionStateNewSessionReceived:
if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 72;
break;
case eSessionStateNewSessionReplySent:
if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 72;
break;
default:
return nullptr;
}
htobe32buf (m->GetPayload (), len);
m->len += len + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
return m;
}
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg)
{
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t payloadLen = 7; // datatime
if (msg && m_Destination)
payloadLen += msg->GetPayloadLength () + 13 + 32;
auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated) ? CreateDatabaseStoreMsg (GetOwner ()->GetLeaseSet ()) : nullptr;
std::shared_ptr<I2NPMessage> deliveryStatus;
if (leaseSet)
{
payloadLen += leaseSet->GetPayloadLength () + 13;
deliveryStatus = CreateEncryptedDeliveryStatusMsg (leaseSet->GetMsgID ());
payloadLen += deliveryStatus->GetPayloadLength () + 49;
if (GetLeaseSetUpdateMsgID ()) GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ()); // remove previous
SetLeaseSetUpdateStatus (eLeaseSetSubmitted);
SetLeaseSetUpdateMsgID (leaseSet->GetMsgID ());
SetLeaseSetSubmissionTime (ts);
GetOwner ()->DeliveryStatusSent (shared_from_this (), leaseSet->GetMsgID ());
}
if (m_AckRequests.size () > 0)
payloadLen += m_AckRequests.size ()*4 + 3;
uint8_t paddingSize;
RAND_bytes (&paddingSize, 1);
paddingSize &= 0x0F; paddingSize++; // 1 - 16
payloadLen += paddingSize + 3;
std::vector<uint8_t> v(payloadLen);
size_t offset = 0;
// DateTime
v[offset] = eECIESx25519BlkDateTime; offset++;
htobe16buf (v.data () + offset, 4); offset += 2;
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
// LeaseSet
if (leaseSet)
offset += CreateGarlicClove (leaseSet, v.data () + offset, payloadLen - offset);
// DeliveryStatus
if (deliveryStatus)
offset += CreateDeliveryStatusClove (deliveryStatus, v.data () + offset, payloadLen - offset);
// msg
if (msg && m_Destination)
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
// ack
if (m_AckRequests.size () > 0)
{
v[offset] = eECIESx25519BlkAck; offset++;
htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2;
for (auto& it: m_AckRequests)
{
htobe16buf (v.data () + offset, it.first); offset += 2;
htobe16buf (v.data () + offset, it.second); offset += 2;
}
m_AckRequests.clear ();
}
// padding
v[offset] = eECIESx25519BlkPadding; offset++;
htobe16buf (v.data () + offset, paddingSize); offset += 2;
memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
return v;
}
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination)
{
if (!msg) return 0;
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
if (isDestination) cloveSize += 32;
if ((int)len < cloveSize + 3) return 0;
buf[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (buf + 1, cloveSize); // size
buf += 3;
if (isDestination)
{
*buf = (eGarlicDeliveryTypeDestination << 5);
memcpy (buf + 1, *m_Destination, 32); buf += 32;
}
else
*buf = 0;
buf++; // flag and delivery instructions
*buf = msg->GetTypeID (); // I2NP msg type
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
return cloveSize + 3;
}
size_t ECIESX25519AEADRatchetSession::CreateDeliveryStatusClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len)
{
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 37 /* delivery instruction */;
if ((int)len < cloveSize + 3) return 0;
buf[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (buf + 1, cloveSize); // size
buf += 3;
if (GetOwner ())
{
auto inboundTunnel = GetOwner ()->GetTunnelPool ()->GetNextInboundTunnel ();
if (inboundTunnel)
{
// delivery instructions
*buf = eGarlicDeliveryTypeTunnel << 5; buf++; // delivery instructions flag tunnel
// hash and tunnelID sequence is reversed for Garlic
memcpy (buf, inboundTunnel->GetNextIdentHash (), 32); buf += 32;// To Hash
htobe32buf (buf, inboundTunnel->GetNextTunnelID ()); buf += 4;// tunnelID
}
else
{
LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus");
return 0;
}
*buf = msg->GetTypeID (); // I2NP msg type
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
}
else
return 0;
return cloveSize + 3;
}
void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (int numTags)
{
for (int i = 0; i < numTags; i++)
{
auto index = m_ReceiveTagset.GetNextIndex ();
uint64_t tag = m_ReceiveTagset.GetNextSessionTag ();
GetOwner ()->AddECIESx25519SessionTag (index, tag, shared_from_this ());
}
}
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
{
CleanupUnconfirmedLeaseSet (ts);
return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT;
}
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
{
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0
size_t offset = 0;
memcpy (buf + offset, &tag, 8); offset += 8;
auto payload = buf + offset;
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
size_t len = cloveSize + 3;
payload[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (payload + 1, cloveSize); // size
payload += 3;
*payload = 0; payload++; // flag and delivery instructions
*payload = msg->GetTypeID (); // I2NP msg type
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return nullptr;
}
offset += len + 16;
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
return m;
}
}
}

View File

@ -0,0 +1,136 @@
#ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__
#include <string.h>
#include <inttypes.h>
#include <functional>
#include <memory>
#include <vector>
#include <list>
#include "Identity.h"
#include "Crypto.h"
#include "Garlic.h"
namespace i2p
{
namespace garlic
{
class RatchetTagSet
{
public:
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
uint64_t GetNextSessionTag ();
int GetNextIndex () const { return m_NextIndex; };
void GetSymmKey (int index, uint8_t * key);
private:
void CalculateSymmKeyCK (int index, uint8_t * key);
private:
union
{
uint64_t ll[8];
uint8_t buf[64];
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
} m_KeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64];
int m_NextIndex, m_NextSymmKeyIndex;
};
enum ECIESx25519BlockType
{
eECIESx25519BlkDateTime = 0,
eECIESx25519BlkSessionID = 1,
eECIESx25519BlkTermination = 4,
eECIESx25519BlkOptions = 5,
eECIESx25519BlkNextSessionKey = 7,
eECIESx25519BlkAck = 8,
eECIESx25519BlkAckRequest = 9,
eECIESx25519BlkGalicClove = 11,
eECIESx25519BlkPadding = 254
};
const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second of inactivity we should restart after
const int ECIESX25519_EXPIRATION_TIMEOUT = 600; // in seconds
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
{
enum SessionState
{
eSessionStateNew =0,
eSessionStateNewSessionReceived,
eSessionStateNewSessionSent,
eSessionStateNewSessionReplySent,
eSessionStateEstablished
};
public:
ECIESX25519AEADRatchetSession (GarlicDestination * owner);
~ECIESX25519AEADRatchetSession ();
bool HandleNextMessage (const uint8_t * buf, size_t len, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
{
if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest));
}
bool CheckExpired (uint64_t ts); // true is expired
bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; }
private:
void ResetKeys ();
void MixHash (const uint8_t * buf, size_t len);
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
uint64_t CreateNewSessionTag () const;
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
bool HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len);
bool HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index);
void HandlePayload (const uint8_t * buf, size_t len, int index = 0);
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
size_t CreateDeliveryStatusClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
void GenerateMoreReceiveTags (int numTags);
private:
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
uint8_t m_NSRHeader[56], m_NSRKey[32]; // new session reply, for incoming only
i2p::crypto::X25519Keys m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
uint64_t m_LastActivityTimestamp = 0; // incoming
RatchetTagSet m_SendTagset, m_ReceiveTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
};
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
}
}
#endif

View File

@ -31,7 +31,7 @@ namespace crypto
BN_mod_inverse (tmp, tmp, q, ctx);
BN_set_word (d, 121665);
BN_set_negative (d, 1);
BN_mul (d, d, tmp, ctx);
BN_mod_mul (d, d, tmp, q, ctx);
// 2^((q-1)/4)
I = BN_new ();
@ -121,8 +121,8 @@ namespace crypto
return passed;
}
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len,
uint8_t * signature) const
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded,
const uint8_t * buf, size_t len, uint8_t * signature) const
{
BN_CTX * bnCtx = BN_CTX_new ();
// calculate r
@ -153,6 +153,44 @@ namespace crypto
BN_CTX_free (bnCtx);
}
void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded,
const uint8_t * buf, size_t len, uint8_t * signature) const
{
BN_CTX * bnCtx = BN_CTX_new ();
// T = 80 random bytes
uint8_t T[80];
RAND_bytes (T, 80);
// calculate r = H*(T || publickey || data)
SHA512_CTX ctx;
SHA512_Init (&ctx);
SHA512_Update (&ctx, T, 80);
SHA512_Update (&ctx, publicKeyEncoded, 32);
SHA512_Update (&ctx, buf, len); // data
uint8_t digest[64];
SHA512_Final (digest, &ctx);
BIGNUM * r = DecodeBN<64> (digest);
BN_mod (r, r, l, bnCtx); // % l
EncodeBN (r, digest, 32);
// calculate R
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R);
// calculate S
SHA512_Init (&ctx);
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key
SHA512_Update (&ctx, buf, len); // data
SHA512_Final (digest, &ctx);
BIGNUM * h = DecodeBN<64> (digest);
// S = (r + h*a) % l
BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (privateKey);
BN_mod_mul (h, h, a, l, bnCtx); // %l
BN_mod_add (h, h, r, l, bnCtx); // %l
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
EncodeBN (h, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S
BN_free (r); BN_free (h); BN_free (a);
BN_CTX_free (bnCtx);
}
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
{
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
@ -411,6 +449,7 @@ namespace crypto
}
}
#if !OPENSSL_X25519
BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
{
BN_CTX_start (ctx);
@ -488,6 +527,40 @@ namespace crypto
EncodeBN (q1, buf, 32);
BN_free (p1); BN_free (n); BN_free (q1);
}
#endif
void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded)
{
BN_CTX * ctx = BN_CTX_new ();
// calculate alpha = seed mod l
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
BN_mod (alpha, alpha, l, ctx); // % l
uint8_t priv[32];
EncodeBN (alpha, priv, 32); // back to Little Endian
BN_free (alpha);
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
auto A1 = Sum (DecodePublicKey (pub, ctx), MulB (priv, ctx), ctx); // pub + B*alpha
EncodePublicKey (A1, blinded, ctx);
BN_CTX_free (ctx);
}
void Ed25519::BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub)
{
BN_CTX * ctx = BN_CTX_new ();
// calculate alpha = seed mod l
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
BN_mod (alpha, alpha, l, ctx); // % l
BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian
BN_add (alpha, alpha, p); // alpha = alpha + priv
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L
BN_mod (alpha, alpha, l, ctx); // % l
EncodeBN (alpha, blindedPriv, 32);
// A' = DERIVE_PUBLIC(a')
auto A1 = MulB (blindedPriv, ctx);
EncodePublicKey (A1, blindedPub, ctx);
BN_free (alpha); BN_free (p);
BN_CTX_free (ctx);
}
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
{
@ -497,6 +570,18 @@ namespace crypto
expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit
}
void Ed25519::CreateRedDSAPrivateKey (uint8_t * priv)
{
uint8_t seed[32];
RAND_bytes (seed, 32);
BIGNUM * p = DecodeBN<32> (seed);
BN_CTX * ctx = BN_CTX_new ();
BN_mod (p, p, l, ctx); // % l
EncodeBN (p, priv, 32);
BN_CTX_free (ctx);
BN_free (p);
}
static std::unique_ptr<Ed25519> g_Ed25519;
std::unique_ptr<Ed25519>& GetEd25519 ()
{

View File

@ -3,6 +3,7 @@
#include <memory>
#include <openssl/bn.h>
#include "Crypto.h"
namespace i2p
{
@ -75,14 +76,20 @@ namespace crypto
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
#if !OPENSSL_X25519
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
#endif
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
void SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
void CreateRedDSAPrivateKey (uint8_t * priv); // priv is 32 bytes
private:
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
@ -100,8 +107,10 @@ namespace crypto
BIGNUM * DecodeBN (const uint8_t * buf) const;
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
#if !OPENSSL_X25519
// for x25519
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
#endif
private:

207
libi2pd/Elligator.cpp Normal file
View File

@ -0,0 +1,207 @@
#include <openssl/rand.h>
#include "Crypto.h"
#include "Elligator.h"
namespace i2p
{
namespace crypto
{
Elligator2::Elligator2 ()
{
// TODO: share with Ed22519
p = BN_new ();
// 2^255-19
BN_set_bit (p, 255); // 2^255
BN_sub_word (p, 19);
p38 = BN_dup (p); BN_add_word (p38, 3); BN_div_word (p38, 8); // (p+3)/8
p12 = BN_dup (p); BN_sub_word (p12, 1); BN_div_word (p12, 2); // (p-1)/2
p14 = BN_dup (p); BN_sub_word (p14, 1); BN_div_word (p14, 4); // (p-1)/4
A = BN_new (); BN_set_word (A, 486662);
nA = BN_new (); BN_sub (nA, p, A);
BN_CTX * ctx = BN_CTX_new ();
// calculate sqrt(-1)
sqrtn1 = BN_new ();
BN_set_word (sqrtn1, 2);
BN_mod_exp (sqrtn1, sqrtn1, p14, p, ctx); // 2^((p-1)/4
u = BN_new (); BN_set_word (u, 2);
iu = BN_new (); BN_mod_inverse (iu, u, p, ctx);
BN_CTX_free (ctx);
}
Elligator2::~Elligator2 ()
{
BN_free (p); BN_free (p38); BN_free (p12); BN_free (p14);
BN_free (sqrtn1); BN_free (A); BN_free (nA);
BN_free (u); BN_free (iu);
}
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
{
bool ret = true;
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
uint8_t key1[32];
for (size_t i = 0; i < 16; i++) // from Little Endian
{
key1[i] = key[31 - i];
key1[31 - i] = key[i];
}
BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key1, 32, x);
BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A
BN_sub (xA, p, xA); // p - (x + A)
BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA
BN_mod_mul (uxxA, u, x, p, ctx);
BN_mod_mul (uxxA, uxxA, xA, p, ctx);
if (Legendre (uxxA, ctx) != -1)
{
uint8_t randByte = 0; // random highest bits and high y
if (random)
{
RAND_bytes (&randByte, 1);
highY = randByte & 0x01;
}
BIGNUM * r = BN_CTX_get (ctx);
if (highY)
{
BN_mod_inverse (r, x, p, ctx);
BN_mod_mul (r, r, xA, p, ctx);
}
else
{
BN_mod_inverse (r, xA, p, ctx);
BN_mod_mul (r, r, x, p, ctx);
}
BN_mod_mul (r, r, iu, p, ctx);
SquareRoot (r, r, ctx);
bn2buf (r, encoded, 32);
if (random)
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
for (size_t i = 0; i < 16; i++) // To Little Endian
{
uint8_t tmp = encoded[i];
encoded[i] = encoded[31 - i];
encoded[31 - i] = tmp;
}
}
else
ret = false;
BN_CTX_end (ctx);
BN_CTX_free (ctx);
return ret;
}
bool Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const
{
bool ret = true;
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
uint8_t encoded1[32];
for (size_t i = 0; i < 16; i++) // from Little Endian
{
encoded1[i] = encoded[31 - i];
encoded1[31 - i] = encoded[i];
}
encoded1[0] &= 0x3F; // drop two highest bits
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
if (BN_cmp (r, p12) <= 0) // r < (p-1)/2
{
// v = -A/(1+u*r^2)
BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx);
BN_mod_mul (v, v, u, p, ctx);
BN_add_word (v, 1);
BN_mod_inverse (v, v, p, ctx);
BN_mod_mul (v, v, nA, p, ctx);
BIGNUM * vpA = BN_CTX_get (ctx);
BN_add (vpA, v, A); // v + A
// t = v^3+A*v^2+v = v^2*(v+A)+v
BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx);
BN_mod_mul (t, t, vpA, p, ctx);
BN_mod_add (t, t, v, p, ctx);
int legendre = Legendre (t, ctx);
BIGNUM * x = BN_CTX_get (ctx);
if (legendre == 1)
BN_copy (x, v);
else
{
BN_sub (x, p, v);
BN_mod_sub (x, x, A, p, ctx);
}
bn2buf (x, key, 32);
for (size_t i = 0; i < 16; i++) // To Little Endian
{
uint8_t tmp = key[i];
key[i] = key[31 - i];
key[31 - i] = tmp;
}
}
else
ret = false;
BN_CTX_end (ctx);
BN_CTX_free (ctx);
return ret;
}
void Elligator2::SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const
{
BIGNUM * t = BN_CTX_get (ctx);
BN_mod_exp (t, x, p14, p, ctx); // t = x^((p-1)/4)
BN_mod_exp (r, x, p38, p, ctx); // r = x^((p+3)/8)
BN_add_word (t, 1);
if (!BN_cmp (t, p))
BN_mod_mul (r, r, sqrtn1, p, ctx);
if (BN_cmp (r, p12) > 0) // r > (p-1)/2
BN_sub (r, p, r);
}
int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const
{
// assume a < p, so don't check for a % p = 0, but a = 0 only
if (BN_is_zero(a)) return 0;
BIGNUM * r = BN_CTX_get (ctx);
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
if (BN_is_word(r, 1))
return 1;
else if (BN_is_zero(r))
return 0;
return -1;
}
static std::unique_ptr<Elligator2> g_Elligator;
std::unique_ptr<Elligator2>& GetElligator ()
{
if (!g_Elligator)
{
auto el = new Elligator2();
if (!g_Elligator) // make sure it was not created already
g_Elligator.reset (el);
else
delete el;
}
return g_Elligator;
}
}
}

39
libi2pd/Elligator.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef ELLIGATOR_H__
#define ELLIGATOR_H__
#include <inttypes.h>
#include <memory>
#include <openssl/bn.h>
namespace i2p
{
namespace crypto
{
class Elligator2
{
public:
Elligator2 ();
~Elligator2 ();
bool Encode (const uint8_t * key, uint8_t * encoded, bool highY = false, bool random = true) const;
bool Decode (const uint8_t * encoded, uint8_t * key) const;
private:
void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const;
int Legendre (const BIGNUM * a, BN_CTX * ctx) const; // a/p
private:
BIGNUM * p, * p38, * p12, * p14, * sqrtn1, * A, * nA, * u, * iu;
};
std::unique_ptr<Elligator2>& GetElligator ();
}
}
#endif

View File

@ -1,61 +0,0 @@
#include "Event.h"
#include "Log.h"
namespace i2p
{
namespace event
{
#ifdef WITH_EVENTS
EventCore core;
#endif
void EventCore::SetListener(EventListener * l)
{
m_listener = l;
LogPrint(eLogInfo, "Event: listener set");
}
void EventCore::QueueEvent(const EventType & ev)
{
if(m_listener) m_listener->HandleEvent(ev);
}
void EventCore::CollectEvent(const std::string & type, const std::string & ident, uint64_t val)
{
std::unique_lock<std::mutex> lock(m_collect_mutex);
std::string key = type + "." + ident;
if (m_collected.find(key) == m_collected.end())
{
m_collected[key] = {type, key, 0};
}
m_collected[key].Val += val;
}
void EventCore::PumpCollected(EventListener * listener)
{
std::unique_lock<std::mutex> lock(m_collect_mutex);
if(listener)
{
for(const auto & ev : m_collected) {
listener->HandlePumpEvent({{"type", ev.second.Key}, {"ident", ev.second.Ident}}, ev.second.Val);
}
}
m_collected.clear();
}
}
}
void QueueIntEvent(const std::string & type, const std::string & ident, uint64_t val)
{
#ifdef WITH_EVENTS
i2p::event::core.CollectEvent(type, ident, val);
#endif
}
void EmitEvent(const EventType & e)
{
#if WITH_EVENTS
i2p::event::core.QueueEvent(e);
#endif
}

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