Compare commits
1071 Commits
Author | SHA1 | Date | |
---|---|---|---|
4e37df26a3 | |||
5e606573b1 | |||
b3974cb52a | |||
b7c206c44b | |||
49c1e47736 | |||
4e1319d874 | |||
a9436aa9af | |||
d503f07564 | |||
aa7750bfd3 | |||
8872d1f389 | |||
f21af4068f | |||
f4ca6bbb52 | |||
869d0156ce | |||
744e893dce | |||
fe9ac10f02 | |||
6fb80f226a | |||
ff19bab800 | |||
962c2160c7 | |||
168da33d8b | |||
b6b25dc9f3 | |||
3ca17fdc03 | |||
2249708097 | |||
2fcaa7d260 | |||
f3b0e57a54 | |||
5da92437a1 | |||
b5bc05ac2b | |||
45145fa50a | |||
dd8200e8b0 | |||
2f56547d5f | |||
82bdcfbbcb | |||
0e38e43315 | |||
63746be4d5 | |||
ee73ee365f | |||
3c53479864 | |||
4adc741de3 | |||
64da62dbe6 | |||
dd9b5faa5c | |||
51d018acc6 | |||
5eec580727 | |||
1e9a53da3f | |||
8dae044600 | |||
2d3fad2cdb | |||
a59a8f62ca | |||
35cfa7d9fb | |||
c6ccb373a2 | |||
b6368170ed | |||
35e8424293 | |||
e969d58689 | |||
ae20e3aa95 | |||
de4cb74173 | |||
4f0da87a7a | |||
97f0347715 | |||
2ffe62ba41 | |||
fe1724e7e6 | |||
2ac2da41cf | |||
ed574f9d79 | |||
e0cb26bd9e | |||
1893127e84 | |||
b02c9fb118 | |||
bca0809918 | |||
00db527377 | |||
2c6e041ae2 | |||
a0d6c654cc | |||
5115c27e72 | |||
d09c3ccb2d | |||
5c308026ac | |||
91919c6d64 | |||
7168738835 | |||
9c9b723cf5 | |||
50450923df | |||
f392edd66c | |||
24b48e5d50 | |||
47f384a0e0 | |||
88594887f9 | |||
32e2f0b1fa | |||
09ed57ad42 | |||
53a6162b0c | |||
694d851cdb | |||
8e53c30a00 | |||
63e807b0b4 | |||
012f22cc47 | |||
9d891ab5dd | |||
d0e78be867 | |||
cbedebc9dd | |||
969f9aa436 | |||
b982be5ff5 | |||
2d154ee640 | |||
49810eb153 | |||
85b88b8749 | |||
239c8b5172 | |||
8c800dc178 | |||
cdd068d99a | |||
48fa10b080 | |||
a1dbec0fcb | |||
abe668f1c3 | |||
77440c235d | |||
fd1ee48dbe | |||
205e807b66 | |||
34295adb05 | |||
7c212bef63 | |||
76f95644b7 | |||
928b90d5bc | |||
09c6c2a4f3 | |||
2b2bd733e9 | |||
0d2d7e5e71 | |||
6142e93252 | |||
ccec3376ba | |||
f497a74ec4 | |||
0e666e7d6a | |||
f498fabd27 | |||
8b49a55442 | |||
a26eb942a9 | |||
eabcafa516 | |||
6cc388c1bc | |||
62e39ddfbd | |||
80373623cd | |||
451c3945f0 | |||
00cb15d9b4 | |||
67dd59125e | |||
b6800dd125 | |||
dc9da69509 | |||
d7d964bf57 | |||
bcfe44db54 | |||
376bf6ba72 | |||
f651baab25 | |||
61752e2aab | |||
b7d3fd959e | |||
7ac05f8487 | |||
4f70822b13 | |||
0007f304d0 | |||
4afef91359 | |||
815b6db0bf | |||
433d3bf582 | |||
a335841509 | |||
26ad793d82 | |||
5337aa10f7 | |||
9f79bdae9b | |||
db84be2488 | |||
599ec62bb0 | |||
19a88300c6 | |||
b5d55e1ffb | |||
521fb83e38 | |||
553d59c32b | |||
9ed58e5186 | |||
36eaaa748c | |||
4d7b86ca26 | |||
5faf84c732 | |||
d7b819267f | |||
7417867d0f | |||
8d74905257 | |||
c38298c06e | |||
3100d587d1 | |||
ba849d0300 | |||
95df3e4b39 | |||
72492e33a0 | |||
934f1269f5 | |||
e6956d9bb0 | |||
2877900233 | |||
df1aa52e08 | |||
5fa2485a7d | |||
29f0e10411 | |||
39300a5bbf | |||
35d6268675 | |||
0abb871f3f | |||
704fca969f | |||
95debf8c80 | |||
dd94b77b2a | |||
6cfe4fa580 | |||
515c086099 | |||
34ce06ac17 | |||
a104c9881e | |||
c3e3c091cc | |||
651240113c | |||
77189bf8e9 | |||
60fd3a4542 | |||
c66f9c8d6d | |||
569088eaca | |||
a7e8dd04fe | |||
dfdd76a1bb | |||
28aac6f93b | |||
c2f47119ce | |||
d6b1d0d4fb | |||
03a861745b | |||
9a7aed20e9 | |||
b7f17d4cb1 | |||
2497c3d187 | |||
f7a084969a | |||
2900bc26a5 | |||
2334c56a96 | |||
90a5d02bf6 | |||
81d9626da9 | |||
44a2549b81 | |||
a2b8d468bc | |||
d523f0cadd | |||
99116ff097 | |||
3939ca9eb4 | |||
b5aa67b491 | |||
e42efec220 | |||
9d06aa2f6a | |||
80765a797b | |||
0b5509a1ed | |||
478d7b4a83 | |||
9d3b38141a | |||
ab3a4d902e | |||
5eab5f2437 | |||
80f632c19a | |||
6e4f18543d | |||
54586c9076 | |||
351c899807 | |||
fe45d431d7 | |||
488c2f6d05 | |||
75ab0909b3 | |||
8f82d563c1 | |||
9bbce5dba6 | |||
099adab9ed | |||
c8cbf425ac | |||
ad9c11cd92 | |||
3872c2a3f5 | |||
e6a09b49c9 | |||
db107602bd | |||
a6558a61a7 | |||
254d2b82b3 | |||
97d9795fc9 | |||
54071b0e5d | |||
925e8316c7 | |||
99e1b74023 | |||
7d68ccca53 | |||
a090114066 | |||
a204841abb | |||
cc451809cc | |||
a605e4bab6 | |||
3f0534134d | |||
3acfb129cd | |||
6ccef66920 | |||
e9fa4e94a6 | |||
fecc0c4640 | |||
b759294975 | |||
a23e845c03 | |||
cb8373e487 | |||
8e919ddc8e | |||
832a9ab6b5 | |||
13732ac333 | |||
3e932a55f4 | |||
74e8610ec9 | |||
089a60ded6 | |||
c8eeefe194 | |||
85eeba14c1 | |||
f6f45eab39 | |||
a74065f775 | |||
48d02f7e09 | |||
e60549f8df | |||
41f4f4713e | |||
213a292fd5 | |||
79630e844b | |||
1c9e46dbb3 | |||
0a299284f8 | |||
347a5f7346 | |||
c6a903572c | |||
14f0d6d26b | |||
485f105555 | |||
686c0b776f | |||
828862ea49 | |||
c4dffa4dc8 | |||
3c1906e3d4 | |||
7147a3694c | |||
64707dbb22 | |||
554e8eeef3 | |||
5e10549543 | |||
685f45bd76 | |||
61d84dd4c1 | |||
4d10593bb1 | |||
fbb8903774 | |||
e8cac91bb7 | |||
7328ffa036 | |||
a03e828317 | |||
93d4dc70cf | |||
8e3d16e9fb | |||
07405e57b9 | |||
354c9187db | |||
af33df3004 | |||
78bfde237f | |||
7b9033d678 | |||
f784cfad46 | |||
e40c139ff1 | |||
edf4f7695d | |||
60ec03237e | |||
a91641e427 | |||
5c3992018f | |||
f5b682619f | |||
743fa745b7 | |||
39400fd381 | |||
5299ac35a6 | |||
ef76ed394c | |||
1472637de7 | |||
3b8baa85a3 | |||
73921b1024 | |||
ece140f18c | |||
5e42947fbd | |||
1bfb9b02f5 | |||
16a14c2b76 | |||
f6199c6c17 | |||
d7e7f06e88 | |||
4c4e856a1a | |||
07bbbbaf61 | |||
3236827781 | |||
0be664cc3d | |||
6cc6849ccc | |||
5d5cd71714 | |||
d248343517 | |||
64d800427f | |||
c4c896a833 | |||
b6b5bb3f75 | |||
5d69bb7383 | |||
76e222079a | |||
73abb9278d | |||
8fd843e7ce | |||
6a497a23d9 | |||
3ac74e1091 | |||
ef0fb48f1f | |||
414ef2bc3d | |||
ea791309ad | |||
706da6e431 | |||
ed116e7cea | |||
5b56f4007b | |||
e2071542bf | |||
cdb217b774 | |||
079798940b | |||
f1c24689bf | |||
1f9cf6ed7c | |||
43f218410f | |||
3fd9d5f641 | |||
f5ab8f2062 | |||
8774a8fbc2 | |||
6f4f0f03d2 | |||
00b5fdce03 | |||
baee6a0d91 | |||
ff44bcc489 | |||
c797ac4268 | |||
d22a76d4d1 | |||
a6642e0ebc | |||
3d4d260a34 | |||
8e4b9da97d | |||
2be80ba30f | |||
2e44c88d6c | |||
21eb1ce6c9 | |||
cdfd411df7 | |||
a6149ca90c | |||
642435486c | |||
fc84d6c4b7 | |||
aa4bddd6ec | |||
8ec12a1b65 | |||
0fbf552e95 | |||
09b1b120d7 | |||
557244bc3f | |||
24c5ed1cff | |||
32e55ebd0c | |||
ea3070d02b | |||
9aaba49a9f | |||
9b64be07a9 | |||
42c3c28ea7 | |||
9e9236badb | |||
560ebcec8d | |||
9b1fe4338b | |||
9188e3ad3f | |||
af65af5be9 | |||
2f0115c300 | |||
0646461342 | |||
ec30ec0996 | |||
cdecb7a43c | |||
aa9c1b66a0 | |||
846eac29dc | |||
0f9e3c5b33 | |||
aa27746982 | |||
d8a4954bf1 | |||
d40a029dae | |||
96d961c393 | |||
7b6814e32d | |||
6fee2d3536 | |||
636fc633d4 | |||
72a239838e | |||
a463dbc5fb | |||
016ae3b9e9 | |||
7d0d421724 | |||
83b5856a19 | |||
f617b27110 | |||
a91a0263cf | |||
80ffe13f3e | |||
1eb726c9bb | |||
1fa3ba8b42 | |||
b6bfd66a49 | |||
1be0e7ddaa | |||
2cac9b03ff | |||
f5f4190803 | |||
a14d554947 | |||
6d9e5147b5 | |||
841452cb9e | |||
9c76368dbc | |||
bd5122c6ea | |||
6643258618 | |||
bc3f02cb6b | |||
d848ae332a | |||
08ddc98303 | |||
a3344c4290 | |||
22c1ce3ea5 | |||
afb14e6782 | |||
e177363377 | |||
ce213934c9 | |||
af286ec52e | |||
f7f2b7607b | |||
60a282826c | |||
3eba599aec | |||
74d876f145 | |||
d7609f119c | |||
65c2c7d80b | |||
468a32a819 | |||
b89cf73ae2 | |||
9cf43dea1a | |||
670ffe2078 | |||
884cf756ed | |||
e44ba54857 | |||
3712749a94 | |||
6569c4aa03 | |||
d6b2b3c996 | |||
06c7900ece | |||
52a6a12a9a | |||
e647603dce | |||
dadf6174ba | |||
84de7675c4 | |||
6311a80d0e | |||
9504e69598 | |||
5398b651f7 | |||
b5596c4596 | |||
fdcea5537c | |||
8ca8bc810d | |||
8f909b051f | |||
90f2b2d249 | |||
f74b27c58c | |||
3f091f4748 | |||
d84c9ad611 | |||
e55e15693d | |||
c54e6bafdb | |||
2e56c4895d | |||
bce4224d6e | |||
812e2814bc | |||
7cd17f8e1f | |||
6193b06708 | |||
12af68bdb5 | |||
881f7e9062 | |||
1db4076bbd | |||
1933e44719 | |||
25441cb650 | |||
bc755ac32f | |||
1fa34be52a | |||
f7a6d57855 | |||
8a987af244 | |||
65cbb06080 | |||
979ea9c252 | |||
aa1f4ee72a | |||
74ce485b73 | |||
165e6508f8 | |||
c7af2889fa | |||
5ab3390434 | |||
67f60f1889 | |||
985a468d0f | |||
34dc6fbdc1 | |||
b57152cc25 | |||
dc9562e430 | |||
05689fe183 | |||
8f6f95211e | |||
f30b6c9e6e | |||
12ac7d6a00 | |||
10251a6447 | |||
089cbbc20a | |||
95ab68acd1 | |||
abc4f6c70b | |||
8fc3a1f9c9 | |||
5c3d0fc02c | |||
7efb47fed4 | |||
7692332f0e | |||
ef6db64e9f | |||
e68f1dbc99 | |||
0c9ebc36d4 | |||
fcd6eb7801 | |||
328c2182c2 | |||
08706f5dfb | |||
d49f165f0d | |||
cf0fc3a4a9 | |||
72c8fd257c | |||
fa620e41a4 | |||
b07f851ce7 | |||
16b3108719 | |||
f385c624c7 | |||
f7e9975192 | |||
cde989b59d | |||
c0e263abd3 | |||
79c0c11e80 | |||
ca671551c8 | |||
42ed312384 | |||
0e9074aaba | |||
7c1961d4ef | |||
71e57717c2 | |||
8a549b83a2 | |||
d7081c5f23 | |||
588d64a30b | |||
8335bdf3d4 | |||
85394f2438 | |||
42b556574f | |||
f34e65ad9e | |||
51352a6819 | |||
d9887ec370 | |||
c994950aaf | |||
a26ed6fe6c | |||
a12a7e73f9 | |||
779228857e | |||
8d0b696d33 | |||
23ae220aa7 | |||
b7940e0002 | |||
b3fd8bd0ae | |||
bffeb237de | |||
23e3602ea1 | |||
34cfd205f6 | |||
df3da8be7a | |||
940243f45e | |||
75d6599143 | |||
929a27a5ac | |||
82ddee2104 | |||
a141678119 | |||
96d109af81 | |||
a309eb9f3c | |||
d034dab265 | |||
883a035e5c | |||
08603091c5 | |||
a2e84e5a1e | |||
d148898ad7 | |||
9439621849 | |||
36cf622979 | |||
15ded89618 | |||
b84f74c167 | |||
a97300f8be | |||
9e12cff317 | |||
ecdf1f4ddc | |||
2fa7a48163 | |||
5e31e533e2 | |||
8adf76dcc9 | |||
15899c10b2 | |||
05ff05ea4b | |||
bd62df48c2 | |||
2366cbc833 | |||
25fb609544 | |||
af793395f0 | |||
8f41776858 | |||
139b13b8d1 | |||
4c611a5be1 | |||
5e7a21e177 | |||
5f7dda5ba8 | |||
2dfa1ca0f2 | |||
358cdcf4c4 | |||
c8f4ace5c4 | |||
5cac6ca8bb | |||
fccad71df1 | |||
97ae2674dc | |||
7c70affd7f | |||
52ff568d86 | |||
b917aeaa0b | |||
8de443ec4c | |||
7d9893c614 | |||
3540712517 | |||
a8b1a86bd7 | |||
1babd3a5a2 | |||
5ecd04dd4f | |||
50399e5194 | |||
b734acf1b1 | |||
33aa8e2471 | |||
2c58fe736b | |||
6fe1de5d86 | |||
064460b95f | |||
2c3b19a539 | |||
dc30a4c1ae | |||
86e9901bf2 | |||
6519e0835a | |||
a52344fc01 | |||
b67424643d | |||
575a4c01c9 | |||
f0d4ee6618 | |||
8753186a0d | |||
ff8fb8000d | |||
9dd38b99d6 | |||
dfe08c1ec9 | |||
fb26e78ecc | |||
4c687036c4 | |||
062d8d0f4f | |||
73b6338f62 | |||
c0d1e2c07a | |||
e70feceafe | |||
71ac0286b1 | |||
022f4d2c11 | |||
a83a839cff | |||
b259ee89aa | |||
65cf14bfce | |||
d9476fb5ca | |||
9882365ab4 | |||
2d758ce963 | |||
1dd003d26a | |||
0df5b77595 | |||
e190a005db | |||
45596a0342 | |||
405429a300 | |||
d009a29426 | |||
f1fb42460a | |||
5e110e9f7b | |||
77a409935d | |||
863baeb68b | |||
11142690a0 | |||
02e8c5faca | |||
c41081d35c | |||
db4c26a400 | |||
331a23fc20 | |||
db5a40d743 | |||
e4ab51329d | |||
8490e7ca7c | |||
86782aeb1b | |||
49a44fc92e | |||
cd39a52c25 | |||
634101ceb5 | |||
55555c8787 | |||
d36d825ac1 | |||
9bb01cd67c | |||
29b91075d2 | |||
6d46fc9f9f | |||
a2c41c9e36 | |||
ee700ac861 | |||
9884a4336f | |||
5b83d4bef8 | |||
d320a89590 | |||
f7e4afc282 | |||
88e87d589b | |||
d8c6dede7e | |||
5cc84133e3 | |||
f7728aa1f6 | |||
2b61f9a731 | |||
f407022fe6 | |||
41b9f19b01 | |||
09c6faf923 | |||
26d0177c01 | |||
f7415c8a8f | |||
4cf79088f9 | |||
50cd321818 | |||
83bbe6a9d9 | |||
0a33c18e36 | |||
6cf158ac63 | |||
f96bfa6afa | |||
2b64cf9126 | |||
a8dcfc44f5 | |||
0ff9c9da27 | |||
07e7c2d852 | |||
10e4b5b2a3 | |||
998653ea9d | |||
1a38e925bf | |||
c8f51380e6 | |||
2406d57d51 | |||
cb1e47eb71 | |||
c0a650f28b | |||
460cf6fd20 | |||
5bedfc1c84 | |||
5001592fb4 | |||
f6495e59c5 | |||
66bf431481 | |||
d9685e991e | |||
e0790700cd | |||
910a9600bd | |||
fc52b2b940 | |||
b99f828583 | |||
f38891cace | |||
8c5111e11a | |||
5575b981c8 | |||
0b36732911 | |||
52f3081a40 | |||
00c71dc26a | |||
5218c8584f | |||
6054bd6621 | |||
55af4ed385 | |||
64aee9c8ae | |||
5233e72205 | |||
db5b45222a | |||
fc4787da4e | |||
4ffbb46cf9 | |||
c3c2550f17 | |||
41e8ab5383 | |||
a802940616 | |||
dec848f072 | |||
fb229d4064 | |||
fc16e76af1 | |||
0dff636dbe | |||
00df3f8d4e | |||
34c45f2694 | |||
a188de2e5c | |||
27fbf67352 | |||
b226e22d2f | |||
5bc157eb19 | |||
f4122abbad | |||
f0b32e3f54 | |||
fe00999b2c | |||
39eed0f6fb | |||
510d29b381 | |||
0aa618b938 | |||
5884852612 | |||
5b29592174 | |||
96411cc93e | |||
7d862d8eba | |||
dd392941d0 | |||
3cec5235c9 | |||
b5682012d3 | |||
4351a2736c | |||
9c7cadb191 | |||
4d9143734f | |||
3cec923294 | |||
58c92b8405 | |||
985b618932 | |||
a027a42c46 | |||
bdc7acffbe | |||
6bd73cdea2 | |||
59954c1d7c | |||
a59cdcc9e0 | |||
e1bfa786fc | |||
d5214099c5 | |||
e05110ff44 | |||
706b976a28 | |||
2bd7a92d20 | |||
6b37a41e00 | |||
5447259e1a | |||
ee0ae0b74b | |||
966256ac32 | |||
6b9061515f | |||
df60e78766 | |||
bf1e1ad457 | |||
7fa5b06359 | |||
3b46e9f351 | |||
046a80cfe4 | |||
a8278fc78b | |||
7f3127ac89 | |||
7cdb021a1f | |||
74c0b729c2 | |||
5cb81f8532 | |||
4f23d7b7df | |||
a70d0edf2e | |||
8c9eaccc11 | |||
86c1984982 | |||
cd0f75106a | |||
b5291b5151 | |||
46283dc0ea | |||
56e76ec59f | |||
4cedaa9e80 | |||
516f140bef | |||
5d86c1c9a6 | |||
d289aa71eb | |||
ed2818eaa2 | |||
f8fe124428 | |||
5ec11c53e9 | |||
42d118d9a2 | |||
d8b4765f23 | |||
be69280d0d | |||
53a1a097a6 | |||
a22e9a2ca7 | |||
db03595473 | |||
8fadac0fdc | |||
a63bc1cdca | |||
6265d452e9 | |||
b095399770 | |||
db8a546b8f | |||
6e95318cba | |||
08a8ab9892 | |||
c7b796ff31 | |||
ad23ccb219 | |||
be7a84fdf3 | |||
2fbbbf298b | |||
0df68872ab | |||
0ced38cdcb | |||
b046c45a9e | |||
2ce1ab1634 | |||
7225231814 | |||
11dca2b352 | |||
97127e86dc | |||
cb81195959 | |||
adaff9f354 | |||
66de7ad049 | |||
1e1e4da144 | |||
623433099b | |||
73b3fbc2da | |||
5f525d0e43 | |||
60463fdafa | |||
b7a67b4b03 | |||
4643c92d33 | |||
396cba7339 | |||
a2b3ee53e0 | |||
2c67d2055c | |||
c8de7aa23c | |||
fa154cc4d6 | |||
d9b8731ddc | |||
6cebc1a2a2 | |||
faac35cd1e | |||
6916147dda | |||
e2da16e9c3 | |||
0c661e7373 | |||
413f8e8462 | |||
eefbbd4efe | |||
83932a6f02 | |||
c175dc30f8 | |||
17aa91803a | |||
48099a367e | |||
a9b64893d8 | |||
387e030d83 | |||
855cc9ed83 | |||
82534eef12 | |||
ff4e254618 | |||
571a13f0a7 | |||
2cb6283d00 | |||
f4056e57bb | |||
e80da3cbeb | |||
c0436297c2 | |||
0d05b4f095 | |||
f06c8710be | |||
f11266972e | |||
479edaf80d | |||
ff5c26adf2 | |||
5361e11395 | |||
b041bcdc65 | |||
b7c350202d | |||
b1a6c5ddf7 | |||
ac943b5712 | |||
ce8d701ecb | |||
182ffe4495 | |||
c13983d395 | |||
066f8863fd | |||
e58aaa3f32 | |||
ca1fa11cb1 | |||
64ed485cdf | |||
b0781668e2 | |||
f9fc744949 | |||
2661db23f6 | |||
7d78f60d29 | |||
1d934bd543 | |||
190435acd9 | |||
656236cb4d | |||
6d15be9a32 | |||
18d3c81018 | |||
12292afdec | |||
aef0f4d7b8 | |||
21545ab7da | |||
5a2b795440 | |||
1303dd478c | |||
7b4fc19fca | |||
008a064764 | |||
82a4630061 | |||
0f77b4810d | |||
2f7cfddfc4 | |||
84608c16b3 | |||
157411dcc6 | |||
59672d23cc | |||
ce30f89c60 | |||
ce9c9411b1 | |||
cf0d5b616d | |||
29e861d1e6 | |||
c7accd4a5c | |||
b469080cd7 | |||
547a0057e6 | |||
b980ca4a9e | |||
098b2e968e | |||
cd59ca8376 | |||
f2e6fad104 | |||
8d7fde0287 | |||
91fdb038d9 | |||
a0188765c5 | |||
b970a005de | |||
b64878f4fa | |||
c8936c79bf | |||
f876cc9079 | |||
a5cc2f3b5d | |||
9c93d6f931 | |||
a077d7671f | |||
6485ebe9a7 | |||
ecb6bb220a | |||
e3dc400d74 | |||
3bb4151074 | |||
1de4c2e8c6 | |||
fbcc4f28e7 | |||
30fb0f5a94 | |||
b02464990b | |||
4988a32d33 | |||
b3e5874631 | |||
f5349dcef9 | |||
486a4cfdd6 | |||
2277dcb069 | |||
a618a01b1e | |||
7e60069968 | |||
91e45d9a4a | |||
dea6fbf285 | |||
48cc0f4289 | |||
cdc5fce583 | |||
b41a17d548 | |||
606cbaa519 | |||
aaf8f527ef | |||
b7596b7f70 | |||
0309b574e8 | |||
ca057177c7 | |||
5d9bf18267 | |||
f1b8742782 | |||
7786c97330 | |||
f2a14047eb | |||
124a9cb030 | |||
3ec000d0f8 | |||
aac1141ca6 | |||
33cb96126a | |||
441db9ad7f | |||
5225e1d7d1 | |||
de849b3f6a | |||
fb4387c41f | |||
a9061a8f58 | |||
0c099dc52b | |||
713e92c28f | |||
d111025012 | |||
5f2e6b1262 | |||
b6d838731f | |||
56db8b40b2 | |||
f488c97a09 | |||
31df49a884 | |||
e5fdced4ac | |||
71546367cf | |||
857817dae8 | |||
ae3fca15c7 | |||
6bb7382dbd | |||
badb837b46 | |||
74f5b70a5d | |||
ac495da5fe | |||
56f6e57118 | |||
33735b343d | |||
1b56d66fc8 | |||
0994211a48 | |||
62d9a47c3d | |||
e77037c2b8 | |||
030a6ebb71 | |||
5a657cff89 | |||
f3488be7af | |||
4af0caa506 | |||
0728991821 | |||
21c35f770b | |||
f039af6eda | |||
eb3f703b46 | |||
b88b82a85c | |||
1d0791dbf5 | |||
87f2eefd35 | |||
b8a2c9f955 | |||
319d748639 | |||
4f84d687e4 | |||
fbb9991128 | |||
62bac24246 | |||
4aa8461bea | |||
ce57a130fc | |||
80567312ed | |||
180730f9cf | |||
fca2693488 | |||
b6e75e9c5a | |||
4901434209 | |||
13d174c09c | |||
5363c063d1 | |||
32d300248e | |||
3426906a4f | |||
3aaa942c94 | |||
95d8887ab0 | |||
6272e15b47 | |||
20b4f6b24d | |||
6ee279d83e | |||
b00ff43be7 | |||
dfbefee477 | |||
8c2de4973c | |||
e1527dc137 | |||
0957f6b143 | |||
7db2e9dc4a | |||
b1c701085b | |||
e8d6c803cd | |||
f4a2dda94e | |||
c4216379ed | |||
52195bf296 | |||
10fe75ed87 | |||
1c659d6ef6 | |||
3ac86db038 | |||
4a77a03033 | |||
3820b51960 | |||
e070ce4e34 | |||
0bb0adbf3e | |||
ddd25f0945 | |||
162bd592f8 | |||
85fa728d41 | |||
c7db9010ad | |||
be16545063 | |||
c730839989 | |||
4ee364640d | |||
56dd0db001 | |||
626ed720a6 | |||
b8fd9ba83f | |||
316a4457af | |||
347a2c2150 | |||
42d3770b14 | |||
39ca07bcc6 | |||
df304fb38b | |||
914566ece0 | |||
f537e7b2c6 | |||
06020b8f54 | |||
b486d1cd27 | |||
b3b38015c2 | |||
4c6988e3bc | |||
0bd4db4cc7 | |||
bc72800fef | |||
951f8972c7 | |||
38b694a055 | |||
44a9c3ca0c | |||
6bf823fb15 | |||
43a751ee0b | |||
207212557e | |||
fd1aeeac92 | |||
50ba52756f | |||
e630b8f8a8 | |||
cf5081d300 | |||
8864cbf80a | |||
81d7a832c0 | |||
d41fabbc9f | |||
46f62e1af9 | |||
b91efaa973 | |||
e3238ff75c | |||
9cc4e8d03a | |||
68b1afa2df | |||
34c98e03c1 | |||
41e40bbc0d | |||
80149342f2 | |||
1967dee50c | |||
ab80def94b | |||
254bf313a2 | |||
938d5d901a | |||
7b00d828b2 | |||
ca49944c85 | |||
d5e9fc7677 | |||
6db7c5733d | |||
418f86ecbd | |||
c68c5af856 | |||
950dffbe06 | |||
5d557003b6 | |||
3b8c3c1346 | |||
1853263f6c | |||
b0f6d81f57 | |||
9ba0329432 | |||
614101c4b8 | |||
50e4fb138a | |||
6dba0c6e0e | |||
0f2d2156e6 | |||
13b17c5a93 | |||
511499d950 | |||
6632b71273 | |||
60ef70cee4 | |||
b3ba0a7241 | |||
fc73dabc0b | |||
1121d45eb6 | |||
18b6353803 | |||
c0c0642bd1 | |||
3cf26a84dc | |||
44d6d4405e | |||
cafa027f0b | |||
276a78cb2e | |||
1008510750 | |||
42483b6f32 | |||
c21c1f5225 | |||
14ca3fc2f3 | |||
36afef3498 |
10
.gitignore
vendored
10
.gitignore
vendored
@ -8,7 +8,7 @@ netDb
|
||||
/i2pd
|
||||
/libi2pd.a
|
||||
/libi2pdclient.a
|
||||
i2pd.exe
|
||||
*.exe
|
||||
|
||||
|
||||
# Autotools
|
||||
@ -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
0
.gitmodules
vendored
Normal file
@ -3,8 +3,8 @@ cache:
|
||||
apt: true
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
dist: trusty
|
||||
#- osx
|
||||
dist: xenial
|
||||
sudo: required
|
||||
compiler:
|
||||
- g++
|
||||
|
239
ChangeLog
239
ChangeLog
@ -1,6 +1,231 @@
|
||||
# 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
|
||||
### Fixed
|
||||
- Handle I2NP messages longer than 32K
|
||||
|
||||
## [2.21.0] - 2018-10-04
|
||||
### Added
|
||||
- EdDSA, x25519 and SipHash from openssl 1.1.1
|
||||
- NTCP2 ipv6 incoming connections
|
||||
- Show total number of destination's outgoing tags in the web console
|
||||
### Changed
|
||||
- Android build with openssl 1.1.1/boost 1.64
|
||||
- Bandwidth classes 'P' and 'X' don't add 'O' anymore
|
||||
### Fixed
|
||||
- Update own RouterInfo if no SSU
|
||||
- Recognize 'P' and 'X' routers as high bandwidth without 'O'
|
||||
- NTCP address doesn't disappear if NTCP2 enabled
|
||||
- Android with api 26+
|
||||
|
||||
## [2.20.0] - 2018-08-23
|
||||
### Added
|
||||
- Full implementation of NTCP2
|
||||
- Assets for android
|
||||
### Changed
|
||||
- armeabi-v7a and x86 in one apk for android
|
||||
- NTCP2 is enabled by default
|
||||
- Show lease's expiration time in readable format in the web console
|
||||
### Fixed
|
||||
- Correct names for transports in the web console
|
||||
|
||||
## [2.19.0] - 2018-06-26
|
||||
### Added
|
||||
- ECIES support for RouterInfo
|
||||
- HTTP outproxy authorization
|
||||
- AVX/AESNI runtime detection
|
||||
- Initial implementation of NTCP2
|
||||
- I2CP session reconfigure
|
||||
- I2CP method ClientServicesInfo
|
||||
- Datagrams to websocks
|
||||
### Changed
|
||||
- RouterInfo uses EdDSA signature by default
|
||||
- Remove stream bans
|
||||
- Android build system changed to gradle
|
||||
- Multiple changes in QT GUI
|
||||
- Dockerfile
|
||||
### Fixed
|
||||
- zero tunnelID issue
|
||||
- tunnels reload
|
||||
- headers in webconsole
|
||||
- XSS in webconsole from SAM session name
|
||||
- build for gcc 8
|
||||
- cmake build scripts
|
||||
- systemd service files
|
||||
- some netbsd issues
|
||||
|
||||
## [2.18.0] - 2018-01-30
|
||||
### Added
|
||||
- Show tunnel nicknames for I2CP destination in WebUI
|
||||
- Re-create HTTP and SOCKS proxy by tunnel reload
|
||||
- Graceful shutdown as soon as no more transit tunnels
|
||||
### Changed
|
||||
- Regenerate shared local destination by tunnel reload
|
||||
- Use transient local destination by default if not specified
|
||||
- Return correct code if pid file can't be created
|
||||
- Timing and number of attempts for adressbook requests
|
||||
- Certificates list
|
||||
### Fixed
|
||||
- Malformed addressbook subsctiption request
|
||||
- Build with boost 1.66
|
||||
- Few race conditions for SAM
|
||||
- Check LeaseSet's signature before update
|
||||
|
||||
## [2.17.0] - 2017-12-04
|
||||
### Added
|
||||
- Reseed through HTTP and SOCKS proxy
|
||||
@ -26,7 +251,7 @@
|
||||
- NTCP soft and hard descriptors limits
|
||||
- Support full timestamps in logs
|
||||
### Changed
|
||||
- Faster implmentation of GOST R 34.11 hash
|
||||
- Faster implementation of GOST R 34.11 hash
|
||||
- Reject routers with RSA signtures
|
||||
- Reload config and shudown from Windows GUI
|
||||
- Update tunnels address(destination) without restart
|
||||
@ -37,7 +262,7 @@
|
||||
|
||||
## [2.15.0] - 2017-08-17
|
||||
### Added
|
||||
- QT GUI
|
||||
- QT GUI
|
||||
- Ability to add and remove I2P tunnels without restart
|
||||
- Ability to disable SOCKS outproxy option
|
||||
### Changed
|
||||
@ -81,7 +306,7 @@
|
||||
- Some stats in a main window for Windows version
|
||||
### Changed
|
||||
- Reseed servers list
|
||||
- MTU of 1488 for ipv6
|
||||
- MTU of 1488 for ipv6
|
||||
- Android and Mac OS X versions use OpenSSL 1.1
|
||||
- New logo for Android
|
||||
### Fixed
|
||||
@ -111,7 +336,7 @@
|
||||
## [2.10.2] - 2016-12-04
|
||||
### Fixed
|
||||
- Fixes UPnP discovery bug, producing excessive CPU usage
|
||||
- Fixes sudden SSU thread stop for Windows.
|
||||
- Fixes sudden SSU thread stop for Windows.
|
||||
|
||||
## [2.10.1] - 2016-11-07
|
||||
### Fixed
|
||||
@ -126,7 +351,7 @@
|
||||
- Initial iOS support
|
||||
|
||||
### Changed
|
||||
- Reduced file descriptiors usage
|
||||
- Reduced file descriptors usage
|
||||
- Strict reseed checks enabled by default
|
||||
|
||||
## Fixed
|
||||
@ -162,12 +387,12 @@
|
||||
- Configurable limit of transit tunnels
|
||||
|
||||
### Changed
|
||||
- Speed-up of assymetric crypto for non-x64 platforms
|
||||
- Speed-up of asymmetric crypto for non-x64 platforms
|
||||
- Refactoring of web-console
|
||||
|
||||
## [2.6.0] - 2016-03-31
|
||||
### Added
|
||||
- Gracefull shutdown on SIGINT
|
||||
- Graceful shutdown on SIGINT
|
||||
- Numeric bandwidth limits (was: by router class)
|
||||
- Jumpservices in web-console
|
||||
- Logging to syslog
|
||||
|
54
Dockerfile
54
Dockerfile
@ -1,54 +0,0 @@
|
||||
FROM alpine:latest
|
||||
|
||||
MAINTAINER Mikal Villa <mikal@sigterm.no>
|
||||
|
||||
ENV GIT_BRANCH="master"
|
||||
ENV I2PD_PREFIX="/opt/i2pd-${GIT_BRANCH}"
|
||||
ENV PATH=${I2PD_PREFIX}/bin:$PATH
|
||||
|
||||
ENV GOSU_VERSION=1.7
|
||||
ENV GOSU_SHASUM="34049cfc713e8b74b90d6de49690fa601dc040021980812b2f1f691534be8a50 /usr/local/bin/gosu"
|
||||
|
||||
RUN mkdir /user && adduser -S -h /user i2pd && chown -R i2pd:nobody /user
|
||||
|
||||
|
||||
#
|
||||
# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the
|
||||
# image under 20mb we need to remove all the build dependencies in the same "RUN" / layer.
|
||||
#
|
||||
|
||||
# 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 \
|
||||
&& mkdir -p /tmp/build \
|
||||
&& cd /tmp/build && git clone -b ${GIT_BRANCH} https://github.com/PurpleI2P/i2pd.git \
|
||||
&& cd i2pd \
|
||||
&& make -j4 \
|
||||
&& mkdir -p ${I2PD_PREFIX}/bin \
|
||||
&& mv i2pd ${I2PD_PREFIX}/bin/ \
|
||||
&& cd ${I2PD_PREFIX}/bin \
|
||||
&& strip i2pd \
|
||||
&& rm -fr /tmp/build && apk --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 \
|
||||
libtool g++ gcc pkgconfig
|
||||
|
||||
# 2. Adding required libraries to run i2pd to ensure it will run.
|
||||
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++
|
||||
|
||||
# Gosu is a replacement for su/sudo in docker and not a backdoor :) See https://github.com/tianon/gosu
|
||||
RUN wget -O /usr/local/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64 \
|
||||
&& echo "${GOSU_SHASUM}" | sha256sum -c && chmod +x /usr/local/bin/gosu
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
RUN chmod a+x /entrypoint.sh
|
||||
RUN echo "export PATH=${PATH}" >> /etc/profile
|
||||
|
||||
VOLUME [ "/var/lib/i2pd" ]
|
||||
|
||||
EXPOSE 7070 4444 4447 7656 2827 7654 7650
|
||||
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
|
28
Makefile
28
Makefile
@ -1,9 +1,9 @@
|
||||
UNAME := $(shell uname -s)
|
||||
SYS := $(shell $(CXX) -dumpmachine)
|
||||
SHLIB := libi2pd.so
|
||||
ARLIB := libi2pd.a
|
||||
SHLIB_CLIENT := libi2pdclient.so
|
||||
ARLIB_CLIENT := libi2pdclient.a
|
||||
I2PD := i2pd
|
||||
I2PD := i2pd
|
||||
GREP := grep
|
||||
DEPS := obj/make.dep
|
||||
|
||||
@ -18,27 +18,33 @@ USE_AVX := yes
|
||||
USE_STATIC := no
|
||||
USE_MESHNET := no
|
||||
USE_UPNP := no
|
||||
DEBUG := yes
|
||||
|
||||
ifeq ($(WEBSOCKETS),1)
|
||||
NEEDED_CXXFLAGS += -DWITH_EVENTS
|
||||
ifeq ($(DEBUG),yes)
|
||||
CXX_DEBUG = -g
|
||||
else
|
||||
CXX_DEBUG = -Os
|
||||
LD_DEBUG = -s
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME),Darwin)
|
||||
ifneq (, $(findstring darwin, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
ifeq ($(HOMEBREW),1)
|
||||
include Makefile.homebrew
|
||||
else
|
||||
include Makefile.osx
|
||||
endif
|
||||
else ifeq ($(shell echo $(UNAME) | $(GREP) -Ec '(Free|Open)BSD'),1)
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifeq ($(UNAME),Linux)
|
||||
else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.linux
|
||||
else
|
||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
|
||||
include Makefile.mingw
|
||||
else # not supported
|
||||
$(error Not supported platform)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_MESHNET),yes)
|
||||
@ -120,6 +126,8 @@ doxygen:
|
||||
.PHONY: deps
|
||||
.PHONY: doxygen
|
||||
.PHONY: dist
|
||||
.PHONY: last-dist
|
||||
.PHONY: api
|
||||
.PHONY: api_client
|
||||
.PHONY: mk_obj_dir
|
||||
.PHONY: install
|
||||
|
@ -1,5 +1,5 @@
|
||||
CXX = clang++
|
||||
CXXFLAGS = -O2
|
||||
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
## For example, when adding 'hardening flags' to the build
|
||||
@ -8,5 +8,5 @@ CXXFLAGS = -O2
|
||||
## custom FLAGS to work at build-time.
|
||||
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
|
@ -1,10 +1,11 @@
|
||||
# root directory holding homebrew
|
||||
BREWROOT = /usr/local
|
||||
BOOSTROOT = ${BREWROOT}/opt/boost
|
||||
SSLROOT = ${BREWROOT}/opt/libressl
|
||||
SSLROOT = ${BREWROOT}/opt/openssl@1.1
|
||||
UPNPROOT = ${BREWROOT}/opt/miniupnpc
|
||||
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||
CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||
LDFLAGS = ${LD_DEBUG}
|
||||
|
||||
ifndef TRAVIS
|
||||
CXX = clang++
|
||||
@ -13,7 +14,7 @@ endif
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
|
||||
else
|
||||
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
@ -33,13 +34,21 @@ endif
|
||||
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
|
||||
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
|
||||
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
|
||||
# note from psi: 2009 macbook does not have aesni
|
||||
#ifeq ($(USE_AESNI),yes)
|
||||
# CXXFLAGS += -maes -DAESNI
|
||||
#endif
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
CXXFLAGS += -maes
|
||||
endif
|
||||
ifeq ($(USE_AVX),1)
|
||||
CXXFLAGS += -mavx
|
||||
endif
|
||||
|
||||
# Disabled, since it will be the default make rule. I think its better
|
||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
||||
#install: all
|
||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
||||
# cp -r i2p ${PREFIX}/
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||
@gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
@ -1,30 +1,30 @@
|
||||
# set defaults instead redefine
|
||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
INCFLAGS ?=
|
||||
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
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
## For example, when adding 'hardening flags' to the build
|
||||
## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
|
||||
## -std=c++11. If you want to remove this variable please do so in a way that allows setting
|
||||
## custom FLAGS to work at build-time.
|
||||
## custom FDLAGS to work at build-time.
|
||||
|
||||
# detect proper flag for c++11 support by compilers
|
||||
CXXVER := $(shell $(CXX) -dumpversion)
|
||||
ifeq ($(shell expr match $(CXX) 'clang'),5)
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
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
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 ubuntu
|
||||
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-9]"),1) # gcc >= 7
|
||||
NEEDED_CXXFLAGS += -std=c++17
|
||||
LDLIBS = -latomic
|
||||
else # not supported
|
||||
$(error Compiler too old)
|
||||
$(error Compiler too old)
|
||||
endif
|
||||
|
||||
NEEDED_CXXFLAGS += -fPIC
|
||||
@ -34,7 +34,7 @@ ifeq ($(USE_STATIC),yes)
|
||||
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
||||
# the shared libraries from the glibc version used for linking
|
||||
LIBDIR := /usr/lib
|
||||
LDLIBS = $(LIBDIR)/libboost_system.a
|
||||
LDLIBS += $(LIBDIR)/libboost_system.a
|
||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||
@ -44,7 +44,7 @@ ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl
|
||||
USE_AESNI := no
|
||||
else
|
||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
# UPNP Support (miniupnpc 1.5 and higher)
|
||||
@ -60,7 +60,12 @@ endif
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
#check if AES-NI is supported by CPU
|
||||
ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0)
|
||||
CPU_FLAGS += -maes -DAESNI
|
||||
machine := $(shell uname -m)
|
||||
ifeq ($(machine), aarch64)
|
||||
CXXFLAGS += -DARM64AES
|
||||
else
|
||||
CPU_FLAGS += -maes
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
114
Makefile.mingw
114
Makefile.mingw
@ -1,54 +1,60 @@
|
||||
USE_WIN32_APP=yes
|
||||
CXX = g++
|
||||
WINDRES = windres
|
||||
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||
NEEDED_CXXFLAGS = -std=c++11
|
||||
BOOST_SUFFIX = -mt
|
||||
INCFLAGS = -Idaemon -I.
|
||||
LDFLAGS = -s -Wl,-rpath,/usr/local/lib -Wl,-Bstatic -static-libgcc -static-libstdc++
|
||||
|
||||
# UPNP Support
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
|
||||
LDLIBS = -lminiupnpc
|
||||
endif
|
||||
|
||||
LDLIBS += \
|
||||
-lboost_system$(BOOST_SUFFIX) \
|
||||
-lboost_date_time$(BOOST_SUFFIX) \
|
||||
-lboost_filesystem$(BOOST_SUFFIX) \
|
||||
-lboost_program_options$(BOOST_SUFFIX) \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lz \
|
||||
-lwsock32 \
|
||||
-lws2_32 \
|
||||
-lgdi32 \
|
||||
-liphlpapi \
|
||||
-lstdc++ \
|
||||
-lpthread
|
||||
|
||||
ifeq ($(USE_WIN32_APP), yes)
|
||||
CXXFLAGS += -DWIN32_APP
|
||||
LDFLAGS += -mwindows
|
||||
DAEMON_RC += Win32/Resource.rc
|
||||
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
||||
endif
|
||||
|
||||
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
|
||||
ifeq ($(USE_AESNI),1)
|
||||
CPU_FLAGS += -maes -DAESNI
|
||||
else
|
||||
CPU_FLAGS += -msse
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AVX),1)
|
||||
CPU_FLAGS += -mavx
|
||||
endif
|
||||
|
||||
ifeq ($(USE_ASLR),yes)
|
||||
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
|
||||
endif
|
||||
|
||||
obj/%.o : %.rc
|
||||
$(WINDRES) -i $< -o $@
|
||||
USE_WIN32_APP=yes
|
||||
CXX = g++
|
||||
WINDRES = windres
|
||||
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||
NEEDED_CXXFLAGS = -std=c++11
|
||||
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
|
||||
LDLIBS = -lminiupnpc
|
||||
endif
|
||||
|
||||
LDLIBS += \
|
||||
-lboost_system$(BOOST_SUFFIX) \
|
||||
-lboost_date_time$(BOOST_SUFFIX) \
|
||||
-lboost_filesystem$(BOOST_SUFFIX) \
|
||||
-lboost_program_options$(BOOST_SUFFIX) \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lz \
|
||||
-lwsock32 \
|
||||
-lws2_32 \
|
||||
-lgdi32 \
|
||||
-liphlpapi \
|
||||
-lstdc++ \
|
||||
-lpthread
|
||||
|
||||
ifeq ($(USE_WIN32_APP), yes)
|
||||
CXXFLAGS += -DWIN32_APP
|
||||
LDFLAGS += -mwindows
|
||||
DAEMON_RC += Win32/Resource.rc
|
||||
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
|
||||
else
|
||||
CPU_FLAGS += -msse
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AVX),1)
|
||||
CPU_FLAGS += -mavx
|
||||
endif
|
||||
|
||||
ifeq ($(USE_ASLR),yes)
|
||||
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
|
||||
endif
|
||||
|
||||
obj/%.o : %.rc
|
||||
$(WINDRES) -i $< -o $@
|
||||
|
18
Makefile.osx
18
Makefile.osx
@ -1,8 +1,10 @@
|
||||
CXX = clang++
|
||||
CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX
|
||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
||||
INCFLAGS = -I/usr/local/include
|
||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
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
|
||||
@ -21,7 +23,7 @@ ifeq ($(USE_UPNP),yes)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AESNI),1)
|
||||
CXXFLAGS += -maes -DAESNI
|
||||
CXXFLAGS += -maes
|
||||
else
|
||||
CXXFLAGS += -msse
|
||||
endif
|
||||
@ -29,9 +31,3 @@ endif
|
||||
ifeq ($(USE_AVX),1)
|
||||
CXXFLAGS += -mavx
|
||||
endif
|
||||
|
||||
# Disabled, since it will be the default make rule. I think its better
|
||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
||||
#install: all
|
||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
||||
# cp -r i2p ${PREFIX}/
|
||||
|
66
README.md
66
README.md
@ -1,29 +1,34 @@
|
||||
[](https://github.com/PurpleI2P/i2pd/releases/latest)
|
||||
[](https://snapcraft.io/i2pd)
|
||||
[](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE)
|
||||
[](https://repology.org/project/i2pd/versions)
|
||||
|
||||
i2pd
|
||||
====
|
||||
|
||||
[Русская версия](https://github.com/PurpleI2P/i2pd_docs_ru/blob/master/README.md)
|
||||
|
||||
i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.
|
||||
i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.
|
||||
|
||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer.
|
||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer.
|
||||
All communications over I2P are anonymous and end-to-end encrypted, participants
|
||||
don't reveal their real IP addresses.
|
||||
don't reveal their real IP addresses.
|
||||
|
||||
I2P client is a software used for building and using anonymous I2P
|
||||
networks. Such networks are commonly used for anonymous peer-to-peer
|
||||
applications (filesharing, cryptocurrencies) and anonymous client-server
|
||||
applications (websites, instant messengers, chat-servers).
|
||||
I2P client is a software used for building and using anonymous I2P
|
||||
networks. Such networks are commonly used for anonymous peer-to-peer
|
||||
applications (filesharing, cryptocurrencies) and anonymous client-server
|
||||
applications (websites, instant messengers, chat-servers).
|
||||
|
||||
I2P allows people from all around the world to communicate and share information
|
||||
without restrictions.
|
||||
without restrictions.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Distributed anonymous networking framework
|
||||
* End-to-end encrypted communications
|
||||
* Small footprint, simple dependencies, fast performance
|
||||
* Rich set of APIs for developers of secure applications
|
||||
* Distributed anonymous networking framework
|
||||
* End-to-end encrypted communications
|
||||
* Small footprint, simple dependencies, fast performance
|
||||
* Rich set of APIs for developers of secure applications
|
||||
|
||||
Resources
|
||||
---------
|
||||
@ -38,10 +43,14 @@ Resources
|
||||
Installing
|
||||
----------
|
||||
|
||||
The easiest way to install i2pd is by using
|
||||
[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest).
|
||||
See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build
|
||||
i2pd from source on your OS.
|
||||
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.
|
||||
|
||||
|
||||
Build instructions:
|
||||
@ -54,32 +63,35 @@ Build instructions:
|
||||
|
||||
**Supported systems:**
|
||||
|
||||
* GNU/Linux x86/x64 - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
||||
* Mac OS X - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||
* GNU/Linux - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||
* CentOS / Fedora / Mageia - [](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
|
||||
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
|
||||
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
||||
* Mac OS X - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||
* Docker image - [](https://hub.docker.com/r/meeh/i2pd/builds/)
|
||||
* Snap - [](https://build.snapcraft.io/user/PurpleI2P/i2pd-snap)
|
||||
* FreeBSD
|
||||
* Android
|
||||
* Android
|
||||
* iOS
|
||||
|
||||
Using i2pd
|
||||
----------
|
||||
|
||||
See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and
|
||||
See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and
|
||||
[example config file](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/i2pd.conf).
|
||||
|
||||
Donations
|
||||
---------
|
||||
|
||||
BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY
|
||||
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
|
||||
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
|
||||
BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f
|
||||
LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59
|
||||
DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y
|
||||
ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z
|
||||
ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d
|
||||
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
|
||||
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
|
||||
GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This project is licensed under the BSD 3-clause license, which can be found in the file
|
||||
LICENSE in the root of the project source code.
|
||||
LICENSE in the root of the project source code.
|
||||
|
@ -21,6 +21,7 @@ namespace util
|
||||
SetConsoleCP(1251);
|
||||
SetConsoleOutputCP(1251);
|
||||
setlocale(LC_ALL, "Russian");
|
||||
setlocale(LC_TIME, "C");
|
||||
|
||||
if (!Daemon_Singleton::init(argc, argv))
|
||||
return false;
|
||||
@ -49,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());
|
||||
@ -68,6 +69,7 @@ namespace util
|
||||
SetConsoleCP(1251);
|
||||
SetConsoleOutputCP(1251);
|
||||
setlocale(LC_ALL, "Russian");
|
||||
setlocale(LC_TIME, "C");
|
||||
#ifdef WIN32_APP
|
||||
if (!i2p::win32::StartWin32App ()) return false;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#define I2Pd_AppName "i2pd"
|
||||
#define I2Pd_ver "2.17.0"
|
||||
#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
|
||||
|
12
android/.gitignore
vendored
12
android/.gitignore
vendored
@ -1,8 +1,16 @@
|
||||
gen
|
||||
tests
|
||||
bin
|
||||
libs
|
||||
log*
|
||||
obj
|
||||
.gradle
|
||||
.idea
|
||||
.externalNativeBuild
|
||||
ant.properties
|
||||
local.properties
|
||||
build.sh
|
||||
bin
|
||||
log*
|
||||
android.iml
|
||||
build
|
||||
*.iml
|
||||
*.local
|
||||
|
@ -1,26 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.purplei2p.i2pd"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.17.0"
|
||||
android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/icon">
|
||||
<receiver android:name=".NetworkStateChangeReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<activity android:name=".I2PD"
|
||||
android:label="@string/app_name">
|
||||
package="org.purplei2p.i2pd"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<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" />
|
||||
<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>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name=".I2PDPermsAskerActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:enabled="true" android:name=".ForegroundService"/>
|
||||
<activity
|
||||
android:name=".I2PDActivity"
|
||||
android:label="@string/app_name" />
|
||||
|
||||
<service
|
||||
android:name=".ForegroundService"
|
||||
android:enabled="true" />
|
||||
|
||||
<activity
|
||||
android:name=".I2PDPermsExplanationActivity"
|
||||
android:label="@string/title_activity_i2_pdperms_asker_prompt"
|
||||
android:parentActivityName=".I2PDPermsAskerActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.purplei2p.i2pd.I2PDPermsAskerActivity" />
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
19
android/README.md
Normal file
19
android/README.md
Normal 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
|
693
android/assets/addressbook/addresses.csv
Normal file
693
android/assets/addressbook/addresses.csv
Normal 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
android/assets/certificates
Symbolic link
1
android/assets/certificates
Symbolic link
@ -0,0 +1 @@
|
||||
../../contrib/certificates
|
90
android/assets/i2pd.conf
Normal file
90
android/assets/i2pd.conf
Normal file
@ -0,0 +1,90 @@
|
||||
## Configuration file for a typical i2pd user
|
||||
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
## for more options you can use in this file.
|
||||
|
||||
#logfile = /sdcard/i2pd/i2pd.log
|
||||
loglevel = none
|
||||
#tunnelsdir = /sdcard/i2pd/tunnels.d
|
||||
|
||||
# host = 1.2.3.4
|
||||
# port = 4567
|
||||
|
||||
ipv4 = true
|
||||
ipv6 = false
|
||||
|
||||
# ntcp = true
|
||||
# ntcpproxy = http://127.0.0.1:8118
|
||||
# ssu = true
|
||||
|
||||
bandwidth = L
|
||||
# share = 100
|
||||
|
||||
# notransit = true
|
||||
# floodfill = true
|
||||
|
||||
[ntcp2]
|
||||
enabled = true
|
||||
|
||||
[http]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 7070
|
||||
# auth = true
|
||||
# user = i2pd
|
||||
# pass = changeme
|
||||
|
||||
[httpproxy]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 4444
|
||||
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.
|
||||
|
||||
[socksproxy]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 4447
|
||||
keys = proxy-keys.dat
|
||||
# outproxy.enabled = false
|
||||
# outproxy = 127.0.0.1
|
||||
# outproxyport = 9050
|
||||
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[sam]
|
||||
enabled = false
|
||||
# address = 127.0.0.1
|
||||
# port = 7656
|
||||
|
||||
[precomputation]
|
||||
elgamal = true
|
||||
|
||||
[upnp]
|
||||
enabled = true
|
||||
# name = I2Pd
|
||||
|
||||
[reseed]
|
||||
verify = true
|
||||
## Path to local reseed data file (.su3) for manual reseeding
|
||||
# file = /path/to/i2pseeds.su3
|
||||
## or HTTPS URL to reseed from
|
||||
# file = https://legit-website.com/i2pseeds.su3
|
||||
## Path to local ZIP file or HTTPS URL to reseed from
|
||||
# zipfile = /path/to/netDb.zip
|
||||
## If you run i2pd behind a proxy server, set proxy server for reseeding here
|
||||
## Should be http://address:port or socks://address:port
|
||||
# proxy = http://127.0.0.1:8118
|
||||
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
|
||||
# threshold = 25
|
||||
|
||||
[limits]
|
||||
transittunnels = 50
|
||||
|
||||
[persist]
|
||||
profiles = false
|
3
android/assets/subscriptions.txt
Normal file
3
android/assets/subscriptions.txt
Normal file
@ -0,0 +1,3 @@
|
||||
http://inr.i2p/export/alive-hosts.txt
|
||||
http://stats.i2p/cgi-bin/newhosts.txt
|
||||
http://i2p-projekt.i2p/hosts.txt
|
33
android/assets/tunnels.conf
Normal file
33
android/assets/tunnels.conf
Normal file
@ -0,0 +1,33 @@
|
||||
[IRC-IRC2P]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6668
|
||||
#destination = irc.postman.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
|
||||
#[IRC-ILITA]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6669
|
||||
#destination = irc.ilita.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
|
||||
#[SMTP]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 7659
|
||||
#destination = smtp.postman.i2p
|
||||
#destinationport = 25
|
||||
#keys = smtp-keys.dat
|
||||
|
||||
#[POP3]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 7660
|
||||
#destination = pop.postman.i2p
|
||||
#destinationport = 110
|
||||
#keys = pop3-keys.dat
|
||||
|
||||
# see more examples at https://i2pd.readthedocs.io/en/latest/user-guide/tunnels/
|
1
android/assets/tunnels.d
Symbolic link
1
android/assets/tunnels.d
Symbolic link
@ -0,0 +1 @@
|
||||
../../contrib/tunnels.d
|
104
android/build.gradle
Normal file
104
android/build.gradle
Normal file
@ -0,0 +1,104 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.core:core:1.0.2'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "28.0.3"
|
||||
defaultConfig {
|
||||
applicationId "org.purplei2p.i2pd"
|
||||
targetSdkVersion 29
|
||||
minSdkVersion 14
|
||||
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 "-j3"
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
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")
|
||||
storePassword "android"
|
||||
keyAlias "i2pdapk"
|
||||
keyPassword "android"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
signingConfig signingConfigs.orignal
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
3
android/gradle.properties
Normal file
3
android/gradle.properties
Normal file
@ -0,0 +1,3 @@
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.parallel=true
|
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
172
android/gradlew
vendored
Executable 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
84
android/gradlew.bat
vendored
Normal 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
|
@ -25,49 +25,49 @@ include $(BUILD_SHARED_LIBRARY)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_system
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_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_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_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_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_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_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_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.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/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.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/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)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
@ -1,27 +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_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 extentions 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
|
||||
|
||||
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
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <exception>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <exception>
|
||||
//#include "mainwindow.h"
|
||||
#include "FS.h"
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -36,7 +39,7 @@ namespace android
|
||||
emit resultReady();
|
||||
}
|
||||
|
||||
Controller::Controller(DaemonAndroidImpl& daemon):
|
||||
Controller::Controller(DaemonAndroidImpl& daemon):
|
||||
m_Daemon (daemon)
|
||||
{
|
||||
Worker *worker = new Worker (m_Daemon);
|
||||
@ -54,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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -79,7 +84,18 @@ namespace android
|
||||
{
|
||||
//mutex=new QMutex(QMutex::Recursive);
|
||||
//setRunningCallback(0);
|
||||
//m_IsRunning=false;
|
||||
//m_IsRunning=false;
|
||||
|
||||
// make sure assets are ready before proceed
|
||||
i2p::fs::DetectDataDir(dataDir, false);
|
||||
int numAttempts = 0;
|
||||
do
|
||||
{
|
||||
if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
|
||||
numAttempts++;
|
||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||
}
|
||||
while (numAttempts <= 10); // 10 seconds max
|
||||
return Daemon.init(argc,argv);
|
||||
}
|
||||
|
||||
@ -111,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();
|
||||
}
|
||||
}
|
||||
@ -169,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(...)
|
||||
{
|
||||
@ -189,5 +205,10 @@ namespace android
|
||||
{
|
||||
daemon.stop();
|
||||
}
|
||||
|
||||
void SetDataDir(std::string jdataDir)
|
||||
{
|
||||
dataDir = jdataDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -11,4 +11,4 @@
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-25
|
||||
target=android-29
|
||||
|
27
android/res/layout/activity_perms_asker.xml
Normal file
27
android/res/layout/activity_perms_asker.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<LinearLayout android:id="@+id/main_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/vertical_page_margin"
|
||||
android:paddingLeft="@dimen/horizontal_page_margin"
|
||||
android:paddingRight="@dimen/horizontal_page_margin"
|
||||
android:paddingTop="@dimen/vertical_page_margin"
|
||||
tools:context=".I2PDPermsAskerActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_retry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_request_write_ext_storage_perms"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Retry requesting the SD card write permissions"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
27
android/res/layout/activity_perms_explanation.xml
Normal file
27
android/res/layout/activity_perms_explanation.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<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="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/vertical_page_margin"
|
||||
android:paddingLeft="@dimen/horizontal_page_margin"
|
||||
android:paddingRight="@dimen/horizontal_page_margin"
|
||||
android:paddingTop="@dimen/vertical_page_margin"
|
||||
tools:context=".I2PDPermsAskerActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_explanation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
||||
android:text="SD card write access is required to write the keys and other files to the I2PD folder on SD card."
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_ok"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="OK"
|
||||
/>
|
||||
</LinearLayout>
|
13
android/res/layout/webview.xml
Normal file
13
android/res/layout/webview.xml
Normal 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>
|
@ -1,16 +1,25 @@
|
||||
<menu
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".I2PD">
|
||||
<item
|
||||
android:id="@+id/action_graceful_quit"
|
||||
android:title="@string/action_graceful_quit"
|
||||
android:orderInCategory="98"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/action_quit"
|
||||
android:title="@string/action_quit"
|
||||
android:orderInCategory="99"
|
||||
/>
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".I2PDActivity">
|
||||
<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>
|
||||
|
28
android/res/values-ru/strings.xml
Executable file
28
android/res/values-ru/strings.xml
Executable 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>
|
@ -1,11 +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="i2pd_started">i2pd started</string>
|
||||
<string name="i2pd_service_started">i2pd service started</string>
|
||||
<string name="i2pd_service_stopped">i2pd service stopped</string>
|
||||
<string name="action_quit">Quit</string>
|
||||
<string name="action_graceful_quit">Graceful Quit</string>
|
||||
<string name="graceful_quit_is_already_in_progress">Graceful quit is already in progress</string>
|
||||
<string name="graceful_quit_is_in_progress">Graceful quit is in progress</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">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>
|
||||
|
16
android/res/values/template-dimens.xml
Normal file
16
android/res/values/template-dimens.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<resources>
|
||||
|
||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
||||
|
||||
<dimen name="margin_tiny">4dp</dimen>
|
||||
<dimen name="margin_small">8dp</dimen>
|
||||
<dimen name="margin_medium">16dp</dimen>
|
||||
<dimen name="margin_large">32dp</dimen>
|
||||
<dimen name="margin_huge">64dp</dimen>
|
||||
|
||||
<!-- Semantic definitions -->
|
||||
|
||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
||||
|
||||
</resources>
|
1
android/settings.gradle
Normal file
1
android/settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = "i2pd"
|
@ -2,95 +2,111 @@ package org.purplei2p.i2pd;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
public class DaemonSingleton {
|
||||
private static final String TAG="i2pd";
|
||||
private static final DaemonSingleton instance = new DaemonSingleton();
|
||||
public static interface StateUpdateListener { void daemonStateUpdate(); }
|
||||
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<StateUpdateListener>();
|
||||
import org.purplei2p.i2pd.R;
|
||||
|
||||
public class DaemonSingleton {
|
||||
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); }
|
||||
|
||||
|
||||
private synchronized void setState(State newState) {
|
||||
if(newState==null)throw new NullPointerException();
|
||||
State oldState = state;
|
||||
if(oldState==null)throw new NullPointerException();
|
||||
if(oldState.equals(newState))return;
|
||||
state=newState;
|
||||
fireStateUpdate1();
|
||||
}
|
||||
public synchronized void stopAcceptingTunnels() {
|
||||
if(isStartedOkay()){
|
||||
state=State.gracefulShutdownInProgress;
|
||||
fireStateUpdate();
|
||||
setState(State.gracefulShutdownInProgress);
|
||||
I2PD_JNI.stopAcceptingTunnels();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNetworkStateChange(boolean isConnected) {
|
||||
I2PD_JNI.onNetworkStateChanged(isConnected);
|
||||
}
|
||||
|
||||
private boolean startedOkay;
|
||||
|
||||
public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress};
|
||||
|
||||
private State state = State.uninitialized;
|
||||
|
||||
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);
|
||||
|
||||
State(int statusStringResourceId) {
|
||||
this.statusStringResourceId = statusStringResourceId;
|
||||
}
|
||||
|
||||
private final int statusStringResourceId;
|
||||
|
||||
public int getStatusStringResourceId() {
|
||||
return statusStringResourceId;
|
||||
}
|
||||
};
|
||||
|
||||
private volatile State state = State.uninitialized;
|
||||
|
||||
public State getState() { return state; }
|
||||
|
||||
public synchronized void start() {
|
||||
if(state != State.uninitialized)return;
|
||||
state = State.starting;
|
||||
fireStateUpdate();
|
||||
|
||||
{
|
||||
setState(State.starting);
|
||||
new Thread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
I2PD_JNI.loadLibraries();
|
||||
synchronized (DaemonSingleton.this) {
|
||||
state = State.jniLibraryLoaded;
|
||||
fireStateUpdate();
|
||||
}
|
||||
setState(State.jniLibraryLoaded);
|
||||
} catch (Throwable tr) {
|
||||
lastThrowable=tr;
|
||||
synchronized (DaemonSingleton.this) {
|
||||
state = State.startFailed;
|
||||
fireStateUpdate();
|
||||
}
|
||||
setState(State.startFailed);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
synchronized (DaemonSingleton.this) {
|
||||
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
|
||||
daemonStartResult = I2PD_JNI.startDaemon();
|
||||
if("ok".equals(daemonStartResult)){
|
||||
state=State.startedOkay;
|
||||
setState(State.startedOkay);
|
||||
setStartedOkay(true);
|
||||
}else state=State.startFailed;
|
||||
fireStateUpdate();
|
||||
}else setState(State.startFailed);
|
||||
}
|
||||
} catch (Throwable tr) {
|
||||
lastThrowable=tr;
|
||||
synchronized (DaemonSingleton.this) {
|
||||
state = State.startFailed;
|
||||
fireStateUpdate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
setState(State.startFailed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}, "i2pdDaemonStart").start();
|
||||
}
|
||||
private Throwable lastThrowable;
|
||||
private String daemonStartResult="N/A";
|
||||
|
||||
private synchronized void fireStateUpdate() {
|
||||
private void fireStateUpdate1() {
|
||||
Log.i(TAG, "daemon state change: "+state);
|
||||
for(StateUpdateListener listener : stateUpdateListeners) {
|
||||
try {
|
||||
listener.daemonStateUpdate();
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG, "exception in listener ignored", tr);
|
||||
try {
|
||||
listener.daemonStateUpdate();
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG, "exception in listener ignored", tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,7 +118,7 @@ public class DaemonSingleton {
|
||||
public String getDaemonStartResult() {
|
||||
return daemonStartResult;
|
||||
}
|
||||
|
||||
|
||||
private final Object startedOkayLock = new Object();
|
||||
|
||||
public boolean isStartedOkay() {
|
||||
@ -121,6 +137,7 @@ public class DaemonSingleton {
|
||||
if(isStartedOkay()){
|
||||
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);}
|
||||
setStartedOkay(false);
|
||||
setState(State.stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,149 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ForegroundService extends Service {
|
||||
private NotificationManager notificationManager;
|
||||
private static final String TAG="FgService";
|
||||
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION = R.string.i2pd_started;
|
||||
private volatile boolean shown;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||
@Override
|
||||
public void daemonStateUpdate() {
|
||||
try {
|
||||
synchronized (ForegroundService.this) {
|
||||
if (shown) cancelNotification();
|
||||
showNotification();
|
||||
}
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG,"error ignored",tr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Display a notification about us starting. We put an icon in the status bar.
|
||||
showNotification();
|
||||
daemon.start();
|
||||
// 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);
|
||||
daemon.start();
|
||||
return START_STICKY;
|
||||
}
|
||||
private NotificationManager notificationManager;
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// Cancel the persistent notification.
|
||||
notificationManager.cancel(NOTIFICATION);
|
||||
|
||||
stopForeground(true);
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION = 1;
|
||||
|
||||
// Tell the user we stopped.
|
||||
Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
/**
|
||||
* 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 IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
// This is the object that receives interactions from clients. See
|
||||
// RemoteService for a more complete example.
|
||||
private final IBinder mBinder = new LocalBinder();
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a notification while this service is running.
|
||||
*/
|
||||
private void showNotification() {
|
||||
// In this sample, we'll use the same text for the ticker and the expanded notification
|
||||
CharSequence text = getText(R.string.i2pd_started);
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
// The PendingIntent to launch our activity if the user selects this notification
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||
new Intent(this, I2PD.class), 0);
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
|
||||
cancelNotification();
|
||||
}
|
||||
|
||||
// Set the info for the views that show in the notification panel.
|
||||
Notification notification = new Notification.Builder(this)
|
||||
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||
.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();
|
||||
private synchronized void cancelNotification() {
|
||||
// Cancel the persistent notification.
|
||||
notificationManager.cancel(NOTIFICATION);
|
||||
|
||||
// Send the notification.
|
||||
//mNM.notify(NOTIFICATION, notification);
|
||||
startForeground(NOTIFICATION, notification);
|
||||
}
|
||||
|
||||
private final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
stopForeground(true);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
// 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 >= 26 ? createNotificationChannel() : "";
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
|
@ -1,245 +0,0 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class I2PD extends Activity {
|
||||
private static final String TAG = "i2pd";
|
||||
|
||||
private TextView textView;
|
||||
|
||||
private final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
|
||||
private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
|
||||
@Override
|
||||
public void daemonStateUpdate() {
|
||||
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():""));
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG,"error ignored",tr);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
textView = new TextView(this);
|
||||
setContentView(textView);
|
||||
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
|
||||
//set the app be foreground
|
||||
doBindService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
localDestroy();
|
||||
}
|
||||
|
||||
private void localDestroy() {
|
||||
textView = null;
|
||||
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
|
||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null) {
|
||||
gracefulQuitTimer.cancel();
|
||||
setGracefulQuitTimer(null);
|
||||
}
|
||||
try{
|
||||
doUnbindService();
|
||||
}catch(Throwable tr){
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence throwableToString(Throwable tr) {
|
||||
StringWriter sw = new StringWriter(8192);
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
tr.printStackTrace(pw);
|
||||
pw.close();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
// private LocalService mBoundService;
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// This is called when the connection with the service has been
|
||||
// established, giving us the service object we can use to
|
||||
// interact with the service. Because we have bound to a explicit
|
||||
// service that we know is running in our own process, we can
|
||||
// cast its IBinder to a concrete class and directly access it.
|
||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
||||
|
||||
// Tell the user about this for our demo.
|
||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
// This is called when the connection with the service has been
|
||||
// unexpectedly disconnected -- that is, its process crashed.
|
||||
// Because it is running in our same process, we should never
|
||||
// see this happen.
|
||||
// mBoundService = null;
|
||||
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private boolean mIsBound;
|
||||
|
||||
private void doBindService() {
|
||||
// Establish a connection with the service. We use an explicit
|
||||
// class name because we want a specific service implementation that
|
||||
// we know will be running in our own process (and thus won't be
|
||||
// supporting component replacement by other applications).
|
||||
bindService(new Intent(this,
|
||||
ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||
mIsBound = true;
|
||||
}
|
||||
|
||||
private void doUnbindService() {
|
||||
if (mIsBound) {
|
||||
// Detach our existing connection.
|
||||
unbindService(mConnection);
|
||||
mIsBound = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(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.
|
||||
int id = item.getItemId();
|
||||
|
||||
switch(id){
|
||||
case R.id.action_quit:
|
||||
quit();
|
||||
return true;
|
||||
case R.id.action_graceful_quit:
|
||||
gracefulQuit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
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);
|
||||
}
|
||||
|
||||
private Timer gracefulQuitTimer;
|
||||
private final Object gracefulQuitTimerLock = new Object();
|
||||
private void gracefulQuit() {
|
||||
if(getGracefulQuitTimer()!=null){
|
||||
Toast.makeText(this, R.string.graceful_quit_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(this, R.string.graceful_quit_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();
|
||||
Timer gracefulQuitTimer = new Timer(true);
|
||||
setGracefulQuitTimer(gracefulQuitTimer);
|
||||
gracefulQuitTimer.schedule(new TimerTask(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
quit();
|
||||
}
|
||||
|
||||
}, 10*60*1000/*milliseconds*/);
|
||||
}else{
|
||||
quit();
|
||||
}
|
||||
} catch(Throwable tr) {
|
||||
Log.e(TAG,"",tr);
|
||||
}
|
||||
}
|
||||
|
||||
},"gracQuitInit").start();
|
||||
}
|
||||
|
||||
private Timer getGracefulQuitTimer() {
|
||||
synchronized (gracefulQuitTimerLock) {
|
||||
return gracefulQuitTimer;
|
||||
}
|
||||
}
|
||||
|
||||
private void setGracefulQuitTimer(Timer gracefulQuitTimer) {
|
||||
synchronized (gracefulQuitTimerLock) {
|
||||
this.gracefulQuitTimer = gracefulQuitTimer;
|
||||
}
|
||||
}
|
||||
}
|
639
android/src/org/purplei2p/i2pd/I2PDActivity.java
Executable file
639
android/src/org/purplei2p/i2pd/I2PDActivity.java
Executable file
@ -0,0 +1,639 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
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 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();
|
||||
|
||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
@Override
|
||||
public void daemonStateUpdate()
|
||||
{
|
||||
processAssets();
|
||||
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;
|
||||
synchronized (graceStartedMillis_LOCK){
|
||||
remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D);
|
||||
}
|
||||
long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D);
|
||||
long remSec=remainingSeconds-remainingMinutes*60;
|
||||
return remainingMinutes+":"+(remSec/10)+remSec%10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.i(TAG, "onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
textView = new TextView(this);
|
||||
setContentView(textView);
|
||||
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();
|
||||
|
||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null){
|
||||
long gracefulStopAtMillis;
|
||||
synchronized (graceStartedMillis_LOCK) {
|
||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||
}
|
||||
rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
|
||||
}
|
||||
|
||||
openBatteryOptimizationDialogIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
textView = null;
|
||||
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||
//cancelGracefulStop0();
|
||||
try{
|
||||
doUnbindService();
|
||||
}catch(Throwable tr){
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
@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();
|
||||
setGracefulQuitTimer(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence throwableToString(Throwable tr) {
|
||||
StringWriter sw = new StringWriter(8192);
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
tr.printStackTrace(pw);
|
||||
pw.close();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
// private LocalService mBoundService;
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// This is called when the connection with the service has been
|
||||
// established, giving us the service object we can use to
|
||||
// interact with the service. Because we have bound to a explicit
|
||||
// service that we know is running in our own process, we can
|
||||
// cast its IBinder to a concrete class and directly access it.
|
||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
||||
|
||||
// Tell the user about this for our demo.
|
||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
// This is called when the connection with the service has been
|
||||
// unexpectedly disconnected -- that is, its process crashed.
|
||||
// Because it is running in our same process, we should never
|
||||
// see this happen.
|
||||
// mBoundService = null;
|
||||
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
private static volatile boolean mIsBound;
|
||||
|
||||
private void doBindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) return;
|
||||
// Establish a connection with the service. We use an explicit
|
||||
// class name because we want a specific service implementation that
|
||||
// we know will be running in our own process (and thus won't be
|
||||
// supporting component replacement by other applications).
|
||||
bindService(new Intent(this, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||
mIsBound = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void doUnbindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) {
|
||||
// Detach our existing connection.
|
||||
unbindService(mConnection);
|
||||
mIsBound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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(@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.
|
||||
int id = item.getItemId();
|
||||
|
||||
switch(id){
|
||||
case R.id.action_stop:
|
||||
i2pdStop();
|
||||
return true;
|
||||
case R.id.action_graceful_stop:
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
private void i2pdGracefulStop() {
|
||||
if(daemon.getState()==DaemonSingleton.State.stopped){
|
||||
Toast.makeText(this, R.string.already_stopped,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if(getGracefulQuitTimer()!=null){
|
||||
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
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());
|
||||
}
|
||||
else
|
||||
i2pdStop();
|
||||
}
|
||||
catch(Throwable tr)
|
||||
{
|
||||
Log.e(TAG,"",tr);
|
||||
}
|
||||
},"gracCancel").start();
|
||||
}
|
||||
|
||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
||||
final Timer gracefulQuitTimer = new Timer(true);
|
||||
setGracefulQuitTimer(gracefulQuitTimer);
|
||||
gracefulQuitTimer.schedule(new TimerTask(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
i2pdStop();
|
||||
}
|
||||
|
||||
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
|
||||
final TimerTask tickerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
}
|
||||
};
|
||||
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
|
||||
}
|
||||
|
||||
private static Timer getGracefulQuitTimer() {
|
||||
return 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the asset at the specified path to this app's data directory. If the
|
||||
* asset is a directory, its contents are also copied.
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyAsset(String path) {
|
||||
AssetManager manager = getAssets();
|
||||
|
||||
// If we have a directory, we make it and recurse. If a file, we copy its
|
||||
// contents.
|
||||
try {
|
||||
String[] contents = manager.list(path);
|
||||
|
||||
// The documentation suggests that list throws an IOException, but doesn't
|
||||
// say under what conditions. It'd be nice if it did so when the path was
|
||||
// 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) {
|
||||
copyFileAsset(path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the directory.
|
||||
File dir = new File(i2pdpath, path);
|
||||
boolean result = dir.mkdirs();
|
||||
Log.d(TAG, "dir.mkdirs() returned " + result);
|
||||
|
||||
// Recurse on the contents.
|
||||
for (String entry : contents) {
|
||||
copyAsset(path + '/' + entry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "ex ignored for path='" + path + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the asset file specified by path to app's data directory. Assumes
|
||||
* parent directories have already been created.
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyFileAsset(String path) {
|
||||
File file = new File(i2pdpath, path);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteRecursive(File fileOrDirectory) {
|
||||
if (fileOrDirectory.isDirectory()) {
|
||||
File[] files = fileOrDirectory.listFiles();
|
||||
if(files!=null) {
|
||||
for (File child : files) {
|
||||
deleteRecursive(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
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
|
||||
FileReader fileReader = new FileReader(holderFile);
|
||||
|
||||
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 {
|
||||
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 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);
|
||||
try {
|
||||
writer.append(versionName);
|
||||
} finally {
|
||||
try{
|
||||
writer.close();
|
||||
}catch (IOException e){
|
||||
Log.e(TAG,"on writer close", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable 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);
|
||||
}
|
||||
}
|
170
android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
Normal file
170
android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
Normal file
@ -0,0 +1,170 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
//dangerous perms, per https://developer.android.com/guide/topics/permissions/normal-permissions.html :
|
||||
//android.permission.WRITE_EXTERNAL_STORAGE
|
||||
public class I2PDPermsAskerActivity extends Activity {
|
||||
|
||||
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private void request_write_ext_storage_perms() {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// 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();
|
||||
|
||||
} else {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
@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.
|
||||
|
||||
startMainActivity();
|
||||
|
||||
} else {
|
||||
|
||||
// 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.
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
@ -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 void stopAcceptingTunnels();
|
||||
|
||||
public static native String startDaemon();
|
||||
|
||||
//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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
android_binary_only/.gitignore
vendored
Normal file
18
android_binary_only/.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
gen
|
||||
tests
|
||||
bin
|
||||
libs
|
||||
log*
|
||||
obj
|
||||
.gradle
|
||||
.idea
|
||||
.externalNativeBuild
|
||||
ant.properties
|
||||
local.properties
|
||||
build.sh
|
||||
android.iml
|
||||
build
|
||||
gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
|
74
android_binary_only/jni/Android.mk
Executable file
74
android_binary_only/jni/Android.mk
Executable file
@ -0,0 +1,74 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := i2pd
|
||||
LOCAL_CPP_FEATURES := rtti exceptions
|
||||
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(DAEMON_SRC_PATH)
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
boost_system \
|
||||
boost_date_time \
|
||||
boost_filesystem \
|
||||
boost_program_options \
|
||||
crypto ssl \
|
||||
miniupnpc
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
LOCAL_SRC_FILES := $(IFADDRS_PATH)/ifaddrs.c \
|
||||
$(wildcard $(LIB_SRC_PATH)/*.cpp)\
|
||||
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
|
||||
$(DAEMON_SRC_PATH)/UnixDaemon.cpp \
|
||||
$(DAEMON_SRC_PATH)/Daemon.cpp \
|
||||
$(DAEMON_SRC_PATH)/UPnP.cpp \
|
||||
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
|
||||
$(DAEMON_SRC_PATH)/I2PControl.cpp \
|
||||
$(DAEMON_SRC_PATH)/i2pd.cpp
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_system
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_date_time
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_filesystem
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_program_options
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crypto
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := ssl
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
||||
LOCAL_STATIC_LIBRARIES := crypto
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
40
android_binary_only/jni/Application.mk
Executable file
40
android_binary_only/jni/Application.mk
Executable file
@ -0,0 +1,40 @@
|
||||
APP_ABI := all
|
||||
#APP_ABI += x86
|
||||
#APP_ABI += x86_64
|
||||
#APP_ABI += armeabi-v7a
|
||||
#APP_ABI += arm64-v8a
|
||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
||||
APP_PLATFORM := android-14
|
||||
|
||||
NDK_TOOLCHAIN_VERSION := clang
|
||||
APP_STL := c++_static
|
||||
|
||||
# Enable c++17 extensions in source code
|
||||
APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE
|
||||
|
||||
APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP
|
||||
APP_LDFLAGS += -rdynamic -fPIE -pie
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
APP_CPPFLAGS += -DANDROID_ARM7A
|
||||
endif
|
||||
|
||||
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
|
||||
#APP_OPTIM := debug
|
||||
|
||||
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
|
||||
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
||||
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
|
||||
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
||||
# change to your own
|
||||
I2PD_LIBS_PATH = /path/to/libraries
|
||||
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
|
||||
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
|
||||
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
|
||||
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
|
||||
|
||||
# don't change me
|
||||
I2PD_SRC_PATH = $(PWD)/..
|
||||
|
||||
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
|
||||
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
|
||||
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon
|
@ -1,4 +1,4 @@
|
||||
version: 2.17.{build}
|
||||
version: 2.31.0.{build}
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
branches:
|
||||
@ -17,7 +17,7 @@ environment:
|
||||
- MSYSTEM: MINGW32
|
||||
|
||||
install:
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc"
|
||||
- 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"
|
||||
|
3
build/.gitignore
vendored
3
build/.gitignore
vendored
@ -8,6 +8,7 @@
|
||||
/CPackConfig.cmake
|
||||
/CPackSourceConfig.cmake
|
||||
/install_manifest.txt
|
||||
/arch.c
|
||||
# windows build script
|
||||
i2pd*.zip
|
||||
build*.log
|
||||
build*.log
|
@ -19,13 +19,15 @@ 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" )
|
||||
set ( CMAKE_SOURCE_DIR ".." )
|
||||
|
||||
# architecture
|
||||
include(TargetArch)
|
||||
target_architecture(ARCHITECTURE)
|
||||
|
||||
set(LIBI2PD_SRC_DIR ../libi2pd)
|
||||
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
|
||||
|
||||
@ -35,6 +37,7 @@ include_directories(${LIBI2PD_CLIENT_SRC_DIR})
|
||||
set (LIBI2PD_SRC
|
||||
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Config.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/CPU.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
|
||||
@ -70,32 +73,33 @@ 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 (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS)
|
||||
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 "")
|
||||
install(TARGETS libi2pd
|
||||
EXPORT libi2pd
|
||||
ARCHIVE DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
|
||||
if (WITH_LIBRARY)
|
||||
install(TARGETS libi2pd
|
||||
EXPORT libi2pd
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
|
||||
# FIXME This pulls stdafx
|
||||
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
set (CLIENT_SRC
|
||||
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
||||
@ -108,13 +112,18 @@ 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(i2pdclient ${CLIENT_SRC})
|
||||
add_library(libi2pdclient ${CLIENT_SRC})
|
||||
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
|
||||
|
||||
if (WITH_LIBRARY)
|
||||
install(TARGETS libi2pdclient
|
||||
EXPORT libi2pdclient
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
endif()
|
||||
|
||||
set(DAEMON_SRC_DIR ../daemon)
|
||||
|
||||
@ -158,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 standart 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")
|
||||
@ -179,6 +188,10 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
endif ()
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# more tweaks
|
||||
if (LINUX)
|
||||
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++" ) # required for <atomic>
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++
|
||||
endif()
|
||||
if (NOT (MSVC OR MSYS OR APPLE))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
|
||||
endif()
|
||||
@ -190,20 +203,14 @@ if (WITH_HARDENING AND MSVC)
|
||||
endif ()
|
||||
|
||||
# compiler flags customization (by system)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
if (UNIX)
|
||||
list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
||||
add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" )
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
||||
add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" )
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS)
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp")
|
||||
if (NOT (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE))
|
||||
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
||||
add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" )
|
||||
endif ()
|
||||
elseif (WIN32 OR MSYS)
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp")
|
||||
if (WITH_GUI)
|
||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Win32App.cpp")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp"
|
||||
@ -215,7 +222,6 @@ endif ()
|
||||
|
||||
if (WITH_AESNI)
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes" )
|
||||
add_definitions ( -DAESNI )
|
||||
endif()
|
||||
|
||||
if (WITH_AVX)
|
||||
@ -302,7 +308,7 @@ if (WITH_PCH)
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
target_compile_options(libi2pd PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
target_compile_options(i2pdclient PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
target_compile_options(libi2pdclient PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
else()
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
||||
get_directory_property(DEFS DEFINITIONS)
|
||||
@ -311,25 +317,21 @@ if (WITH_PCH)
|
||||
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
|
||||
)
|
||||
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
|
||||
target_compile_options(i2pdclient PRIVATE -include libi2pd/stdafx.h)
|
||||
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
|
||||
endif()
|
||||
target_link_libraries(libi2pd stdafx)
|
||||
endif()
|
||||
|
||||
target_link_libraries(i2pdclient libi2pd)
|
||||
target_link_libraries(libi2pdclient libi2pd)
|
||||
|
||||
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
||||
endif()
|
||||
|
||||
find_package ( OpenSSL REQUIRED )
|
||||
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
||||
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
||||
else()
|
||||
if(NOT (OPENSSL_VERSION VERSION_LESS 1.1))
|
||||
message(WARNING "Your OpenSSL version ${OPENSSL_VERSION} >=1.1 is experimental: build with v1.0 when possible.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_UPNP)
|
||||
@ -348,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
|
||||
@ -366,11 +368,13 @@ if (NOT ZLIB_FOUND )
|
||||
if (NOT WITH_STATIC)
|
||||
set ( ZLIB_LIBRARY debug zlibd optimized zlib CACHE STRING "zlib libraries" FORCE)
|
||||
endif ()
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib)
|
||||
else()
|
||||
link_directories(${ZLIB_ROOT}/lib)
|
||||
endif ()
|
||||
if (WITH_STATIC AND (MSVC OR MSYS))
|
||||
set ( ZLIB_LIBRARY debug zlibstaticd optimized zlibstatic CACHE STRING "zlib libraries" FORCE)
|
||||
endif ()
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib ${ZLIB_ROOT}/lib)
|
||||
|
||||
# load includes
|
||||
include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
|
||||
@ -382,6 +386,8 @@ if (WITH_MESHNET)
|
||||
message(WARNING "This build will NOT work on mainline i2p")
|
||||
endif()
|
||||
|
||||
include(CheckAtomic)
|
||||
|
||||
|
||||
# show summary
|
||||
message(STATUS "---------------------------------------")
|
||||
@ -389,6 +395,7 @@ message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "Compiler vendor : ${CMAKE_CXX_COMPILER_ID}")
|
||||
message(STATUS "Compiler version : ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
message(STATUS "Compiler path : ${CMAKE_CXX_COMPILER}")
|
||||
message(STATUS "Architecture : ${ARCHITECTURE}")
|
||||
message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS "Options:")
|
||||
message(STATUS " AESNI : ${WITH_AESNI}")
|
||||
@ -402,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
|
||||
@ -448,7 +453,8 @@ if (WITH_BINARY)
|
||||
if (WITH_STATIC)
|
||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB})
|
||||
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)
|
||||
set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
@ -461,12 +467,6 @@ if (WITH_BINARY)
|
||||
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
|
||||
" COMPONENT Runtime)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if (NOT (MSVC OR MSYS OR APPLE)) # for Clang build on Linux
|
||||
target_link_libraries("${PROJECT_NAME}" stdc++)
|
||||
endif()
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
install(FILES ../LICENSE
|
||||
|
@ -6,7 +6,7 @@ REM Copyright (c) 2013-2017, The PurpleI2P Project
|
||||
REM This file is part of Purple i2pd project and licensed under BSD3
|
||||
REM See full license text in LICENSE file at top of project tree
|
||||
|
||||
REM To use that script, you must have installed in your MSYS installation theese packages:
|
||||
REM To use that script, you must have installed in your MSYS installation these packages:
|
||||
REM Base: git make zip
|
||||
REM x86_64: mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc
|
||||
REM i686: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc
|
||||
@ -16,10 +16,13 @@ REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\m
|
||||
set "WD=C:\msys64\usr\bin\"
|
||||
set MSYS2_PATH_TYPE=inherit
|
||||
set CHERE_INVOKING=enabled_from_arguments
|
||||
set MSYSTEM=MSYS
|
||||
REM set MSYSTEM=MSYS
|
||||
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
|
||||
|
||||
@ -51,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...
|
||||
@ -58,14 +69,21 @@ pause
|
||||
exit /b 0
|
||||
|
||||
:BUILDING
|
||||
%xSH% "make clean" >> nul
|
||||
echo Building i2pd %tag% for win%bitness%:
|
||||
echo Build AVX+AESNI...
|
||||
%xSH% "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1
|
||||
%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 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 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 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
|
106
build/cmake_modules/CheckAtomic.cmake
Normal file
106
build/cmake_modules/CheckAtomic.cmake
Normal file
@ -0,0 +1,106 @@
|
||||
# atomic builtins are required for threading support.
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
std::atomic<int> x;
|
||||
int main() {
|
||||
return x;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_working_cxx_atomics)
|
||||
|
||||
function(check_working_cxx_atomics64 varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<uint64_t> x (0);
|
||||
int main() {
|
||||
uint64_t i = x.load(std::memory_order_relaxed);
|
||||
return 0;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_working_cxx_atomics64)
|
||||
|
||||
|
||||
# This isn't necessary on MSVC, so avoid command-line switch annoyance
|
||||
# by only running on GCC-like hosts.
|
||||
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if( HAVE_LIBATOMIC )
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for 64 bit atomic operations.
|
||||
if(MSVC)
|
||||
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
|
||||
else()
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
endif()
|
||||
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
|
||||
if(HAVE_CXX_LIBATOMICS64)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
## TODO: This define is only used for the legacy atomic operations in
|
||||
## llvm's Atomic.h, which should be replaced. Other code simply
|
||||
## assumes C++11 <atomic> works.
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifdef _MSC_VER
|
||||
#include <Intrin.h> /* Workaround for PR19898. */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
int main() {
|
||||
#ifdef _MSC_VER
|
||||
volatile LONG val = 1;
|
||||
MemoryBarrier();
|
||||
InterlockedCompareExchange(&val, 0, 1);
|
||||
InterlockedIncrement(&val);
|
||||
InterlockedDecrement(&val);
|
||||
#else
|
||||
volatile unsigned long val = 1;
|
||||
__sync_synchronize();
|
||||
__sync_val_compare_and_swap(&val, 1, 0);
|
||||
__sync_add_and_fetch(&val, 1);
|
||||
__sync_sub_and_fetch(&val, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
" LLVM_HAS_ATOMICS)
|
||||
|
||||
if( NOT LLVM_HAS_ATOMICS )
|
||||
message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")
|
||||
endif()
|
@ -24,5 +24,5 @@ else()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY)
|
||||
|
||||
|
||||
endif()
|
||||
|
134
build/cmake_modules/TargetArch.cmake
Normal file
134
build/cmake_modules/TargetArch.cmake
Normal file
@ -0,0 +1,134 @@
|
||||
# Based on the Qt 5 processor detection code, so should be very accurate
|
||||
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
|
||||
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
|
||||
|
||||
# Regarding POWER/PowerPC, just as is noted in the Qt source,
|
||||
# "There are many more known variants/revisions that we do not handle/detect."
|
||||
|
||||
set(archdetect_c_code "
|
||||
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
|
||||
#if defined(__ARM_ARCH_7__) \\
|
||||
|| defined(__ARM_ARCH_7A__) \\
|
||||
|| defined(__ARM_ARCH_7R__) \\
|
||||
|| defined(__ARM_ARCH_7M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
|
||||
#error cmake_ARCH armv7
|
||||
#elif defined(__ARM_ARCH_6__) \\
|
||||
|| defined(__ARM_ARCH_6J__) \\
|
||||
|| defined(__ARM_ARCH_6T2__) \\
|
||||
|| defined(__ARM_ARCH_6Z__) \\
|
||||
|| defined(__ARM_ARCH_6K__) \\
|
||||
|| defined(__ARM_ARCH_6ZK__) \\
|
||||
|| defined(__ARM_ARCH_6M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
|
||||
#error cmake_ARCH armv6
|
||||
#elif defined(__ARM_ARCH_5TEJ__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
|
||||
#error cmake_ARCH armv5
|
||||
#else
|
||||
#error cmake_ARCH arm
|
||||
#endif
|
||||
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
#error cmake_ARCH i386
|
||||
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
|
||||
#error cmake_ARCH x86_64
|
||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||
#error cmake_ARCH ia64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
||||
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
||||
|| defined(_M_MPPC) || defined(_M_PPC)
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
|
||||
#error cmake_ARCH ppc64
|
||||
#else
|
||||
#error cmake_ARCH ppc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#error cmake_ARCH unknown
|
||||
")
|
||||
|
||||
# Set ppc_support to TRUE before including this file or ppc and ppc64
|
||||
# will be treated as invalid architectures since they are no longer supported by Apple
|
||||
|
||||
function(target_architecture output_var)
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
|
||||
# First let's normalize the order of the values
|
||||
|
||||
# Note that it's not possible to compile PowerPC applications if you are using
|
||||
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
|
||||
# disable it by default
|
||||
# See this page for more information:
|
||||
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
|
||||
|
||||
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
|
||||
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
|
||||
|
||||
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
|
||||
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
|
||||
set(osx_arch_ppc TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "i386")
|
||||
set(osx_arch_i386 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "x86_64")
|
||||
set(osx_arch_x86_64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
||||
set(osx_arch_ppc64 TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Now add all the architectures in our normalized order
|
||||
if(osx_arch_ppc)
|
||||
list(APPEND ARCH ppc)
|
||||
endif()
|
||||
|
||||
if(osx_arch_i386)
|
||||
list(APPEND ARCH i386)
|
||||
endif()
|
||||
|
||||
if(osx_arch_x86_64)
|
||||
list(APPEND ARCH x86_64)
|
||||
endif()
|
||||
|
||||
if(osx_arch_ppc64)
|
||||
list(APPEND ARCH ppc64)
|
||||
endif()
|
||||
else()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
|
||||
|
||||
enable_language(C)
|
||||
|
||||
# Detect the architecture in a rather creative way...
|
||||
# This compiles a small C program which is a series of ifdefs that selects a
|
||||
# particular #error preprocessor directive whose message string contains the
|
||||
# target architecture. The program will always fail to compile (both because
|
||||
# file is not a valid C program, and obviously because of the presence of the
|
||||
# #error preprocessor directives... but by exploiting the preprocessor in this
|
||||
# way, we can detect the correct target architecture even when cross-compiling,
|
||||
# since the program itself never needs to be run (only the compiler/preprocessor)
|
||||
try_run(
|
||||
run_result_unused
|
||||
compile_result_unused
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_BINARY_DIR}/arch.c"
|
||||
COMPILE_OUTPUT_VARIABLE ARCH
|
||||
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
|
||||
)
|
||||
|
||||
# Parse the architecture name from the compiler output
|
||||
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
|
||||
|
||||
# Get rid of the value marker leaving just the architecture name
|
||||
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
|
||||
|
||||
# If we are compiling with an unknown architecture this variable should
|
||||
# already be set to "unknown" but in the case that it's empty (i.e. due
|
||||
# to a typo in the code), then set it to unknown
|
||||
if (NOT ARCH)
|
||||
set(ARCH unknown)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${output_var} "${ARCH}" PARENT_SCOPE)
|
||||
endfunction()
|
@ -28,7 +28,7 @@ Options are set via docker environment variables. This can be set at run with -e
|
||||
|
||||
**Logging**
|
||||
|
||||
Logging happens to STDOUT as the best practise with docker containers, since infrastructure systems like kubernetes with ELK integration can automaticly forward the log to say, kibana or greylog without manual setup. :)
|
||||
Logging happens to STDOUT as the best practise with docker containers, since infrastructure systems like kubernetes with ELK integration can automatically forward the log to say, kibana or greylog without manual setup. :)
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \
|
||||
libssl-dev git build-essential
|
||||
|
||||
RUN git clone https://github.com/PurpleI2P/i2pd.git
|
||||
WORKDIR /i2pd
|
||||
WORKDIR /i2pd
|
||||
RUN make
|
||||
|
||||
CMD ./i2pd
|
||||
|
2
contrib/android_binary_pack/.gitignore
vendored
Normal file
2
contrib/android_binary_pack/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
archive
|
||||
i2pd_*_android_binary.zip
|
45
contrib/android_binary_pack/build-archive
Executable file
45
contrib/android_binary_pack/build-archive
Executable 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
|
33
contrib/android_binary_pack/i2pd
Executable file
33
contrib/android_binary_pack/i2pd
Executable 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
|
@ -1,4 +1,4 @@
|
||||
# Basic profile for i2pd
|
||||
# Basic profile for i2pd
|
||||
# Should work without modifications with Ubuntu/Debian packages
|
||||
# Author: Darknet Villain <supervillain@riseup.net>
|
||||
#
|
||||
@ -17,14 +17,20 @@
|
||||
/etc/host.conf r,
|
||||
/etc/hosts r,
|
||||
/etc/nsswitch.conf r,
|
||||
/etc/resolv.conf r,
|
||||
/run/resolvconf/resolv.conf r,
|
||||
/run/systemd/resolve/stub-resolv.conf r,
|
||||
|
||||
# path specific (feel free to modify if you have another paths)
|
||||
/etc/i2pd/** r,
|
||||
/run/i2pd/i2pd.pid rwk,
|
||||
/var/lib/i2pd/** rw,
|
||||
/var/log/i2pd.log w,
|
||||
/var/run/i2pd/i2pd.pid rw,
|
||||
/var/log/i2pd/i2pd.log w,
|
||||
/var/run/i2pd/i2pd.pid rwk,
|
||||
/usr/sbin/i2pd mr,
|
||||
/usr/share/i2pd/** r,
|
||||
|
||||
|
||||
# user homedir (if started not by init.d or systemd)
|
||||
owner @{HOME}/.i2pd/ rw,
|
||||
owner @{HOME}/.i2pd/** rwk,
|
||||
}
|
||||
|
@ -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-----
|
@ -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-----
|
@ -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-----
|
@ -1,32 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFhTCCA22gAwIBAgIELuRWgDANBgkqhkiG9w0BAQ0FADBzMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEcMBoGA1UEAwwTa2lsbHlvdXJ0dkBt
|
||||
YWlsLmkycDAeFw0xMzEwMDYyMTM5MzFaFw0yMzEwMDYyMTM5MzFaMHMxCzAJBgNV
|
||||
BAYTAlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBB
|
||||
bm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRwwGgYDVQQDDBNraWxseW91
|
||||
cnR2QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAig3u
|
||||
niLWm0y/TFJtciHgmWUt20FOdQrxkiSZ87G8xjuGfq7TbGIiVDn7pQZcHidpq+Dk
|
||||
47sm+Swqhb4psSijj0AXUEVKlV39jF5IZE+VUgmEtMqQbnBkWudaTJPWcEe9T/Kd
|
||||
8Oz2jgsnrD/EGVTMKBBjt/gk8VqTWvpCdCF1GhqcCeUTFHzjhN9jtoRCaJ2DClpO
|
||||
Px+86+d3s9PqUFo8gcD/dbbyJCMqUCMBLtIy/Ooouxb9cfWtXfyOlphU+enmdvuA
|
||||
0BDewb9pOJg2/kVd9/9moDWcBGChLOlfSlxpDwyUtcclcpvwnG7c6o4or6gqLeOf
|
||||
AbCpse623utV7fWlFWG7M4AQ/2emhhe4YoMJQnflydzV8bPRJxRTeW1j/9UfpvLT
|
||||
nO5LHp0oBXE0GqAPjxuAr+r5IDXFbkKYNjK5oWQB/Ul3LkexulYdCzHWbGd1Ja5b
|
||||
sbiOy6t/hH6G8DD75HYb+PQZaNZWBv90EyOq1JDSUPw6nxVbhiBldi3ipc8/1X51
|
||||
FbzBqJ+QO1XKrKqxWxBKoTekuy38KRzsmkSCpY+WJ9f0gLOKtxzVO2HNNqqVFGQf
|
||||
RGIbrNA0JSRQ1fgelccfrcRIXIZ3B8Tk/wxCIzCY6Yvg2jezz2xJkVdqOUsznS2v
|
||||
+xJe67PYIAeMVtcfO4kmuCvyIYhsUEpob2n/5lkCAwEAAaMhMB8wHQYDVR0OBBYE
|
||||
FCLneov6QMtvra5FSoSLhdymi++rMA0GCSqGSIb3DQEBDQUAA4ICAQAIcqbiwjdQ
|
||||
M9VlGBiHe5eVsL6OM9zfRqR1wnRg4Q6ce65XDfEOYleBWaaNJA4BdykcA4fkUN1h
|
||||
M2D9FDQScsyPTOuzJ6o75TYh0JOtF51yCi9iuemcosxAwsm90ZXGuMDfDYeyND5c
|
||||
PAkWfyCP+jwLYbNo/hkNqyv+XWHXPQmT2adRnPXINVUQuBxVPC//C9wv2uDYWhgS
|
||||
f8M425VPp4/R/uks9mlzTx08DwacvouD0YOC+HZE4sWq+2smgeBInMiyr/THYzl+
|
||||
baMtYgVs8IKUD2gtjfXZoaQNg3eq5SedSf/5F0S/LCdu9/ccQ8CzSEoVTiQFtO78
|
||||
SaU37xai8+QTSVpPuINigxCoXmkubBd+voEmWRcBd/XB5L+u+MFU/jXyyBj2BXVj
|
||||
6agqVzY53KVYt23/63QliAUWyxT+ns9gRxVN1jrMhHdiDwsdT4NbzHxg1Su4eiHv
|
||||
C/wjD3Dga0BRTEGylpHZGzb1U1rZRHM3ho3f1QkmRPPLcBUMTyUTxJm+GEeuhPvp
|
||||
+TBf3Kg/YkdpnEMlagqcyHuIrf3m8Z/pTmpOIbekJWbbA7tluvWbMWw2ARB7dUOE
|
||||
fHYVISh0DTw2oVXxM82/q8XXHnhEXv2nW3K40x1VabxUN+sF4M/7YA8nJqwsPJei
|
||||
749STYJRfZXdIe69M9zpM5unxENAsiPJgQ==
|
||||
-----END CERTIFICATE-----
|
@ -1,32 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFezCCA2OgAwIBAgIEHLJfZzANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p
|
||||
MnAwHhcNMTMxMDI2MTExODQxWhcNMjMxMDI2MTExODQxWjBuMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p
|
||||
MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvw0vTay1IPOgxvwe8
|
||||
yt5jGakha20kw9qDb6zbEL87EWEkeOzdu7iUC69lkxVP9Ws8EbLtkeMf/CXg6CC1
|
||||
e+w8WpOHj5prOsiOlrIO+2I1tKMaMUuJDX2wK4I5ZSw/Kieimh9xqOBZknDmtwjw
|
||||
2HPW8rpxMqrScaGAP6sQD8Gh4XKKkLogfxYPzF8NnC6O8vBkFKVU2WSVZ0jPAQfv
|
||||
6luPdA+5lES+5UPWr9Yhv/CX4siGKUTxchqJRf2VU4o5BzzXae4asVA/NY7lKgEw
|
||||
eDDufbm0mRFWP4mbmXRlODuJ8GMnJbMQkNcAvZUnUcvpSTnGnIvxyxtXP5P6ic8V
|
||||
3b9HV2eIsbfO1xrgyr6/9qgGpXcdDJejhvNg6fZgQeO40bOGQYwV8bNvsNQHqnZl
|
||||
KsVhsMQkOubMxcHTBadcifi8PmdeJ5hxyyqJmyrwkmg2ijnN521M6YkoBzl+8VAi
|
||||
zLmqKZfvN5t+pb9PZ3U3jHfkeIEwDRYRAOsvVqch5+ZfSv8x/Te6o15zDKPJQtWK
|
||||
ty42GV1vERw30oSZQdrRRy/+4+HSRs3/Zb368OdAbcr+f/xPvwceYGWPeNNIoZ/x
|
||||
xkIQE3xgEK+eJyPM9McjlCAezZZclT7fWfiEYNJAiS3fGALi+a+cGYWWULxCXpz+
|
||||
y397OHhZBhnh7D9K8aPePB8tCwIDAQABoyEwHzAdBgNVHQ4EFgQUezvGHq3h1gbC
|
||||
Hs2LLVoll5fIUWMwDQYJKoZIhvcNAQENBQADggIBAF7SG1WBcE1r5eyTp/BLFZfG
|
||||
iPtvqu+B1L2HutPum/Xf8A5fxR4kcKAKpVdu6vnDzCRAsAC9YvyETgAzI2nfVgLk
|
||||
l9YZ31tSi6qxnMsQsV5o9lt/q2Rvsf2Zi/Ir8AlWtvnP8YG0Aj/8AG8MyhMLaIdj
|
||||
M2FuakPs8RqEjoJL9dTOC9VTQpNTwBH9guP9UalWYwlkaXDzMoyO4nswT/GpCpg8
|
||||
4m4RO6grzdsEIamD/PCBM5f/vq+y08GaqfXpX9+8CbaX3tdzd3x48wPphmdpkptk
|
||||
aRELIpLJZiK+Mos7W+0ZS8SHxGDIosjqVsgbZPmk12+VBcVgLOr8W1D7osS4OY59
|
||||
2GMUVV/GhoDh8wR/Td5wpZlcPE0NWmljjVg9+1E8ePAyMZy+U1KCiMlRVdRy518O
|
||||
dOzzUUQGqGQHosRrH0ypS3MGbMLmbuWFRiz7q/3mUmW2xikH9I1t/6ZMNUvh+IWL
|
||||
kGAaEf2JIv/D8+QsC0Un1W09DgvYz7qmKSeHhBixlLe68vgXtz/Fa+rRMsmPrueo
|
||||
4wk/u/VyILo0BJP860APJMZbm+DPfGhV9DF9L5Gx9+d/BlduBVGHc+AQSWbU70dS
|
||||
eH4/rgUYRikWlgwUxjY8/QQTlfx5xl28tG0xdO9libN22z7UwTGfm48BQIdrTyER
|
||||
hqQ7usTy3oaWD85MbJ0q
|
||||
-----END CERTIFICATE-----
|
@ -1,32 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFdzCCA1+gAwIBAgIEcwrwsjANBgkqhkiG9w0BAQ0FADBsMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEVMBMGA1UEAwwMenp6QG1haWwuaTJw
|
||||
MB4XDTEzMDkzMDE3NDEyNVoXDTIzMDkzMDE3NDEyNVowbDELMAkGA1UEBhMCWFgx
|
||||
CzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91
|
||||
cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxFTATBgNVBAMMDHp6ekBtYWlsLmkycDCC
|
||||
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJV4ptvhlfrcize9/ARz4lUy
|
||||
iLtLMSvSST1BdZjLJTwus05EUs0oiqnv9qXYIWGRB97aKlAmqSxsn4ZgBttCgmev
|
||||
IkuiZ8kbdqI5YaT98yKW5P2Prt9p9cPbnz5/qjwZ5L9W+k/Itx7bv2pkNEP0NLYo
|
||||
NrgHHTb1hsyRxc0lfPYk2BwsIi8hIWBHNrRpR41EWFXfqPcdsxS8cQhxVj4zLG/R
|
||||
aMm4H8T+V1R1Khl4R4qqRgXBP305xqqRoawHmZ/S9/RkF0Ji6IYwBq9iWthWol6W
|
||||
sMDn1xhZk9765fk+ohAC2XWuGSFCr02JOILRV3x/8OUxT1GYgYjc7FfyWIekg/pZ
|
||||
yotlhL2I3SMWOH3PdG58iDY121hq/LsSKM9aP20rwtvssnw+8Aex01YDkI3bM6yO
|
||||
HNi+tRojaJcJciBWv6cuiFKvQdxj/mOhOr0u0lHLlJ4jqES8uvVJkS7X/C4BB7ra
|
||||
bJYQgumZMYvVQJFIjo8vZxMXue53o65FRidvAUT29ay54UTiL7jRV9w1wHnzLapU
|
||||
xT1v7kWpWJcZ1zzC8coJjW+6ijkk38cVLb80u1Q4kEbmP2rDxw6jRvmqg6DcCKjK
|
||||
oqDt+XQ6P5grxAxLT+VMfB404WHHwNs6BB841//4ZnXvy3msMONY/5y0fsblURgh
|
||||
IS2UG1TAjR+x7+XikGx9AgMBAAGjITAfMB0GA1UdDgQWBBSvx/fCCP8UeHwjN65p
|
||||
EoHjgRfiIzANBgkqhkiG9w0BAQ0FAAOCAgEAYgVE1Aa/Ok5k+Jvujbx72bktRWXo
|
||||
Y4UfbWH/426VdgqXt3n9XtJUNM2oI4ODwITM4O15SyXQTLJhnvJz5ELcJV8nqviZ
|
||||
RjK2HNX1BW7IEta3tacCvVnjzZ265kCT59uW+qmd+5PiaAYI5lYUn8P6pe+6neSa
|
||||
HW6ecXCrdxJetSYfUUuKeV6YHpdzfjtZClLmwl91sJUBKcjK+Q9G/cE6HnwcDH1s
|
||||
uXr7SgkBt/qc/OlNuu4fnTqUA58TAumdq9cD+eLBilDFrux1HsUZMuBUp64x5oPi
|
||||
gme+3VewsczfFEtrxaG6+l6UA40Lerdx9XECZcDCcFsK6MS1uQ2HYjsyZcWnNT3l
|
||||
6eDNUbjrllwxDdRAk0cbWiMuc21CFq/1v2QMXk88EiBjEajqzyXUPmKzwFhit6pr
|
||||
5kfjfXNq+pxQSCoaqjpzVKjb3CqMhSlC8cLgrPw6HEgGnjCy4cTLFHlVmD64M778
|
||||
tj6rE7CntcmUi8GKmZKyaMyUo3QQUcrjO5IQ4+3iGUgMkZuujyjrZiOJbvircPmK
|
||||
4IQEXzJ/G00upqtqKstRybaWSbJ/k6iuturtA2n8MJiCBjhLy8dtTgDbFaDaNF7F
|
||||
NHeqQjIJDLhYDy6mi4gya3A0ort777Inl/rWYLo067pYM+EWDw66GdpbEIB0Bp71
|
||||
pwvcQcjIzbUzEK0=
|
||||
-----END CERTIFICATE-----
|
@ -1,27 +0,0 @@
|
||||
[Unit]
|
||||
Description=I2P Router written in C++
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=i2pd
|
||||
Group=i2pd
|
||||
RuntimeDirectory=i2pd
|
||||
RuntimeDirectoryMode=0700
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --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
|
||||
#Restart=on-failure
|
||||
|
||||
### Use SIGINT for gracefull stop daemon.
|
||||
# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die.
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=10m
|
||||
|
||||
# If you have problems with hunging i2pd, you can try enable this
|
||||
#LimitNOFILE=4096
|
||||
PrivateDevices=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
1
contrib/debian/i2pd.service
Symbolic link
1
contrib/debian/i2pd.service
Symbolic link
@ -0,0 +1 @@
|
||||
../i2pd.service
|
@ -2,7 +2,7 @@ FROM alpine:latest
|
||||
LABEL authors "Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
|
||||
|
||||
# Expose git branch, tag and URL variables as arguments
|
||||
ARG GIT_BRANCH="master"
|
||||
ARG GIT_BRANCH="openssl"
|
||||
ENV GIT_BRANCH=${GIT_BRANCH}
|
||||
ARG GIT_TAG=""
|
||||
ENV GIT_TAG=${GIT_TAG}
|
||||
@ -17,14 +17,14 @@ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
|
||||
&& chown -R i2pd:nobody "$I2PD_HOME"
|
||||
|
||||
#
|
||||
# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the
|
||||
# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the
|
||||
# image under 20mb we need to remove all the build dependencies in the same "RUN" / layer.
|
||||
#
|
||||
|
||||
# 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 \
|
||||
# 1. install deps, clone and build.
|
||||
# 2. strip binaries.
|
||||
# 3. Purge all dependencies and other unrelated packages, including build directory.
|
||||
RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl git \
|
||||
&& mkdir -p /tmp/build \
|
||||
&& cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \
|
||||
&& cd i2pd \
|
||||
@ -35,9 +35,9 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boos
|
||||
&& mv i2pd /usr/local/bin \
|
||||
&& cd /usr/local/bin \
|
||||
&& strip i2pd \
|
||||
&& rm -fr /tmp/build && apk --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 \
|
||||
&& rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \
|
||||
boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \
|
||||
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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
## Configuration file for a typical i2pd user
|
||||
## See https://i2pd.readthedocs.org/en/latest/configuration.html
|
||||
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
## for more options you can use in this file.
|
||||
|
||||
## Lines that begin with "## " try to explain what's going on. Lines
|
||||
@ -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
|
||||
|
||||
@ -26,15 +31,11 @@
|
||||
## Log messages above this level (debug, *info, warn, error, none)
|
||||
## If you set it to none, logging will be disabled
|
||||
# loglevel = info
|
||||
|
||||
## Path to storage of i2pd data (RI, keys, peer profiles, ...)
|
||||
## Default: ~/.i2pd or /var/lib/i2pd
|
||||
# datadir = /var/lib/i2pd
|
||||
## Write full CLF-formatted date and time to log (default: write only time)
|
||||
# logclftime = true
|
||||
|
||||
## Daemon mode. Router will go to background after start
|
||||
# daemon = true
|
||||
## Run as a service. Router will use system folders like ‘/var/lib/i2pd’
|
||||
# service = true
|
||||
|
||||
## Specify a family, router belongs to (default - none)
|
||||
# family =
|
||||
@ -54,10 +55,16 @@ ipv4 = true
|
||||
ipv6 = false
|
||||
|
||||
## Network interface to bind to
|
||||
# ifname =
|
||||
# ifname =
|
||||
## You can specify different interfaces for IPv4 and IPv6
|
||||
# ifname4 =
|
||||
# ifname6 =
|
||||
|
||||
## Enable NTCP transport (default = true)
|
||||
# ntcp = true
|
||||
## If you run i2pd behind a proxy server, you can only use NTCP transport with ntcpproxy option
|
||||
## Should be http://address:port or socks://address:port
|
||||
# ntcpproxy = http://127.0.0.1:8118
|
||||
## Enable SSU transport (default = true)
|
||||
# ssu = true
|
||||
|
||||
@ -69,6 +76,8 @@ ipv6 = false
|
||||
## X - unlimited
|
||||
## Default is X for floodfill, L for regular node
|
||||
# bandwidth = L
|
||||
## Max % of bandwidth limit for transit. 0-100. 100 by default
|
||||
# share = 100
|
||||
|
||||
## Router will not accept transit tunnels, disabling transit traffic completely
|
||||
## (default = false)
|
||||
@ -77,46 +86,19 @@ ipv6 = false
|
||||
## Router will be floodfill
|
||||
# floodfill = true
|
||||
|
||||
[limits]
|
||||
## Maximum active transit sessions (default:2500)
|
||||
# transittunnels = 2500
|
||||
|
||||
[precomputation]
|
||||
## Enable or disable elgamal precomputation table
|
||||
## By default, enabled on i386 hosts
|
||||
# elgamal = true
|
||||
|
||||
[upnp]
|
||||
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
|
||||
# enabled = false
|
||||
|
||||
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
|
||||
# name = I2Pd
|
||||
|
||||
[reseed]
|
||||
## Enable or disable reseed data verification.
|
||||
verify = true
|
||||
## URLs to request reseed data from, separated by comma
|
||||
## Default: "mainline" I2P Network reseeds
|
||||
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
|
||||
## Path to local reseed data file (.su3) for manual reseeding
|
||||
# file = /path/to/i2pseeds.su3
|
||||
## or HTTPS URL to reseed from
|
||||
# file = https://legit-website.com/i2pseeds.su3
|
||||
|
||||
[addressbook]
|
||||
## AddressBook subscription URL for initial setup
|
||||
## Default: inr.i2p at "mainline" I2P Network
|
||||
# defaulturl = http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt
|
||||
## Optional subscriptions URLs, separated by comma
|
||||
# subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
|
||||
|
||||
[http]
|
||||
## Web Console settings
|
||||
## Uncomment and set to 'false' to disable Web Console
|
||||
# enabled = true
|
||||
## 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
|
||||
# pass = changeme
|
||||
|
||||
[httpproxy]
|
||||
## Uncomment and set to 'false' to disable HTTP Proxy
|
||||
@ -126,6 +108,11 @@ address = 127.0.0.1
|
||||
port = 4444
|
||||
## Optional keys file for proxy local destination
|
||||
# keys = http-proxy-keys.dat
|
||||
## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
|
||||
# addresshelper = true
|
||||
## Address of a proxy server inside I2P, which is used to visit regular Internet
|
||||
# outproxy = http://false.i2p
|
||||
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[socksproxy]
|
||||
## Uncomment and set to 'false' to disable SOCKS Proxy
|
||||
@ -135,13 +122,13 @@ address = 127.0.0.1
|
||||
port = 4447
|
||||
## Optional keys file for proxy local destination
|
||||
# keys = socks-proxy-keys.dat
|
||||
|
||||
## Socks outproxy. Example below is set to use Tor for all connections except i2p
|
||||
## Uncomment and set to 'true' to enable using of SOCKS outproxy
|
||||
# outproxy.enabled = false
|
||||
## Address and port of outproxy
|
||||
# outproxy = 127.0.0.1
|
||||
# outproxyport = 9050
|
||||
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[sam]
|
||||
## Uncomment and set to 'true' to enable SAM Bridge
|
||||
@ -170,3 +157,75 @@ enabled = true
|
||||
## Address and port service will listen on
|
||||
# address = 127.0.0.1
|
||||
# port = 7650
|
||||
## Authentication password. "itoopie" by default
|
||||
# password = itoopie
|
||||
|
||||
[precomputation]
|
||||
## Enable or disable elgamal precomputation table
|
||||
## By default, enabled on i386 hosts
|
||||
# elgamal = true
|
||||
|
||||
[upnp]
|
||||
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
|
||||
# enabled = false
|
||||
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
|
||||
# name = I2Pd
|
||||
|
||||
[reseed]
|
||||
## Options for bootstrapping into I2P network, aka reseeding
|
||||
## Enable or disable reseed data verification.
|
||||
verify = true
|
||||
## URLs to request reseed data from, separated by comma
|
||||
## Default: "mainline" I2P Network reseeds
|
||||
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
|
||||
## Path to local reseed data file (.su3) for manual reseeding
|
||||
# file = /path/to/i2pseeds.su3
|
||||
## or HTTPS URL to reseed from
|
||||
# file = https://legit-website.com/i2pseeds.su3
|
||||
## Path to local ZIP file or HTTPS URL to reseed from
|
||||
# zipfile = /path/to/netDb.zip
|
||||
## If you run i2pd behind a proxy server, set proxy server for reseeding here
|
||||
## Should be http://address:port or socks://address:port
|
||||
# proxy = http://127.0.0.1:8118
|
||||
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
|
||||
# threshold = 25
|
||||
|
||||
[addressbook]
|
||||
## AddressBook subscription URL for initial setup
|
||||
## Default: inr.i2p at "mainline" I2P Network
|
||||
# defaulturl = http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt
|
||||
## Optional subscriptions URLs, separated by comma
|
||||
# subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
|
||||
|
||||
[limits]
|
||||
## Maximum active transit sessions (default:2500)
|
||||
# transittunnels = 2500
|
||||
## Limit number of open file descriptors (0 - use system limit)
|
||||
# openfiles = 0
|
||||
## Maximum size of corefile in Kb (0 - use system limit)
|
||||
# coresize = 0
|
||||
## Threshold to start probabalistic backoff with ntcp sessions (0 - use system limit)
|
||||
# ntcpsoft = 0
|
||||
## Maximum number of ntcp sessions (0 - use system limit)
|
||||
# ntcphard = 0
|
||||
|
||||
[trust]
|
||||
## Enable explicit trust options. false by default
|
||||
# enabled = true
|
||||
## Make direct I2P connections only to routers in specified Family.
|
||||
# family = MyFamily
|
||||
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
|
||||
# routers =
|
||||
## Should we hide our router from other routers? false by default
|
||||
# hidden = true
|
||||
|
||||
[exploratory]
|
||||
## Exploratory tunnels settings with default values
|
||||
# inbound.length = 2
|
||||
# inbound.quantity = 3
|
||||
# outbound.length = 2
|
||||
# outbound.quantity = 3
|
||||
|
||||
[persist]
|
||||
## Save peer profiles on disk (default: true)
|
||||
# profiles = true
|
||||
|
33
contrib/i2pd.service
Normal file
33
contrib/i2pd.service
Normal file
@ -0,0 +1,33 @@
|
||||
[Unit]
|
||||
Description=I2P Router written in C++
|
||||
Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=i2pd
|
||||
Group=i2pd
|
||||
RuntimeDirectory=i2pd
|
||||
RuntimeDirectoryMode=0700
|
||||
LogsDirectory=i2pd
|
||||
LogsDirectoryMode=0700
|
||||
Type=forking
|
||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/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
|
||||
#Restart=on-failure
|
||||
|
||||
KillSignal=SIGQUIT
|
||||
# If you have the patience waiting 10 min on restarting/stopping it, uncomment this.
|
||||
# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die.
|
||||
#KillSignal=SIGINT
|
||||
#TimeoutStopSec=10m
|
||||
|
||||
# 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]
|
||||
WantedBy=multi-user.target
|
152
contrib/rpm/i2pd-git.spec
Normal file
152
contrib/rpm/i2pd-git.spec
Normal file
@ -0,0 +1,152 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.31.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
|
||||
License: BSD
|
||||
URL: https://github.com/PurpleI2P/i2pd
|
||||
Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz
|
||||
|
||||
%if 0%{?rhel} == 7
|
||||
BuildRequires: cmake3
|
||||
%else
|
||||
BuildRequires: cmake
|
||||
%endif
|
||||
|
||||
BuildRequires: chrpath
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: zlib-devel
|
||||
BuildRequires: boost-devel
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: miniupnpc-devel
|
||||
BuildRequires: systemd-units
|
||||
|
||||
Requires: systemd
|
||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||
|
||||
%description
|
||||
C++ implementation of I2P.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
|
||||
%build
|
||||
cd build
|
||||
%if 0%{?rhel} == 7
|
||||
%cmake3 \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
-DWITH_HARDENING=ON \
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||
%else
|
||||
%cmake \
|
||||
-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
|
||||
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/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
|
||||
|
||||
|
||||
%pre
|
||||
getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd
|
||||
getent passwd i2pd >/dev/null || \
|
||||
%{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \
|
||||
-d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd
|
||||
|
||||
|
||||
%post
|
||||
%systemd_post i2pd.service
|
||||
|
||||
|
||||
%preun
|
||||
%systemd_preun i2pd.service
|
||||
|
||||
|
||||
%postun
|
||||
%systemd_postun_with_restart i2pd.service
|
||||
|
||||
|
||||
%files
|
||||
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
|
||||
%{_sbindir}/i2pd
|
||||
%config(noreplace) %{_sysconfdir}/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
|
@ -1,16 +0,0 @@
|
||||
[Unit]
|
||||
Description=I2P router
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=i2pd
|
||||
Group=i2pd
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/i2pd --service
|
||||
PIDFile=/var/lib/i2pd/i2pd.pid
|
||||
Restart=always
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
1
contrib/rpm/i2pd.service
Symbolic link
1
contrib/rpm/i2pd.service
Symbolic link
@ -0,0 +1 @@
|
||||
../i2pd.service
|
@ -1,9 +1,8 @@
|
||||
%define build_timestamp %(date +"%Y%m%d")
|
||||
|
||||
Name: i2pd
|
||||
Version: 2.17.0
|
||||
Release: %{build_timestamp}git%{?dist}
|
||||
Version: 2.31.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
|
||||
License: BSD
|
||||
URL: https://github.com/PurpleI2P/i2pd
|
||||
@ -23,32 +22,19 @@ BuildRequires: openssl-devel
|
||||
BuildRequires: miniupnpc-devel
|
||||
BuildRequires: systemd-units
|
||||
|
||||
%description
|
||||
C++ implementation of I2P.
|
||||
|
||||
|
||||
%package systemd
|
||||
Summary: Files to run I2P router under systemd
|
||||
Requires: i2pd
|
||||
Requires: systemd
|
||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||
Obsoletes: %{name}-daemon
|
||||
|
||||
|
||||
%description systemd
|
||||
%description
|
||||
C++ implementation of I2P.
|
||||
|
||||
This package contains systemd unit file to run i2pd as a system service
|
||||
using dedicated user's permissions.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
|
||||
%build
|
||||
cd build
|
||||
%if 0%{?rhel} == 7
|
||||
%if 0%{?rhel} == 7
|
||||
%cmake3 \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
@ -59,123 +45,156 @@ 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}%{_bindir}/i2pd
|
||||
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 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 systemd
|
||||
%pre
|
||||
getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd
|
||||
getent passwd i2pd >/dev/null || \
|
||||
%{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \
|
||||
-d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd
|
||||
|
||||
|
||||
%post systemd
|
||||
%post
|
||||
%systemd_post i2pd.service
|
||||
|
||||
|
||||
%preun systemd
|
||||
%preun
|
||||
%systemd_preun i2pd.service
|
||||
|
||||
|
||||
%postun systemd
|
||||
%postun
|
||||
%systemd_postun_with_restart i2pd.service
|
||||
|
||||
|
||||
%files
|
||||
%doc LICENSE README.md
|
||||
%_bindir/i2pd
|
||||
|
||||
|
||||
%files systemd
|
||||
/%_unitdir/i2pd.service
|
||||
%dir %attr(0700,i2pd,i2pd) %_sharedstatedir/i2pd
|
||||
%{_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
|
||||
%{_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
|
||||
- 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
|
||||
- update to 2.21.0
|
||||
|
||||
* Thu Aug 23 2018 orignal <i2porignal@yandex.ru> - 2.20.0
|
||||
- update to 2.20.0
|
||||
|
||||
* Tue Jun 26 2018 orignal <i2porignal@yandex.ru> - 2.19.0
|
||||
- update to 2.19.0
|
||||
|
||||
* Mon Feb 05 2018 r4sas <r4sas@i2pmail.org> - 2.18.0-2
|
||||
- Fixed blocking system shutdown for 10 minutes (#1089)
|
||||
|
||||
* Thu Feb 01 2018 r4sas <r4sas@i2pmail.org> - 2.18.0-1
|
||||
- Added to conflicts i2pd-git package
|
||||
- Fixed release versioning
|
||||
- Fixed paths with double slashes
|
||||
|
||||
* Tue Jan 30 2018 orignal <i2porignal@yandex.ru> - 2.18.0
|
||||
- update to 2.18.0
|
||||
|
||||
* Sat Jan 27 2018 l-n-s <supervillain@riseup.net> - 2.17.0-1
|
||||
- Added certificates and default configuration files
|
||||
- Merge i2pd with i2pd-systemd package
|
||||
- Fixed package changelogs to comply with guidelines
|
||||
|
||||
* Mon Dec 04 2017 orignal <i2porignal@yandex.ru> - 2.17.0
|
||||
- Added reseed through HTTP and SOCKS proxy
|
||||
- Added show status of client services through web console
|
||||
- Added change log level through web connsole
|
||||
- Added transient keys for tunnels
|
||||
- Added i2p.streaming.initialAckDelay parameter
|
||||
- Added CRYPTO_TYPE for SAM destination
|
||||
- Added signature and crypto type for newkeys BOB command
|
||||
- Changed - correct publication of ECIES destinations
|
||||
- Changed - disable RSA signatures completely
|
||||
- Fixed CVE-2017-17066
|
||||
- Fixed possible buffer overflow for RSA-4096
|
||||
- Fixed shutdown from web console for Windows
|
||||
- Fixed web console page layout
|
||||
- update to 2.17.0
|
||||
|
||||
* Mon Nov 13 2017 orignal <i2porignal@yandex.ru> - 2.16.0
|
||||
- Added https and "Connect" method for HTTP proxy
|
||||
- Added outproxy for HTTP proxy
|
||||
- Added initial support of ECIES crypto
|
||||
- Added NTCP soft and hard descriptors limits
|
||||
- Added support full timestamps in logs
|
||||
- Changed faster implmentation of GOST R 34.11 hash
|
||||
- Changed reject routers with RSA signtures
|
||||
- Changed reload config and shudown from Windows GUI
|
||||
- Changed update tunnels address(destination) without restart
|
||||
- Fixed BOB crashes if destination is not set
|
||||
- Fixed correct SAM tunnel name
|
||||
- Fixed QT GUI issues
|
||||
- update to 2.16.0
|
||||
|
||||
* Thu Aug 17 2017 orignal <i2porignal@yandex.ru> - 2.15.0
|
||||
- Added QT GUI
|
||||
- Added ability add and remove I2P tunnels without restart
|
||||
- Added ability to disable SOCKS outproxy option
|
||||
- Changed strip-out Accept-* hedaers in HTTP proxy
|
||||
- Changed peer test if nat=false
|
||||
- Changed separate output of NTCP and SSU sessions in Transports tab
|
||||
- Fixed handle lines with comments in hosts.txt file for address book
|
||||
- Fixed run router with empty netdb for testnet
|
||||
- Fixed skip expired introducers by iexp
|
||||
- update to 2.15.0
|
||||
|
||||
* Thu Jun 01 2017 orignal <i2porignal@yandex.ru> - 2.14.0
|
||||
- Added transit traffic bandwidth limitation
|
||||
- Added NTCP connections through HTTP and SOCKS proxies
|
||||
- Added ability to disable address helper for HTTP proxy
|
||||
- Changed reseed servers list
|
||||
- update to 2.14.0
|
||||
|
||||
* Thu Apr 06 2017 orignal <i2porignal@yandex.ru> - 2.13.0
|
||||
- Added persist local destination's tags
|
||||
- Added GOST signature types 9 and 10
|
||||
- Added exploratory tunnels configuration
|
||||
- Changed reseed servers list
|
||||
- Changed inactive NTCP sockets get closed faster
|
||||
- Changed some EdDSA speed up
|
||||
- Fixed multiple acceptors for SAM
|
||||
- Fixed follow on data after STREAM CREATE for SAM
|
||||
- Fixed memory leaks
|
||||
- update to 2.13.0
|
||||
|
||||
* Tue Feb 14 2017 orignal <i2porignal@yandex.ru> - 2.12.0
|
||||
- Additional HTTP and SOCKS proxy tunnels
|
||||
- Reseed from ZIP archive
|
||||
- 'X' bandwidth code
|
||||
- Reduced memory and file descriptors usage
|
||||
- update to 2.12.0
|
||||
|
||||
* Mon Dec 19 2016 orignal <i2porignal@yandex.ru> - 2.11.0
|
||||
- Full support of zero-hops tunnels
|
||||
- Tunnel configuration for HTTP and SOCKS proxy
|
||||
- Websockets support
|
||||
- Multiple acceptors for SAM destination
|
||||
- Routing path for UDP tunnels
|
||||
- Reseed through a floodfill
|
||||
- Use AVX instructions for DHT and HMAC if applicable
|
||||
- Fixed UPnP discovery bug, producing excessive CPU usage
|
||||
- Handle multiple lookups of the same LeaseSet correctly
|
||||
- update to 2.11.0
|
||||
|
||||
* Thu Oct 20 2016 Anatolii Vorona <vorona.tolik@gmail.com> - 2.10.0-3
|
||||
- add support C7
|
||||
|
@ -30,4 +30,4 @@ keys = irc-keys.dat
|
||||
#destinationport = 110
|
||||
#keys = pop3-keys.dat
|
||||
|
||||
# see more examples in /usr/share/doc/i2pd/configuration.md.gz
|
||||
# see more examples at https://i2pd.readthedocs.io/en/latest/user-guide/tunnels/
|
||||
|
7
contrib/tunnels.d/IRC-Ilita.conf
Normal file
7
contrib/tunnels.d/IRC-Ilita.conf
Normal 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
|
7
contrib/tunnels.d/IRC-Irc2P.conf
Normal file
7
contrib/tunnels.d/IRC-Irc2P.conf
Normal 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
4
contrib/tunnels.d/README
Normal 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
|
@ -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,7 +56,11 @@ namespace i2p
|
||||
return service;
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::init(int argc, char* argv[])
|
||||
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)
|
||||
{
|
||||
i2p::config::Init();
|
||||
i2p::config::ParseCmdline(argc, argv);
|
||||
@ -104,7 +104,10 @@ namespace i2p
|
||||
logs = "file";
|
||||
|
||||
i2p::log::Logger().SetLogLevel(loglevel);
|
||||
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);
|
||||
@ -118,13 +121,7 @@ namespace i2p
|
||||
// use stdout -- default
|
||||
}
|
||||
|
||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
||||
#ifdef AESNI
|
||||
LogPrint(eLogInfo, "AESNI enabled");
|
||||
#endif
|
||||
#if defined(__AVX__)
|
||||
LogPrint(eLogInfo, "AVX enabled");
|
||||
#endif
|
||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
||||
LogPrint(eLogDebug, "FS: main config file: ", config);
|
||||
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
||||
|
||||
@ -148,8 +145,31 @@ 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 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
|
||||
}
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
@ -207,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
|
||||
@ -227,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;
|
||||
@ -240,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()
|
||||
@ -268,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");
|
||||
@ -275,9 +303,10 @@ namespace i2p
|
||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
||||
|
||||
i2p::transport::transports.Start(ntcp, ssu);
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU()) {
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
} else {
|
||||
else
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||
/** shut down netdb right away */
|
||||
i2p::transport::transports.Stop();
|
||||
@ -288,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();
|
||||
@ -310,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");
|
||||
@ -356,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();
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -12,8 +13,9 @@ namespace util
|
||||
class Daemon_Singleton
|
||||
{
|
||||
public:
|
||||
virtual bool init(int argc, char* argv[]);
|
||||
virtual bool start();
|
||||
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||
virtual bool init(int argc, char* argv[]);
|
||||
virtual bool start();
|
||||
virtual bool stop();
|
||||
virtual void run () {};
|
||||
|
||||
@ -44,19 +46,6 @@ namespace util
|
||||
}
|
||||
};
|
||||
|
||||
#elif defined(ANDROID)
|
||||
#define Daemon i2p::util::DaemonAndroid::Instance()
|
||||
// dummy, invoked from android/jni/DaemonAndroid.*
|
||||
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
||||
{
|
||||
public:
|
||||
static DaemonAndroid& Instance()
|
||||
{
|
||||
static DaemonAndroid instance;
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#define Daemon i2p::util::DaemonWin32::Instance()
|
||||
class DaemonWin32 : public Daemon_Singleton
|
||||
@ -77,7 +66,18 @@ namespace util
|
||||
|
||||
DaemonWin32 ():isGraceful(false) {}
|
||||
};
|
||||
|
||||
#elif (defined(ANDROID) && !defined(ANDROID_BINARY))
|
||||
#define Daemon i2p::util::DaemonAndroid::Instance()
|
||||
// dummy, invoked from android/jni/DaemonAndroid.*
|
||||
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
||||
{
|
||||
public:
|
||||
static DaemonAndroid& Instance()
|
||||
{
|
||||
static DaemonAndroid instance;
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
#else
|
||||
#define Daemon i2p::util::DaemonLinux::Instance()
|
||||
class DaemonLinux : public Daemon_Singleton
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Base.h"
|
||||
#include "FS.h"
|
||||
@ -53,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"
|
||||
@ -62,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";
|
||||
@ -88,9 +92,13 @@ 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)
|
||||
{
|
||||
int num;
|
||||
@ -152,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 */
|
||||
@ -170,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>";
|
||||
@ -198,7 +210,7 @@ namespace http {
|
||||
s << "<b>ERROR:</b> " << string << "<br>\r\n";
|
||||
}
|
||||
|
||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent)
|
||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat)
|
||||
{
|
||||
s << "<b>Uptime:</b> ";
|
||||
ShowUptime(s, i2p::context.GetUptime ());
|
||||
@ -224,12 +236,9 @@ namespace http {
|
||||
default: s << "Unknown";
|
||||
}
|
||||
s << "<br>\r\n";
|
||||
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
|
||||
if (auto remains = Daemon.gracefulShutdownInterval) {
|
||||
s << "<b>Stopping in:</b> ";
|
||||
s << remains << " seconds";
|
||||
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> " << remains << " seconds<br>\r\n";
|
||||
#endif
|
||||
auto family = i2p::context.GetFamily ();
|
||||
if (family.length () > 0)
|
||||
@ -245,35 +254,55 @@ 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'><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";
|
||||
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";
|
||||
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<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 << "<td>NTCP2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << "</td><td>supported</td>\r\n</tr>\r\n";
|
||||
continue;
|
||||
}
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
if (address->host.is_v6 ())
|
||||
s << "NTCP6 ";
|
||||
else
|
||||
s << "NTCP ";
|
||||
break;
|
||||
{
|
||||
s << "<td>NTCP";
|
||||
if (address->IsPublishedNTCP2 ()) s << "2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << "</td>\r\n";
|
||||
break;
|
||||
}
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
{
|
||||
s << "<td>SSU";
|
||||
if (address->host.is_v6 ())
|
||||
s << "SSU6 ";
|
||||
else
|
||||
s << "SSU ";
|
||||
break;
|
||||
s << "v6";
|
||||
s << "</td>\r\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
s << "Unknown ";
|
||||
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 << "</tbody></table>\r\n";
|
||||
}
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
if(outputFormat==OutputFormatEnum::forQtUi) {
|
||||
s << "<br>";
|
||||
}
|
||||
s << "</p>\r\n</div>\r\n";
|
||||
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";
|
||||
@ -285,24 +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";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -316,8 +348,9 @@ namespace http {
|
||||
if (dest)
|
||||
{
|
||||
auto ident = dest->GetIdentHash ();
|
||||
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
|
||||
auto& name = dest->GetNickname ();
|
||||
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
|
||||
s << name << " ]</a> ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"<br>\r\n" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,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)
|
||||
{
|
||||
@ -357,28 +399,33 @@ namespace http {
|
||||
s << "<br>\r\n";
|
||||
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
|
||||
if (!dest->GetSessions ().empty ()) {
|
||||
s << "<div class='slide'><label for='slide-tags'>Outgoing:</label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n";
|
||||
for (const auto& it: dest->GetSessions ())
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
|
||||
s << "</p>\r\n</div>\r\n";
|
||||
std::stringstream tmp_s; uint32_t out_tags = 0;
|
||||
for (const auto& it: dest->GetSessions ()) {
|
||||
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
|
||||
out_tags = 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"
|
||||
<< "<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>";
|
||||
@ -387,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\"> ✘ </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>";
|
||||
@ -404,7 +458,7 @@ namespace http {
|
||||
s << "<td>" << (int)it->GetStatus () << "</td>";
|
||||
s << "</tr>\r\n";
|
||||
}
|
||||
s << "</table>";
|
||||
s << "</tbody>\r\n</table>";
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,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> " << 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> " << 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)
|
||||
@ -484,47 +560,97 @@ 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";
|
||||
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
|
||||
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 () << " ⇒ ";
|
||||
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
|
||||
s << " ⇒ " << it->GetTunnelID ();
|
||||
else
|
||||
s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
|
||||
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 () << " ⇒ ";
|
||||
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
|
||||
s << " ⇒ " << it->GetTunnelID ();
|
||||
else
|
||||
s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
|
||||
s << " " << it->GetNumTransmittedBytes () << "<br>\r\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "<b>Transit tunnels:</b> no transit tunnels currently built.<br>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Sessions>
|
||||
static void ShowNTCPTransports (std::stringstream& s, const Sessions& sessions, const std::string name)
|
||||
{
|
||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||
for (const auto& it: sessions )
|
||||
{
|
||||
if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
// incoming connection doesn't have remote RI
|
||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s << "<br>\r\n" << std::endl;
|
||||
cnt++;
|
||||
}
|
||||
if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]";
|
||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s6 << "<br>\r\n" << std::endl;
|
||||
cnt6++;
|
||||
}
|
||||
}
|
||||
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<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<div class='content'>"
|
||||
<< tmp_s6.str () << "</div>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,43 +662,14 @@ namespace http {
|
||||
{
|
||||
auto sessions = ntcpServer->GetNTCPSessions ();
|
||||
if (!sessions.empty ())
|
||||
{
|
||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||
for (const auto& it: sessions )
|
||||
{
|
||||
if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
// incoming connection doesn't have remote RI
|
||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s << "<br>\r\n" << std::endl;
|
||||
cnt++;
|
||||
}
|
||||
if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]";
|
||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s6 << "<br>\r\n" << std::endl;
|
||||
cnt6++;
|
||||
}
|
||||
}
|
||||
if (!tmp_s.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ntcp'><b>NTCP</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_ntcp'/>\r\n<p class='content'>";
|
||||
s << tmp_s.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
if (!tmp_s6.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ntcp6'><b>NTCP6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_ntcp6'/>\r\n<p class='content'>";
|
||||
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
ShowNTCPTransports (s, sessions, "NTCP");
|
||||
}
|
||||
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
||||
if (ntcp2Server)
|
||||
{
|
||||
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
||||
if (!sessions.empty ())
|
||||
ShowNTCPTransports (s, sessions, "NTCP2");
|
||||
}
|
||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||
if (ssuServer)
|
||||
@ -580,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 ();
|
||||
@ -592,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_ssu6'><b>SSU6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssu6'/>\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 ();
|
||||
@ -609,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) {
|
||||
@ -644,11 +750,11 @@ 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";
|
||||
for (const auto& it: session->ListSockets())
|
||||
for (const auto& it: sam->ListSockets(id))
|
||||
{
|
||||
switch (it->GetSocketType ())
|
||||
{
|
||||
@ -664,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> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "<br>\r\n"<< std::endl;
|
||||
@ -677,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> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "<br>\r\n"<< std::endl;
|
||||
@ -686,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> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "<br>\r\n"<< std::endl;
|
||||
@ -697,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> ⇒ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << ":" << it.second->GetLocalPort ();
|
||||
@ -711,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> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "<br>\r\n"<< std::endl;
|
||||
@ -724,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> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "<br>\r\n"<< std::endl;
|
||||
@ -732,8 +839,18 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
|
||||
std::string ConvertTime (uint64_t time)
|
||||
{
|
||||
ldiv_t divTime = ldiv(time,1000);
|
||||
time_t t = divTime.quot;
|
||||
struct tm *tm = localtime(&t);
|
||||
char date[128];
|
||||
snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem);
|
||||
return date;
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||
m_Socket (socket), m_BufferLen (0), expected_host(hostname)
|
||||
{
|
||||
/* cache options */
|
||||
i2p::config::GetOption("http.auth", needAuth);
|
||||
@ -785,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;
|
||||
@ -796,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 ());
|
||||
@ -832,7 +936,28 @@ namespace http {
|
||||
SendReply(res, content);
|
||||
return;
|
||||
}
|
||||
|
||||
bool strictheaders;
|
||||
i2p::config::GetOption("http.strictheaders", strictheaders);
|
||||
if (strictheaders)
|
||||
{
|
||||
std::string http_hostname;
|
||||
i2p::config::GetOption("http.hostname", http_hostname);
|
||||
std::string host = req.GetHeader("Host");
|
||||
auto idx = host.find(':');
|
||||
/* strip out port so it's just host */
|
||||
if (idx != std::string::npos && idx > 0)
|
||||
{
|
||||
host = host.substr(0, idx);
|
||||
}
|
||||
if (!(host == expected_host || host == http_hostname))
|
||||
{
|
||||
/* deny request as it's from a non whitelisted hostname */
|
||||
res.code = 403;
|
||||
content = "host mismatch";
|
||||
SendReply(res, content);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Html5 head start
|
||||
ShowPageHead (s);
|
||||
if (req.uri.find("page=") != std::string::npos) {
|
||||
@ -840,7 +965,7 @@ namespace http {
|
||||
} else if (req.uri.find("cmd=") != std::string::npos) {
|
||||
HandleCommand (req, res, s);
|
||||
} else {
|
||||
ShowStatus (s, true);
|
||||
ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole);
|
||||
res.add_header("Refresh", "10");
|
||||
}
|
||||
ShowPageTail (s);
|
||||
@ -850,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;
|
||||
@ -867,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)
|
||||
@ -886,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)
|
||||
@ -912,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");
|
||||
@ -928,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))
|
||||
#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))
|
||||
#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>: Stream closed<br><br>\r\n";
|
||||
else
|
||||
s << "<b>ERROR</b>: Stream not found or already was closed<br><br>\r\n";
|
||||
}
|
||||
else
|
||||
s << "<b>ERROR</b>: Destination not found<br><br>\r\n";
|
||||
}
|
||||
else
|
||||
s << "<b>ERROR</b>: 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>: 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;
|
||||
|
||||
@ -975,7 +1153,8 @@ namespace http {
|
||||
|
||||
HTTPServer::HTTPServer (const std::string& address, int port):
|
||||
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
||||
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port))
|
||||
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)),
|
||||
m_Hostname(address)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1060,7 +1239,7 @@ namespace http {
|
||||
|
||||
void HTTPServer::CreateConnection(std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
|
||||
{
|
||||
auto conn = std::make_shared<HTTPConnection> (newSocket);
|
||||
auto conn = std::make_shared<HTTPConnection> (m_Hostname, newSocket);
|
||||
conn->Receive ();
|
||||
}
|
||||
} // http
|
||||
|
@ -10,20 +10,20 @@
|
||||
#include <sstream>
|
||||
#include "HTTP.h"
|
||||
|
||||
namespace i2p
|
||||
namespace i2p
|
||||
{
|
||||
namespace http
|
||||
namespace http
|
||||
{
|
||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
|
||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
|
||||
|
||||
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
|
||||
{
|
||||
public:
|
||||
|
||||
HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||
HTTPConnection (std::string serverhost, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||
void Receive ();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
@ -35,17 +35,18 @@ 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;
|
||||
bool needAuth;
|
||||
std::string user;
|
||||
std::string pass;
|
||||
std::string expected_host;
|
||||
|
||||
static std::map<uint32_t, uint32_t> m_Tokens; // token->timestamp in seconds
|
||||
};
|
||||
@ -63,11 +64,11 @@ namespace http
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
void Accept ();
|
||||
void Accept ();
|
||||
void HandleAccept(const boost::system::error_code& ecode,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> newSocket);
|
||||
void CreateConnection(std::shared_ptr<boost::asio::ip::tcp::socket> newSocket);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsRunning;
|
||||
@ -75,10 +76,12 @@ namespace http
|
||||
boost::asio::io_service m_Service;
|
||||
boost::asio::io_service::work m_Work;
|
||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||
std::string m_Hostname;
|
||||
};
|
||||
|
||||
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
|
||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent);
|
||||
enum OutputFormatEnum { forWebConsole, forQtUi };
|
||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
|
||||
void ShowLocalDestinations (std::stringstream& s);
|
||||
void ShowLeasesSets(std::stringstream& s);
|
||||
void ShowTunnels (std::stringstream& s);
|
||||
@ -86,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
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace client
|
||||
I2PControlService::I2PControlService (const std::string& address, int port):
|
||||
m_IsRunning (false), m_Thread (nullptr),
|
||||
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)),
|
||||
m_SSLContext (m_Service, boost::asio::ssl::context::sslv23),
|
||||
m_SSLContext (boost::asio::ssl::context::sslv23),
|
||||
m_ShutdownTimer (m_Service)
|
||||
{
|
||||
i2p::config::GetOption("i2pcontrol.password", m_Password);
|
||||
@ -65,9 +65,10 @@ namespace client
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
|
||||
// I2PControl
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
|
||||
// RouterInfo
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
@ -80,18 +81,26 @@ namespace client
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
||||
&I2PControlService::TunnelsSuccessRateHandler;
|
||||
&I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
// RouterManager
|
||||
// RouterManager
|
||||
m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler;
|
||||
m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler;
|
||||
m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler;
|
||||
m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler;
|
||||
|
||||
// NetworkSetting
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlService::OutboundBandwidthLimit;
|
||||
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@ -133,8 +142,8 @@ namespace client
|
||||
m_Service.run ();
|
||||
} catch (std::exception& ex) {
|
||||
LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::Accept ()
|
||||
@ -160,7 +169,7 @@ namespace client
|
||||
void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
|
||||
{
|
||||
socket->async_handshake(boost::asio::ssl::stream_base::server,
|
||||
std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
|
||||
std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
|
||||
}
|
||||
|
||||
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
|
||||
@ -168,7 +177,7 @@ namespace client
|
||||
if (ecode) {
|
||||
LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
//std::this_thread::sleep_for (std::chrono::milliseconds(5));
|
||||
ReadRequest (socket);
|
||||
}
|
||||
@ -187,15 +196,15 @@ namespace client
|
||||
}
|
||||
|
||||
void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode,
|
||||
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
||||
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf)
|
||||
{
|
||||
if (ecode)
|
||||
if (ecode)
|
||||
{
|
||||
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
||||
return;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isHtml = !memcmp (buf->data (), "POST", 4);
|
||||
try
|
||||
@ -243,8 +252,8 @@ namespace client
|
||||
response << "{\"id\":" << id << ",\"result\":{";
|
||||
(this->*(it->second))(pt.get_child ("params"), response);
|
||||
response << "},\"jsonrpc\":\"2.0\"}";
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
||||
response << "{\"id\":null,\"error\":";
|
||||
@ -289,6 +298,13 @@ namespace client
|
||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
|
||||
{
|
||||
std::ostringstream buf;
|
||||
boost::property_tree::write_json (buf, value, false);
|
||||
ss << "\"" << name << "\":" << buf.str();
|
||||
}
|
||||
|
||||
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
||||
{
|
||||
@ -337,9 +353,9 @@ namespace client
|
||||
InsertParam (results, "API", api);
|
||||
results << ",";
|
||||
std::string token = boost::lexical_cast<std::string>(i2p::util::GetSecondsSinceEpoch ());
|
||||
m_Tokens.insert (token);
|
||||
m_Tokens.insert (token);
|
||||
InsertParam (results, "Token", token);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
@ -364,7 +380,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: I2PControl unknown request: ", it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::PasswordHandler (const std::string& value)
|
||||
@ -378,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
|
||||
@ -394,28 +412,28 @@ namespace client
|
||||
|
||||
void I2PControlService::UptimeHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000);
|
||||
InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000);
|
||||
}
|
||||
|
||||
void I2PControlService::VersionHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.version", VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::StatusHandler (std::ostringstream& results)
|
||||
{
|
||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
|
||||
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
|
||||
}
|
||||
|
||||
void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ());
|
||||
InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetDbActivePeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ());
|
||||
InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetStatusHandler (std::ostringstream& results)
|
||||
@ -457,17 +475,18 @@ namespace client
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
|
||||
// RouterManager
|
||||
|
||||
void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
if (it != params.begin ()) results << ",";
|
||||
if (it != params.begin ()) results << ",";
|
||||
LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first);
|
||||
auto it1 = m_RouterManagerHandlers.find (it->first);
|
||||
if (it1 != m_RouterManagerHandlers.end ()) {
|
||||
(this->*(it1->second))(results);
|
||||
(this->*(it1->second))(results);
|
||||
} else
|
||||
LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first);
|
||||
}
|
||||
@ -516,7 +535,7 @@ namespace client
|
||||
auto it1 = m_NetworkSettingHandlers.find (it->first);
|
||||
if (it1 != m_NetworkSettingHandlers.end ()) {
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(it->second.data (), results);
|
||||
(this->*(it1->second))(it->second.data (), results);
|
||||
} else
|
||||
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);
|
||||
}
|
||||
@ -538,7 +557,7 @@ namespace client
|
||||
InsertParam (results, "i2p.router.net.bw.out", bw);
|
||||
}
|
||||
|
||||
// certificate
|
||||
// certificate
|
||||
void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
@ -552,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)
|
||||
@ -586,5 +605,178 @@ namespace client
|
||||
}
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first);
|
||||
auto it1 = m_ClientServicesInfoHandlers.find (it->first);
|
||||
if (it1 != m_ClientServicesInfoHandlers.end ())
|
||||
{
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::I2PTunnelInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::ptree client_tunnels, server_tunnels;
|
||||
|
||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
|
||||
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
|
||||
if (!serverTunnels.empty ()) {
|
||||
for (auto& it: serverTunnels)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
st.put("port", it.second->GetLocalPort ());
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
auto& clientForwards = i2p::client::context.GetClientForwards ();
|
||||
if (!clientForwards.empty ())
|
||||
{
|
||||
for (auto& it: clientForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
}
|
||||
|
||||
auto& serverForwards = i2p::client::context.GetServerForwards ();
|
||||
if (!serverForwards.empty ())
|
||||
{
|
||||
for (auto& it: serverForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
pt.add_child("client", client_tunnels);
|
||||
pt.add_child("server", server_tunnels);
|
||||
|
||||
InsertParam (results, "I2PTunnel", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::HTTPProxyInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto httpProxy = i2p::client::context.GetHttpProxy ();
|
||||
if (httpProxy)
|
||||
{
|
||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "HTTPProxy", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SOCKSInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto socksProxy = i2p::client::context.GetSocksProxy ();
|
||||
if (socksProxy)
|
||||
{
|
||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "SOCKS", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto sam = i2p::client::context.GetSAMBridge ();
|
||||
if (sam)
|
||||
{
|
||||
pt.put("enabled", true);
|
||||
boost::property_tree::ptree sam_sessions;
|
||||
for (auto& it: sam->GetSessions ())
|
||||
{
|
||||
boost::property_tree::ptree sam_session, sam_session_sockets;
|
||||
auto& name = it.second->localDestination->GetNickname ();
|
||||
auto& ident = it.second->localDestination->GetIdentHash();
|
||||
sam_session.put("name", name);
|
||||
sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
|
||||
for (const auto& socket: sam->ListSockets(it.first))
|
||||
{
|
||||
boost::property_tree::ptree stream;
|
||||
stream.put("type", socket->GetSocketType ());
|
||||
stream.put("peer", socket->GetSocket ().remote_endpoint());
|
||||
|
||||
sam_session_sockets.push_back(std::make_pair("", stream));
|
||||
}
|
||||
sam_session.add_child("sockets", sam_session_sockets);
|
||||
sam_sessions.add_child(it.first, sam_session);
|
||||
}
|
||||
|
||||
pt.add_child("sessions", sam_sessions);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "SAM", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::BOBInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto bob = i2p::client::context.GetBOBCommandChannel ();
|
||||
if (bob)
|
||||
{
|
||||
/* TODO more info */
|
||||
pt.put("enabled", true);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "BOB", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto i2cp = i2p::client::context.GetI2CPServer ();
|
||||
if (i2cp)
|
||||
{
|
||||
/* TODO more info */
|
||||
pt.put("enabled", true);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "I2CP", pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
namespace i2p
|
||||
@ -57,6 +57,7 @@ namespace client
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||
|
||||
// methods
|
||||
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
@ -67,6 +68,7 @@ namespace client
|
||||
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
||||
// I2PControl
|
||||
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
||||
@ -98,6 +100,15 @@ namespace client
|
||||
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
||||
void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
||||
|
||||
// ClientServicesInfo
|
||||
typedef void (I2PControlService::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Password;
|
||||
@ -115,6 +126,7 @@ namespace client
|
||||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
|
||||
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
||||
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
153
daemon/UPnP.cpp
153
daemon/UPnP.cpp
@ -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,21 +142,69 @@ 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();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
TryPortMapping (address);
|
||||
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 ()
|
||||
@ -148,58 +212,47 @@ namespace transport
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
CloseMapping (address);
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
||||
bool m_IsRunning;
|
||||
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;
|
||||
private:
|
||||
|
||||
// For miniupnpc
|
||||
char * m_MulticastIf = 0;
|
||||
char * m_Minissdpdpath = 0;
|
||||
struct UPNPDev * m_Devlist = 0;
|
||||
char m_NetworkAddr[64];
|
||||
char m_externalIPAddress[40];
|
||||
bool m_IsRunning;
|
||||
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;
|
||||
bool m_upnpUrlsInitialized=false;
|
||||
struct UPNPUrls m_upnpUrls;
|
||||
struct IGDdatas m_upnpData;
|
||||
|
||||
// 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
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "Config.h"
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
#include "Tunnel.h"
|
||||
#include "RouterContext.h"
|
||||
#include "ClientContext.h"
|
||||
|
||||
@ -137,11 +138,14 @@ namespace i2p
|
||||
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
if (lockf(pidFH, F_TLOCK, 0) != 0)
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
char pid[10];
|
||||
sprintf(pid, "%d\n", getpid());
|
||||
ftruncate(pidFH, 0);
|
||||
@ -183,7 +187,7 @@ namespace i2p
|
||||
if (gracefulShutdownInterval)
|
||||
{
|
||||
gracefulShutdownInterval--; // - 1 second
|
||||
if (gracefulShutdownInterval <= 0)
|
||||
if (gracefulShutdownInterval <= 0 || i2p::tunnel::tunnels.CountTransitTunnels() <= 0)
|
||||
{
|
||||
LogPrint(eLogInfo, "Graceful shutdown");
|
||||
return;
|
||||
|
@ -22,6 +22,8 @@ int main( int argc, char* argv[] )
|
||||
{
|
||||
if (Daemon.start())
|
||||
Daemon.run ();
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
Daemon.stop();
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
4
debian/.gitignore
vendored
4
debian/.gitignore
vendored
@ -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/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user