mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
427 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08603091c5 | ||
|
|
9439621849 | ||
|
|
15ded89618 | ||
|
|
b84f74c167 | ||
|
|
a97300f8be | ||
|
|
9e12cff317 | ||
|
|
ecdf1f4ddc | ||
|
|
2fa7a48163 | ||
|
|
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 | ||
|
|
50399e5194 | ||
|
|
b734acf1b1 | ||
|
|
33aa8e2471 | ||
|
|
2c58fe736b | ||
|
|
6fe1de5d86 | ||
|
|
064460b95f | ||
|
|
2c3b19a539 | ||
|
|
dc30a4c1ae | ||
|
|
86e9901bf2 | ||
|
|
6519e0835a | ||
|
|
a52344fc01 | ||
|
|
b67424643d | ||
|
|
575a4c01c9 | ||
|
|
f0d4ee6618 | ||
|
|
8753186a0d | ||
|
|
ff8fb8000d | ||
|
|
9dd38b99d6 | ||
|
|
dfe08c1ec9 | ||
|
|
062d8d0f4f | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
df304fb38b | ||
|
|
68b1afa2df | ||
|
|
80149342f2 | ||
|
|
1967dee50c | ||
|
|
ab80def94b | ||
|
|
254bf313a2 | ||
|
|
938d5d901a | ||
|
|
7b00d828b2 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,7 +8,7 @@ netDb
|
|||||||
/i2pd
|
/i2pd
|
||||||
/libi2pd.a
|
/libi2pd.a
|
||||||
/libi2pdclient.a
|
/libi2pdclient.a
|
||||||
i2pd.exe
|
*.exe
|
||||||
|
|
||||||
|
|
||||||
# Autotools
|
# Autotools
|
||||||
|
|||||||
60
ChangeLog
60
ChangeLog
@@ -1,6 +1,62 @@
|
|||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [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
|
## [2.18.0] - 2018-01-30
|
||||||
### Added
|
### Added
|
||||||
- Show tunnel nicknames for I2CP destination in WebUI
|
- Show tunnel nicknames for I2CP destination in WebUI
|
||||||
@@ -43,7 +99,7 @@
|
|||||||
- NTCP soft and hard descriptors limits
|
- NTCP soft and hard descriptors limits
|
||||||
- Support full timestamps in logs
|
- Support full timestamps in logs
|
||||||
### Changed
|
### Changed
|
||||||
- Faster implmentation of GOST R 34.11 hash
|
- Faster implementation of GOST R 34.11 hash
|
||||||
- Reject routers with RSA signtures
|
- Reject routers with RSA signtures
|
||||||
- Reload config and shudown from Windows GUI
|
- Reload config and shudown from Windows GUI
|
||||||
- Update tunnels address(destination) without restart
|
- Update tunnels address(destination) without restart
|
||||||
@@ -143,7 +199,7 @@
|
|||||||
- Initial iOS support
|
- Initial iOS support
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Reduced file descriptiors usage
|
- Reduced file descriptors usage
|
||||||
- Strict reseed checks enabled by default
|
- Strict reseed checks enabled by default
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|||||||
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" ]
|
|
||||||
|
|
||||||
16
Makefile
16
Makefile
@@ -18,6 +18,14 @@ USE_AVX := yes
|
|||||||
USE_STATIC := no
|
USE_STATIC := no
|
||||||
USE_MESHNET := no
|
USE_MESHNET := no
|
||||||
USE_UPNP := no
|
USE_UPNP := no
|
||||||
|
DEBUG := yes
|
||||||
|
|
||||||
|
ifeq ($(DEBUG),yes)
|
||||||
|
CXX_DEBUG = -g
|
||||||
|
else
|
||||||
|
CXX_DEBUG = -Os
|
||||||
|
LD_DEBUG = -s
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(WEBSOCKETS),1)
|
ifeq ($(WEBSOCKETS),1)
|
||||||
NEEDED_CXXFLAGS += -DWITH_EVENTS
|
NEEDED_CXXFLAGS += -DWITH_EVENTS
|
||||||
@@ -30,12 +38,12 @@ ifneq (, $(findstring darwin, $(SYS)))
|
|||||||
else
|
else
|
||||||
include Makefile.osx
|
include Makefile.osx
|
||||||
endif
|
endif
|
||||||
|
else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||||
|
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||||
|
include Makefile.linux
|
||||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||||
include Makefile.bsd
|
include Makefile.bsd
|
||||||
else ifneq (, $(findstring linux, $(SYS)))
|
|
||||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
|
||||||
include Makefile.linux
|
|
||||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
|
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
|
||||||
include Makefile.mingw
|
include Makefile.mingw
|
||||||
@@ -122,6 +130,8 @@ doxygen:
|
|||||||
.PHONY: deps
|
.PHONY: deps
|
||||||
.PHONY: doxygen
|
.PHONY: doxygen
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
|
.PHONY: last-dist
|
||||||
.PHONY: api
|
.PHONY: api
|
||||||
.PHONY: api_client
|
.PHONY: api_client
|
||||||
.PHONY: mk_obj_dir
|
.PHONY: mk_obj_dir
|
||||||
|
.PHONY: install
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
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
|
## 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.
|
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||||
## For example, when adding 'hardening flags' to the build
|
## For example, when adding 'hardening flags' to the build
|
||||||
@@ -8,5 +8,5 @@ CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-ind
|
|||||||
## custom FLAGS to work at build-time.
|
## custom FLAGS to work at build-time.
|
||||||
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
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
|
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
# root directory holding homebrew
|
# root directory holding homebrew
|
||||||
BREWROOT = /usr/local
|
BREWROOT = /usr/local
|
||||||
BOOSTROOT = ${BREWROOT}/opt/boost
|
BOOSTROOT = ${BREWROOT}/opt/boost
|
||||||
SSLROOT = ${BREWROOT}/opt/libressl
|
SSLROOT = ${BREWROOT}/opt/openssl@1.1
|
||||||
UPNPROOT = ${BREWROOT}/opt/miniupnpc
|
UPNPROOT = ${BREWROOT}/opt/miniupnpc
|
||||||
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
||||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||||
|
LDFLAGS = ${LD_DEBUG}
|
||||||
|
|
||||||
ifndef TRAVIS
|
ifndef TRAVIS
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
@@ -13,7 +14,7 @@ endif
|
|||||||
ifeq ($(USE_STATIC),yes)
|
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
|
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
|
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
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -33,13 +34,21 @@ endif
|
|||||||
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
|
# 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
|
# 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
|
# 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)
|
||||||
#ifeq ($(USE_AESNI),yes)
|
CXXFLAGS += -maes
|
||||||
# CXXFLAGS += -maes -DAESNI
|
endif
|
||||||
#endif
|
ifeq ($(USE_AVX),1)
|
||||||
|
CXXFLAGS += -mavx
|
||||||
|
endif
|
||||||
|
|
||||||
# Disabled, since it will be the default make rule. I think its better
|
install: all
|
||||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||||
#install: all
|
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||||
# cp -r i2p ${PREFIX}/
|
@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,13 +1,13 @@
|
|||||||
# set defaults instead redefine
|
# set defaults instead redefine
|
||||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||||
INCFLAGS ?=
|
LDFLAGS ?= ${LD_DEBUG}
|
||||||
|
|
||||||
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
## 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.
|
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||||
## For example, when adding 'hardening flags' to the 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
|
## (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
|
## -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
|
# detect proper flag for c++11 support by compilers
|
||||||
CXXVER := $(shell $(CXX) -dumpversion)
|
CXXVER := $(shell $(CXX) -dumpversion)
|
||||||
@@ -21,8 +21,10 @@ else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6
|
|||||||
NEEDED_CXXFLAGS += -std=c++0x
|
NEEDED_CXXFLAGS += -std=c++0x
|
||||||
else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0
|
else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 ubuntu
|
LDLIBS = -latomic
|
||||||
|
else ifeq ($(shell expr match ${CXXVER} "[7-8]"),1) # gcc 7 ubuntu or gcc 8 arch
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
|
LDLIBS = -latomic
|
||||||
else # not supported
|
else # not supported
|
||||||
$(error Compiler too old)
|
$(error Compiler too old)
|
||||||
endif
|
endif
|
||||||
@@ -34,7 +36,7 @@ ifeq ($(USE_STATIC),yes)
|
|||||||
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
||||||
# the shared libraries from the glibc version used for linking
|
# the shared libraries from the glibc version used for linking
|
||||||
LIBDIR := /usr/lib
|
LIBDIR := /usr/lib
|
||||||
LDLIBS = $(LIBDIR)/libboost_system.a
|
LDLIBS += $(LIBDIR)/libboost_system.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||||
@@ -44,7 +46,7 @@ ifeq ($(USE_STATIC),yes)
|
|||||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl
|
LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl
|
||||||
USE_AESNI := no
|
USE_AESNI := no
|
||||||
else
|
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
|
endif
|
||||||
|
|
||||||
# UPNP Support (miniupnpc 1.5 and higher)
|
# UPNP Support (miniupnpc 1.5 and higher)
|
||||||
@@ -60,7 +62,12 @@ endif
|
|||||||
ifeq ($(USE_AESNI),yes)
|
ifeq ($(USE_AESNI),yes)
|
||||||
#check if AES-NI is supported by CPU
|
#check if AES-NI is supported by CPU
|
||||||
ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0)
|
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
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
108
Makefile.mingw
108
Makefile.mingw
@@ -1,54 +1,54 @@
|
|||||||
USE_WIN32_APP=yes
|
USE_WIN32_APP=yes
|
||||||
CXX = g++
|
CXX = g++
|
||||||
WINDRES = windres
|
WINDRES = windres
|
||||||
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||||
NEEDED_CXXFLAGS = -std=c++11
|
NEEDED_CXXFLAGS = -std=c++11
|
||||||
BOOST_SUFFIX = -mt
|
BOOST_SUFFIX = -mt
|
||||||
INCFLAGS = -Idaemon -I.
|
INCFLAGS = -Idaemon -I.
|
||||||
LDFLAGS = -s -Wl,-rpath,/usr/local/lib -Wl,-Bstatic -static-libgcc -static-libstdc++
|
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++
|
||||||
|
|
||||||
# UPNP Support
|
# UPNP Support
|
||||||
ifeq ($(USE_UPNP),yes)
|
ifeq ($(USE_UPNP),yes)
|
||||||
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
|
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
|
||||||
LDLIBS = -lminiupnpc
|
LDLIBS = -lminiupnpc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDLIBS += \
|
LDLIBS += \
|
||||||
-lboost_system$(BOOST_SUFFIX) \
|
-lboost_system$(BOOST_SUFFIX) \
|
||||||
-lboost_date_time$(BOOST_SUFFIX) \
|
-lboost_date_time$(BOOST_SUFFIX) \
|
||||||
-lboost_filesystem$(BOOST_SUFFIX) \
|
-lboost_filesystem$(BOOST_SUFFIX) \
|
||||||
-lboost_program_options$(BOOST_SUFFIX) \
|
-lboost_program_options$(BOOST_SUFFIX) \
|
||||||
-lssl \
|
-lssl \
|
||||||
-lcrypto \
|
-lcrypto \
|
||||||
-lz \
|
-lz \
|
||||||
-lwsock32 \
|
-lwsock32 \
|
||||||
-lws2_32 \
|
-lws2_32 \
|
||||||
-lgdi32 \
|
-lgdi32 \
|
||||||
-liphlpapi \
|
-liphlpapi \
|
||||||
-lstdc++ \
|
-lstdc++ \
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
ifeq ($(USE_WIN32_APP), yes)
|
ifeq ($(USE_WIN32_APP), yes)
|
||||||
CXXFLAGS += -DWIN32_APP
|
CXXFLAGS += -DWIN32_APP
|
||||||
LDFLAGS += -mwindows
|
LDFLAGS += -mwindows
|
||||||
DAEMON_RC += Win32/Resource.rc
|
DAEMON_RC += Win32/Resource.rc
|
||||||
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
|
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
|
||||||
ifeq ($(USE_AESNI),1)
|
ifeq ($(USE_AESNI),1)
|
||||||
CPU_FLAGS += -maes -DAESNI
|
CPU_FLAGS += -maes
|
||||||
else
|
else
|
||||||
CPU_FLAGS += -msse
|
CPU_FLAGS += -msse
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AVX),1)
|
ifeq ($(USE_AVX),1)
|
||||||
CPU_FLAGS += -mavx
|
CPU_FLAGS += -mavx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_ASLR),yes)
|
ifeq ($(USE_ASLR),yes)
|
||||||
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
|
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/%.o : %.rc
|
obj/%.o : %.rc
|
||||||
$(WINDRES) -i $< -o $@
|
$(WINDRES) -i $< -o $@
|
||||||
|
|||||||
13
Makefile.osx
13
Makefile.osx
@@ -1,8 +1,7 @@
|
|||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX
|
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX
|
||||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
|
||||||
INCFLAGS = -I/usr/local/include
|
INCFLAGS = -I/usr/local/include
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||||
|
|
||||||
ifeq ($(USE_STATIC),yes)
|
ifeq ($(USE_STATIC),yes)
|
||||||
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||||
@@ -21,7 +20,7 @@ ifeq ($(USE_UPNP),yes)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AESNI),1)
|
ifeq ($(USE_AESNI),1)
|
||||||
CXXFLAGS += -maes -DAESNI
|
CXXFLAGS += -maes
|
||||||
else
|
else
|
||||||
CXXFLAGS += -msse
|
CXXFLAGS += -msse
|
||||||
endif
|
endif
|
||||||
@@ -29,9 +28,3 @@ endif
|
|||||||
ifeq ($(USE_AVX),1)
|
ifeq ($(USE_AVX),1)
|
||||||
CXXFLAGS += -mavx
|
CXXFLAGS += -mavx
|
||||||
endif
|
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}/
|
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ Build instructions:
|
|||||||
* GNU/Linux x86/x64 - [](https://travis-ci.org/PurpleI2P/i2pd)
|
* GNU/Linux x86/x64 - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||||
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
||||||
* Mac OS X - [](https://travis-ci.org/PurpleI2P/i2pd)
|
* Mac OS X - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||||
|
* CentOS / Fedora - [](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
|
||||||
|
* Docker image - [](https://hub.docker.com/r/meeh/i2pd/builds/)
|
||||||
* FreeBSD
|
* FreeBSD
|
||||||
* Android
|
* Android
|
||||||
* iOS
|
* iOS
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace util
|
|||||||
SetConsoleCP(1251);
|
SetConsoleCP(1251);
|
||||||
SetConsoleOutputCP(1251);
|
SetConsoleOutputCP(1251);
|
||||||
setlocale(LC_ALL, "Russian");
|
setlocale(LC_ALL, "Russian");
|
||||||
|
setlocale(LC_TIME, "C");
|
||||||
|
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
return false;
|
return false;
|
||||||
@@ -68,6 +69,7 @@ namespace util
|
|||||||
SetConsoleCP(1251);
|
SetConsoleCP(1251);
|
||||||
SetConsoleOutputCP(1251);
|
SetConsoleOutputCP(1251);
|
||||||
setlocale(LC_ALL, "Russian");
|
setlocale(LC_ALL, "Russian");
|
||||||
|
setlocale(LC_TIME, "C");
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
if (!i2p::win32::StartWin32App ()) return false;
|
if (!i2p::win32::StartWin32App ()) return false;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#define I2Pd_AppName "i2pd"
|
#define I2Pd_AppName "i2pd"
|
||||||
#define I2Pd_ver "2.18.0"
|
#define I2Pd_ver "2.21.1"
|
||||||
#define I2Pd_Publisher "PurpleI2P"
|
#define I2Pd_Publisher "PurpleI2P"
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
|||||||
14
android/.gitignore
vendored
14
android/.gitignore
vendored
@@ -1,8 +1,18 @@
|
|||||||
gen
|
gen
|
||||||
tests
|
tests
|
||||||
|
bin
|
||||||
|
libs
|
||||||
|
log*
|
||||||
|
obj
|
||||||
|
.gradle
|
||||||
.idea
|
.idea
|
||||||
|
.externalNativeBuild
|
||||||
ant.properties
|
ant.properties
|
||||||
local.properties
|
local.properties
|
||||||
build.sh
|
build.sh
|
||||||
bin
|
android.iml
|
||||||
log*
|
build
|
||||||
|
gradle
|
||||||
|
gradlew
|
||||||
|
gradlew.bat
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,57 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.purplei2p.i2pd"
|
package="org.purplei2p.i2pd"
|
||||||
android:versionCode="1"
|
android:installLocation="auto"
|
||||||
android:versionName="2.18.0"
|
android:versionCode="1"
|
||||||
android:installLocation="auto">
|
android:versionName="2.21.1">
|
||||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25"/>
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-sdk
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
android:minSdkVersion="14"
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
android:targetSdkVersion="28" />
|
||||||
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/icon">
|
|
||||||
<receiver android:name=".NetworkStateChangeReceiver">
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<intent-filter>
|
<uses-permission android:name="android.permission.INTERNET" /> <!-- normal perm, per https://developer.android.com/guide/topics/permissions/normal-permissions.html -->
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
</intent-filter>
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
</receiver>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
|
||||||
<activity android:name=".I2PD"
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- required in API 26+ -->
|
||||||
android:label="@string/app_name">
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/icon"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@android:style/Theme.Holo.Light.DarkActionBar"
|
||||||
|
>
|
||||||
|
<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>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
1
android/assets/certificates
Symbolic link
1
android/assets/certificates
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../contrib/certificates
|
||||||
81
android/assets/i2pd.conf
Normal file
81
android/assets/i2pd.conf
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
## 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# keys = http-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 = socks-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
|
||||||
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,33 +1,54 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url 'https://maven.google.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'com.android.support:support-compat:28.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 28
|
||||||
buildToolsVersion "25.0.2"
|
buildToolsVersion "28.0.1"
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.purplei2p.i2pd"
|
applicationId "org.purplei2p.i2pd"
|
||||||
targetSdkVersion 25
|
targetSdkVersion 28
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "2.17.1"
|
versionName "2.21.1"
|
||||||
|
ndk {
|
||||||
|
abiFilters 'armeabi-v7a'
|
||||||
|
abiFilters 'x86'
|
||||||
}
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
arguments "-j4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
manifest.srcFile 'AndroidManifest.xml'
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
java.srcDirs = ['src']
|
java.srcDirs = ['src']
|
||||||
res.srcDirs = ['res']
|
res.srcDirs = ['res']
|
||||||
jniLibs.srcDirs = ['libs']
|
jniLibs.srcDirs = ['libs']
|
||||||
}
|
assets.srcDirs = ['assets']
|
||||||
}
|
}
|
||||||
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
orignal {
|
orignal {
|
||||||
storeFile file("i2pdapk.jks")
|
storeFile file("i2pdapk.jks")
|
||||||
@@ -37,11 +58,17 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
signingConfig signingConfigs.orignal
|
signingConfig signingConfigs.orignal
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
path './jni/Android.mk'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
android/gradle.properties
Normal file
1
android/gradle.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
org.gradle.parallel=true
|
||||||
@@ -25,49 +25,49 @@ include $(BUILD_SHARED_LIBRARY)
|
|||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_system
|
LOCAL_MODULE := boost_system
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_date_time
|
LOCAL_MODULE := boost_date_time
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_filesystem
|
LOCAL_MODULE := boost_filesystem
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_program_options
|
LOCAL_MODULE := boost_program_options
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := crypto
|
LOCAL_MODULE := crypto
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := ssl
|
LOCAL_MODULE := ssl
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||||
LOCAL_STATIC_LIBRARIES := crypto
|
LOCAL_STATIC_LIBRARIES := crypto
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := miniupnpc
|
LOCAL_MODULE := miniupnpc
|
||||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#APP_ABI := all
|
#APP_ABI := all
|
||||||
#APP_ABI := armeabi-v7a x86
|
APP_ABI := armeabi-v7a x86
|
||||||
#APP_ABI := x86
|
#APP_ABI := x86
|
||||||
#APP_ABI := x86_64
|
#APP_ABI := x86_64
|
||||||
APP_ABI := armeabi-v7a
|
#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.
|
#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
|
||||||
|
|
||||||
@@ -19,7 +19,8 @@ ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
|||||||
APP_CPPFLAGS += -DANDROID_ARM7A
|
APP_CPPFLAGS += -DANDROID_ARM7A
|
||||||
endif
|
endif
|
||||||
|
|
||||||
APP_OPTIM := debug
|
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
|
||||||
|
#APP_OPTIM := debug
|
||||||
|
|
||||||
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
|
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
|
||||||
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#include "DaemonAndroid.h"
|
|
||||||
#include "Daemon.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <exception>
|
||||||
#include <boost/exception/diagnostic_information.hpp>
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
#include <boost/exception_ptr.hpp>
|
#include <boost/exception_ptr.hpp>
|
||||||
#include <exception>
|
|
||||||
//#include "mainwindow.h"
|
//#include "mainwindow.h"
|
||||||
|
#include "FS.h"
|
||||||
|
#include "DaemonAndroid.h"
|
||||||
|
#include "Daemon.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@@ -80,6 +83,17 @@ namespace android
|
|||||||
//mutex=new QMutex(QMutex::Recursive);
|
//mutex=new QMutex(QMutex::Recursive);
|
||||||
//setRunningCallback(0);
|
//setRunningCallback(0);
|
||||||
//m_IsRunning=false;
|
//m_IsRunning=false;
|
||||||
|
|
||||||
|
// make sure assets are ready before proceed
|
||||||
|
i2p::fs::DetectDataDir("", 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);
|
return Daemon.init(argc,argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-25
|
target=android-28
|
||||||
|
|||||||
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>
|
||||||
@@ -2,15 +2,15 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".I2PD">
|
tools:context=".I2PDActivity">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_graceful_quit"
|
android:id="@+id/action_graceful_stop"
|
||||||
android:title="@string/action_graceful_quit"
|
android:title="@string/action_graceful_stop"
|
||||||
android:orderInCategory="98"
|
android:orderInCategory="98"
|
||||||
/>
|
/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_quit"
|
android:id="@+id/action_stop"
|
||||||
android:title="@string/action_quit"
|
android:title="@string/action_stop"
|
||||||
android:orderInCategory="99"
|
android:orderInCategory="99"
|
||||||
/>
|
/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
<string name="i2pd_started">i2pd started</string>
|
<string name="action_stop">Stop</string>
|
||||||
<string name="i2pd_service_started">i2pd service started</string>
|
<string name="action_graceful_stop">Graceful Stop</string>
|
||||||
<string name="i2pd_service_stopped">i2pd service stopped</string>
|
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
||||||
<string name="action_quit">Quit</string>
|
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
||||||
<string name="action_graceful_quit">Graceful Quit</string>
|
<string name="already_stopped">Already stopped</string>
|
||||||
<string name="graceful_quit_is_already_in_progress">Graceful quit is already in progress</string>
|
<string name="uninitialized">i2pd initializing</string>
|
||||||
<string name="graceful_quit_is_in_progress">Graceful quit is in progress</string>
|
<string name="starting">i2pd is starting</string>
|
||||||
|
<string name="jniLibraryLoaded">i2pd: loaded JNI libraries</string>
|
||||||
|
<string name="startedOkay">i2pd started</string>
|
||||||
|
<string name="startFailed">i2pd start failed</string>
|
||||||
|
<string name="gracefulShutdownInProgress">i2pd: graceful shutdown in progress</string>
|
||||||
|
<string name="stopped">i2pd has stopped</string>
|
||||||
|
<string name="remaining">remaining</string>
|
||||||
|
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
||||||
</resources>
|
</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"
|
||||||
@@ -8,8 +8,8 @@ import android.util.Log;
|
|||||||
public class DaemonSingleton {
|
public class DaemonSingleton {
|
||||||
private static final String TAG="i2pd";
|
private static final String TAG="i2pd";
|
||||||
private static final DaemonSingleton instance = new DaemonSingleton();
|
private static final DaemonSingleton instance = new DaemonSingleton();
|
||||||
public static interface StateUpdateListener { void daemonStateUpdate(); }
|
public interface StateUpdateListener { void daemonStateUpdate(); }
|
||||||
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<StateUpdateListener>();
|
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
||||||
|
|
||||||
public static DaemonSingleton getInstance() {
|
public static DaemonSingleton getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
@@ -18,63 +18,72 @@ public class DaemonSingleton {
|
|||||||
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
|
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
|
||||||
public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(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() {
|
public synchronized void stopAcceptingTunnels() {
|
||||||
if(isStartedOkay()){
|
if(isStartedOkay()){
|
||||||
state=State.gracefulShutdownInProgress;
|
setState(State.gracefulShutdownInProgress);
|
||||||
fireStateUpdate();
|
|
||||||
I2PD_JNI.stopAcceptingTunnels();
|
I2PD_JNI.stopAcceptingTunnels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNetworkStateChange(boolean isConnected) {
|
private volatile boolean startedOkay;
|
||||||
I2PD_JNI.onNetworkStateChanged(isConnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
||||||
|
|
||||||
public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress};
|
State(int statusStringResourceId) {
|
||||||
|
this.statusStringResourceId = statusStringResourceId;
|
||||||
|
}
|
||||||
|
|
||||||
private State state = State.uninitialized;
|
private final int statusStringResourceId;
|
||||||
|
|
||||||
|
public int getStatusStringResourceId() {
|
||||||
|
return statusStringResourceId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private volatile State state = State.uninitialized;
|
||||||
|
|
||||||
public State getState() { return state; }
|
public State getState() { return state; }
|
||||||
|
|
||||||
public synchronized void start() {
|
{
|
||||||
if(state != State.uninitialized)return;
|
setState(State.starting);
|
||||||
state = State.starting;
|
|
||||||
fireStateUpdate();
|
|
||||||
new Thread(new Runnable(){
|
new Thread(new Runnable(){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
I2PD_JNI.loadLibraries();
|
I2PD_JNI.loadLibraries();
|
||||||
synchronized (DaemonSingleton.this) {
|
setState(State.jniLibraryLoaded);
|
||||||
state = State.jniLibraryLoaded;
|
|
||||||
fireStateUpdate();
|
|
||||||
}
|
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
lastThrowable=tr;
|
lastThrowable=tr;
|
||||||
synchronized (DaemonSingleton.this) {
|
setState(State.startFailed);
|
||||||
state = State.startFailed;
|
|
||||||
fireStateUpdate();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
synchronized (DaemonSingleton.this) {
|
synchronized (DaemonSingleton.this) {
|
||||||
daemonStartResult = I2PD_JNI.startDaemon();
|
daemonStartResult = I2PD_JNI.startDaemon();
|
||||||
if("ok".equals(daemonStartResult)){
|
if("ok".equals(daemonStartResult)){
|
||||||
state=State.startedOkay;
|
setState(State.startedOkay);
|
||||||
setStartedOkay(true);
|
setStartedOkay(true);
|
||||||
}else state=State.startFailed;
|
}else setState(State.startFailed);
|
||||||
fireStateUpdate();
|
|
||||||
}
|
}
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
lastThrowable=tr;
|
lastThrowable=tr;
|
||||||
synchronized (DaemonSingleton.this) {
|
setState(State.startFailed);
|
||||||
state = State.startFailed;
|
|
||||||
fireStateUpdate();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +93,7 @@ public class DaemonSingleton {
|
|||||||
private Throwable lastThrowable;
|
private Throwable lastThrowable;
|
||||||
private String daemonStartResult="N/A";
|
private String daemonStartResult="N/A";
|
||||||
|
|
||||||
private synchronized void fireStateUpdate() {
|
private void fireStateUpdate1() {
|
||||||
Log.i(TAG, "daemon state change: "+state);
|
Log.i(TAG, "daemon state change: "+state);
|
||||||
for(StateUpdateListener listener : stateUpdateListeners) {
|
for(StateUpdateListener listener : stateUpdateListeners) {
|
||||||
try {
|
try {
|
||||||
@@ -121,6 +130,7 @@ public class DaemonSingleton {
|
|||||||
if(isStartedOkay()){
|
if(isStartedOkay()){
|
||||||
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);}
|
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);}
|
||||||
setStartedOkay(false);
|
setStartedOkay(false);
|
||||||
|
setState(State.stopped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,47 @@
|
|||||||
package org.purplei2p.i2pd;
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.RequiresApi;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class ForegroundService extends Service {
|
public class ForegroundService extends Service {
|
||||||
|
private static final String TAG="FgService";
|
||||||
|
|
||||||
|
private volatile boolean shown;
|
||||||
|
|
||||||
|
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||||
|
new DaemonSingleton.StateUpdateListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void daemonStateUpdate() {
|
||||||
|
try {
|
||||||
|
synchronized (ForegroundService.this) {
|
||||||
|
if (shown) cancelNotification();
|
||||||
|
showNotification();
|
||||||
|
}
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
Log.e(TAG,"error ignored",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
private NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
|
|
||||||
// Unique Identification Number for the Notification.
|
// Unique Identification Number for the Notification.
|
||||||
// We use it on Notification start, and to cancel it.
|
// We use it on Notification start, and to cancel it.
|
||||||
private int NOTIFICATION = R.string.i2pd_started;
|
private int NOTIFICATION = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for clients to access. Because we know this service always
|
* Class for clients to access. Because we know this service always
|
||||||
@@ -32,29 +58,35 @@ public class ForegroundService extends Service {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
// Display a notification about us starting. We put an icon in the status bar.
|
synchronized (this) {
|
||||||
showNotification();
|
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
|
||||||
daemon.start();
|
if (!shown) daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
|
}
|
||||||
// Tell the user we started.
|
// Tell the user we started.
|
||||||
Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
|
// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
|
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
|
||||||
daemon.start();
|
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
|
||||||
|
cancelNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void cancelNotification() {
|
||||||
// Cancel the persistent notification.
|
// Cancel the persistent notification.
|
||||||
notificationManager.cancel(NOTIFICATION);
|
notificationManager.cancel(NOTIFICATION);
|
||||||
|
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
// Tell the user we stopped.
|
// Tell the user we stopped.
|
||||||
Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
|
// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
|
||||||
|
shown=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,29 +101,49 @@ public class ForegroundService extends Service {
|
|||||||
/**
|
/**
|
||||||
* Show a notification while this service is running.
|
* Show a notification while this service is running.
|
||||||
*/
|
*/
|
||||||
private void showNotification() {
|
private synchronized void showNotification() {
|
||||||
// In this sample, we'll use the same text for the ticker and the expanded notification
|
// In this sample, we'll use the same text for the ticker and the expanded notification
|
||||||
CharSequence text = getText(R.string.i2pd_started);
|
CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId());
|
||||||
|
|
||||||
// The PendingIntent to launch our activity if the user selects this notification
|
// The PendingIntent to launch our activity if the user selects this notification
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||||
new Intent(this, I2PD.class), 0);
|
new Intent(this, I2PDActivity.class), 0);
|
||||||
|
|
||||||
|
// If earlier version channel ID is not used
|
||||||
|
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||||
|
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
|
||||||
|
|
||||||
// Set the info for the views that show in the notification panel.
|
// Set the info for the views that show in the notification panel.
|
||||||
Notification notification = new Notification.Builder(this)
|
Notification notification = new NotificationCompat.Builder(this, channelId)
|
||||||
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
.setOngoing(true)
|
||||||
.setTicker(text) // the status text
|
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||||
.setWhen(System.currentTimeMillis()) // the time stamp
|
.setPriority(Notification.PRIORITY_DEFAULT)
|
||||||
.setContentTitle(getText(R.string.app_name)) // the label of the entry
|
.setCategory(Notification.CATEGORY_SERVICE)
|
||||||
.setContentText(text) // the contents of the entry
|
.setTicker(text) // the status text
|
||||||
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
.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();
|
.build();
|
||||||
|
|
||||||
// Send the notification.
|
// Send the notification.
|
||||||
//mNM.notify(NOTIFICATION, notification);
|
//mNM.notify(NOTIFICATION, notification);
|
||||||
startForeground(NOTIFICATION, notification);
|
startForeground(NOTIFICATION, notification);
|
||||||
|
shown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
private synchronized String createNotificationChannel() {
|
||||||
|
String channelId = getString(R.string.app_name);
|
||||||
|
CharSequence channelName = "I2Pd service";
|
||||||
|
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
|
||||||
|
//chan.setLightColor(Color.PURPLE);
|
||||||
|
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||||
|
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
service.createNotificationChannel(chan);
|
||||||
|
return channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
419
android/src/org/purplei2p/i2pd/I2PDActivity.java
Executable file
419
android/src/org/purplei2p/i2pd/I2PDActivity.java
Executable file
@@ -0,0 +1,419 @@
|
|||||||
|
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.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
// For future package update checking
|
||||||
|
import org.purplei2p.i2pd.BuildConfig;
|
||||||
|
|
||||||
|
public class I2PDActivity extends Activity {
|
||||||
|
private static final String TAG = "i2pdActvt";
|
||||||
|
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
||||||
|
|
||||||
|
private TextView textView;
|
||||||
|
private boolean assetsCopied;
|
||||||
|
private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/";
|
||||||
|
|
||||||
|
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||||
|
|
||||||
|
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||||
|
new DaemonSingleton.StateUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void daemonStateUpdate()
|
||||||
|
{
|
||||||
|
processAssets();
|
||||||
|
runOnUiThread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if(textView==null) return;
|
||||||
|
Throwable tr = daemon.getLastThrowable();
|
||||||
|
if(tr!=null) {
|
||||||
|
textView.setText(throwableToString(tr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DaemonSingleton.State state = daemon.getState();
|
||||||
|
textView.setText(
|
||||||
|
String.valueOf(state)+
|
||||||
|
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
|
||||||
|
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
|
||||||
|
);
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
Log.e(TAG,"error ignored",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private static volatile long graceStartedMillis;
|
||||||
|
private static final Object graceStartedMillis_LOCK=new Object();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
textView = new TextView(this);
|
||||||
|
setContentView(textView);
|
||||||
|
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||||
|
daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
textView = null;
|
||||||
|
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||||
|
//cancelGracefulStop();
|
||||||
|
try{
|
||||||
|
doUnbindService();
|
||||||
|
}catch(Throwable tr){
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void cancelGracefulStop() {
|
||||||
|
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);
|
||||||
|
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_stop:
|
||||||
|
i2pdStop();
|
||||||
|
return true;
|
||||||
|
case R.id.action_graceful_stop:
|
||||||
|
i2pdGracefulStop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void i2pdStop() {
|
||||||
|
cancelGracefulStop();
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Log.d(TAG, "stopping");
|
||||||
|
try{
|
||||||
|
daemon.stopDaemon();
|
||||||
|
}catch (Throwable tr) {
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},"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(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try{
|
||||||
|
Log.d(TAG, "grac stopping");
|
||||||
|
if(daemon.isStartedOkay()) {
|
||||||
|
daemon.stopAcceptingTunnels();
|
||||||
|
long gracefulStopAtMillis;
|
||||||
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
|
graceStartedMillis = System.currentTimeMillis();
|
||||||
|
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||||
|
}
|
||||||
|
rescheduleGraceStop(null,gracefulStopAtMillis);
|
||||||
|
}else{
|
||||||
|
i2pdStop();
|
||||||
|
}
|
||||||
|
} catch(Throwable tr) {
|
||||||
|
Log.e(TAG,"",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},"gracInit").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 static void setGracefulQuitTimer(Timer gracefulQuitTimer) {
|
||||||
|
I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
throw new IOException();
|
||||||
|
|
||||||
|
// Make the directory.
|
||||||
|
File dir = new File(i2pdpath, path);
|
||||||
|
dir.mkdirs();
|
||||||
|
|
||||||
|
// Recurse on the contents.
|
||||||
|
for (String entry : contents) {
|
||||||
|
copyAsset(path + "/" + entry);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
copyFileAsset(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
InputStream in = getAssets().open(path);
|
||||||
|
OutputStream out = new FileOutputStream(file);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int read = in.read(buffer);
|
||||||
|
while (read != -1) {
|
||||||
|
out.write(buffer, 0, read);
|
||||||
|
read = in.read(buffer);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteRecursive(File fileOrDirectory) {
|
||||||
|
if (fileOrDirectory.isDirectory()) {
|
||||||
|
for (File child : fileOrDirectory.listFiles()) {
|
||||||
|
deleteRecursive(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileOrDirectory.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
BufferedReader br = new BufferedReader(new FileReader(holderfile));
|
||||||
|
String line;
|
||||||
|
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
text.append(line);
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if version differs from current app version or null, try to delete certificates folder
|
||||||
|
if (!text.toString().contains(versionName)) try {
|
||||||
|
holderfile.delete();
|
||||||
|
File certpath = new File(i2pdpath, "certificates");
|
||||||
|
deleteRecursive(certpath);
|
||||||
|
}
|
||||||
|
catch (Throwable tr) {
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy assets. If processed file exists, it won't be overwrited
|
||||||
|
copyAsset("certificates");
|
||||||
|
copyAsset("i2pd.conf");
|
||||||
|
copyAsset("subscriptions.txt");
|
||||||
|
copyAsset("tunnels.conf");
|
||||||
|
|
||||||
|
// update holder file about successful copying
|
||||||
|
FileWriter writer = new FileWriter(holderfile);
|
||||||
|
writer.append(versionName);
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch (Throwable tr)
|
||||||
|
{
|
||||||
|
Log.e(TAG,"copy assets",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
171
android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
Normal file
171
android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
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("SD card write permission denied, you need to allow this to continue");
|
||||||
|
textview_retry.setVisibility(TextView.VISIBLE);
|
||||||
|
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
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_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_date_time
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_filesystem
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_program_options
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := crypto
|
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := ssl
|
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||||
|
LOCAL_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)
|
||||||
43
android_binary_only/jni/Application.mk
Executable file
43
android_binary_only/jni/Application.mk
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
# http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
|
||||||
|
NDK_TOOLCHAIN_VERSION := 4.9
|
||||||
|
# APP_STL := stlport_shared --> does not seem to contain C++11 features
|
||||||
|
#APP_STL := gnustl_shared
|
||||||
|
APP_STL := gnustl_static
|
||||||
|
|
||||||
|
# Enable c++11 extensions in source code
|
||||||
|
APP_CPPFLAGS += -std=c++11 -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
|
||||||
|
# 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.18.{build}
|
version: 2.21.1.{build}
|
||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
branches:
|
branches:
|
||||||
@@ -18,9 +18,9 @@ environment:
|
|||||||
|
|
||||||
install:
|
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"
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
|
||||||
|
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
|
||||||
|
|
||||||
- if "%MSYSTEM%" == "MINGW64" (
|
- if "%MSYSTEM%" == "MINGW64" (
|
||||||
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"
|
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ include_directories(${LIBI2PD_CLIENT_SRC_DIR})
|
|||||||
set (LIBI2PD_SRC
|
set (LIBI2PD_SRC
|
||||||
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
|
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Config.cpp"
|
"${LIBI2PD_SRC_DIR}/Config.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/CPU.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
|
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
|
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
|
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
|
||||||
@@ -76,6 +77,10 @@ set (LIBI2PD_SRC
|
|||||||
"${LIBI2PD_SRC_DIR}/api.cpp"
|
"${LIBI2PD_SRC_DIR}/api.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Event.cpp"
|
"${LIBI2PD_SRC_DIR}/Event.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Gost.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"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_WEBSOCKETS)
|
if (WITH_WEBSOCKETS)
|
||||||
@@ -93,13 +98,17 @@ endif()
|
|||||||
|
|
||||||
add_library(libi2pd ${LIBI2PD_SRC})
|
add_library(libi2pd ${LIBI2PD_SRC})
|
||||||
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
||||||
install(TARGETS libi2pd
|
|
||||||
EXPORT libi2pd
|
if (WITH_LIBRARY)
|
||||||
ARCHIVE DESTINATION lib
|
install(TARGETS libi2pd
|
||||||
COMPONENT Libraries)
|
EXPORT libi2pd
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
COMPONENT Libraries)
|
||||||
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
|
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
|
||||||
# FIXME This pulls stdafx
|
# FIXME This pulls stdafx
|
||||||
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
set (CLIENT_SRC
|
set (CLIENT_SRC
|
||||||
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
||||||
@@ -118,7 +127,17 @@ set (CLIENT_SRC
|
|||||||
if(WITH_WEBSOCKETS)
|
if(WITH_WEBSOCKETS)
|
||||||
list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp")
|
list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp")
|
||||||
endif ()
|
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)
|
set(DAEMON_SRC_DIR ../daemon)
|
||||||
|
|
||||||
@@ -171,7 +190,7 @@ if (CXX11_SUPPORTED)
|
|||||||
elseif (CXX0X_SUPPORTED) # gcc 4.6
|
elseif (CXX0X_SUPPORTED) # gcc 4.6
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
|
||||||
elseif (NOT MSVC)
|
elseif (NOT MSVC)
|
||||||
message(SEND_ERROR "C++11 standart not seems to be supported by compiler. Too old version?")
|
message(SEND_ERROR "C++11 standard not seems to be supported by compiler. Too old version?")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
@@ -183,6 +202,10 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
endif ()
|
endif ()
|
||||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
# more tweaks
|
# 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))
|
if (NOT (MSVC OR MSYS OR APPLE))
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
|
||||||
endif()
|
endif()
|
||||||
@@ -213,7 +236,6 @@ endif ()
|
|||||||
|
|
||||||
if (WITH_AESNI)
|
if (WITH_AESNI)
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes" )
|
||||||
add_definitions ( -DAESNI )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_AVX)
|
if (WITH_AVX)
|
||||||
@@ -300,7 +322,7 @@ if (WITH_PCH)
|
|||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
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(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()
|
else()
|
||||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
||||||
get_directory_property(DEFS DEFINITIONS)
|
get_directory_property(DEFS DEFINITIONS)
|
||||||
@@ -309,25 +331,21 @@ if (WITH_PCH)
|
|||||||
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
|
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(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()
|
endif()
|
||||||
target_link_libraries(libi2pd stdafx)
|
target_link_libraries(libi2pd stdafx)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(i2pdclient libi2pd)
|
target_link_libraries(libi2pdclient libi2pd)
|
||||||
|
|
||||||
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
||||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
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()
|
endif()
|
||||||
|
|
||||||
find_package ( OpenSSL REQUIRED )
|
find_package ( OpenSSL REQUIRED )
|
||||||
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
||||||
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
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()
|
endif()
|
||||||
|
|
||||||
if (WITH_UPNP)
|
if (WITH_UPNP)
|
||||||
@@ -451,7 +469,7 @@ if (WITH_BINARY)
|
|||||||
if (WITH_STATIC)
|
if (WITH_STATIC)
|
||||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
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)
|
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
||||||
set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\m
|
|||||||
set "WD=C:\msys64\usr\bin\"
|
set "WD=C:\msys64\usr\bin\"
|
||||||
set MSYS2_PATH_TYPE=inherit
|
set MSYS2_PATH_TYPE=inherit
|
||||||
set CHERE_INVOKING=enabled_from_arguments
|
set CHERE_INVOKING=enabled_from_arguments
|
||||||
set MSYSTEM=MSYS
|
REM set MSYSTEM=MSYS
|
||||||
|
set MSYSTEM=MINGW32
|
||||||
|
|
||||||
set "xSH=%WD%bash -lc"
|
set "xSH=%WD%bash -lc"
|
||||||
|
|
||||||
@@ -61,12 +62,12 @@ exit /b 0
|
|||||||
%xSH% "make clean" >> nul
|
%xSH% "make clean" >> nul
|
||||||
echo Building i2pd %tag% for win%bitness%:
|
echo Building i2pd %tag% for win%bitness%:
|
||||||
echo Build AVX+AESNI...
|
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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1
|
||||||
echo Build AVX...
|
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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.log 2>&1
|
||||||
echo Build AESNI...
|
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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.log 2>&1
|
||||||
echo Build without extensions...
|
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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1
|
||||||
|
|
||||||
:EOF
|
:EOF
|
||||||
@@ -17,14 +17,16 @@
|
|||||||
/etc/host.conf r,
|
/etc/host.conf r,
|
||||||
/etc/hosts r,
|
/etc/hosts r,
|
||||||
/etc/nsswitch.conf r,
|
/etc/nsswitch.conf r,
|
||||||
|
/etc/resolv.conf r,
|
||||||
/run/resolvconf/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)
|
# path specific (feel free to modify if you have another paths)
|
||||||
/etc/i2pd/** r,
|
/etc/i2pd/** r,
|
||||||
/run/i2pd/i2pd.pid rw,
|
/run/i2pd/i2pd.pid rwk,
|
||||||
/var/lib/i2pd/** rw,
|
/var/lib/i2pd/** rw,
|
||||||
/var/log/i2pd/i2pd.log w,
|
/var/log/i2pd/i2pd.log w,
|
||||||
/var/run/i2pd/i2pd.pid rw,
|
/var/run/i2pd/i2pd.pid rwk,
|
||||||
/usr/sbin/i2pd mr,
|
/usr/sbin/i2pd mr,
|
||||||
/usr/share/i2pd/** r,
|
/usr/share/i2pd/** r,
|
||||||
|
|
||||||
|
|||||||
33
contrib/certificates/reseed/hottuna_at_mail.i2p.crt
Normal file
33
contrib/certificates/reseed/hottuna_at_mail.i2p.crt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFxzCCA6+gAwIBAgIQZfqn0yiJL3dGgCjeOeWS6DANBgkqhkiG9w0BAQsFADBw
|
||||||
|
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
|
||||||
|
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ
|
||||||
|
aG90dHVuYUBtYWlsLmkycDAeFw0xNjExMDkwMzE1MzJaFw0yNjExMDkwMzE1MzJa
|
||||||
|
MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV
|
||||||
|
BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD
|
||||||
|
DBBob3R0dW5hQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
|
||||||
|
AgEA21Bfgcc9VVH4l2u1YvYlTw2OPUyQb16X2IOW0PzdsUO5W78Loueu974BkiKi
|
||||||
|
84lQZanLr0OwEopdfutGc6gegSLmwaWx5YCG5uwpLOPkDiObfX+nptH6As/B1cn+
|
||||||
|
mzejYdVKRnWd7EtHW0iseSsILBK1YbGw4AGpXJ8k18DJSzUt2+spOkpBW6XqectN
|
||||||
|
8y2JDSTns8yiNxietVeRN/clolDXT9ZwWHkd+QMHTKhgl3Uz1knOffU0L9l4ij4E
|
||||||
|
oFgPfQo8NL63kLM24hF1hM/At7XvE4iOlObFwPXE+H5EGZpT5+A7Oezepvd/VMzM
|
||||||
|
tCJ49hM0OlR393tKFONye5GCYeSDJGdPEB6+rBptpRrlch63tG9ktpCRrg2wQWgC
|
||||||
|
e3aOE1xVRrmwiTZ+jpfsOCbZrrSA/C4Bmp6AfGchyHuDGGkRU/FJwa1YLJe0dkWG
|
||||||
|
ITLWeh4zeVuAS5mctdv9NQ5wflSGz9S8HjsPBS5+CDOFHh4cexXRG3ITfk6aLhuY
|
||||||
|
KTMlkIO4SHKmnwAvy1sFlsqj6PbfVjpHPLg625fdNxBpe57TLxtIdBB3C7ccQSRW
|
||||||
|
+UG6Cmbcmh80PbsSR132NLMlzLhbaOjxeCWWJRo6cLuHBptAFMNwqsXt8xVf9M0N
|
||||||
|
NdJoKUmblyvjnq0N8aMEqtQ1uGMTaCB39cutHQq+reD/uzsCAwEAAaNdMFswDgYD
|
||||||
|
VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV
|
||||||
|
HRMBAf8EBTADAQH/MBkGA1UdDgQSBBBob3R0dW5hQG1haWwuaTJwMA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4ICAQCibFV8t4pajP176u3jx31x1kgqX6Nd+0YFARPZQjq99kUyoZer
|
||||||
|
GyHGsMWgM281RxiZkveHxR7Hm7pEd1nkhG3rm+d7GdJ2p2hujr9xUvl0zEqAAqtm
|
||||||
|
lkYI6uJ13WBjFc9/QuRIdeIeSUN+eazSXNg2nJhoV4pF9n2Q2xDc9dH4GWO93cMX
|
||||||
|
JPKVGujT3s0b7LWsEguZBPdaPW7wwZd902Cg/M5fE1hZQ8/SIAGUtylb/ZilVeTS
|
||||||
|
spxWP1gX3NT1SSvv0s6oL7eADCgtggWaMxEjZhi6WMnPUeeFY8X+6trkTlnF9+r/
|
||||||
|
HiVvvzQKrPPtB3j1xfQCAF6gUKN4iY+2AOExv4rl/l+JJbPhpd/FuvD8AVkLMZ8X
|
||||||
|
uPe0Ew2xv30cc8JjGDzQvoSpBmVTra4f+xqH+w8UEmxnx97Ye2aUCtnPykACnFte
|
||||||
|
oT97K5052B1zq+4fu4xaHZnEzPYVK5POzOufNLPgciJsWrR5GDWtHd+ht/ZD37+b
|
||||||
|
+j1BXpeBWUBQgluFv+lNMVNPJxc2OMELR1EtEwXD7mTuuUEtF5Pi63IerQ5LzD3G
|
||||||
|
KBvXhMB0XhpE6WG6pBwAvkGf5zVv/CxClJH4BQbdZwj9HYddfEQlPl0z/XFR2M0+
|
||||||
|
9/8nBfGSPYIt6KeHBCeyQWTdE9gqSzMwTMFsennXmaT8gyc7eKqKF6adqw==
|
||||||
|
-----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 --tunconf=/etc/i2pd/tunnels.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 graceful 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 hanging 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>"
|
LABEL authors "Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
|
||||||
|
|
||||||
# Expose git branch, tag and URL variables as arguments
|
# Expose git branch, tag and URL variables as arguments
|
||||||
ARG GIT_BRANCH="master"
|
ARG GIT_BRANCH="openssl"
|
||||||
ENV GIT_BRANCH=${GIT_BRANCH}
|
ENV GIT_BRANCH=${GIT_BRANCH}
|
||||||
ARG GIT_TAG=""
|
ARG GIT_TAG=""
|
||||||
ENV GIT_TAG=${GIT_TAG}
|
ENV GIT_TAG=${GIT_TAG}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
## Configuration file for a typical i2pd user
|
## 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.
|
## for more options you can use in this file.
|
||||||
|
|
||||||
## Lines that begin with "## " try to explain what's going on. Lines
|
## Lines that begin with "## " try to explain what's going on. Lines
|
||||||
@@ -26,15 +26,11 @@
|
|||||||
## Log messages above this level (debug, *info, warn, error, none)
|
## Log messages above this level (debug, *info, warn, error, none)
|
||||||
## If you set it to none, logging will be disabled
|
## If you set it to none, logging will be disabled
|
||||||
# loglevel = info
|
# loglevel = info
|
||||||
|
## Write full CLF-formatted date and time to log (default: write only time)
|
||||||
## Path to storage of i2pd data (RI, keys, peer profiles, ...)
|
# logclftime = true
|
||||||
## Default: ~/.i2pd or /var/lib/i2pd
|
|
||||||
# datadir = /var/lib/i2pd
|
|
||||||
|
|
||||||
## Daemon mode. Router will go to background after start
|
## Daemon mode. Router will go to background after start
|
||||||
# daemon = true
|
# 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)
|
## Specify a family, router belongs to (default - none)
|
||||||
# family =
|
# family =
|
||||||
@@ -55,9 +51,15 @@ ipv6 = false
|
|||||||
|
|
||||||
## Network interface to bind to
|
## Network interface to bind to
|
||||||
# ifname =
|
# ifname =
|
||||||
|
## You can specify different interfaces for IPv4 and IPv6
|
||||||
|
# ifname4 =
|
||||||
|
# ifname6 =
|
||||||
|
|
||||||
## Enable NTCP transport (default = true)
|
## Enable NTCP transport (default = true)
|
||||||
# ntcp = 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)
|
## Enable SSU transport (default = true)
|
||||||
# ssu = true
|
# ssu = true
|
||||||
|
|
||||||
@@ -69,6 +71,8 @@ ipv6 = false
|
|||||||
## X - unlimited
|
## X - unlimited
|
||||||
## Default is X for floodfill, L for regular node
|
## Default is X for floodfill, L for regular node
|
||||||
# bandwidth = L
|
# 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
|
## Router will not accept transit tunnels, disabling transit traffic completely
|
||||||
## (default = false)
|
## (default = false)
|
||||||
@@ -77,46 +81,17 @@ ipv6 = false
|
|||||||
## Router will be floodfill
|
## Router will be floodfill
|
||||||
# floodfill = true
|
# 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]
|
[http]
|
||||||
|
## Web Console settings
|
||||||
## Uncomment and set to 'false' to disable Web Console
|
## Uncomment and set to 'false' to disable Web Console
|
||||||
# enabled = true
|
# enabled = true
|
||||||
## Address and port service will listen on
|
## Address and port service will listen on
|
||||||
address = 127.0.0.1
|
address = 127.0.0.1
|
||||||
port = 7070
|
port = 7070
|
||||||
|
## Uncomment following lines to enable Web Console authentication
|
||||||
|
# auth = true
|
||||||
|
# user = i2pd
|
||||||
|
# pass = changeme
|
||||||
|
|
||||||
[httpproxy]
|
[httpproxy]
|
||||||
## Uncomment and set to 'false' to disable HTTP Proxy
|
## Uncomment and set to 'false' to disable HTTP Proxy
|
||||||
@@ -126,6 +101,11 @@ address = 127.0.0.1
|
|||||||
port = 4444
|
port = 4444
|
||||||
## Optional keys file for proxy local destination
|
## Optional keys file for proxy local destination
|
||||||
# keys = http-proxy-keys.dat
|
# 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]
|
[socksproxy]
|
||||||
## Uncomment and set to 'false' to disable SOCKS Proxy
|
## Uncomment and set to 'false' to disable SOCKS Proxy
|
||||||
@@ -135,13 +115,13 @@ address = 127.0.0.1
|
|||||||
port = 4447
|
port = 4447
|
||||||
## Optional keys file for proxy local destination
|
## Optional keys file for proxy local destination
|
||||||
# keys = socks-proxy-keys.dat
|
# keys = socks-proxy-keys.dat
|
||||||
|
|
||||||
## Socks outproxy. Example below is set to use Tor for all connections except i2p
|
## 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
|
## Uncomment and set to 'true' to enable using of SOCKS outproxy
|
||||||
# outproxy.enabled = false
|
# outproxy.enabled = false
|
||||||
## Address and port of outproxy
|
## Address and port of outproxy
|
||||||
# outproxy = 127.0.0.1
|
# outproxy = 127.0.0.1
|
||||||
# outproxyport = 9050
|
# outproxyport = 9050
|
||||||
|
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||||
|
|
||||||
[sam]
|
[sam]
|
||||||
## Uncomment and set to 'true' to enable SAM Bridge
|
## Uncomment and set to 'true' to enable SAM Bridge
|
||||||
@@ -170,3 +150,71 @@ enabled = true
|
|||||||
## Address and port service will listen on
|
## Address and port service will listen on
|
||||||
# address = 127.0.0.1
|
# address = 127.0.0.1
|
||||||
# port = 7650
|
# 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
|
||||||
|
|||||||
31
contrib/i2pd.service
Normal file
31
contrib/i2pd.service
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
[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 --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 enable this
|
||||||
|
LimitNOFILE=4096
|
||||||
|
PrivateDevices=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
102
contrib/rpm/i2pd-git.spec
Normal file
102
contrib/rpm/i2pd-git.spec
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||||
|
|
||||||
|
Name: i2pd-git
|
||||||
|
Version: 2.21.1
|
||||||
|
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 \
|
||||||
|
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||||
|
%endif
|
||||||
|
|
||||||
|
make %{?_smp_mflags}
|
||||||
|
|
||||||
|
|
||||||
|
%install
|
||||||
|
cd build
|
||||||
|
chrpath -d i2pd
|
||||||
|
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||||
|
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
|
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||||
|
install -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||||
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||||
|
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
|
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
|
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
|
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
|
||||||
|
%{_sbindir}/i2pd
|
||||||
|
%{_datadir}/i2pd/certificates
|
||||||
|
%config(noreplace) %{_sysconfdir}/i2pd/*
|
||||||
|
/%{_unitdir}/i2pd.service
|
||||||
|
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||||
|
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||||
|
%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu Feb 01 2018 r4sas <r4sas@i2pmail.org> - 2.18.0
|
||||||
|
- Initial i2pd-git based on i2pd 2.18.0-1 spec
|
||||||
@@ -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 --tunconf=/etc/i2pd/tunnels.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 graceful 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/rpm/i2pd.service
Symbolic link
1
contrib/rpm/i2pd.service
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../i2pd.service
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
%define build_timestamp %(date +"%Y%m%d")
|
|
||||||
|
|
||||||
Name: i2pd
|
Name: i2pd
|
||||||
Version: 2.18.0
|
Version: 2.21.1
|
||||||
Release: %{build_timestamp}git%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Obsoletes: %{name}-systemd
|
Conflicts: i2pd-git
|
||||||
|
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: https://github.com/PurpleI2P/i2pd
|
URL: https://github.com/PurpleI2P/i2pd
|
||||||
@@ -59,12 +57,12 @@ chrpath -d i2pd
|
|||||||
install -D -m 755 i2pd %{buildroot}%{_sbindir}/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/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 %{_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
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||||
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}/%{_unitdir}/i2pd.service
|
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
install -d -m 700 %{buildroot}/%{_sharedstatedir}/i2pd
|
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd
|
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates
|
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
@@ -98,7 +96,27 @@ getent passwd i2pd >/dev/null || \
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue Jan 30 2018 orignal <i2porignal@yandex.ru>> - 2.18.0
|
* Thu 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
|
- update to 2.18.0
|
||||||
|
|
||||||
* Sat Jan 27 2018 l-n-s <supervillain@riseup.net> - 2.17.0-1
|
* Sat Jan 27 2018 l-n-s <supervillain@riseup.net> - 2.17.0-1
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ keys = irc-keys.dat
|
|||||||
#destinationport = 110
|
#destinationport = 110
|
||||||
#keys = pop3-keys.dat
|
#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/
|
||||||
|
|||||||
@@ -60,8 +60,12 @@ namespace i2p
|
|||||||
return service;
|
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::Init();
|
||||||
i2p::config::ParseCmdline(argc, argv);
|
i2p::config::ParseCmdline(argc, argv);
|
||||||
|
|
||||||
@@ -104,7 +108,10 @@ namespace i2p
|
|||||||
logs = "file";
|
logs = "file";
|
||||||
|
|
||||||
i2p::log::Logger().SetLogLevel(loglevel);
|
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 == "")
|
if (logfile == "")
|
||||||
logfile = i2p::fs::DataDirPath("i2pd.log");
|
logfile = i2p::fs::DataDirPath("i2pd.log");
|
||||||
LogPrint(eLogInfo, "Log: will send messages to ", logfile);
|
LogPrint(eLogInfo, "Log: will send messages to ", logfile);
|
||||||
@@ -119,12 +126,6 @@ namespace i2p
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
||||||
#ifdef AESNI
|
|
||||||
LogPrint(eLogInfo, "AESNI enabled");
|
|
||||||
#endif
|
|
||||||
#if defined(__AVX__)
|
|
||||||
LogPrint(eLogInfo, "AVX enabled");
|
|
||||||
#endif
|
|
||||||
LogPrint(eLogDebug, "FS: main config file: ", config);
|
LogPrint(eLogDebug, "FS: main config file: ", config);
|
||||||
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
||||||
|
|
||||||
@@ -151,6 +152,19 @@ namespace i2p
|
|||||||
i2p::context.SetSupportsV6 (ipv6);
|
i2p::context.SetSupportsV6 (ipv6);
|
||||||
i2p::context.SetSupportsV4 (ipv4);
|
i2p::context.SetSupportsV4 (ipv4);
|
||||||
|
|
||||||
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
|
if (ntcp2)
|
||||||
|
{
|
||||||
|
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||||
|
if (published)
|
||||||
|
{
|
||||||
|
uint16_t port; i2p::config::GetOption("ntcp2.port", port);
|
||||||
|
i2p::context.PublishNTCP2Address (port, true); // publish
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i2p::context.PublishNTCP2Address (port, false); // unpublish
|
||||||
|
}
|
||||||
|
|
||||||
bool transit; i2p::config::GetOption("notransit", transit);
|
bool transit; i2p::config::GetOption("notransit", transit);
|
||||||
i2p::context.SetAcceptsTunnels (!transit);
|
i2p::context.SetAcceptsTunnels (!transit);
|
||||||
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
|
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
|
||||||
@@ -275,9 +289,10 @@ namespace i2p
|
|||||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
||||||
|
|
||||||
i2p::transport::transports.Start(ntcp, ssu);
|
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");
|
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||||
/** shut down netdb right away */
|
/** shut down netdb right away */
|
||||||
i2p::transport::transports.Stop();
|
i2p::transport::transports.Stop();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@@ -12,8 +13,9 @@ namespace util
|
|||||||
class Daemon_Singleton
|
class Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool init(int argc, char* argv[]);
|
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||||
virtual bool start();
|
virtual bool init(int argc, char* argv[]);
|
||||||
|
virtual bool start();
|
||||||
virtual bool stop();
|
virtual bool stop();
|
||||||
virtual void run () {};
|
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)
|
#elif defined(_WIN32)
|
||||||
#define Daemon i2p::util::DaemonWin32::Instance()
|
#define Daemon i2p::util::DaemonWin32::Instance()
|
||||||
class DaemonWin32 : public Daemon_Singleton
|
class DaemonWin32 : public Daemon_Singleton
|
||||||
@@ -77,7 +66,18 @@ namespace util
|
|||||||
|
|
||||||
DaemonWin32 ():isGraceful(false) {}
|
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
|
#else
|
||||||
#define Daemon i2p::util::DaemonLinux::Instance()
|
#define Daemon i2p::util::DaemonLinux::Instance()
|
||||||
class DaemonLinux : public Daemon_Singleton
|
class DaemonLinux : public Daemon_Singleton
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
@@ -91,6 +92,8 @@ namespace http {
|
|||||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||||
|
|
||||||
|
static std::string ConvertTime (uint64_t time);
|
||||||
|
|
||||||
static void ShowUptime (std::stringstream& s, int seconds)
|
static void ShowUptime (std::stringstream& s, int seconds)
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
@@ -198,7 +201,10 @@ namespace http {
|
|||||||
s << "<b>ERROR:</b> " << string << "<br>\r\n";
|
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> ";
|
s << "<b>Uptime:</b> ";
|
||||||
ShowUptime(s, i2p::context.GetUptime ());
|
ShowUptime(s, i2p::context.GetUptime ());
|
||||||
@@ -224,7 +230,7 @@ namespace http {
|
|||||||
default: s << "Unknown";
|
default: s << "Unknown";
|
||||||
}
|
}
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
|
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||||
if (auto remains = Daemon.gracefulShutdownInterval) {
|
if (auto remains = Daemon.gracefulShutdownInterval) {
|
||||||
s << "<b>Stopping in:</b> ";
|
s << "<b>Stopping in:</b> ";
|
||||||
s << remains << " seconds";
|
s << remains << " seconds";
|
||||||
@@ -245,25 +251,37 @@ namespace http {
|
|||||||
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
|
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
|
||||||
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n";
|
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n";
|
||||||
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n";
|
s << "<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(includeHiddenContent) {
|
if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) {
|
||||||
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
s << "<label for='slide-info'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide-info'/>\r\n<p class='content'>\r\n";
|
||||||
|
}
|
||||||
|
if(includeHiddenContent) {
|
||||||
|
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||||
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
s << "<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>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" ;
|
||||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||||
{
|
{
|
||||||
|
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
|
||||||
|
{
|
||||||
|
s << "NTCP2";
|
||||||
|
if (address->host.is_v6 ()) s << "v6";
|
||||||
|
s << " supported <br>\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
switch (address->transportStyle)
|
switch (address->transportStyle)
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP:
|
case i2p::data::RouterInfo::eTransportNTCP:
|
||||||
if (address->host.is_v6 ())
|
{
|
||||||
s << "NTCP6 ";
|
s << "NTCP";
|
||||||
else
|
if (address->IsPublishedNTCP2 ()) s << "2";
|
||||||
s << "NTCP ";
|
if (address->host.is_v6 ()) s << "v6";
|
||||||
break;
|
s << " ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
case i2p::data::RouterInfo::eTransportSSU:
|
case i2p::data::RouterInfo::eTransportSSU:
|
||||||
if (address->host.is_v6 ())
|
if (address->host.is_v6 ())
|
||||||
s << "SSU6 ";
|
s << "SSUv6 ";
|
||||||
else
|
else
|
||||||
s << "SSU ";
|
s << "SSU ";
|
||||||
break;
|
break;
|
||||||
@@ -272,9 +290,12 @@ namespace http {
|
|||||||
}
|
}
|
||||||
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
|
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << "</p>\r\n</div>\r\n";
|
s << "</p>\r\n</div>\r\n";
|
||||||
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
if(outputFormat==OutputFormatEnum::forQtUi) {
|
||||||
|
s << "<br>";
|
||||||
|
}
|
||||||
|
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
||||||
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
|
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
|
||||||
s << "<b>LeaseSets:</b> " << i2p::data::netdb.GetNumLeaseSets () << "<br>\r\n";
|
s << "<b>LeaseSets:</b> " << i2p::data::netdb.GetNumLeaseSets () << "<br>\r\n";
|
||||||
|
|
||||||
@@ -285,15 +306,17 @@ namespace http {
|
|||||||
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
|
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 << "<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";
|
if(outputFormat==OutputFormatEnum::forWebConsole) {
|
||||||
s << "<tr><td>" << "HTTP Proxy" << "</td><td><div class='" << ((i2p::client::context.GetHttpProxy ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
|
s << "<table><caption>Services</caption><tr><th>Service</th><th>State</th></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>" << "HTTP Proxy" << "</td><td><div class='" << ((i2p::client::context.GetHttpProxy ()) ? "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>" << "SOCKS Proxy" << "</td><td><div class='" << ((i2p::client::context.GetSocksProxy ()) ? "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>" << "BOB" << "</td><td><div class='" << ((i2p::client::context.GetBOBCommandChannel ()) ? "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>" << "SAM" << "</td><td><div class='" << ((i2p::client::context.GetSAMBridge ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
|
||||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
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";
|
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||||
s << "</table>\r\n";
|
s << "<tr><td>" << "I2PControl" << "</td><td><div class='" << ((i2pcontrol) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
|
||||||
|
s << "</table>\r\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowLocalDestinations (std::stringstream& s)
|
void ShowLocalDestinations (std::stringstream& s)
|
||||||
@@ -358,10 +381,12 @@ namespace http {
|
|||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
|
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
|
||||||
if (!dest->GetSessions ().empty ()) {
|
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";
|
std::stringstream tmp_s; uint32_t out_tags = 0;
|
||||||
for (const auto& it: dest->GetSessions ())
|
for (const auto& it: dest->GetSessions ()) {
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
|
tmp_s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
|
||||||
s << "</p>\r\n</div>\r\n";
|
out_tags = out_tags + it.second->GetNumOutgoingTags ();
|
||||||
|
}
|
||||||
|
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n" << tmp_s.str () << "</p>\r\n</div>\r\n";
|
||||||
} else
|
} else
|
||||||
s << "Outgoing: <i>0</i><br>\r\n";
|
s << "Outgoing: <i>0</i><br>\r\n";
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
@@ -443,14 +468,14 @@ namespace http {
|
|||||||
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
|
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
|
||||||
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\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 << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<p class='content'>\r\n";
|
||||||
s << "<b>Expires:</b> " << ls.GetExpirationTime() << "<br>\r\n";
|
s << "<b>Expires:</b> " << ConvertTime(ls.GetExpirationTime()) << "<br>\r\n";
|
||||||
auto leases = ls.GetNonExpiredLeases();
|
auto leases = ls.GetNonExpiredLeases();
|
||||||
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
|
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
|
||||||
for ( auto & l : leases )
|
for ( auto & l : leases )
|
||||||
{
|
{
|
||||||
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
|
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
|
||||||
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
|
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
|
||||||
s << "<b>EndDate:</b> " << l->endDate << "<br>\r\n";
|
s << "<b>EndDate:</b> " << ConvertTime(l->endDate) << "<br>\r\n";
|
||||||
}
|
}
|
||||||
s << "</p>\r\n</div>\r\n</div>\r\n";
|
s << "</p>\r\n</div>\r\n</div>\r\n";
|
||||||
}
|
}
|
||||||
@@ -493,7 +518,7 @@ namespace http {
|
|||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
|
||||||
else
|
else
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
|
||||||
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
|
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||||
if (Daemon.gracefulShutdownInterval)
|
if (Daemon.gracefulShutdownInterval)
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
||||||
else
|
else
|
||||||
@@ -529,6 +554,46 @@ namespace http {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<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_" << boost::algorithm::to_lower_copy(name) << "v6'><b>" << name << "v6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "v6'/>\r\n<p class='content'>";
|
||||||
|
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShowTransports (std::stringstream& s)
|
void ShowTransports (std::stringstream& s)
|
||||||
{
|
{
|
||||||
s << "<b>Transports:</b><br>\r\n<br>\r\n";
|
s << "<b>Transports:</b><br>\r\n<br>\r\n";
|
||||||
@@ -537,43 +602,14 @@ namespace http {
|
|||||||
{
|
{
|
||||||
auto sessions = ntcpServer->GetNTCPSessions ();
|
auto sessions = ntcpServer->GetNTCPSessions ();
|
||||||
if (!sessions.empty ())
|
if (!sessions.empty ())
|
||||||
{
|
ShowNTCPTransports (s, sessions, "NTCP");
|
||||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
}
|
||||||
for (const auto& it: sessions )
|
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
||||||
{
|
if (ntcp2Server)
|
||||||
if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
{
|
||||||
{
|
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
||||||
// incoming connection doesn't have remote RI
|
if (!sessions.empty ())
|
||||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
ShowNTCPTransports (s, sessions, "NTCP2");
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||||
if (ssuServer)
|
if (ssuServer)
|
||||||
@@ -598,7 +634,7 @@ namespace http {
|
|||||||
auto sessions6 = ssuServer->GetSessionsV6 ();
|
auto sessions6 = ssuServer->GetSessionsV6 ();
|
||||||
if (!sessions6.empty ())
|
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<p class='content'>";
|
||||||
for (const auto& it: sessions6)
|
for (const auto& it: sessions6)
|
||||||
{
|
{
|
||||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||||
@@ -649,7 +685,7 @@ namespace http {
|
|||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
s << "<b>Streams:</b><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 ())
|
switch (it->GetSocketType ())
|
||||||
{
|
{
|
||||||
@@ -733,8 +769,19 @@ namespace http {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
std::string ConvertTime (uint64_t time)
|
||||||
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
|
{
|
||||||
|
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_Timer (socket->get_io_service ()), m_BufferLen (0),
|
||||||
|
expected_host(hostname)
|
||||||
{
|
{
|
||||||
/* cache options */
|
/* cache options */
|
||||||
i2p::config::GetOption("http.auth", needAuth);
|
i2p::config::GetOption("http.auth", needAuth);
|
||||||
@@ -833,7 +880,28 @@ namespace http {
|
|||||||
SendReply(res, content);
|
SendReply(res, content);
|
||||||
return;
|
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
|
// Html5 head start
|
||||||
ShowPageHead (s);
|
ShowPageHead (s);
|
||||||
if (req.uri.find("page=") != std::string::npos) {
|
if (req.uri.find("page=") != std::string::npos) {
|
||||||
@@ -841,7 +909,7 @@ namespace http {
|
|||||||
} else if (req.uri.find("cmd=") != std::string::npos) {
|
} else if (req.uri.find("cmd=") != std::string::npos) {
|
||||||
HandleCommand (req, res, s);
|
HandleCommand (req, res, s);
|
||||||
} else {
|
} else {
|
||||||
ShowStatus (s, true);
|
ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole);
|
||||||
res.add_header("Refresh", "10");
|
res.add_header("Refresh", "10");
|
||||||
}
|
}
|
||||||
ShowPageTail (s);
|
ShowPageTail (s);
|
||||||
@@ -931,14 +999,14 @@ namespace http {
|
|||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_START) {
|
else if (cmd == HTTP_COMMAND_SHUTDOWN_START) {
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
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;
|
Daemon.gracefulShutdownInterval = 10*60;
|
||||||
#elif defined(WIN32_APP)
|
#elif defined(WIN32_APP)
|
||||||
i2p::win32::GracefulShutdown ();
|
i2p::win32::GracefulShutdown ();
|
||||||
#endif
|
#endif
|
||||||
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
|
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
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;
|
Daemon.gracefulShutdownInterval = 0;
|
||||||
#elif defined(WIN32_APP)
|
#elif defined(WIN32_APP)
|
||||||
i2p::win32::StopGracefulShutdown ();
|
i2p::win32::StopGracefulShutdown ();
|
||||||
@@ -976,7 +1044,8 @@ namespace http {
|
|||||||
|
|
||||||
HTTPServer::HTTPServer (const std::string& address, int port):
|
HTTPServer::HTTPServer (const std::string& address, int port):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,7 +1130,7 @@ namespace http {
|
|||||||
|
|
||||||
void HTTPServer::CreateConnection(std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
|
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 ();
|
conn->Receive ();
|
||||||
}
|
}
|
||||||
} // http
|
} // http
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace http
|
|||||||
{
|
{
|
||||||
public:
|
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 ();
|
void Receive ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -46,6 +46,7 @@ namespace http
|
|||||||
bool needAuth;
|
bool needAuth;
|
||||||
std::string user;
|
std::string user;
|
||||||
std::string pass;
|
std::string pass;
|
||||||
|
std::string expected_host;
|
||||||
|
|
||||||
static std::map<uint32_t, uint32_t> m_Tokens; // token->timestamp in seconds
|
static std::map<uint32_t, uint32_t> m_Tokens; // token->timestamp in seconds
|
||||||
};
|
};
|
||||||
@@ -75,10 +76,12 @@ namespace http
|
|||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::io_service::work m_Work;
|
boost::asio::io_service::work m_Work;
|
||||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
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
|
//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 ShowLocalDestinations (std::stringstream& s);
|
||||||
void ShowLeasesSets(std::stringstream& s);
|
void ShowLeasesSets(std::stringstream& s);
|
||||||
void ShowTunnels (std::stringstream& s);
|
void ShowTunnels (std::stringstream& s);
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ namespace client
|
|||||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||||
|
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||||
|
|
||||||
// I2PControl
|
// I2PControl
|
||||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||||
@@ -92,6 +93,14 @@ namespace client
|
|||||||
// NetworkSetting
|
// NetworkSetting
|
||||||
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
|
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
|
||||||
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlService::OutboundBandwidthLimit;
|
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 ()
|
I2PControlService::~I2PControlService ()
|
||||||
@@ -289,6 +298,13 @@ namespace client
|
|||||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
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,
|
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
||||||
{
|
{
|
||||||
@@ -457,6 +473,7 @@ namespace client
|
|||||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// RouterManager
|
// RouterManager
|
||||||
|
|
||||||
void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||||
@@ -586,5 +603,178 @@ namespace client
|
|||||||
}
|
}
|
||||||
EVP_PKEY_free (pkey);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, int value) const;
|
||||||
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
||||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const;
|
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const;
|
||||||
|
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
|
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 RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||||
void RouterManagerHandler (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 NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||||
|
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||||
|
|
||||||
// I2PControl
|
// I2PControl
|
||||||
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
||||||
@@ -98,6 +100,15 @@ namespace client
|
|||||||
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
||||||
void OutboundBandwidthLimit (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:
|
private:
|
||||||
|
|
||||||
std::string m_Password;
|
std::string m_Password;
|
||||||
@@ -115,6 +126,7 @@ namespace client
|
|||||||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||||
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
|
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
|
||||||
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
||||||
|
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ namespace transport
|
|||||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||||
for (const auto& address : a)
|
for (const auto& address : a)
|
||||||
{
|
{
|
||||||
if (!address->host.is_v6 ())
|
if (!address->host.is_v6 () && address->port)
|
||||||
TryPortMapping (address);
|
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)
|
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
|
||||||
@@ -148,7 +148,7 @@ namespace transport
|
|||||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||||
for (const auto& address : a)
|
for (const auto& address : a)
|
||||||
{
|
{
|
||||||
if (!address->host.is_v6 ())
|
if (!address->host.is_v6 () && address->port)
|
||||||
CloseMapping (address);
|
CloseMapping (address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,11 +138,14 @@ namespace i2p
|
|||||||
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
|
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
if (lockf(pidFH, F_TLOCK, 0) != 0)
|
if (lockf(pidFH, F_TLOCK, 0) != 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
|
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
char pid[10];
|
char pid[10];
|
||||||
sprintf(pid, "%d\n", getpid());
|
sprintf(pid, "%d\n", getpid());
|
||||||
ftruncate(pidFH, 0);
|
ftruncate(pidFH, 0);
|
||||||
|
|||||||
29
debian/changelog
vendored
29
debian/changelog
vendored
@@ -1,3 +1,32 @@
|
|||||||
|
i2pd (2.21.1-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.21.1
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Thu, 22 Oct 2018 16:00:00 +0000
|
||||||
|
|
||||||
|
i2pd (2.21.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.21.0/0.9.37
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Thu, 4 Oct 2018 16:00:00 +0000
|
||||||
|
|
||||||
|
i2pd (2.20.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.20.0/0.9.36
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Thu, 23 Aug 2018 16:00:00 +0000
|
||||||
|
|
||||||
|
i2pd (2.19.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.19.0/0.9.35
|
||||||
|
* update manpage (1)
|
||||||
|
* update docfiles
|
||||||
|
* update build rules
|
||||||
|
* fixes in systemd unit (#1089, #1142, #1154, #1155)
|
||||||
|
* package now building with systemd support
|
||||||
|
|
||||||
|
-- R4SAS <r4sas@i2pmail.org> Tue, 26 Jun 2018 16:27:45 +0000
|
||||||
|
|
||||||
i2pd (2.18.0-1) unstable; urgency=low
|
i2pd (2.18.0-1) unstable; urgency=low
|
||||||
|
|
||||||
* updated to version 2.18.0/0.9.33
|
* updated to version 2.18.0/0.9.33
|
||||||
|
|||||||
10
debian/control
vendored
10
debian/control
vendored
@@ -1,8 +1,8 @@
|
|||||||
Source: i2pd
|
Source: i2pd
|
||||||
Section: net
|
Section: net
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: R4SAS <r4sas@i2pmail.org>
|
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||||
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor
|
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.17.2~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
|
||||||
Standards-Version: 3.9.6
|
Standards-Version: 3.9.6
|
||||||
Homepage: http://i2pd.website/
|
Homepage: http://i2pd.website/
|
||||||
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
||||||
@@ -11,9 +11,8 @@ Vcs-Browser: https://github.com/PurpleI2P/i2pd
|
|||||||
Package: i2pd
|
Package: i2pd
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Pre-Depends: adduser
|
Pre-Depends: adduser
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
|
||||||
Suggests: tor, privoxy, apparmor
|
Description: Full-featured C++ implementation of I2P client.
|
||||||
Description: A full-featured C++ implementation of I2P client.
|
|
||||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
||||||
communications over I2P are anonymous and end-to-end encrypted, participants
|
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.
|
||||||
@@ -25,7 +24,6 @@ Architecture: any
|
|||||||
Priority: extra
|
Priority: extra
|
||||||
Section: debug
|
Section: debug
|
||||||
Depends: i2pd (= ${binary:Version}), ${misc:Depends}
|
Depends: i2pd (= ${binary:Version}), ${misc:Depends}
|
||||||
Suggests: gdb
|
|
||||||
Description: i2pd debugging symbols
|
Description: i2pd debugging symbols
|
||||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
||||||
communications over I2P are anonymous and end-to-end encrypted, participants
|
communications over I2P are anonymous and end-to-end encrypted, participants
|
||||||
|
|||||||
3
debian/docs
vendored
3
debian/docs
vendored
@@ -1 +1,4 @@
|
|||||||
README.md
|
README.md
|
||||||
|
contrib/i2pd.conf
|
||||||
|
contrib/subscriptions.txt
|
||||||
|
contrib/tunnels.conf
|
||||||
|
|||||||
90
debian/i2pd.1
vendored
90
debian/i2pd.1
vendored
@@ -1,22 +1,19 @@
|
|||||||
.TH I2PD "1" "March 31, 2015"
|
.TH "I2PD" "1" "June 20, 2018"
|
||||||
|
|
||||||
.SH NAME
|
.SH "NAME"
|
||||||
i2pd \- Load-balanced unspoofable packet switching network
|
i2pd \- Full-featured C++ implementation of I2P client.
|
||||||
|
.SH "SYNOPSIS"
|
||||||
.SH SYNOPSIS
|
|
||||||
.B i2pd
|
.B i2pd
|
||||||
[\fIOPTION1\fR] [\fIOPTION2\fR]...
|
[\fIOPTION1\fR] [\fIOPTION2\fR]...
|
||||||
|
.SH "DESCRIPTION"
|
||||||
.SH DESCRIPTION
|
|
||||||
i2pd
|
i2pd
|
||||||
is a C++ implementation of the router for the I2P anonymizing network, offering
|
is a C++ implementation of the router for the I2P anonymizing network, offering
|
||||||
a simple layer that identity-sensitive applications can use to securely
|
a simple layer that identity-sensitive applications can use to securely
|
||||||
communicate. All data is wrapped with several layers of encryption, and the
|
communicate. All data is wrapped with several layers of encryption, and the
|
||||||
network is both distributed and dynamic, with no trusted parties.
|
network is both distributed and dynamic, with no trusted parties.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
Any of the configuration options below can be used in the \fBDAEMON_ARGS\fR variable in \fI/etc/default/i2pd\fR.
|
Any of the configuration options below can be used in the \fBDAEMON_ARGS\fR variable in \fI/etc/default/i2pd\fR.
|
||||||
.BR
|
.SH "OPTIONS"
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-help\fR
|
\fB\-\-help\fR
|
||||||
Show available options.
|
Show available options.
|
||||||
@@ -36,11 +33,14 @@ Where to write pidfile (don\'t write by default)
|
|||||||
\fB\-\-log=\fR
|
\fB\-\-log=\fR
|
||||||
Logs destination: \fIstdout\fR, \fIfile\fR, \fIsyslog\fR (\fIstdout\fR if not set, \fIfile\fR - otherwise, for compatibility)
|
Logs destination: \fIstdout\fR, \fIfile\fR, \fIsyslog\fR (\fIstdout\fR if not set, \fIfile\fR - otherwise, for compatibility)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-logfile\fR
|
\fB\-\-logfile=\fR
|
||||||
Path to logfile (default - autodetect)
|
Path to logfile (default - autodetect)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-loglevel=\fR
|
\fB\-\-loglevel=\fR
|
||||||
Log messages above this level (\fIdebug\fR, \fBinfo\fR, \fIwarn\fR, \fIerror\fR)
|
Log messages above this level (\fIdebug\fR, \fBinfo\fR, \fIwarn\fR, \fIerror\fR, \fInone\fR)
|
||||||
|
.TP
|
||||||
|
\fB\-\-logclftime\fR
|
||||||
|
Log messages with full CLF-formatted date and time (\fIdisabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-datadir=\fR
|
\fB\-\-datadir=\fR
|
||||||
Path to storage of i2pd data (RI, keys, peer profiles, ...)
|
Path to storage of i2pd data (RI, keys, peer profiles, ...)
|
||||||
@@ -51,35 +51,58 @@ The external IP address
|
|||||||
\fB\-\-port=\fR
|
\fB\-\-port=\fR
|
||||||
The port to listen on for incoming connections
|
The port to listen on for incoming connections
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-daemon\fR
|
\fB\-\-ifname=\fR
|
||||||
Router will go to background after start
|
The network interface to bind to
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-service\fR
|
\fB\-\-ifname4=\fR
|
||||||
Router will use system folders like \fI/var/lib/i2pd\fR
|
The network interface to bind to for IPv4 connections
|
||||||
|
.TP
|
||||||
|
\fB\-\-ifname6=\fR
|
||||||
|
The network interface to bind to for IPv6 connections
|
||||||
|
.TP
|
||||||
|
\fB\-\-ipv4=\fR
|
||||||
|
Enable communication through ipv6 (\fIenabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-ipv6\fR
|
\fB\-\-ipv6\fR
|
||||||
Enable communication through ipv6. false by default
|
Enable communication through ipv6 (\fIdisabled\fR by default)
|
||||||
|
.TP
|
||||||
|
\fB\-\-ntcp=\fR
|
||||||
|
Enable usage of NTCP transport (\fIenabled\fR by default)
|
||||||
|
.TP
|
||||||
|
\fB\-\-ntcpproxy=\fR
|
||||||
|
Set proxy URL for NTCP transport
|
||||||
|
.TP
|
||||||
|
\fB\-\-ssu=\fR
|
||||||
|
Enable usage of SSU transport (\fIenabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-notransit\fR
|
\fB\-\-notransit\fR
|
||||||
Router will not accept transit tunnels at startup
|
Router will not accept transit tunnels at startup (\fIdisabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-floodfill\fR
|
\fB\-\-floodfill\fR
|
||||||
Router will be floodfill
|
Router will be floodfill (\fIdisabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-bandwidth=\fR
|
\fB\-\-bandwidth=\fR
|
||||||
Bandwidth limit: integer in KBps or letter aliases: \fIL (32KBps)\fR, O (256), P (2048), X (>9000)
|
Bandwidth limit: integer in KBps or letter aliases: \fBL (32KBps)\fR, \fIO (256)\fR, \fIP (2048)\fR, \fIX (>9000)\fR
|
||||||
|
.TP
|
||||||
|
\fB\-\-share=\fR
|
||||||
|
Limit of transit traffic from max bandwidth in percents. (default: 100)
|
||||||
|
.TP
|
||||||
|
\fB\-\-daemon\fR
|
||||||
|
Router will go to background after start (\fIdisabled\fR by default)
|
||||||
|
.TP
|
||||||
|
\fB\-\-service\fR
|
||||||
|
Router will use system folders like \fI/var/lib/i2pd\fR (\fIdisabled\fR by default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-family=\fR
|
\fB\-\-family=\fR
|
||||||
Name of a family, router belongs to.
|
Name of a family, router belongs to.
|
||||||
.PP
|
.PP
|
||||||
See service-specific parameters in example config file \fIcontrib/i2pd.conf\fR
|
Switches, which enabled by default (like \fB\-\-ssu\fR, \fB\-\-ntcp\fR, etc.), can be disabled in config file.
|
||||||
|
.RE
|
||||||
.SH FILES
|
See service-specific parameters in example config file \fI/usr/share/doc/i2pd/i2pd.conf.gz\fR
|
||||||
.PP
|
.SH "FILES"
|
||||||
/etc/i2pd/i2pd.conf, /etc/i2pd/tunnels.conf, /etc/default/i2pd
|
/etc/i2pd/i2pd.conf, /etc/i2pd/tunnels.conf, /etc/default/i2pd
|
||||||
.RS 4
|
.RS 4
|
||||||
i2pd configuration files (when running as a system service)
|
i2pd configuration files (when running as a system service)
|
||||||
|
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
/var/lib/i2pd/
|
/var/lib/i2pd/
|
||||||
@@ -90,16 +113,15 @@ i2pd profile directory (when running as a system service, see \fB\-\-service\fR
|
|||||||
$HOME/.i2pd/
|
$HOME/.i2pd/
|
||||||
.RS 4
|
.RS 4
|
||||||
i2pd profile directory (when running as a normal user)
|
i2pd profile directory (when running as a normal user)
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
Documentation at Read the Docs: \m[blue]\fBhttps://i2pd\&.readthedocs\&.io/en/latest/\fR\m[]
|
||||||
|
.SH "AUTHOR"
|
||||||
|
This manual page was written by kytv <\m[blue]\fBkillyourtv@i2pmail\&.org\fR\m[]> for the Debian system (but may be used by others).
|
||||||
.RE
|
.RE
|
||||||
|
Updated by hagen <\m[blue]\fBhagen@i2pmail\&.org\fR\m[]> in 2016.
|
||||||
|
.RE
|
||||||
|
Updated by R4SAS <\m[blue]\fBr4sas@i2pmail\&.org\fR\m[]> in 2018.
|
||||||
.PP
|
.PP
|
||||||
/usr/share/doc/i2pd/examples/hosts.txt.gz
|
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation.
|
||||||
.RS 4
|
.RE
|
||||||
default I2P hosts file
|
|
||||||
.SH AUTHOR
|
|
||||||
This manual page was written by kytv <killyourtv@i2pmail.org> for the Debian system (but may be used by others).
|
|
||||||
.PP
|
|
||||||
Updated by hagen <hagen@i2pmail.org> in 2016.
|
|
||||||
.PP
|
|
||||||
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation
|
|
||||||
.BR
|
|
||||||
On Debian systems, the complete text of the GNU General Public License can be found in \fI/usr/share/common-licenses/GPL\fR
|
On Debian systems, the complete text of the GNU General Public License can be found in \fI/usr/share/common-licenses/GPL\fR
|
||||||
|
|||||||
1
debian/i2pd.service
vendored
Symbolic link
1
debian/i2pd.service
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../contrib/debian/i2pd.service
|
||||||
1
debian/i2pd.tmpfile
vendored
Symbolic link
1
debian/i2pd.tmpfile
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../contrib/debian/i2pd.tmpfile
|
||||||
4
debian/patches/01-tune-build-opts.patch
vendored
4
debian/patches/01-tune-build-opts.patch
vendored
@@ -13,5 +13,5 @@ index bdadfe0..2f71eec 100644
|
|||||||
USE_STATIC := no
|
USE_STATIC := no
|
||||||
USE_MESHNET := no
|
USE_MESHNET := no
|
||||||
USE_UPNP := no
|
USE_UPNP := no
|
||||||
|
DEBUG := yes
|
||||||
ifeq ($(WEBSOCKETS),1)
|
|
||||||
|
|||||||
25
debian/patches/fix-#1210
vendored
Normal file
25
debian/patches/fix-#1210
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Description: fix #1210
|
||||||
|
Disables two options, which not presented in old systemd versions
|
||||||
|
Author: r4sas <r4sas@i2pmail.org>
|
||||||
|
|
||||||
|
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
|
||||||
|
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||||
|
Last-Update: 2018-08-25
|
||||||
|
|
||||||
|
--- i2pd-2.20.0.orig/contrib/i2pd.service
|
||||||
|
+++ i2pd-2.20.0/contrib/i2pd.service
|
||||||
|
@@ -6,10 +6,10 @@ After=network.target
|
||||||
|
[Service]
|
||||||
|
User=i2pd
|
||||||
|
Group=i2pd
|
||||||
|
-RuntimeDirectory=i2pd
|
||||||
|
-RuntimeDirectoryMode=0700
|
||||||
|
-LogsDirectory=i2pd
|
||||||
|
-LogsDirectoryMode=0700
|
||||||
|
+#RuntimeDirectory=i2pd
|
||||||
|
+#RuntimeDirectoryMode=0700
|
||||||
|
+#LogsDirectory=i2pd
|
||||||
|
+#LogsDirectoryMode=0700
|
||||||
|
Type=forking
|
||||||
|
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
1
debian/patches/series
vendored
1
debian/patches/series
vendored
@@ -1 +1,2 @@
|
|||||||
01-tune-build-opts.patch
|
01-tune-build-opts.patch
|
||||||
|
fix-#1210
|
||||||
|
|||||||
15
debian/rules
vendored
15
debian/rules
vendored
@@ -5,17 +5,18 @@
|
|||||||
#export DH_VERBOSE=1
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
|
DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
|
||||||
DPKG_EXPORT_BUILDFLAGS = 1
|
#DPKG_EXPORT_BUILDFLAGS = 1
|
||||||
include /usr/share/dpkg/buildflags.mk
|
#include /usr/share/dpkg/buildflags.mk
|
||||||
CXXFLAGS+=$(CPPFLAGS)
|
#CXXFLAGS+=$(CPPFLAGS)
|
||||||
PREFIX=/usr
|
#PREFIX=/usr
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@ --parallel
|
dh $@ --parallel
|
||||||
dh_apparmor --profile-name=usr.sbin.i2pd -pi2pd
|
# dh_apparmor --profile-name=usr.sbin.i2pd -pi2pd
|
||||||
|
|
||||||
override_dh_strip:
|
override_dh_strip:
|
||||||
dh_strip --dbg-package=i2pd-dbg
|
dh_strip --dbg-package=i2pd-dbg
|
||||||
|
|
||||||
override_dh_shlibdeps:
|
## uncomment this if you have "missing info" problem when building package
|
||||||
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
#override_dh_shlibdeps:
|
||||||
|
# dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
||||||
|
|||||||
@@ -1094,7 +1094,7 @@ HTML_STYLESHEET =
|
|||||||
# cascading style sheets that are included after the standard style sheets
|
# cascading style sheets that are included after the standard style sheets
|
||||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||||
# standard style sheet and is therefor more robust against future updates.
|
# standard style sheet and is therefore more robust against future updates.
|
||||||
# Doxygen will copy the style sheet files to the output directory.
|
# Doxygen will copy the style sheet files to the output directory.
|
||||||
# Note: The order of the extra stylesheet files is of importance (e.g. the last
|
# Note: The order of the extra stylesheet files is of importance (e.g. the last
|
||||||
# stylesheet in the list overrules the setting of the previous ones in the
|
# stylesheet in the list overrules the setting of the previous ones in the
|
||||||
@@ -1637,7 +1637,7 @@ EXTRA_PACKAGES =
|
|||||||
# Note: Only use a user-defined header if you know what you are doing! The
|
# Note: Only use a user-defined header if you know what you are doing! The
|
||||||
# following commands have a special meaning inside the header: $title,
|
# following commands have a special meaning inside the header: $title,
|
||||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
|
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty string,
|
||||||
# for the replacement values of the other commands the user is referred to
|
# for the replacement values of the other commands the user is referred to
|
||||||
# HTML_HEADER.
|
# HTML_HEADER.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
ARGS=""
|
|
||||||
if [ "${ENABLE_IPV6}" != "" ]; then
|
|
||||||
ARGS="${ARGS} –ipv6"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${LOGLEVEL}" != "" ]; then
|
|
||||||
ARGS="${ARGS} –loglevel=${LOGLEVEL}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${ENABLE_AUTH}" != "" ]; then
|
|
||||||
ARGS="${ARGS} –http.auth"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# To make ports exposeable
|
|
||||||
DEFAULT_ARGS=" –http.address=0.0.0.0 –httpproxy.address=0.0.0.0 -socksproxy.address=0.0.0.0 –sam.address=0.0.0.0 –bob.address=0.0.0.0 –i2cp.address=0.0.0.0 –i2pcontrol.port=0.0.0.0 –upnp.enabled=false -service "
|
|
||||||
|
|
||||||
mkdir -p /var/lib/i2pd && chown -R i2pd:nobody /var/lib/i2pd && chmod u+rw /var/lib/i2pd
|
|
||||||
|
|
||||||
gosu i2pd i2pd $DEFAULT_ARGS $ARGS
|
|
||||||
|
|
||||||
|
|
||||||
@@ -210,6 +210,21 @@ namespace data
|
|||||||
return 4*d.quot;
|
return 4*d.quot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ToBase64Standard (const std::string& in)
|
||||||
|
{
|
||||||
|
auto len = Base64EncodingBufferSize (in.length ());
|
||||||
|
char * str = new char[len+1];
|
||||||
|
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
|
||||||
|
str[l] = 0;
|
||||||
|
// replace '-' by '+' and '~' by '/'
|
||||||
|
for (size_t i = 0; i < l; i++)
|
||||||
|
if (str[i] == '-') str[i] = '+';
|
||||||
|
else if (str[i] == '~') str[i] = '/';
|
||||||
|
std::string s(str);
|
||||||
|
delete[] str;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* iT64
|
* iT64
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ namespace data {
|
|||||||
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
|
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
|
||||||
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||||
*/
|
*/
|
||||||
size_t Base64EncodingBufferSize(const size_t input_size);
|
size_t Base64EncodingBufferSize(const size_t input_size);
|
||||||
|
|
||||||
|
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|||||||
55
libi2pd/CPU.cpp
Normal file
55
libi2pd/CPU.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "CPU.h"
|
||||||
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
#include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
#ifndef bit_AES
|
||||||
|
#define bit_AES (1 << 25)
|
||||||
|
#endif
|
||||||
|
#ifndef bit_AVX
|
||||||
|
#define bit_AVX (1 << 28)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace cpu
|
||||||
|
{
|
||||||
|
bool aesni = false;
|
||||||
|
bool avx = false;
|
||||||
|
|
||||||
|
void Detect()
|
||||||
|
{
|
||||||
|
#if defined(__AES__) || defined(__AVX__)
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
int info[4];
|
||||||
|
__cpuid(0, info[0], info[1], info[2], info[3]);
|
||||||
|
if (info[0] >= 0x00000001) {
|
||||||
|
__cpuid(0x00000001, info[0], info[1], info[2], info[3]);
|
||||||
|
#ifdef __AES__
|
||||||
|
aesni = info[2] & bit_AES; // AESNI
|
||||||
|
#endif // __AES__
|
||||||
|
#ifdef __AVX__
|
||||||
|
avx = info[2] & bit_AVX; // AVX
|
||||||
|
#endif // __AVX__
|
||||||
|
}
|
||||||
|
#endif // defined(__x86_64__) || defined(__i386__)
|
||||||
|
|
||||||
|
#ifdef __AES__
|
||||||
|
if(aesni)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "AESNI enabled");
|
||||||
|
}
|
||||||
|
#endif // __AES__
|
||||||
|
#ifdef __AVX__
|
||||||
|
if(avx)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "AVX enabled");
|
||||||
|
}
|
||||||
|
#endif // __AVX__
|
||||||
|
#endif // defined(__AES__) || defined(__AVX__)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
libi2pd/CPU.h
Normal file
15
libi2pd/CPU.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef LIBI2PD_CPU_H
|
||||||
|
#define LIBI2PD_CPU_H
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace cpu
|
||||||
|
{
|
||||||
|
extern bool aesni;
|
||||||
|
extern bool avx;
|
||||||
|
|
||||||
|
void Detect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
147
libi2pd/ChaCha20.cpp
Normal file
147
libi2pd/ChaCha20.cpp
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#include "ChaCha20.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License
|
||||||
|
Copyright 2018 Jeff Becker
|
||||||
|
|
||||||
|
Kovri go write your own code
|
||||||
|
|
||||||
|
*/
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
namespace chacha
|
||||||
|
{
|
||||||
|
constexpr int rounds = 20;
|
||||||
|
constexpr std::size_t blocksize = 64;
|
||||||
|
|
||||||
|
void u32t8le(uint32_t v, uint8_t * p)
|
||||||
|
{
|
||||||
|
p[0] = v & 0xff;
|
||||||
|
p[1] = (v >> 8) & 0xff;
|
||||||
|
p[2] = (v >> 16) & 0xff;
|
||||||
|
p[3] = (v >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t u8t32le(const uint8_t * p)
|
||||||
|
{
|
||||||
|
uint32_t value = p[3];
|
||||||
|
|
||||||
|
value = (value << 8) | p[2];
|
||||||
|
value = (value << 8) | p[1];
|
||||||
|
value = (value << 8) | p[0];
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rotl32(uint32_t x, int n)
|
||||||
|
{
|
||||||
|
return x << n | (x >> (-n & 31));
|
||||||
|
}
|
||||||
|
|
||||||
|
void quarterround(uint32_t *x, int a, int b, int c, int d)
|
||||||
|
{
|
||||||
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
|
||||||
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
|
||||||
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
|
||||||
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State_t
|
||||||
|
{
|
||||||
|
State_t() {};
|
||||||
|
State_t(State_t &&) = delete;
|
||||||
|
|
||||||
|
State_t & operator += (const State_t & other)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
data[i] += other.data[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Copy(const State_t & other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
||||||
|
}
|
||||||
|
uint32_t data[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Block_t
|
||||||
|
{
|
||||||
|
Block_t() {};
|
||||||
|
Block_t(Block_t &&) = delete;
|
||||||
|
|
||||||
|
uint8_t data[blocksize];
|
||||||
|
|
||||||
|
void operator << (const State_t & st)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
u32t8le(st.data[i], data + (i << 2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void block(const State_t &input, Block_t & block, int rounds)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
State_t x;
|
||||||
|
x.Copy(input);
|
||||||
|
|
||||||
|
for (i = rounds; i > 0; i -= 2)
|
||||||
|
{
|
||||||
|
quarterround(x.data, 0, 4, 8, 12);
|
||||||
|
quarterround(x.data, 1, 5, 9, 13);
|
||||||
|
quarterround(x.data, 2, 6, 10, 14);
|
||||||
|
quarterround(x.data, 3, 7, 11, 15);
|
||||||
|
quarterround(x.data, 0, 5, 10, 15);
|
||||||
|
quarterround(x.data, 1, 6, 11, 12);
|
||||||
|
quarterround(x.data, 2, 7, 8, 13);
|
||||||
|
quarterround(x.data, 3, 4, 9, 14);
|
||||||
|
}
|
||||||
|
x += input;
|
||||||
|
block << x;
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace chacha
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
{
|
||||||
|
chacha::State_t state;
|
||||||
|
chacha::Block_t block;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
state.data[0] = 0x61707865;
|
||||||
|
state.data[1] = 0x3320646e;
|
||||||
|
state.data[2] = 0x79622d32;
|
||||||
|
state.data[3] = 0x6b206574;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
||||||
|
|
||||||
|
|
||||||
|
state.data[12] = counter;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < sz; i += chacha::blocksize)
|
||||||
|
{
|
||||||
|
chacha::block(state, block, chacha::rounds);
|
||||||
|
state.data[12]++;
|
||||||
|
for (j = i; j < i + chacha::blocksize; j++)
|
||||||
|
{
|
||||||
|
if (j >= sz) break;
|
||||||
|
buf[j] ^= block.data[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
26
libi2pd/ChaCha20.h
Normal file
26
libi2pd/ChaCha20.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
This code is licensed under the MCGSI Public License
|
||||||
|
Copyright 2018 Jeff Becker
|
||||||
|
|
||||||
|
Kovri go write your own code
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef LIBI2PD_CHACHA20_H
|
||||||
|
#define LIBI2PD_CHACHA20_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
const std::size_t CHACHA20_KEY_BYTES = 32;
|
||||||
|
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
||||||
|
|
||||||
|
/** encrypt buf in place with chacha20 */
|
||||||
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -34,35 +34,36 @@ namespace config {
|
|||||||
("help", "Show this message")
|
("help", "Show this message")
|
||||||
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
|
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
|
||||||
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
|
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
|
||||||
|
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
|
||||||
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
||||||
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
|
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
|
||||||
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
|
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
|
||||||
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
|
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error, none)")
|
||||||
("logclftime", value<bool>()->default_value(false), "Write full CLF-formatted date and time to log (default: write only time)")
|
("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)")
|
||||||
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
|
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
|
||||||
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
|
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
|
||||||
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
|
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
|
||||||
("ifname", value<std::string>()->default_value(""), "Network interface to bind to")
|
("ifname", value<std::string>()->default_value(""), "Network interface to bind to")
|
||||||
("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4")
|
("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4")
|
||||||
("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6")
|
("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6")
|
||||||
("nat", value<bool>()->default_value(true), "Should we assume we are behind NAT?")
|
("nat", value<bool>()->default_value(true), "Should we assume we are behind NAT? (default: enabled)")
|
||||||
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
|
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
|
||||||
("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4")
|
("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4 (default: enabled)")
|
||||||
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
|
("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)")
|
||||||
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
|
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
|
||||||
("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start")
|
("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)")
|
||||||
("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'")
|
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
|
||||||
("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
|
("notransit", bool_switch()->default_value(false), "Router will not accept transit tunnels at startup (default: disabled)")
|
||||||
("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
|
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
||||||
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
||||||
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100")
|
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
|
||||||
("ntcp", value<bool>()->default_value(true), "Enable NTCP transport")
|
("ntcp", value<bool>()->default_value(true), "Enable NTCP transport (default: enabled)")
|
||||||
("ssu", value<bool>()->default_value(true), "Enable SSU transport")
|
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||||
("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
|
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||||
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something
|
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -73,16 +74,19 @@ namespace config {
|
|||||||
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
|
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
|
||||||
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabalistic backoff with ntcp sessions (default: use system limit)")
|
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabalistic backoff with ntcp sessions (default: use system limit)")
|
||||||
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
|
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
|
||||||
|
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description httpserver("HTTP Server options");
|
options_description httpserver("HTTP Server options");
|
||||||
httpserver.add_options()
|
httpserver.add_options()
|
||||||
("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole")
|
("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole")
|
||||||
("http.address", value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address")
|
("http.address", value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address")
|
||||||
("http.port", value<uint16_t>()->default_value(7070), "Webconsole listen port")
|
("http.port", value<uint16_t>()->default_value(7070), "Webconsole listen port")
|
||||||
("http.auth", value<bool>()->default_value(false), "Enable Basic HTTP auth for webconsole")
|
("http.auth", value<bool>()->default_value(false), "Enable Basic HTTP auth for webconsole")
|
||||||
("http.user", value<std::string>()->default_value("i2pd"), "Username for basic auth")
|
("http.user", value<std::string>()->default_value("i2pd"), "Username for basic auth")
|
||||||
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
|
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
|
||||||
|
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
|
||||||
|
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description httpproxy("HTTP Proxy options");
|
options_description httpproxy("HTTP Proxy options");
|
||||||
@@ -188,7 +192,7 @@ namespace config {
|
|||||||
// "https://uk.reseed.i2p2.no:444/," // mamoth's shit
|
// "https://uk.reseed.i2p2.no:444/," // mamoth's shit
|
||||||
"https://i2p-0.manas.ca:8443/,"
|
"https://i2p-0.manas.ca:8443/,"
|
||||||
"https://download.xxlspeed.com/,"
|
"https://download.xxlspeed.com/,"
|
||||||
"https://reseed-ru.lngserv.ru/,"
|
"https://reseed-fr.i2pd.xyz/,"
|
||||||
"https://reseed.atomike.ninja/,"
|
"https://reseed.atomike.ninja/,"
|
||||||
"https://reseed.memcpy.io/,"
|
"https://reseed.memcpy.io/,"
|
||||||
"https://reseed.onion.im/,"
|
"https://reseed.onion.im/,"
|
||||||
@@ -228,6 +232,13 @@ namespace config {
|
|||||||
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
|
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
options_description ntcp2("NTCP2 Options");
|
||||||
|
ntcp2.add_options()
|
||||||
|
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
|
||||||
|
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
|
||||||
|
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
|
||||||
|
;
|
||||||
|
|
||||||
m_OptionsDesc
|
m_OptionsDesc
|
||||||
.add(general)
|
.add(general)
|
||||||
.add(limits)
|
.add(limits)
|
||||||
@@ -245,6 +256,7 @@ namespace config {
|
|||||||
.add(trust)
|
.add(trust)
|
||||||
.add(websocket)
|
.add(websocket)
|
||||||
.add(exploratory)
|
.add(exploratory)
|
||||||
|
.add(ntcp2)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,4 +339,3 @@ namespace config {
|
|||||||
|
|
||||||
} // namespace config
|
} // namespace config
|
||||||
} // namespace i2p
|
} // namespace i2p
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,14 @@
|
|||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include "TunnelBase.h"
|
#include "TunnelBase.h"
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include "Log.h"
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
|
#include "ChaCha20.h"
|
||||||
|
#include "Poly1305.h"
|
||||||
|
#endif
|
||||||
|
#include "Ed25519.h"
|
||||||
|
#include "I2PEndian.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@@ -271,6 +277,70 @@ namespace crypto
|
|||||||
BN_free (pk);
|
BN_free (pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// x25519
|
||||||
|
X25519Keys::X25519Keys ()
|
||||||
|
{
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
|
||||||
|
#else
|
||||||
|
m_Ctx = BN_CTX_new ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
||||||
|
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||||
|
memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
|
||||||
|
#else
|
||||||
|
memcpy (m_PrivateKey, priv, 32);
|
||||||
|
memcpy (m_PublicKey, pub, 32);
|
||||||
|
m_Ctx = BN_CTX_new ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
X25519Keys::~X25519Keys ()
|
||||||
|
{
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
EVP_PKEY_CTX_free (m_Ctx);
|
||||||
|
if (m_Pkey)
|
||||||
|
EVP_PKEY_free (m_Pkey);
|
||||||
|
#else
|
||||||
|
BN_CTX_free (m_Ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void X25519Keys::GenerateKeys ()
|
||||||
|
{
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
m_Pkey = nullptr;
|
||||||
|
EVP_PKEY_keygen_init (m_Ctx);
|
||||||
|
EVP_PKEY_keygen (m_Ctx, &m_Pkey);
|
||||||
|
EVP_PKEY_CTX_free (m_Ctx);
|
||||||
|
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
|
||||||
|
size_t len = 32;
|
||||||
|
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
||||||
|
#else
|
||||||
|
RAND_bytes (m_PrivateKey, 32);
|
||||||
|
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
|
||||||
|
{
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
EVP_PKEY_derive_init (m_Ctx);
|
||||||
|
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
|
||||||
|
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
|
||||||
|
size_t len = 32;
|
||||||
|
EVP_PKEY_derive (m_Ctx, shared, &len);
|
||||||
|
EVP_PKEY_free (pkey);
|
||||||
|
#else
|
||||||
|
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
@@ -373,7 +443,7 @@ namespace crypto
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ECIES
|
// ECIES
|
||||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
BIGNUM * q = BN_CTX_get (ctx);
|
BIGNUM * q = BN_CTX_get (ctx);
|
||||||
@@ -386,10 +456,19 @@ namespace crypto
|
|||||||
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
|
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
|
||||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||||
encrypted[0] = 0;
|
if (zeroPadding)
|
||||||
bn2buf (x, encrypted + 1, len);
|
{
|
||||||
bn2buf (y, encrypted + 1 + len, len);
|
encrypted[0] = 0;
|
||||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
bn2buf (x, encrypted + 1, len);
|
||||||
|
bn2buf (y, encrypted + 1 + len, len);
|
||||||
|
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bn2buf (x, encrypted, len);
|
||||||
|
bn2buf (y, encrypted + len, len);
|
||||||
|
RAND_bytes (encrypted + 2*len, 256 - 2*len);
|
||||||
|
}
|
||||||
// ecryption key and iv
|
// ecryption key and iv
|
||||||
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
|
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
|
||||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||||
@@ -403,16 +482,21 @@ namespace crypto
|
|||||||
memcpy (m+33, data, 222);
|
memcpy (m+33, data, 222);
|
||||||
SHA256 (m+33, 222, m+1);
|
SHA256 (m+33, 222, m+1);
|
||||||
// encrypt
|
// encrypt
|
||||||
encrypted[257] = 0;
|
|
||||||
CBCEncryption encryption;
|
CBCEncryption encryption;
|
||||||
encryption.SetKey (shared);
|
encryption.SetKey (shared);
|
||||||
encryption.SetIV (iv);
|
encryption.SetIV (iv);
|
||||||
encryption.Encrypt (m, 256, encrypted + 258);
|
if (zeroPadding)
|
||||||
|
{
|
||||||
|
encrypted[257] = 0;
|
||||||
|
encryption.Encrypt (m, 256, encrypted + 258);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
encryption.Encrypt (m, 256, encrypted + 256);
|
||||||
EC_POINT_free (p);
|
EC_POINT_free (p);
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
@@ -421,8 +505,16 @@ namespace crypto
|
|||||||
int len = BN_num_bytes (q);
|
int len = BN_num_bytes (q);
|
||||||
// point for shared secret
|
// point for shared secret
|
||||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||||
BN_bin2bn (encrypted + 1, len, x);
|
if (zeroPadding)
|
||||||
BN_bin2bn (encrypted + 1 + len, len, y);
|
{
|
||||||
|
BN_bin2bn (encrypted + 1, len, x);
|
||||||
|
BN_bin2bn (encrypted + 1 + len, len, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BN_bin2bn (encrypted, len, x);
|
||||||
|
BN_bin2bn (encrypted + len, len, y);
|
||||||
|
}
|
||||||
auto p = EC_POINT_new (curve);
|
auto p = EC_POINT_new (curve);
|
||||||
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
|
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
|
||||||
{
|
{
|
||||||
@@ -439,7 +531,10 @@ namespace crypto
|
|||||||
CBCDecryption decryption;
|
CBCDecryption decryption;
|
||||||
decryption.SetKey (shared);
|
decryption.SetKey (shared);
|
||||||
decryption.SetIV (iv);
|
decryption.SetIV (iv);
|
||||||
decryption.Decrypt (encrypted + 258, 256, m);
|
if (zeroPadding)
|
||||||
|
decryption.Decrypt (encrypted + 258, 256, m);
|
||||||
|
else
|
||||||
|
decryption.Decrypt (encrypted + 256, 256, m);
|
||||||
// verify and copy
|
// verify and copy
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
SHA256 (m + 33, 222, hash);
|
SHA256 (m + 33, 222, hash);
|
||||||
@@ -479,10 +574,9 @@ namespace crypto
|
|||||||
const uint64_t IPAD = 0x3636363636363636;
|
const uint64_t IPAD = 0x3636363636363636;
|
||||||
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
|
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
|
||||||
|
|
||||||
#if defined(__AVX__)
|
|
||||||
static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD };
|
static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD };
|
||||||
static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD };
|
static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD };
|
||||||
#endif
|
|
||||||
|
|
||||||
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
|
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
|
||||||
// key is 32 bytes
|
// key is 32 bytes
|
||||||
@@ -491,47 +585,52 @@ namespace crypto
|
|||||||
{
|
{
|
||||||
uint64_t buf[256];
|
uint64_t buf[256];
|
||||||
uint64_t hash[12]; // 96 bytes
|
uint64_t hash[12]; // 96 bytes
|
||||||
#if defined(__AVX__) // for AVX
|
#ifdef __AVX__
|
||||||
__asm__
|
if(i2p::cpu::avx)
|
||||||
(
|
{
|
||||||
"vmovups %[key], %%ymm0 \n"
|
__asm__
|
||||||
"vmovups %[ipad], %%ymm1 \n"
|
(
|
||||||
"vmovups %%ymm1, 32(%[buf]) \n"
|
"vmovups %[key], %%ymm0 \n"
|
||||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
"vmovups %[ipad], %%ymm1 \n"
|
||||||
"vmovups %%ymm1, (%[buf]) \n"
|
"vmovups %%ymm1, 32(%[buf]) \n"
|
||||||
"vmovups %[opad], %%ymm1 \n"
|
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||||
"vmovups %%ymm1, 32(%[hash]) \n"
|
"vmovups %%ymm1, (%[buf]) \n"
|
||||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
"vmovups %[opad], %%ymm1 \n"
|
||||||
"vmovups %%ymm1, (%[hash]) \n"
|
"vmovups %%ymm1, 32(%[hash]) \n"
|
||||||
"vzeroall \n" // end of AVX
|
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||||
"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
|
"vmovups %%ymm1, (%[hash]) \n"
|
||||||
:
|
"vzeroall \n" // end of AVX
|
||||||
: [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads),
|
"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
|
||||||
[buf]"r"(buf), [hash]"r"(hash)
|
:
|
||||||
: "memory", "%xmm0" // TODO: change to %ymm0 later
|
: [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads),
|
||||||
);
|
[buf]"r"(buf), [hash]"r"(hash)
|
||||||
#else
|
: "memory", "%xmm0" // TODO: change to %ymm0 later
|
||||||
// ikeypad
|
);
|
||||||
buf[0] = key.GetLL ()[0] ^ IPAD;
|
}
|
||||||
buf[1] = key.GetLL ()[1] ^ IPAD;
|
else
|
||||||
buf[2] = key.GetLL ()[2] ^ IPAD;
|
|
||||||
buf[3] = key.GetLL ()[3] ^ IPAD;
|
|
||||||
buf[4] = IPAD;
|
|
||||||
buf[5] = IPAD;
|
|
||||||
buf[6] = IPAD;
|
|
||||||
buf[7] = IPAD;
|
|
||||||
// okeypad
|
|
||||||
hash[0] = key.GetLL ()[0] ^ OPAD;
|
|
||||||
hash[1] = key.GetLL ()[1] ^ OPAD;
|
|
||||||
hash[2] = key.GetLL ()[2] ^ OPAD;
|
|
||||||
hash[3] = key.GetLL ()[3] ^ OPAD;
|
|
||||||
hash[4] = OPAD;
|
|
||||||
hash[5] = OPAD;
|
|
||||||
hash[6] = OPAD;
|
|
||||||
hash[7] = OPAD;
|
|
||||||
// fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
|
|
||||||
memset (hash + 10, 0, 16);
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
// ikeypad
|
||||||
|
buf[0] = key.GetLL ()[0] ^ IPAD;
|
||||||
|
buf[1] = key.GetLL ()[1] ^ IPAD;
|
||||||
|
buf[2] = key.GetLL ()[2] ^ IPAD;
|
||||||
|
buf[3] = key.GetLL ()[3] ^ IPAD;
|
||||||
|
buf[4] = IPAD;
|
||||||
|
buf[5] = IPAD;
|
||||||
|
buf[6] = IPAD;
|
||||||
|
buf[7] = IPAD;
|
||||||
|
// okeypad
|
||||||
|
hash[0] = key.GetLL ()[0] ^ OPAD;
|
||||||
|
hash[1] = key.GetLL ()[1] ^ OPAD;
|
||||||
|
hash[2] = key.GetLL ()[2] ^ OPAD;
|
||||||
|
hash[3] = key.GetLL ()[3] ^ OPAD;
|
||||||
|
hash[4] = OPAD;
|
||||||
|
hash[5] = OPAD;
|
||||||
|
hash[6] = OPAD;
|
||||||
|
hash[7] = OPAD;
|
||||||
|
// fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
|
||||||
|
memset (hash + 10, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
// concatenate with msg
|
// concatenate with msg
|
||||||
memcpy (buf + 8, msg, len);
|
memcpy (buf + 8, msg, len);
|
||||||
@@ -543,7 +642,13 @@ namespace crypto
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AES
|
// AES
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
|
#ifdef ARM64AES
|
||||||
|
void init_aesenc(void){
|
||||||
|
// TODO: Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define KeyExpansion256(round0,round1) \
|
#define KeyExpansion256(round0,round1) \
|
||||||
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
|
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
|
||||||
@@ -567,7 +672,9 @@ namespace crypto
|
|||||||
"pxor %%xmm4, %%xmm3 \n" \
|
"pxor %%xmm4, %%xmm3 \n" \
|
||||||
"pxor %%xmm2, %%xmm3 \n" \
|
"pxor %%xmm2, %%xmm3 \n" \
|
||||||
"movaps %%xmm3, "#round1"(%[sched]) \n"
|
"movaps %%xmm3, "#round1"(%[sched]) \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __AES__
|
||||||
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
|
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
|
||||||
{
|
{
|
||||||
__asm__
|
__asm__
|
||||||
@@ -605,7 +712,10 @@ namespace crypto
|
|||||||
: "%xmm1", "%xmm2", "%xmm3", "%xmm4", "memory" // clogged
|
: "%xmm1", "%xmm2", "%xmm3", "%xmm4", "memory" // clogged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __AES__
|
||||||
#define EncryptAES256(sched) \
|
#define EncryptAES256(sched) \
|
||||||
"pxor (%["#sched"]), %%xmm0 \n" \
|
"pxor (%["#sched"]), %%xmm0 \n" \
|
||||||
"aesenc 16(%["#sched"]), %%xmm0 \n" \
|
"aesenc 16(%["#sched"]), %%xmm0 \n" \
|
||||||
@@ -622,18 +732,29 @@ namespace crypto
|
|||||||
"aesenc 192(%["#sched"]), %%xmm0 \n" \
|
"aesenc 192(%["#sched"]), %%xmm0 \n" \
|
||||||
"aesenc 208(%["#sched"]), %%xmm0 \n" \
|
"aesenc 208(%["#sched"]), %%xmm0 \n" \
|
||||||
"aesenclast 224(%["#sched"]), %%xmm0 \n"
|
"aesenclast 224(%["#sched"]), %%xmm0 \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out)
|
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
__asm__
|
#ifdef __AES__
|
||||||
(
|
if(i2p::cpu::aesni)
|
||||||
"movups (%[in]), %%xmm0 \n"
|
{
|
||||||
EncryptAES256(sched)
|
__asm__
|
||||||
"movups %%xmm0, (%[out]) \n"
|
(
|
||||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
"movups (%[in]), %%xmm0 \n"
|
||||||
);
|
EncryptAES256(sched)
|
||||||
|
"movups %%xmm0, (%[out]) \n"
|
||||||
|
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
AES_encrypt (in->buf, out->buf, &m_Key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __AES__
|
||||||
#define DecryptAES256(sched) \
|
#define DecryptAES256(sched) \
|
||||||
"pxor 224(%["#sched"]), %%xmm0 \n" \
|
"pxor 224(%["#sched"]), %%xmm0 \n" \
|
||||||
"aesdec 208(%["#sched"]), %%xmm0 \n" \
|
"aesdec 208(%["#sched"]), %%xmm0 \n" \
|
||||||
@@ -650,79 +771,117 @@ namespace crypto
|
|||||||
"aesdec 32(%["#sched"]), %%xmm0 \n" \
|
"aesdec 32(%["#sched"]), %%xmm0 \n" \
|
||||||
"aesdec 16(%["#sched"]), %%xmm0 \n" \
|
"aesdec 16(%["#sched"]), %%xmm0 \n" \
|
||||||
"aesdeclast (%["#sched"]), %%xmm0 \n"
|
"aesdeclast (%["#sched"]), %%xmm0 \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out)
|
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
__asm__
|
#ifdef __AES__
|
||||||
(
|
if(i2p::cpu::aesni)
|
||||||
"movups (%[in]), %%xmm0 \n"
|
{
|
||||||
DecryptAES256(sched)
|
__asm__
|
||||||
"movups %%xmm0, (%[out]) \n"
|
(
|
||||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
"movups (%[in]), %%xmm0 \n"
|
||||||
);
|
DecryptAES256(sched)
|
||||||
|
"movups %%xmm0, (%[out]) \n"
|
||||||
|
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
AES_decrypt (in->buf, out->buf, &m_Key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __AES__
|
||||||
#define CallAESIMC(offset) \
|
#define CallAESIMC(offset) \
|
||||||
"movaps "#offset"(%[shed]), %%xmm0 \n" \
|
"movaps "#offset"(%[shed]), %%xmm0 \n" \
|
||||||
"aesimc %%xmm0, %%xmm0 \n" \
|
"aesimc %%xmm0, %%xmm0 \n" \
|
||||||
"movaps %%xmm0, "#offset"(%[shed]) \n"
|
"movaps %%xmm0, "#offset"(%[shed]) \n"
|
||||||
|
#endif
|
||||||
|
|
||||||
void ECBDecryptionAESNI::SetKey (const AESKey& key)
|
void ECBEncryption::SetKey (const AESKey& key)
|
||||||
{
|
{
|
||||||
ExpandKey (key); // expand encryption key first
|
#ifdef __AES__
|
||||||
// then invert it using aesimc
|
if(i2p::cpu::aesni)
|
||||||
__asm__
|
{
|
||||||
(
|
ExpandKey (key);
|
||||||
CallAESIMC(16)
|
}
|
||||||
CallAESIMC(32)
|
else
|
||||||
CallAESIMC(48)
|
#endif
|
||||||
CallAESIMC(64)
|
{
|
||||||
CallAESIMC(80)
|
AES_set_encrypt_key (key, 256, &m_Key);
|
||||||
CallAESIMC(96)
|
}
|
||||||
CallAESIMC(112)
|
|
||||||
CallAESIMC(128)
|
|
||||||
CallAESIMC(144)
|
|
||||||
CallAESIMC(160)
|
|
||||||
CallAESIMC(176)
|
|
||||||
CallAESIMC(192)
|
|
||||||
CallAESIMC(208)
|
|
||||||
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ECBDecryption::SetKey (const AESKey& key)
|
||||||
|
{
|
||||||
|
#ifdef __AES__
|
||||||
|
if(i2p::cpu::aesni)
|
||||||
|
{
|
||||||
|
ExpandKey (key); // expand encryption key first
|
||||||
|
// then invert it using aesimc
|
||||||
|
__asm__
|
||||||
|
(
|
||||||
|
CallAESIMC(16)
|
||||||
|
CallAESIMC(32)
|
||||||
|
CallAESIMC(48)
|
||||||
|
CallAESIMC(64)
|
||||||
|
CallAESIMC(80)
|
||||||
|
CallAESIMC(96)
|
||||||
|
CallAESIMC(112)
|
||||||
|
CallAESIMC(128)
|
||||||
|
CallAESIMC(144)
|
||||||
|
CallAESIMC(160)
|
||||||
|
CallAESIMC(176)
|
||||||
|
CallAESIMC(192)
|
||||||
|
CallAESIMC(208)
|
||||||
|
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
AES_set_decrypt_key (key, 256, &m_Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
|
||||||
"movups (%[iv]), %%xmm1 \n"
|
|
||||||
"1: \n"
|
|
||||||
"movups (%[in]), %%xmm0 \n"
|
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
|
||||||
EncryptAES256(sched)
|
|
||||||
"movaps %%xmm0, %%xmm1 \n"
|
|
||||||
"movups %%xmm0, (%[out]) \n"
|
|
||||||
"add $16, %[in] \n"
|
|
||||||
"add $16, %[out] \n"
|
|
||||||
"dec %[num] \n"
|
|
||||||
"jnz 1b \n"
|
|
||||||
"movups %%xmm1, (%[iv]) \n"
|
|
||||||
:
|
|
||||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
|
||||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
|
||||||
: "%xmm0", "%xmm1", "cc", "memory"
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
for (int i = 0; i < numBlocks; i++)
|
|
||||||
{
|
{
|
||||||
*m_LastBlock.GetChipherBlock () ^= in[i];
|
__asm__
|
||||||
m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
|
(
|
||||||
out[i] = *m_LastBlock.GetChipherBlock ();
|
"movups (%[iv]), %%xmm1 \n"
|
||||||
|
"1: \n"
|
||||||
|
"movups (%[in]), %%xmm0 \n"
|
||||||
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
|
EncryptAES256(sched)
|
||||||
|
"movaps %%xmm0, %%xmm1 \n"
|
||||||
|
"movups %%xmm0, (%[out]) \n"
|
||||||
|
"add $16, %[in] \n"
|
||||||
|
"add $16, %[out] \n"
|
||||||
|
"dec %[num] \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
"movups %%xmm1, (%[iv]) \n"
|
||||||
|
:
|
||||||
|
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||||
|
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||||
|
: "%xmm0", "%xmm1", "cc", "memory"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numBlocks; i++)
|
||||||
|
{
|
||||||
|
*m_LastBlock.GetChipherBlock () ^= in[i];
|
||||||
|
m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
|
||||||
|
out[i] = *m_LastBlock.GetChipherBlock ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
|
void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
|
||||||
@@ -735,57 +894,65 @@ namespace crypto
|
|||||||
|
|
||||||
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
{
|
||||||
"movups (%[iv]), %%xmm1 \n"
|
__asm__
|
||||||
"movups (%[in]), %%xmm0 \n"
|
(
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
"movups (%[iv]), %%xmm1 \n"
|
||||||
EncryptAES256(sched)
|
"movups (%[in]), %%xmm0 \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
"movups %%xmm0, (%[iv]) \n"
|
EncryptAES256(sched)
|
||||||
:
|
"movups %%xmm0, (%[out]) \n"
|
||||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
"movups %%xmm0, (%[iv]) \n"
|
||||||
[in]"r"(in), [out]"r"(out)
|
:
|
||||||
: "%xmm0", "%xmm1", "memory"
|
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||||
);
|
[in]"r"(in), [out]"r"(out)
|
||||||
#else
|
: "%xmm0", "%xmm1", "memory"
|
||||||
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
|
||||||
"movups (%[iv]), %%xmm1 \n"
|
|
||||||
"1: \n"
|
|
||||||
"movups (%[in]), %%xmm0 \n"
|
|
||||||
"movaps %%xmm0, %%xmm2 \n"
|
|
||||||
DecryptAES256(sched)
|
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
|
||||||
"movups %%xmm0, (%[out]) \n"
|
|
||||||
"movaps %%xmm2, %%xmm1 \n"
|
|
||||||
"add $16, %[in] \n"
|
|
||||||
"add $16, %[out] \n"
|
|
||||||
"dec %[num] \n"
|
|
||||||
"jnz 1b \n"
|
|
||||||
"movups %%xmm1, (%[iv]) \n"
|
|
||||||
:
|
|
||||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
|
||||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
|
||||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
for (int i = 0; i < numBlocks; i++)
|
|
||||||
{
|
{
|
||||||
ChipherBlock tmp = in[i];
|
__asm__
|
||||||
m_ECBDecryption.Decrypt (in + i, out + i);
|
(
|
||||||
out[i] ^= *m_IV.GetChipherBlock ();
|
"movups (%[iv]), %%xmm1 \n"
|
||||||
*m_IV.GetChipherBlock () = tmp;
|
"1: \n"
|
||||||
|
"movups (%[in]), %%xmm0 \n"
|
||||||
|
"movaps %%xmm0, %%xmm2 \n"
|
||||||
|
DecryptAES256(sched)
|
||||||
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
|
"movups %%xmm0, (%[out]) \n"
|
||||||
|
"movaps %%xmm2, %%xmm1 \n"
|
||||||
|
"add $16, %[in] \n"
|
||||||
|
"add $16, %[out] \n"
|
||||||
|
"dec %[num] \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
"movups %%xmm1, (%[iv]) \n"
|
||||||
|
:
|
||||||
|
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||||
|
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||||
|
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numBlocks; i++)
|
||||||
|
{
|
||||||
|
ChipherBlock tmp = in[i];
|
||||||
|
m_ECBDecryption.Decrypt (in + i, out + i);
|
||||||
|
out[i] ^= *m_IV.GetChipherBlock ();
|
||||||
|
*m_IV.GetChipherBlock () = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
|
void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
|
||||||
@@ -797,98 +964,208 @@ namespace crypto
|
|||||||
|
|
||||||
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
{
|
||||||
"movups (%[iv]), %%xmm1 \n"
|
__asm__
|
||||||
"movups (%[in]), %%xmm0 \n"
|
(
|
||||||
"movups %%xmm0, (%[iv]) \n"
|
"movups (%[iv]), %%xmm1 \n"
|
||||||
DecryptAES256(sched)
|
"movups (%[in]), %%xmm0 \n"
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
"movups %%xmm0, (%[iv]) \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
DecryptAES256(sched)
|
||||||
:
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
"movups %%xmm0, (%[out]) \n"
|
||||||
[in]"r"(in), [out]"r"(out)
|
:
|
||||||
: "%xmm0", "%xmm1", "memory"
|
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||||
);
|
[in]"r"(in), [out]"r"(out)
|
||||||
#else
|
: "%xmm0", "%xmm1", "memory"
|
||||||
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
{
|
||||||
// encrypt IV
|
__asm__
|
||||||
"movups (%[in]), %%xmm0 \n"
|
(
|
||||||
EncryptAES256(sched_iv)
|
// encrypt IV
|
||||||
"movaps %%xmm0, %%xmm1 \n"
|
"movups (%[in]), %%xmm0 \n"
|
||||||
// double IV encryption
|
EncryptAES256(sched_iv)
|
||||||
EncryptAES256(sched_iv)
|
"movaps %%xmm0, %%xmm1 \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
// double IV encryption
|
||||||
// encrypt data, IV is xmm1
|
EncryptAES256(sched_iv)
|
||||||
"1: \n"
|
"movups %%xmm0, (%[out]) \n"
|
||||||
"add $16, %[in] \n"
|
// encrypt data, IV is xmm1
|
||||||
"add $16, %[out] \n"
|
"1: \n"
|
||||||
"movups (%[in]), %%xmm0 \n"
|
"add $16, %[in] \n"
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
"add $16, %[out] \n"
|
||||||
EncryptAES256(sched_l)
|
"movups (%[in]), %%xmm0 \n"
|
||||||
"movaps %%xmm0, %%xmm1 \n"
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
EncryptAES256(sched_l)
|
||||||
"dec %[num] \n"
|
"movaps %%xmm0, %%xmm1 \n"
|
||||||
"jnz 1b \n"
|
"movups %%xmm0, (%[out]) \n"
|
||||||
:
|
"dec %[num] \n"
|
||||||
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()),
|
"jnz 1b \n"
|
||||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
:
|
||||||
: "%xmm0", "%xmm1", "cc", "memory"
|
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
|
||||||
);
|
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||||
#else
|
: "%xmm0", "%xmm1", "cc", "memory"
|
||||||
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
);
|
||||||
m_LayerEncryption.SetIV (out);
|
}
|
||||||
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
else
|
||||||
m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||||
|
m_LayerEncryption.SetIV (out);
|
||||||
|
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||||
|
m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||||
{
|
{
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
__asm__
|
if(i2p::cpu::aesni)
|
||||||
(
|
{
|
||||||
// decrypt IV
|
__asm__
|
||||||
"movups (%[in]), %%xmm0 \n"
|
(
|
||||||
DecryptAES256(sched_iv)
|
// decrypt IV
|
||||||
"movaps %%xmm0, %%xmm1 \n"
|
"movups (%[in]), %%xmm0 \n"
|
||||||
// double IV encryption
|
DecryptAES256(sched_iv)
|
||||||
DecryptAES256(sched_iv)
|
"movaps %%xmm0, %%xmm1 \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
// double IV encryption
|
||||||
// decrypt data, IV is xmm1
|
DecryptAES256(sched_iv)
|
||||||
"1: \n"
|
"movups %%xmm0, (%[out]) \n"
|
||||||
"add $16, %[in] \n"
|
// decrypt data, IV is xmm1
|
||||||
"add $16, %[out] \n"
|
"1: \n"
|
||||||
"movups (%[in]), %%xmm0 \n"
|
"add $16, %[in] \n"
|
||||||
"movaps %%xmm0, %%xmm2 \n"
|
"add $16, %[out] \n"
|
||||||
DecryptAES256(sched_l)
|
"movups (%[in]), %%xmm0 \n"
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
"movaps %%xmm0, %%xmm2 \n"
|
||||||
"movups %%xmm0, (%[out]) \n"
|
DecryptAES256(sched_l)
|
||||||
"movaps %%xmm2, %%xmm1 \n"
|
"pxor %%xmm1, %%xmm0 \n"
|
||||||
"dec %[num] \n"
|
"movups %%xmm0, (%[out]) \n"
|
||||||
"jnz 1b \n"
|
"movaps %%xmm2, %%xmm1 \n"
|
||||||
:
|
"dec %[num] \n"
|
||||||
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()),
|
"jnz 1b \n"
|
||||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
:
|
||||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
|
||||||
);
|
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||||
#else
|
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||||
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
);
|
||||||
m_LayerDecryption.SetIV (out);
|
}
|
||||||
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
else
|
||||||
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||||
|
m_LayerDecryption.SetIV (out);
|
||||||
|
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||||
|
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AEAD/ChaCha20/Poly1305
|
||||||
|
|
||||||
|
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt)
|
||||||
|
{
|
||||||
|
if (len < msgLen) return false;
|
||||||
|
if (encrypt && len < msgLen + 16) return false;
|
||||||
|
bool ret = true;
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
|
// generate one time poly key
|
||||||
|
uint8_t polyKey[64];
|
||||||
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
|
chacha20 (polyKey, 64, nonce, key, 0);
|
||||||
|
|
||||||
|
// create Poly1305 message
|
||||||
|
if (!ad) adLen = 0;
|
||||||
|
std::vector<uint8_t> polyMsg(adLen + msgLen + 3*16);
|
||||||
|
size_t offset = 0;
|
||||||
|
uint8_t padding[16]; memset (padding, 0, 16);
|
||||||
|
if (ad)
|
||||||
|
{
|
||||||
|
memcpy (polyMsg.data (), ad, adLen); offset += adLen; // additional authenticated data
|
||||||
|
auto rem = adLen & 0x0F; // %16
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
// padding1
|
||||||
|
rem = 16 - rem;
|
||||||
|
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// encrypt/decrypt data and add to hash
|
||||||
|
if (buf != msg)
|
||||||
|
memcpy (buf, msg, msgLen);
|
||||||
|
if (encrypt)
|
||||||
|
{
|
||||||
|
chacha20 (buf, msgLen, nonce, key, 1); // encrypt
|
||||||
|
memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption
|
||||||
|
chacha20 (buf, msgLen, nonce, key, 1); // decrypt
|
||||||
|
}
|
||||||
|
offset += msgLen; // encrypted data
|
||||||
|
|
||||||
|
auto rem = msgLen & 0x0F; // %16
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
// padding2
|
||||||
|
rem = 16 - rem;
|
||||||
|
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
|
||||||
|
}
|
||||||
|
htole64buf (polyMsg.data () + offset, adLen); offset += 8;
|
||||||
|
htole64buf (polyMsg.data () + offset, msgLen); offset += 8;
|
||||||
|
|
||||||
|
if (encrypt)
|
||||||
|
{
|
||||||
|
// calculate Poly1305 tag and write in after encrypted data
|
||||||
|
Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)polyKey, polyMsg.data (), offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t tag[8];
|
||||||
|
// calculate Poly1305 tag
|
||||||
|
Poly1305HMAC (tag, (uint32_t *)polyKey, polyMsg.data (), offset);
|
||||||
|
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int outlen = 0;
|
||||||
|
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||||
|
if (encrypt)
|
||||||
|
{
|
||||||
|
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||||
|
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||||
|
EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
|
||||||
|
EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
|
||||||
|
EVP_EncryptFinal_ex(ctx, buf, &outlen);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen));
|
||||||
|
EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||||
|
EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen);
|
||||||
|
EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen);
|
||||||
|
ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init and terminate
|
||||||
|
|
||||||
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
||||||
static void OpensslLockingCallback(int mode, int type, const char * file, int line)
|
static void OpensslLockingCallback(int mode, int type, const char * file, int line)
|
||||||
{
|
{
|
||||||
@@ -904,6 +1181,7 @@ namespace crypto
|
|||||||
|
|
||||||
void InitCrypto (bool precomputation)
|
void InitCrypto (bool precomputation)
|
||||||
{
|
{
|
||||||
|
i2p::cpu::Detect ();
|
||||||
SSL_library_init ();
|
SSL_library_init ();
|
||||||
/* auto numLocks = CRYPTO_num_locks();
|
/* auto numLocks = CRYPTO_num_locks();
|
||||||
for (int i = 0; i < numLocks; i++)
|
for (int i = 0; i < numLocks; i++)
|
||||||
|
|||||||
182
libi2pd/Crypto.h
182
libi2pd/Crypto.h
@@ -13,9 +13,23 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Tag.h"
|
#include "Tag.h"
|
||||||
|
#include "CPU.h"
|
||||||
|
|
||||||
|
// recognize openssl version and features
|
||||||
|
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||||
|
# define LEGACY_OPENSSL 1
|
||||||
|
#else
|
||||||
|
# define LEGACY_OPENSSL 0
|
||||||
|
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||||
|
# define OPENSSL_EDDSA 1
|
||||||
|
# define OPENSSL_X25519 1
|
||||||
|
# define OPENSSL_SIPHASH 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@@ -47,14 +61,39 @@ namespace crypto
|
|||||||
uint8_t m_PublicKey[256];
|
uint8_t m_PublicKey[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// x25519
|
||||||
|
class X25519Keys
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
X25519Keys ();
|
||||||
|
X25519Keys (const uint8_t * priv, const uint8_t * pub); // for RouterContext
|
||||||
|
~X25519Keys ();
|
||||||
|
|
||||||
|
void GenerateKeys ();
|
||||||
|
const uint8_t * GetPublicKey () const { return m_PublicKey; };
|
||||||
|
void Agree (const uint8_t * pub, uint8_t * shared);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t m_PublicKey[32];
|
||||||
|
#if OPENSSL_X25519
|
||||||
|
EVP_PKEY_CTX * m_Ctx;
|
||||||
|
EVP_PKEY * m_Pkey;
|
||||||
|
#else
|
||||||
|
BN_CTX * m_Ctx;
|
||||||
|
uint8_t m_PrivateKey[32];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
|
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
|
||||||
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||||
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
|
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
|
||||||
|
|
||||||
// ECIES
|
// ECIES
|
||||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); // 222 bytes data, 514 bytes encrypted
|
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
|
||||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||||
|
|
||||||
// HMAC
|
// HMAC
|
||||||
@@ -68,33 +107,27 @@ namespace crypto
|
|||||||
|
|
||||||
void operator^=(const ChipherBlock& other) // XOR
|
void operator^=(const ChipherBlock& other) // XOR
|
||||||
{
|
{
|
||||||
#if defined(__AVX__) // AVX
|
#ifdef __AVX__
|
||||||
__asm__
|
if (i2p::cpu::avx)
|
||||||
(
|
{
|
||||||
"vmovups (%[buf]), %%xmm0 \n"
|
__asm__
|
||||||
"vmovups (%[other]), %%xmm1 \n"
|
(
|
||||||
"vxorps %%xmm0, %%xmm1, %%xmm0 \n"
|
"vmovups (%[buf]), %%xmm0 \n"
|
||||||
"vmovups %%xmm0, (%[buf]) \n"
|
"vmovups (%[other]), %%xmm1 \n"
|
||||||
:
|
"vxorps %%xmm0, %%xmm1, %%xmm0 \n"
|
||||||
: [buf]"r"(buf), [other]"r"(other.buf)
|
"vmovups %%xmm0, (%[buf]) \n"
|
||||||
: "%xmm0", "%xmm1", "memory"
|
:
|
||||||
);
|
: [buf]"r"(buf), [other]"r"(other.buf)
|
||||||
#elif defined(__SSE__) // SSE
|
: "%xmm0", "%xmm1", "memory"
|
||||||
__asm__
|
);
|
||||||
(
|
}
|
||||||
"movups (%[buf]), %%xmm0 \n"
|
else
|
||||||
"movups (%[other]), %%xmm1 \n"
|
|
||||||
"pxor %%xmm1, %%xmm0 \n"
|
|
||||||
"movups %%xmm0, (%[buf]) \n"
|
|
||||||
:
|
|
||||||
: [buf]"r"(buf), [other]"r"(other.buf)
|
|
||||||
: "%xmm0", "%xmm1", "memory"
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
// TODO: implement it better
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
buf[i] ^= other.buf[i];
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
// TODO: implement it better
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
buf[i] ^= other.buf[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,7 +158,10 @@ namespace crypto
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef AESNI
|
#ifdef __AES__
|
||||||
|
#ifdef ARM64AES
|
||||||
|
void init_aesenc(void) __attribute__((constructor));
|
||||||
|
#endif
|
||||||
class ECBCryptoAESNI
|
class ECBCryptoAESNI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -138,69 +174,40 @@ namespace crypto
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes
|
AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class ECBEncryptionAESNI: public ECBCryptoAESNI
|
#ifdef __AES__
|
||||||
|
class ECBEncryption: public ECBCryptoAESNI
|
||||||
|
#else
|
||||||
|
class ECBEncryption
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void SetKey (const AESKey& key) { ExpandKey (key); };
|
void SetKey (const AESKey& key);
|
||||||
void Encrypt (const ChipherBlock * in, ChipherBlock * out);
|
|
||||||
|
void Encrypt(const ChipherBlock * in, ChipherBlock * out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AES_KEY m_Key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ECBDecryptionAESNI: public ECBCryptoAESNI
|
#ifdef __AES__
|
||||||
|
class ECBDecryption: public ECBCryptoAESNI
|
||||||
|
#else
|
||||||
|
class ECBDecryption
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void SetKey (const AESKey& key);
|
void SetKey (const AESKey& key);
|
||||||
void Decrypt (const ChipherBlock * in, ChipherBlock * out);
|
void Decrypt (const ChipherBlock * in, ChipherBlock * out);
|
||||||
};
|
|
||||||
|
|
||||||
typedef ECBEncryptionAESNI ECBEncryption;
|
|
||||||
typedef ECBDecryptionAESNI ECBDecryption;
|
|
||||||
|
|
||||||
#else // use openssl
|
|
||||||
|
|
||||||
class ECBEncryption
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
void SetKey (const AESKey& key)
|
|
||||||
{
|
|
||||||
AES_set_encrypt_key (key, 256, &m_Key);
|
|
||||||
}
|
|
||||||
void Encrypt (const ChipherBlock * in, ChipherBlock * out)
|
|
||||||
{
|
|
||||||
AES_encrypt (in->buf, out->buf, &m_Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AES_KEY m_Key;
|
AES_KEY m_Key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ECBDecryption
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
void SetKey (const AESKey& key)
|
|
||||||
{
|
|
||||||
AES_set_decrypt_key (key, 256, &m_Key);
|
|
||||||
}
|
|
||||||
void Decrypt (const ChipherBlock * in, ChipherBlock * out)
|
|
||||||
{
|
|
||||||
AES_decrypt (in->buf, out->buf, &m_Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
AES_KEY m_Key;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CBCEncryption
|
class CBCEncryption
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -209,11 +216,14 @@ namespace crypto
|
|||||||
|
|
||||||
void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes
|
void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes
|
||||||
void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_LastBlock, iv, 16); }; // 16 bytes
|
void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_LastBlock, iv, 16); }; // 16 bytes
|
||||||
|
void GetIV (uint8_t * iv) const { memcpy (iv, (const uint8_t *)m_LastBlock, 16); };
|
||||||
|
|
||||||
void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
|
void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
|
||||||
void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out);
|
void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out);
|
||||||
void Encrypt (const uint8_t * in, uint8_t * out); // one block
|
void Encrypt (const uint8_t * in, uint8_t * out); // one block
|
||||||
|
|
||||||
|
ECBEncryption & ECB() { return m_ECBEncryption; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AESAlignedBuffer<16> m_LastBlock;
|
AESAlignedBuffer<16> m_LastBlock;
|
||||||
@@ -229,11 +239,14 @@ namespace crypto
|
|||||||
|
|
||||||
void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes
|
void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes
|
||||||
void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_IV, iv, 16); }; // 16 bytes
|
void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_IV, iv, 16); }; // 16 bytes
|
||||||
|
void GetIV (uint8_t * iv) const { memcpy (iv, (const uint8_t *)m_IV, 16); };
|
||||||
|
|
||||||
void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
|
void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
|
||||||
void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out);
|
void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out);
|
||||||
void Decrypt (const uint8_t * in, uint8_t * out); // one block
|
void Decrypt (const uint8_t * in, uint8_t * out); // one block
|
||||||
|
|
||||||
|
ECBDecryption & ECB() { return m_ECBDecryption; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AESAlignedBuffer<16> m_IV;
|
AESAlignedBuffer<16> m_IV;
|
||||||
@@ -255,11 +268,7 @@ namespace crypto
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
ECBEncryption m_IVEncryption;
|
ECBEncryption m_IVEncryption;
|
||||||
#ifdef AESNI
|
|
||||||
ECBEncryption m_LayerEncryption;
|
|
||||||
#else
|
|
||||||
CBCEncryption m_LayerEncryption;
|
CBCEncryption m_LayerEncryption;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TunnelDecryption // with double IV encryption
|
class TunnelDecryption // with double IV encryption
|
||||||
@@ -277,21 +286,20 @@ namespace crypto
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
ECBDecryption m_IVDecryption;
|
ECBDecryption m_IVDecryption;
|
||||||
#ifdef AESNI
|
|
||||||
ECBDecryption m_LayerDecryption;
|
|
||||||
#else
|
|
||||||
CBCDecryption m_LayerDecryption;
|
CBCDecryption m_LayerDecryption;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// AEAD/ChaCha20/Poly1305
|
||||||
|
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
|
||||||
|
|
||||||
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation);
|
void InitCrypto (bool precomputation);
|
||||||
void TerminateCrypto ();
|
void TerminateCrypto ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care about openssl version
|
// take care about openssl below 1.1.0
|
||||||
#include <openssl/opensslv.h>
|
#if LEGACY_OPENSSL
|
||||||
#if (OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER) // 1.1.0 or LibreSSL
|
|
||||||
// define getters and setters introduced in 1.1.0
|
// define getters and setters introduced in 1.1.0
|
||||||
inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ namespace crypto
|
|||||||
memcpy (m_PublicKey, pub, 256);
|
memcpy (m_PublicKey, pub, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, true);
|
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
|
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
|
||||||
@@ -22,9 +22,9 @@ namespace crypto
|
|||||||
memcpy (m_PrivateKey, priv, 256);
|
memcpy (m_PrivateKey, priv, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, true);
|
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
|
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
|
||||||
@@ -44,10 +44,10 @@ namespace crypto
|
|||||||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
if (m_Curve && m_PublicKey)
|
if (m_Curve && m_PublicKey)
|
||||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx);
|
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
|
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
|
||||||
@@ -62,10 +62,10 @@ namespace crypto
|
|||||||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
if (m_Curve && m_PrivateKey)
|
if (m_Curve && m_PrivateKey)
|
||||||
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx);
|
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,10 +104,10 @@ namespace crypto
|
|||||||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
if (m_PublicKey)
|
if (m_PublicKey)
|
||||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx);
|
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
|
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
|
||||||
@@ -120,10 +120,10 @@ namespace crypto
|
|||||||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
if (m_PrivateKey)
|
if (m_PrivateKey)
|
||||||
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx);
|
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace crypto
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~CryptoKeyEncryptor () {};
|
virtual ~CryptoKeyEncryptor () {};
|
||||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted
|
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) = 0; // 222 bytes data, 512/514 bytes encrypted
|
||||||
};
|
};
|
||||||
|
|
||||||
class CryptoKeyDecryptor
|
class CryptoKeyDecryptor
|
||||||
@@ -21,7 +21,7 @@ namespace crypto
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~CryptoKeyDecryptor () {};
|
virtual ~CryptoKeyDecryptor () {};
|
||||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) = 0; // 512 bytes encrypted, 222 bytes data
|
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data
|
||||||
};
|
};
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
@@ -30,7 +30,7 @@ namespace crypto
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
ElGamalEncryptor (const uint8_t * pub);
|
ElGamalEncryptor (const uint8_t * pub);
|
||||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ namespace crypto
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
ElGamalDecryptor (const uint8_t * priv);
|
ElGamalDecryptor (const uint8_t * priv);
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ namespace crypto
|
|||||||
|
|
||||||
ECIESP256Encryptor (const uint8_t * pub);
|
ECIESP256Encryptor (const uint8_t * pub);
|
||||||
~ECIESP256Encryptor ();
|
~ECIESP256Encryptor ();
|
||||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ namespace crypto
|
|||||||
|
|
||||||
ECIESP256Decryptor (const uint8_t * priv);
|
ECIESP256Decryptor (const uint8_t * priv);
|
||||||
~ECIESP256Decryptor ();
|
~ECIESP256Decryptor ();
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ namespace crypto
|
|||||||
|
|
||||||
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
||||||
~ECIESGOSTR3410Encryptor ();
|
~ECIESGOSTR3410Encryptor ();
|
||||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ namespace crypto
|
|||||||
|
|
||||||
ECIESGOSTR3410Decryptor (const uint8_t * priv);
|
ECIESGOSTR3410Decryptor (const uint8_t * priv);
|
||||||
~ECIESGOSTR3410Decryptor ();
|
~ECIESGOSTR3410Decryptor ();
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
81
libi2pd/CryptoWorker.h
Normal file
81
libi2pd/CryptoWorker.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef CRYPTO_WORKER_H_
|
||||||
|
#define CRYPTO_WORKER_H_
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <deque>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace worker
|
||||||
|
{
|
||||||
|
template<typename Caller>
|
||||||
|
struct ThreadPool
|
||||||
|
{
|
||||||
|
typedef std::function<void(void)> ResultFunc;
|
||||||
|
typedef std::function<ResultFunc(void)> WorkFunc;
|
||||||
|
typedef std::pair<std::shared_ptr<Caller>, WorkFunc> Job;
|
||||||
|
typedef std::mutex mtx_t;
|
||||||
|
typedef std::unique_lock<mtx_t> lock_t;
|
||||||
|
typedef std::condition_variable cond_t;
|
||||||
|
ThreadPool(int workers)
|
||||||
|
{
|
||||||
|
stop = false;
|
||||||
|
if(workers > 0)
|
||||||
|
{
|
||||||
|
while(workers--)
|
||||||
|
{
|
||||||
|
threads.emplace_back([this] {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Job job;
|
||||||
|
{
|
||||||
|
lock_t lock(this->queue_mutex);
|
||||||
|
this->condition.wait(
|
||||||
|
lock, [this] { return this->stop || !this->jobs.empty(); });
|
||||||
|
if (this->stop && this->jobs.empty()) return;
|
||||||
|
job = std::move(this->jobs.front());
|
||||||
|
this->jobs.pop_front();
|
||||||
|
}
|
||||||
|
ResultFunc result = job.second();
|
||||||
|
job.first->GetService().post(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Offer(const Job & job)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
lock_t lock(queue_mutex);
|
||||||
|
if (stop) return;
|
||||||
|
jobs.emplace_back(job);
|
||||||
|
}
|
||||||
|
condition.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ThreadPool()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
lock_t lock(queue_mutex);
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
condition.notify_all();
|
||||||
|
for(auto &t: threads) t.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
std::deque<Job> jobs;
|
||||||
|
mtx_t queue_mutex;
|
||||||
|
cond_t condition;
|
||||||
|
bool stop;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -64,7 +64,7 @@ namespace client
|
|||||||
{
|
{
|
||||||
it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME);
|
it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME);
|
||||||
if (it != params->end ()) m_Nickname = it->second;
|
if (it != params->end ()) m_Nickname = it->second;
|
||||||
// otherwise we set deafult nickname in Start when we know local address
|
// otherwise we set default nickname in Start when we know local address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,6 +169,46 @@ namespace client
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
||||||
|
if (itr != params.end())
|
||||||
|
{
|
||||||
|
m_IsPublic = itr->second != "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
||||||
|
std::map<std::string, int&> intOpts = {
|
||||||
|
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
||||||
|
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
|
||||||
|
{I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant},
|
||||||
|
{I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant},
|
||||||
|
{I2CP_PARAM_TAGS_TO_SEND, numTags},
|
||||||
|
{I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency},
|
||||||
|
{I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto pool = GetTunnelPool();
|
||||||
|
inLen = pool->GetNumInboundHops();
|
||||||
|
outLen = pool->GetNumOutboundHops();
|
||||||
|
inQuant = pool->GetNumInboundTunnels();
|
||||||
|
outQuant = pool->GetNumOutboundTunnels();
|
||||||
|
minLatency = 0;
|
||||||
|
maxLatency = 0;
|
||||||
|
|
||||||
|
for (auto & opt : intOpts)
|
||||||
|
{
|
||||||
|
itr = params.find(opt.first);
|
||||||
|
if(itr != params.end())
|
||||||
|
{
|
||||||
|
opt.second = std::stoi(itr->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pool->RequireLatency(minLatency, maxLatency);
|
||||||
|
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
||||||
@@ -241,8 +281,12 @@ namespace client
|
|||||||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
{
|
{
|
||||||
m_PublishVerificationTimer.cancel ();
|
auto s = shared_from_this ();
|
||||||
Publish ();
|
m_Service.post ([s](void)
|
||||||
|
{
|
||||||
|
s->m_PublishVerificationTimer.cancel ();
|
||||||
|
s->Publish ();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,17 +329,17 @@ namespace client
|
|||||||
switch (typeID)
|
switch (typeID)
|
||||||
{
|
{
|
||||||
case eI2NPData:
|
case eI2NPData:
|
||||||
HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
|
HandleDataMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
|
||||||
break;
|
break;
|
||||||
case eI2NPDeliveryStatus:
|
case eI2NPDeliveryStatus:
|
||||||
// we assume tunnel tests non-encrypted
|
// we assume tunnel tests non-encrypted
|
||||||
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
|
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
|
||||||
break;
|
break;
|
||||||
case eI2NPDatabaseStore:
|
case eI2NPDatabaseStore:
|
||||||
HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
|
HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
|
||||||
break;
|
break;
|
||||||
case eI2NPDatabaseSearchReply:
|
case eI2NPDatabaseSearchReply:
|
||||||
HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
|
HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
|
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
|
||||||
@@ -815,6 +859,11 @@ namespace client
|
|||||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint32_t length = bufbe32toh (buf);
|
uint32_t length = bufbe32toh (buf);
|
||||||
|
if(length > len - 4)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Destination: Data message length ", length, " exceeds buffer length ", len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
buf += 4;
|
buf += 4;
|
||||||
// we assume I2CP payload
|
// we assume I2CP payload
|
||||||
uint16_t fromPort = bufbe16toh (buf + 4), // source
|
uint16_t fromPort = bufbe16toh (buf + 4), // source
|
||||||
@@ -984,7 +1033,7 @@ namespace client
|
|||||||
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||||
{
|
{
|
||||||
if (m_Decryptor)
|
if (m_Decryptor)
|
||||||
return m_Decryptor->Decrypt (encrypted, data, ctx);
|
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destinations: decryptor is not set");
|
LogPrint (eLogError, "Destinations: decryptor is not set");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ namespace client
|
|||||||
|
|
||||||
virtual bool Start ();
|
virtual bool Start ();
|
||||||
virtual bool Stop ();
|
virtual bool Stop ();
|
||||||
|
|
||||||
|
/** i2cp reconfigure */
|
||||||
|
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
|
||||||
|
|
||||||
bool IsRunning () const { return m_IsRunning; };
|
bool IsRunning () const { return m_IsRunning; };
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
||||||
|
|||||||
515
libi2pd/Ed25519.cpp
Normal file
515
libi2pd/Ed25519.cpp
Normal file
@@ -0,0 +1,515 @@
|
|||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Crypto.h"
|
||||||
|
#include "Ed25519.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
Ed25519::Ed25519 ()
|
||||||
|
{
|
||||||
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
|
BIGNUM * tmp = BN_new ();
|
||||||
|
|
||||||
|
q = BN_new ();
|
||||||
|
// 2^255-19
|
||||||
|
BN_set_bit (q, 255); // 2^255
|
||||||
|
BN_sub_word (q, 19);
|
||||||
|
|
||||||
|
l = BN_new ();
|
||||||
|
// 2^252 + 27742317777372353535851937790883648493
|
||||||
|
BN_set_bit (l, 252);
|
||||||
|
two_252_2 = BN_dup (l);
|
||||||
|
BN_dec2bn (&tmp, "27742317777372353535851937790883648493");
|
||||||
|
BN_add (l, l, tmp);
|
||||||
|
BN_sub_word (two_252_2, 2); // 2^252 - 2
|
||||||
|
|
||||||
|
// -121665*inv(121666)
|
||||||
|
d = BN_new ();
|
||||||
|
BN_set_word (tmp, 121666);
|
||||||
|
BN_mod_inverse (tmp, tmp, q, ctx);
|
||||||
|
BN_set_word (d, 121665);
|
||||||
|
BN_set_negative (d, 1);
|
||||||
|
BN_mul (d, d, tmp, ctx);
|
||||||
|
|
||||||
|
// 2^((q-1)/4)
|
||||||
|
I = BN_new ();
|
||||||
|
BN_free (tmp);
|
||||||
|
tmp = BN_dup (q);
|
||||||
|
BN_sub_word (tmp, 1);
|
||||||
|
BN_div_word (tmp, 4);
|
||||||
|
BN_set_word (I, 2);
|
||||||
|
BN_mod_exp (I, I, tmp, q, ctx);
|
||||||
|
BN_free (tmp);
|
||||||
|
|
||||||
|
// 4*inv(5)
|
||||||
|
BIGNUM * By = BN_new ();
|
||||||
|
BN_set_word (By, 5);
|
||||||
|
BN_mod_inverse (By, By, q, ctx);
|
||||||
|
BN_mul_word (By, 4);
|
||||||
|
BIGNUM * Bx = RecoverX (By, ctx);
|
||||||
|
BN_mod (Bx, Bx, q, ctx); // % q
|
||||||
|
BN_mod (By, By, q, ctx); // % q
|
||||||
|
|
||||||
|
// precalculate Bi256 table
|
||||||
|
Bi256Carry = { Bx, By }; // B
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
Bi256[i][0] = Bi256Carry; // first point
|
||||||
|
for (int j = 1; j < 128; j++)
|
||||||
|
Bi256[i][j] = Sum (Bi256[i][j-1], Bi256[i][0], ctx); // (256+j+1)^i*B
|
||||||
|
Bi256Carry = Bi256[i][127];
|
||||||
|
for (int j = 0; j < 128; j++) // add first point 128 more times
|
||||||
|
Bi256Carry = Sum (Bi256Carry, Bi256[i][0], ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
BN_CTX_free (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ed25519::Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)),
|
||||||
|
d (BN_dup (other.d)), I (BN_dup (other.I)), two_252_2 (BN_dup (other.two_252_2)),
|
||||||
|
Bi256Carry (other.Bi256Carry)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
for (int j = 0; j < 128; j++)
|
||||||
|
Bi256[i][j] = other.Bi256[i][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
Ed25519::~Ed25519 ()
|
||||||
|
{
|
||||||
|
BN_free (q);
|
||||||
|
BN_free (l);
|
||||||
|
BN_free (d);
|
||||||
|
BN_free (I);
|
||||||
|
BN_free (two_252_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
return MulB (expandedPrivateKey, ctx); // left half of expanded key, considered as Little Endian
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
return DecodePoint (buf, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
EncodePoint (Normalize (publicKey, ctx), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ed25519::Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const
|
||||||
|
{
|
||||||
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
|
BIGNUM * h = DecodeBN<64> (digest);
|
||||||
|
// signature 0..31 - R, 32..63 - S
|
||||||
|
// B*S = R + PK*h => R = B*S - PK*h
|
||||||
|
// we don't decode R, but encode (B*S - PK*h)
|
||||||
|
auto Bs = MulB (signature + EDDSA25519_SIGNATURE_LENGTH/2, ctx); // B*S;
|
||||||
|
BN_mod (h, h, l, ctx); // public key is multiple of B, but B%l = 0
|
||||||
|
auto PKh = Mul (publicKey, h, ctx); // PK*h
|
||||||
|
uint8_t diff[32];
|
||||||
|
EncodePoint (Normalize (Sum (Bs, -PKh, ctx), ctx), diff); // Bs - PKh encoded
|
||||||
|
bool passed = !memcmp (signature, diff, 32); // R
|
||||||
|
BN_free (h);
|
||||||
|
BN_CTX_free (ctx);
|
||||||
|
if (!passed)
|
||||||
|
LogPrint (eLogError, "25519 signature verification failed");
|
||||||
|
return passed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len,
|
||||||
|
uint8_t * signature) const
|
||||||
|
{
|
||||||
|
BN_CTX * bnCtx = BN_CTX_new ();
|
||||||
|
// calculate r
|
||||||
|
SHA512_CTX ctx;
|
||||||
|
SHA512_Init (&ctx);
|
||||||
|
SHA512_Update (&ctx, expandedPrivateKey + EDDSA25519_PRIVATE_KEY_LENGTH, EDDSA25519_PRIVATE_KEY_LENGTH); // right half of expanded key
|
||||||
|
SHA512_Update (&ctx, buf, len); // data
|
||||||
|
uint8_t digest[64];
|
||||||
|
SHA512_Final (digest, &ctx);
|
||||||
|
BIGNUM * r = DecodeBN<32> (digest); // DecodeBN<64> (digest); // for test vectors
|
||||||
|
// calculate R
|
||||||
|
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
|
||||||
|
EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors
|
||||||
|
// calculate S
|
||||||
|
SHA512_Init (&ctx);
|
||||||
|
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
||||||
|
SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key
|
||||||
|
SHA512_Update (&ctx, buf, len); // data
|
||||||
|
SHA512_Final (digest, &ctx);
|
||||||
|
BIGNUM * h = DecodeBN<64> (digest);
|
||||||
|
// S = (r + h*a) % l
|
||||||
|
BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (expandedPrivateKey); // left half of expanded key
|
||||||
|
BN_mod_mul (h, h, a, l, bnCtx); // %l
|
||||||
|
BN_mod_add (h, h, r, l, bnCtx); // %l
|
||||||
|
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
|
||||||
|
EncodeBN (h, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S
|
||||||
|
BN_free (r); BN_free (h); BN_free (a);
|
||||||
|
BN_CTX_free (bnCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
|
||||||
|
// y3 = (y1*y2+x1*x2)*(z1*z2+d*t1*t2)
|
||||||
|
// z3 = (z1*z2-d*t1*t2)*(z1*z2+d*t1*t2)
|
||||||
|
// t3 = (y1*y2+x1*x2)*(x1*y2+y1*x2)
|
||||||
|
BIGNUM * x3 = BN_new (), * y3 = BN_new (), * z3 = BN_new (), * t3 = BN_new ();
|
||||||
|
|
||||||
|
BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2
|
||||||
|
BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2
|
||||||
|
|
||||||
|
BN_CTX_start (ctx);
|
||||||
|
BIGNUM * t1 = p1.t, * t2 = p2.t;
|
||||||
|
if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); }
|
||||||
|
if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); }
|
||||||
|
BN_mul (t3, t1, t2, ctx);
|
||||||
|
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
|
||||||
|
|
||||||
|
if (p1.z)
|
||||||
|
{
|
||||||
|
if (p2.z)
|
||||||
|
BN_mul (z3, p1.z, p2.z, ctx); // D = z1*z2
|
||||||
|
else
|
||||||
|
BN_copy (z3, p1.z); // D = z1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p2.z)
|
||||||
|
BN_copy (z3, p2.z); // D = z2
|
||||||
|
else
|
||||||
|
BN_one (z3); // D = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx);
|
||||||
|
BN_add (E, p1.x, p1.y);
|
||||||
|
BN_add (F, p2.x, p2.y);
|
||||||
|
BN_mul (E, E, F, ctx); // (x1 + y1)*(x2 + y2)
|
||||||
|
BN_sub (E, E, x3);
|
||||||
|
BN_sub (E, E, y3); // E = (x1 + y1)*(x2 + y2) - A - B
|
||||||
|
BN_sub (F, z3, t3); // F = D - C
|
||||||
|
BN_add (G, z3, t3); // G = D + C
|
||||||
|
BN_add (H, y3, x3); // H = B + A
|
||||||
|
|
||||||
|
BN_mod_mul (x3, E, F, q, ctx); // x3 = E*F
|
||||||
|
BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H
|
||||||
|
BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G
|
||||||
|
BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H
|
||||||
|
|
||||||
|
BN_CTX_end (ctx);
|
||||||
|
|
||||||
|
return EDDSAPoint {x3, y3, z3, t3};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::Double (EDDSAPoint& p, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BN_CTX_start (ctx);
|
||||||
|
BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * z2 = BN_CTX_get (ctx), * t2 = BN_CTX_get (ctx);
|
||||||
|
|
||||||
|
BN_sqr (x2, p.x, ctx); // x2 = A = x^2
|
||||||
|
BN_sqr (y2, p.y, ctx); // y2 = B = y^2
|
||||||
|
if (p.t)
|
||||||
|
BN_sqr (t2, p.t, ctx); // t2 = t^2
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BN_mul (t2, p.x, p.y, ctx); // t = x*y
|
||||||
|
BN_sqr (t2, t2, ctx); // t2 = t^2
|
||||||
|
}
|
||||||
|
BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2
|
||||||
|
if (p.z)
|
||||||
|
BN_sqr (z2, p.z, ctx); // z2 = D = z^2
|
||||||
|
else
|
||||||
|
BN_one (z2); // z2 = 1
|
||||||
|
|
||||||
|
BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx);
|
||||||
|
// E = (x+y)*(x+y)-A-B = x^2+y^2+2xy-A-B = 2xy
|
||||||
|
BN_mul (E, p.x, p.y, ctx);
|
||||||
|
BN_lshift1 (E, E); // E =2*x*y
|
||||||
|
BN_sub (F, z2, t2); // F = D - C
|
||||||
|
BN_add (G, z2, t2); // G = D + C
|
||||||
|
BN_add (H, y2, x2); // H = B + A
|
||||||
|
|
||||||
|
BN_mod_mul (p.x, E, F, q, ctx); // x2 = E*F
|
||||||
|
BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H
|
||||||
|
if (!p.z) p.z = BN_new ();
|
||||||
|
BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G
|
||||||
|
if (!p.t) p.t = BN_new ();
|
||||||
|
BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H
|
||||||
|
|
||||||
|
BN_CTX_end (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BIGNUM * zero = BN_new (), * one = BN_new ();
|
||||||
|
BN_zero (zero); BN_one (one);
|
||||||
|
EDDSAPoint res {zero, one};
|
||||||
|
if (!BN_is_zero (e))
|
||||||
|
{
|
||||||
|
int bitCount = BN_num_bits (e);
|
||||||
|
for (int i = bitCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Double (res, ctx);
|
||||||
|
if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::MulB (const uint8_t * e, BN_CTX * ctx) const // B*e, e is 32 bytes Little Endian
|
||||||
|
{
|
||||||
|
BIGNUM * zero = BN_new (), * one = BN_new ();
|
||||||
|
BN_zero (zero); BN_one (one);
|
||||||
|
EDDSAPoint res {zero, one};
|
||||||
|
bool carry = false;
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
uint8_t x = e[i];
|
||||||
|
if (carry)
|
||||||
|
{
|
||||||
|
if (x < 255)
|
||||||
|
{
|
||||||
|
x++;
|
||||||
|
carry = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
if (x > 0)
|
||||||
|
{
|
||||||
|
if (x <= 128)
|
||||||
|
res = Sum (res, Bi256[i][x-1], ctx);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = Sum (res, -Bi256[i][255-x], ctx); // -Bi[256-x]
|
||||||
|
carry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (carry) res = Sum (res, Bi256Carry, ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::Normalize (const EDDSAPoint& p, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
if (p.z)
|
||||||
|
{
|
||||||
|
BIGNUM * x = BN_new (), * y = BN_new ();
|
||||||
|
BN_mod_inverse (y, p.z, q, ctx);
|
||||||
|
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
|
||||||
|
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
|
||||||
|
return EDDSAPoint{x, y};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ed25519::IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BN_CTX_start (ctx);
|
||||||
|
BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * tmp = BN_CTX_get (ctx);
|
||||||
|
BN_sqr (x2, p.x, ctx); // x^2
|
||||||
|
BN_sqr (y2, p.y, ctx); // y^2
|
||||||
|
// y^2 - x^2 - 1 - d*x^2*y^2
|
||||||
|
BN_mul (tmp, d, x2, ctx);
|
||||||
|
BN_mul (tmp, tmp, y2, ctx);
|
||||||
|
BN_sub (tmp, y2, tmp);
|
||||||
|
BN_sub (tmp, tmp, x2);
|
||||||
|
BN_sub_word (tmp, 1);
|
||||||
|
BN_mod (tmp, tmp, q, ctx); // % q
|
||||||
|
bool ret = BN_is_zero (tmp);
|
||||||
|
BN_CTX_end (ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIGNUM * Ed25519::RecoverX (const BIGNUM * y, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BN_CTX_start (ctx);
|
||||||
|
BIGNUM * y2 = BN_CTX_get (ctx), * xx = BN_CTX_get (ctx);
|
||||||
|
BN_sqr (y2, y, ctx); // y^2
|
||||||
|
// xx = (y^2 -1)*inv(d*y^2 +1)
|
||||||
|
BN_mul (xx, d, y2, ctx);
|
||||||
|
BN_add_word (xx, 1);
|
||||||
|
BN_mod_inverse (xx, xx, q, ctx);
|
||||||
|
BN_sub_word (y2, 1);
|
||||||
|
BN_mul (xx, y2, xx, ctx);
|
||||||
|
// x = srqt(xx) = xx^(2^252-2)
|
||||||
|
BIGNUM * x = BN_new ();
|
||||||
|
BN_mod_exp (x, xx, two_252_2, q, ctx);
|
||||||
|
// check (x^2 -xx) % q
|
||||||
|
BN_sqr (y2, x, ctx);
|
||||||
|
BN_mod_sub (y2, y2, xx, q, ctx);
|
||||||
|
if (!BN_is_zero (y2))
|
||||||
|
BN_mod_mul (x, x, I, q, ctx);
|
||||||
|
if (BN_is_odd (x))
|
||||||
|
BN_sub (x, q, x);
|
||||||
|
BN_CTX_end (ctx);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint Ed25519::DecodePoint (const uint8_t * buf, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
// buf is 32 bytes Little Endian, convert it to Big Endian
|
||||||
|
uint8_t buf1[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
|
for (size_t i = 0; i < EDDSA25519_PUBLIC_KEY_LENGTH/2; i++) // invert bytes
|
||||||
|
{
|
||||||
|
buf1[i] = buf[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i];
|
||||||
|
buf1[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i] = buf[i];
|
||||||
|
}
|
||||||
|
bool isHighestBitSet = buf1[0] & 0x80;
|
||||||
|
if (isHighestBitSet)
|
||||||
|
buf1[0] &= 0x7f; // clear highest bit
|
||||||
|
BIGNUM * y = BN_new ();
|
||||||
|
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
|
||||||
|
BIGNUM * x = RecoverX (y, ctx);
|
||||||
|
if (BN_is_bit_set (x, 0) != isHighestBitSet)
|
||||||
|
BN_sub (x, q, x); // x = q - x
|
||||||
|
BIGNUM * z = BN_new (), * t = BN_new ();
|
||||||
|
BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t
|
||||||
|
EDDSAPoint p {x, y, z, t};
|
||||||
|
if (!IsOnCurve (p, ctx))
|
||||||
|
LogPrint (eLogError, "Decoded point is not on 25519");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::EncodePoint (const EDDSAPoint& p, uint8_t * buf) const
|
||||||
|
{
|
||||||
|
EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||||
|
if (BN_is_bit_set (p.x, 0)) // highest bit
|
||||||
|
buf[EDDSA25519_PUBLIC_KEY_LENGTH - 1] |= 0x80; // set highest bit
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int len>
|
||||||
|
BIGNUM * Ed25519::DecodeBN (const uint8_t * buf) const
|
||||||
|
{
|
||||||
|
// buf is Little Endian convert it to Big Endian
|
||||||
|
uint8_t buf1[len];
|
||||||
|
for (size_t i = 0; i < len/2; i++) // invert bytes
|
||||||
|
{
|
||||||
|
buf1[i] = buf[len -1 - i];
|
||||||
|
buf1[len -1 - i] = buf[i];
|
||||||
|
}
|
||||||
|
BIGNUM * res = BN_new ();
|
||||||
|
BN_bin2bn (buf1, len, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const
|
||||||
|
{
|
||||||
|
bn2buf (bn, buf, len);
|
||||||
|
// To Little Endian
|
||||||
|
for (size_t i = 0; i < len/2; i++) // invert bytes
|
||||||
|
{
|
||||||
|
uint8_t tmp = buf[i];
|
||||||
|
buf[i] = buf[len -1 - i];
|
||||||
|
buf[len -1 - i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BN_CTX_start (ctx);
|
||||||
|
auto x1 = BN_CTX_get (ctx); BN_copy (x1, u);
|
||||||
|
auto x2 = BN_CTX_get (ctx); BN_one (x2);
|
||||||
|
auto z2 = BN_CTX_get (ctx); BN_zero (z2);
|
||||||
|
auto x3 = BN_CTX_get (ctx); BN_copy (x3, u);
|
||||||
|
auto z3 = BN_CTX_get (ctx); BN_one (z3);
|
||||||
|
auto c121666 = BN_CTX_get (ctx); BN_set_word (c121666, 121666);
|
||||||
|
auto tmp0 = BN_CTX_get (ctx); auto tmp1 = BN_CTX_get (ctx);
|
||||||
|
unsigned int swap = 0;
|
||||||
|
auto bits = BN_num_bits (k);
|
||||||
|
while(bits)
|
||||||
|
{
|
||||||
|
--bits;
|
||||||
|
auto k_t = BN_is_bit_set(k, bits) ? 1 : 0;
|
||||||
|
swap ^= k_t;
|
||||||
|
if (swap)
|
||||||
|
{
|
||||||
|
std::swap (x2, x3);
|
||||||
|
std::swap (z2, z3);
|
||||||
|
}
|
||||||
|
swap = k_t;
|
||||||
|
BN_mod_sub(tmp0, x3, z3, q, ctx);
|
||||||
|
BN_mod_sub(tmp1, x2, z2, q, ctx);
|
||||||
|
BN_mod_add(x2, x2, z2, q, ctx);
|
||||||
|
BN_mod_add(z2, x3, z3, q, ctx);
|
||||||
|
BN_mod_mul(z3, tmp0, x2, q, ctx);
|
||||||
|
BN_mod_mul(z2, z2, tmp1, q, ctx);
|
||||||
|
BN_mod_sqr(tmp0, tmp1, q, ctx);
|
||||||
|
BN_mod_sqr(tmp1, x2, q, ctx);
|
||||||
|
BN_mod_add(x3, z3, z2, q, ctx);
|
||||||
|
BN_mod_sub(z2, z3, z2, q, ctx);
|
||||||
|
BN_mod_mul(x2, tmp1, tmp0, q, ctx);
|
||||||
|
BN_mod_sub(tmp1, tmp1, tmp0, q, ctx);
|
||||||
|
BN_mod_sqr(z2, z2, q, ctx);
|
||||||
|
BN_mod_mul(z3, tmp1, c121666, q, ctx);
|
||||||
|
BN_mod_sqr(x3, x3, q, ctx);
|
||||||
|
BN_mod_add(tmp0, tmp0, z3, q, ctx);
|
||||||
|
BN_mod_mul(z3, x1, z2, q, ctx);
|
||||||
|
BN_mod_mul(z2, tmp1, tmp0, q, ctx);
|
||||||
|
}
|
||||||
|
if (swap)
|
||||||
|
{
|
||||||
|
std::swap (x2, x3);
|
||||||
|
std::swap (z2, z3);
|
||||||
|
}
|
||||||
|
BN_mod_inverse (z2, z2, q, ctx);
|
||||||
|
BIGNUM * res = BN_new (); // not from ctx
|
||||||
|
BN_mod_mul(res, x2, z2, q, ctx);
|
||||||
|
BN_CTX_end (ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BIGNUM * p1 = DecodeBN<32> (p);
|
||||||
|
uint8_t k[32];
|
||||||
|
memcpy (k, e, 32);
|
||||||
|
k[0] &= 248; k[31] &= 127; k[31] |= 64;
|
||||||
|
BIGNUM * n = DecodeBN<32> (k);
|
||||||
|
BIGNUM * q1 = ScalarMul (p1, n, ctx);
|
||||||
|
EncodeBN (q1, buf, 32);
|
||||||
|
BN_free (p1); BN_free (n); BN_free (q1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||||
|
{
|
||||||
|
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
|
||||||
|
uint8_t k[32];
|
||||||
|
memcpy (k, e, 32);
|
||||||
|
k[0] &= 248; k[31] &= 127; k[31] |= 64;
|
||||||
|
BIGNUM * n = DecodeBN<32> (k);
|
||||||
|
BIGNUM * q1 = ScalarMul (p1, n, ctx);
|
||||||
|
EncodeBN (q1, buf, 32);
|
||||||
|
BN_free (p1); BN_free (n); BN_free (q1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
|
||||||
|
{
|
||||||
|
SHA512 (key, EDDSA25519_PRIVATE_KEY_LENGTH, expandedKey);
|
||||||
|
expandedKey[0] &= 0xF8; // drop last 3 bits
|
||||||
|
expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0x3F; // drop first 2 bits
|
||||||
|
expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<Ed25519> g_Ed25519;
|
||||||
|
std::unique_ptr<Ed25519>& GetEd25519 ()
|
||||||
|
{
|
||||||
|
if (!g_Ed25519)
|
||||||
|
{
|
||||||
|
auto c = new Ed25519();
|
||||||
|
if (!g_Ed25519) // make sure it was not created already
|
||||||
|
g_Ed25519.reset (c);
|
||||||
|
else
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
return g_Ed25519;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
124
libi2pd/Ed25519.h
Normal file
124
libi2pd/Ed25519.h
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#ifndef ED25519_H__
|
||||||
|
#define ED25519_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
struct EDDSAPoint
|
||||||
|
{
|
||||||
|
BIGNUM * x {nullptr};
|
||||||
|
BIGNUM * y {nullptr};
|
||||||
|
BIGNUM * z {nullptr};
|
||||||
|
BIGNUM * t {nullptr}; // projective coordinates
|
||||||
|
|
||||||
|
EDDSAPoint () {}
|
||||||
|
EDDSAPoint (const EDDSAPoint& other) { *this = other; }
|
||||||
|
EDDSAPoint (EDDSAPoint&& other) { *this = std::move (other); }
|
||||||
|
EDDSAPoint (BIGNUM * x1, BIGNUM * y1, BIGNUM * z1 = nullptr, BIGNUM * t1 = nullptr)
|
||||||
|
: x(x1)
|
||||||
|
, y(y1)
|
||||||
|
, z(z1)
|
||||||
|
, t(t1)
|
||||||
|
{}
|
||||||
|
~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); }
|
||||||
|
|
||||||
|
EDDSAPoint& operator=(EDDSAPoint&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
BN_free (x); x = other.x; other.x = nullptr;
|
||||||
|
BN_free (y); y = other.y; other.y = nullptr;
|
||||||
|
BN_free (z); z = other.z; other.z = nullptr;
|
||||||
|
BN_free (t); t = other.t; other.t = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint& operator=(const EDDSAPoint& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
BN_free (x); x = other.x ? BN_dup (other.x) : nullptr;
|
||||||
|
BN_free (y); y = other.y ? BN_dup (other.y) : nullptr;
|
||||||
|
BN_free (z); z = other.z ? BN_dup (other.z) : nullptr;
|
||||||
|
BN_free (t); t = other.t ? BN_dup (other.t) : nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
EDDSAPoint operator-() const
|
||||||
|
{
|
||||||
|
BIGNUM * x1 = NULL, * y1 = NULL, * z1 = NULL, * t1 = NULL;
|
||||||
|
if (x) { x1 = BN_dup (x); BN_set_negative (x1, !BN_is_negative (x)); };
|
||||||
|
if (y) y1 = BN_dup (y);
|
||||||
|
if (z) z1 = BN_dup (z);
|
||||||
|
if (t) { t1 = BN_dup (t); BN_set_negative (t1, !BN_is_negative (t)); };
|
||||||
|
return EDDSAPoint {x1, y1, z1, t1};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t EDDSA25519_PUBLIC_KEY_LENGTH = 32;
|
||||||
|
const size_t EDDSA25519_SIGNATURE_LENGTH = 64;
|
||||||
|
const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32;
|
||||||
|
class Ed25519
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Ed25519 ();
|
||||||
|
Ed25519 (const Ed25519& other);
|
||||||
|
~Ed25519 ();
|
||||||
|
|
||||||
|
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
|
||||||
|
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
|
||||||
|
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
|
||||||
|
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
|
||||||
|
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
||||||
|
|
||||||
|
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
|
||||||
|
void Double (EDDSAPoint& p, BN_CTX * ctx) const;
|
||||||
|
EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const;
|
||||||
|
EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const; // B*e, e is 32 bytes Little Endian
|
||||||
|
EDDSAPoint Normalize (const EDDSAPoint& p, BN_CTX * ctx) const;
|
||||||
|
|
||||||
|
bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const;
|
||||||
|
BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const;
|
||||||
|
EDDSAPoint DecodePoint (const uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const;
|
||||||
|
|
||||||
|
template<int len>
|
||||||
|
BIGNUM * DecodeBN (const uint8_t * buf) const;
|
||||||
|
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
|
// for x25519
|
||||||
|
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
BIGNUM * q, * l, * d, * I;
|
||||||
|
// transient values
|
||||||
|
BIGNUM * two_252_2; // 2^252-2
|
||||||
|
EDDSAPoint Bi256[32][128]; // per byte, Bi256[i][j] = (256+j+1)^i*B, we don't store zeroes
|
||||||
|
// if j > 128 we use 256 - j and carry 1 to next byte
|
||||||
|
// Bi256[0][0] = B, base point
|
||||||
|
EDDSAPoint Bi256Carry; // Bi256[32][0]
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<Ed25519>& GetEd25519 ();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <stdio.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@@ -21,6 +22,13 @@ namespace http {
|
|||||||
const std::vector<std::string> HTTP_VERSIONS = {
|
const std::vector<std::string> HTTP_VERSIONS = {
|
||||||
"HTTP/1.0", "HTTP/1.1"
|
"HTTP/1.0", "HTTP/1.1"
|
||||||
};
|
};
|
||||||
|
const std::vector<const char *> weekdays = {
|
||||||
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||||
|
};
|
||||||
|
const std::vector<const char *> months = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||||
|
};
|
||||||
|
|
||||||
inline bool is_http_version(const std::string & str) {
|
inline bool is_http_version(const std::string & str) {
|
||||||
return std::find(HTTP_VERSIONS.begin(), HTTP_VERSIONS.end(), str) != std::end(HTTP_VERSIONS);
|
return std::find(HTTP_VERSIONS.begin(), HTTP_VERSIONS.end(), str) != std::end(HTTP_VERSIONS);
|
||||||
@@ -56,10 +64,14 @@ namespace http {
|
|||||||
return std::make_pair(line.substr(0, pos), line.substr(pos + len));
|
return std::make_pair(line.substr(0, pos), line.substr(pos + len));
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_rfc1123_date(std::string & out) {
|
void gen_rfc7231_date(std::string & out) {
|
||||||
std::time_t now = std::time(nullptr);
|
std::time_t now = std::time(nullptr);
|
||||||
char buf[128];
|
char buf[128];
|
||||||
std::strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", std::gmtime(&now));
|
std::tm *tm = std::gmtime(&now);
|
||||||
|
snprintf(buf, sizeof(buf), "%s, %02d %s %d %02d:%02d:%02d GMT",
|
||||||
|
weekdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon],
|
||||||
|
tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec
|
||||||
|
);
|
||||||
out = buf;
|
out = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +96,11 @@ namespace http {
|
|||||||
pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */
|
pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */
|
||||||
if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) {
|
if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) {
|
||||||
std::size_t delim = url.find(':', pos_p);
|
std::size_t delim = url.find(':', pos_p);
|
||||||
if (delim != std::string::npos && delim < pos_c) {
|
if (delim && delim != std::string::npos && delim < pos_c) {
|
||||||
user = url.substr(pos_p, delim - pos_p);
|
user = url.substr(pos_p, delim - pos_p);
|
||||||
delim += 1;
|
delim += 1;
|
||||||
pass = url.substr(delim, pos_c - delim);
|
pass = url.substr(delim, pos_c - delim);
|
||||||
} else {
|
} else if(delim) {
|
||||||
user = url.substr(pos_p, pos_c - pos_p);
|
user = url.substr(pos_p, pos_c - pos_p);
|
||||||
}
|
}
|
||||||
pos_p = pos_c + 1;
|
pos_p = pos_c + 1;
|
||||||
@@ -400,7 +412,7 @@ namespace http {
|
|||||||
std::string HTTPRes::to_string() {
|
std::string HTTPRes::to_string() {
|
||||||
if (version == "HTTP/1.1" && headers.count("Date") == 0) {
|
if (version == "HTTP/1.1" && headers.count("Date") == 0) {
|
||||||
std::string date;
|
std::string date;
|
||||||
gen_rfc1123_date(date);
|
gen_rfc7231_date(date);
|
||||||
add_header("Date", date.c_str());
|
add_header("Date", date.c_str());
|
||||||
}
|
}
|
||||||
if (status == "OK" && code != 200)
|
if (status == "OK" && code != 200)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace i2p
|
|||||||
|
|
||||||
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
|
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
|
||||||
{
|
{
|
||||||
return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage ();
|
return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID)
|
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID)
|
||||||
@@ -327,7 +327,7 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
|
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
// replace record to reply
|
// replace record to reply
|
||||||
if (i2p::context.AcceptsTunnels () &&
|
if (i2p::context.AcceptsTunnels () &&
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace i2p
|
|||||||
const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1;
|
const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1;
|
||||||
const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4;
|
const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4;
|
||||||
|
|
||||||
|
// I2NP NTCP2 header
|
||||||
|
const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4;
|
||||||
|
|
||||||
// Tunnel Gateway header
|
// Tunnel Gateway header
|
||||||
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
|
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
|
||||||
const size_t TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET = TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET + 4;
|
const size_t TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET = TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET + 4;
|
||||||
@@ -103,7 +106,7 @@ namespace tunnel
|
|||||||
class TunnelPool;
|
class TunnelPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t I2NP_MAX_MESSAGE_SIZE = 32768;
|
const size_t I2NP_MAX_MESSAGE_SIZE = 62708;
|
||||||
const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096;
|
const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096;
|
||||||
const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT)
|
const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT)
|
||||||
const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds
|
const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds
|
||||||
@@ -194,6 +197,24 @@ namespace tunnel
|
|||||||
len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET);
|
len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET);
|
||||||
return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET);
|
return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET);
|
||||||
}
|
}
|
||||||
|
// for NTCP2 only
|
||||||
|
uint8_t * GetNTCP2Header () { return GetPayload () - I2NP_NTCP2_HEADER_SIZE; };
|
||||||
|
size_t GetNTCP2Length () const { return GetPayloadLength () + I2NP_NTCP2_HEADER_SIZE; };
|
||||||
|
void FromNTCP2 ()
|
||||||
|
{
|
||||||
|
const uint8_t * ntcp2 = GetNTCP2Header ();
|
||||||
|
memcpy (GetHeader () + I2NP_HEADER_TYPEID_OFFSET, ntcp2 + I2NP_HEADER_TYPEID_OFFSET, 5); // typeid + msgid
|
||||||
|
SetExpiration (bufbe32toh (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET)*1000LL);
|
||||||
|
SetSize (len - offset - I2NP_HEADER_SIZE);
|
||||||
|
SetChks (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToNTCP2 ()
|
||||||
|
{
|
||||||
|
uint8_t * ntcp2 = GetNTCP2Header ();
|
||||||
|
htobe32buf (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET, bufbe64toh (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL);
|
||||||
|
memcpy (ntcp2 + I2NP_HEADER_TYPEID_OFFSET, GetHeader () + I2NP_HEADER_TYPEID_OFFSET, 5); // typeid + msgid
|
||||||
|
}
|
||||||
|
|
||||||
void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0);
|
void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0);
|
||||||
void RenewI2NPMessageHeader ();
|
void RenewI2NPMessageHeader ();
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||||
#include <sys/endian.h>
|
#include <sys/endian.h>
|
||||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
|
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
|
|
||||||
@@ -113,7 +113,20 @@ inline void htobe64buf(void *buf, uint64_t big64)
|
|||||||
htobuf64(buf, htobe64(big64));
|
htobuf64(buf, htobe64(big64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void htole16buf(void *buf, uint16_t big16)
|
||||||
|
{
|
||||||
|
htobuf16(buf, htole16(big16));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void htole32buf(void *buf, uint32_t big32)
|
||||||
|
{
|
||||||
|
htobuf32(buf, htole32(big32));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void htole64buf(void *buf, uint64_t big64)
|
||||||
|
{
|
||||||
|
htobuf64(buf, htole64(big64));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // I2PENDIAN_H__
|
#endif // I2PENDIAN_H__
|
||||||
|
|
||||||
|
|||||||
@@ -72,29 +72,10 @@ namespace data
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||||
{
|
|
||||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
|
||||||
excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256 - 128
|
|
||||||
excessBuf = new uint8_t[excessLen];
|
|
||||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||||
{
|
|
||||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
|
||||||
excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384 - 128
|
|
||||||
excessBuf = new uint8_t[excessLen];
|
|
||||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
{
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
|
||||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
break;
|
||||||
excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512 - 128
|
|
||||||
excessBuf = new uint8_t[excessLen];
|
|
||||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
{
|
{
|
||||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||||
@@ -368,32 +349,10 @@ namespace data
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||||
{
|
|
||||||
uint8_t signingKey[i2p::crypto::RSASHA2562048_KEY_LENGTH];
|
|
||||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
|
||||||
size_t excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256- 128
|
|
||||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
|
||||||
UpdateVerifier (new i2p::crypto:: RSASHA2562048Verifier (signingKey));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||||
{
|
|
||||||
uint8_t signingKey[i2p::crypto::RSASHA3843072_KEY_LENGTH];
|
|
||||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
|
||||||
size_t excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384- 128
|
|
||||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
|
||||||
UpdateVerifier (new i2p::crypto:: RSASHA3843072Verifier (signingKey));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
{
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported");
|
||||||
uint8_t signingKey[i2p::crypto::RSASHA5124096_KEY_LENGTH];
|
break;
|
||||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
|
||||||
size_t excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512- 128
|
|
||||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
|
||||||
UpdateVerifier (new i2p::crypto:: RSASHA5124096Verifier (signingKey));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
{
|
{
|
||||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||||
@@ -564,13 +523,9 @@ namespace data
|
|||||||
m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey));
|
m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey));
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||||
m_Signer.reset (new i2p::crypto::RSASHA2562048Signer (m_SigningPrivateKey));
|
|
||||||
break;
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||||
m_Signer.reset (new i2p::crypto::RSASHA3843072Signer (m_SigningPrivateKey));
|
|
||||||
break;
|
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
m_Signer.reset (new i2p::crypto::RSASHA5124096Signer (m_SigningPrivateKey));
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
|
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
|
||||||
@@ -642,7 +597,7 @@ namespace data
|
|||||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA");
|
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
||||||
// no break here
|
// no break here
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
|
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
|
||||||
@@ -719,24 +674,29 @@ namespace data
|
|||||||
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
||||||
{
|
{
|
||||||
XORMetric m;
|
XORMetric m;
|
||||||
#if defined(__AVX__) // for AVX
|
#ifdef __AVX__
|
||||||
__asm__
|
if(i2p::cpu::avx)
|
||||||
(
|
{
|
||||||
"vmovups %1, %%ymm0 \n"
|
__asm__
|
||||||
"vmovups %2, %%ymm1 \n"
|
(
|
||||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
"vmovups %1, %%ymm0 \n"
|
||||||
"vmovups %%ymm1, %0 \n"
|
"vmovups %2, %%ymm1 \n"
|
||||||
: "=m"(*m.metric)
|
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||||
: "m"(*key1), "m"(*key2)
|
"vmovups %%ymm1, %0 \n"
|
||||||
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
|
: "=m"(*m.metric)
|
||||||
);
|
: "m"(*key1), "m"(*key2)
|
||||||
#else
|
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
|
||||||
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
);
|
||||||
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
}
|
||||||
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
else
|
||||||
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
|
||||||
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
||||||
|
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
||||||
|
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
||||||
|
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
||||||
|
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
||||||
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
|
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
|
||||||
if (encryptor)
|
if (encryptor)
|
||||||
encryptor->Encrypt (data, encrypted, ctx);
|
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
|
//for std::transform
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace log {
|
namespace log {
|
||||||
static Log logger;
|
static Log logger;
|
||||||
@@ -107,7 +110,18 @@ namespace log {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SetLogLevel (const std::string& level) {
|
std::string str_tolower(std::string s) {
|
||||||
|
std::transform(s.begin(), s.end(), s.begin(),
|
||||||
|
// static_cast<int(*)(int)>(std::tolower) // wrong
|
||||||
|
// [](int c){ return std::tolower(c); } // wrong
|
||||||
|
// [](char c){ return std::tolower(c); } // wrong
|
||||||
|
[](unsigned char c){ return std::tolower(c); } // correct
|
||||||
|
);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Log::SetLogLevel (const std::string& level_) {
|
||||||
|
std::string level=str_tolower(level_);
|
||||||
if (level == "none") { m_MinLevel = eLogNone; }
|
if (level == "none") { m_MinLevel = eLogNone; }
|
||||||
else if (level == "error") { m_MinLevel = eLogError; }
|
else if (level == "error") { m_MinLevel = eLogError; }
|
||||||
else if (level == "warn") { m_MinLevel = eLogWarning; }
|
else if (level == "warn") { m_MinLevel = eLogWarning; }
|
||||||
|
|||||||
1350
libi2pd/NTCP2.cpp
Normal file
1350
libi2pd/NTCP2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
268
libi2pd/NTCP2.h
Normal file
268
libi2pd/NTCP2.h
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2018, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*
|
||||||
|
* Kovri go write your own code
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef NTCP2_H__
|
||||||
|
#define NTCP2_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <array>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include "Crypto.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "RouterInfo.h"
|
||||||
|
#include "TransportSession.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace transport
|
||||||
|
{
|
||||||
|
|
||||||
|
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
|
||||||
|
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
|
||||||
|
|
||||||
|
const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||||
|
const int NTCP2_ESTABLISH_TIMEOUT = 10; // 10 seconds
|
||||||
|
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||||
|
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||||
|
|
||||||
|
const int NTCP2_CLOCK_SKEW = 60; // in seconds
|
||||||
|
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
|
||||||
|
|
||||||
|
enum NTCP2BlockType
|
||||||
|
{
|
||||||
|
eNTCP2BlkDateTime = 0,
|
||||||
|
eNTCP2BlkOptions, // 1
|
||||||
|
eNTCP2BlkRouterInfo, // 2
|
||||||
|
eNTCP2BlkI2NPMessage, // 3
|
||||||
|
eNTCP2BlkTermination, // 4
|
||||||
|
eNTCP2BlkPadding = 254
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NTCP2TerminationReason
|
||||||
|
{
|
||||||
|
eNTCP2NormalClose = 0,
|
||||||
|
eNTCP2TerminationReceived, // 1
|
||||||
|
eNTCP2IdleTimeout, // 2
|
||||||
|
eNTCP2RouterShutdown, // 3
|
||||||
|
eNTCP2DataPhaseAEADFailure, // 4
|
||||||
|
eNTCP2IncompatibleOptions, // 5
|
||||||
|
eNTCP2IncompatibleSignatureType, // 6
|
||||||
|
eNTCP2ClockSkew, // 7
|
||||||
|
eNTCP2PaddingViolation, // 8
|
||||||
|
eNTCP2AEADFramingError, // 9
|
||||||
|
eNTCP2PayloadFormatError, // 10
|
||||||
|
eNTCP2Message1Error, // 11
|
||||||
|
eNTCP2Message2Error, // 12
|
||||||
|
eNTCP2Message3Error, // 13
|
||||||
|
eNTCP2IntraFrameReadTimeout, // 14
|
||||||
|
eNTCP2RouterInfoSignatureVerificationFail, // 15
|
||||||
|
eNTCP2IncorrectSParameter, // 16
|
||||||
|
eNTCP2Banned, // 17
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::array<uint8_t, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE> NTCP2FrameBuffer;
|
||||||
|
struct NTCP2Establisher
|
||||||
|
{
|
||||||
|
NTCP2Establisher ();
|
||||||
|
~NTCP2Establisher ();
|
||||||
|
|
||||||
|
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); };
|
||||||
|
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
||||||
|
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
||||||
|
|
||||||
|
const uint8_t * GetK () const { return m_K; };
|
||||||
|
const uint8_t * GetCK () const { return m_CK; };
|
||||||
|
const uint8_t * GetH () const { return m_H; };
|
||||||
|
|
||||||
|
void KDF1Alice ();
|
||||||
|
void KDF1Bob ();
|
||||||
|
void KDF2Alice ();
|
||||||
|
void KDF2Bob ();
|
||||||
|
void KDF3Alice (); // for SessionConfirmed part 2
|
||||||
|
void KDF3Bob ();
|
||||||
|
|
||||||
|
void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived);
|
||||||
|
void KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
|
||||||
|
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate
|
||||||
|
void CreateEphemeralKey ();
|
||||||
|
|
||||||
|
void CreateSessionRequestMessage ();
|
||||||
|
void CreateSessionCreatedMessage ();
|
||||||
|
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
|
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||||
|
|
||||||
|
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
|
||||||
|
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||||
|
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
|
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
||||||
|
|
||||||
|
i2p::crypto::X25519Keys m_EphemeralKeys;
|
||||||
|
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
||||||
|
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
|
||||||
|
i2p::data::IdentHash m_RemoteIdentHash;
|
||||||
|
uint16_t m3p2Len;
|
||||||
|
|
||||||
|
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
|
||||||
|
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class NTCP2Server;
|
||||||
|
class NTCP2Session: public TransportSession, public std::enable_shared_from_this<NTCP2Session>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
||||||
|
~NTCP2Session ();
|
||||||
|
void Terminate ();
|
||||||
|
void TerminateByTimeout ();
|
||||||
|
void Done ();
|
||||||
|
|
||||||
|
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||||
|
|
||||||
|
bool IsEstablished () const { return m_IsEstablished; };
|
||||||
|
bool IsTerminated () const { return m_IsTerminated; };
|
||||||
|
|
||||||
|
void ClientLogin (); // Alice
|
||||||
|
void ServerLogin (); // Bob
|
||||||
|
|
||||||
|
void SendLocalRouterInfo (); // after handshake
|
||||||
|
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Established ();
|
||||||
|
|
||||||
|
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||||
|
void KeyDerivationFunctionDataPhase ();
|
||||||
|
void SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey);
|
||||||
|
|
||||||
|
// establish
|
||||||
|
void SendSessionRequest ();
|
||||||
|
void SendSessionCreated ();
|
||||||
|
void SendSessionConfirmed ();
|
||||||
|
|
||||||
|
void HandleSessionRequestSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionRequestReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionRequestPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
|
||||||
|
// data
|
||||||
|
void ReceiveLength ();
|
||||||
|
void HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void Receive ();
|
||||||
|
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void ProcessNextFrame (const uint8_t * frame, size_t len);
|
||||||
|
|
||||||
|
void SendNextFrame (const uint8_t * payload, size_t len);
|
||||||
|
void HandleNextFrameSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void SendQueue ();
|
||||||
|
void SendRouterInfo ();
|
||||||
|
void SendTermination (NTCP2TerminationReason reason);
|
||||||
|
void SendTerminationAndTerminate (NTCP2TerminationReason reason);
|
||||||
|
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
NTCP2Server& m_Server;
|
||||||
|
boost::asio::ip::tcp::socket m_Socket;
|
||||||
|
bool m_IsEstablished, m_IsTerminated;
|
||||||
|
|
||||||
|
std::unique_ptr<NTCP2Establisher> m_Establisher;
|
||||||
|
// data phase
|
||||||
|
uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32];
|
||||||
|
const uint8_t * m_SendKey, * m_ReceiveKey;
|
||||||
|
#if OPENSSL_SIPHASH
|
||||||
|
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
|
||||||
|
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
||||||
|
#else
|
||||||
|
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
||||||
|
#endif
|
||||||
|
uint16_t m_NextReceivedLen;
|
||||||
|
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint8_t buf[8];
|
||||||
|
uint16_t key;
|
||||||
|
} m_ReceiveIV, m_SendIV;
|
||||||
|
uint64_t m_ReceiveSequenceNumber, m_SendSequenceNumber;
|
||||||
|
|
||||||
|
i2p::I2NPMessagesHandler m_Handler;
|
||||||
|
|
||||||
|
bool m_IsSending;
|
||||||
|
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NTCP2Server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
NTCP2Server ();
|
||||||
|
~NTCP2Server ();
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
|
||||||
|
bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||||
|
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||||
|
std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident);
|
||||||
|
|
||||||
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
|
|
||||||
|
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCP2Session> conn);
|
||||||
|
|
||||||
|
NTCP2FrameBuffer * NewNTCP2FrameBuffer () { return m_NTCP2FrameBuffersPool.Acquire(); }
|
||||||
|
void DeleteNTCP2FrameBuffer (NTCP2FrameBuffer * buf) { return m_NTCP2FrameBuffersPool.Release(buf); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Run ();
|
||||||
|
void HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||||
|
void HandleAcceptV6 (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||||
|
|
||||||
|
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
||||||
|
|
||||||
|
// timer
|
||||||
|
void ScheduleTermination ();
|
||||||
|
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool m_IsRunning;
|
||||||
|
std::thread * m_Thread;
|
||||||
|
boost::asio::io_service m_Service;
|
||||||
|
boost::asio::io_service::work m_Work;
|
||||||
|
boost::asio::deadline_timer m_TerminationTimer;
|
||||||
|
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor;
|
||||||
|
std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions;
|
||||||
|
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
||||||
|
|
||||||
|
i2p::util::MemoryPool<NTCP2FrameBuffer> m_NTCP2FrameBuffersPool;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// for HTTP/I2PControl
|
||||||
|
const decltype(m_NTCP2Sessions)& GetNTCP2Sessions () const { return m_NTCP2Sessions; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -24,6 +24,12 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
namespace transport
|
namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct NTCPWork
|
||||||
|
{
|
||||||
|
std::shared_ptr<NTCPSession> session;
|
||||||
|
};
|
||||||
|
|
||||||
NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
||||||
TransportSession (in_RemoteRouter, NTCP_ESTABLISH_TIMEOUT),
|
TransportSession (in_RemoteRouter, NTCP_ESTABLISH_TIMEOUT),
|
||||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||||
@@ -105,6 +111,11 @@ namespace transport
|
|||||||
transports.PeerConnected (shared_from_this ());
|
transports.PeerConnected (shared_from_this ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::asio::io_service & NTCPSession::GetService()
|
||||||
|
{
|
||||||
|
return m_Server.GetService();
|
||||||
|
}
|
||||||
|
|
||||||
void NTCPSession::ClientLogin ()
|
void NTCPSession::ClientLogin ()
|
||||||
{
|
{
|
||||||
if (!m_DHKeysPair)
|
if (!m_DHKeysPair)
|
||||||
@@ -171,32 +182,21 @@ namespace transport
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 7)
|
|
||||||
// due the bug in gcc 4.7. std::shared_future.get() is not const
|
|
||||||
if (!m_DHKeysPair)
|
|
||||||
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
|
||||||
CreateAESKey (m_Establisher->phase1.pubKey);
|
|
||||||
SendPhase2 ();
|
|
||||||
#else
|
|
||||||
// TODO: check for number of pending keys
|
// TODO: check for number of pending keys
|
||||||
auto s = shared_from_this ();
|
auto work = new NTCPWork{shared_from_this()};
|
||||||
auto keyCreated = std::async (std::launch::async, [s] ()
|
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||||
{
|
if (!work->session->m_DHKeysPair)
|
||||||
if (!s->m_DHKeysPair)
|
work->session->m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
s->m_DHKeysPair = transports.GetNextDHKeysPair ();
|
work->session->CreateAESKey (work->session->m_Establisher->phase1.pubKey);
|
||||||
s->CreateAESKey (s->m_Establisher->phase1.pubKey);
|
return std::bind(&NTCPSession::SendPhase2, work->session, work);
|
||||||
}).share ();
|
|
||||||
m_Server.GetService ().post ([s, keyCreated]()
|
|
||||||
{
|
|
||||||
keyCreated.get ();
|
|
||||||
s->SendPhase2 ();
|
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::SendPhase2 ()
|
void NTCPSession::SendPhase2 (NTCPWork * work)
|
||||||
{
|
{
|
||||||
|
if(work)
|
||||||
|
delete work;
|
||||||
const uint8_t * y = m_DHKeysPair->GetPublicKey ();
|
const uint8_t * y = m_DHKeysPair->GetPublicKey ();
|
||||||
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
||||||
uint8_t xy[512];
|
uint8_t xy[512];
|
||||||
@@ -211,9 +211,8 @@ namespace transport
|
|||||||
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||||
|
|
||||||
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase2, sizeof (NTCPPhase2)), boost::asio::transfer_all (),
|
boost::asio::async_write(m_Socket, boost::asio::buffer (&m_Establisher->phase2, sizeof (NTCPPhase2)), boost::asio::transfer_all(),
|
||||||
std::bind(&NTCPSession::HandlePhase2Sent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, tsB));
|
std::bind(&NTCPSession::HandlePhase2Sent, shared_from_this(), std::placeholders::_1, std::placeholders::_2, tsB));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB)
|
void NTCPSession::HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB)
|
||||||
@@ -250,29 +249,17 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 7)
|
auto work = new NTCPWork{shared_from_this()};
|
||||||
// due the bug in gcc 4.7. std::shared_future.get() is not const
|
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||||
CreateAESKey (m_Establisher->phase2.pubKey);
|
work->session->CreateAESKey (work->session->m_Establisher->phase2.pubKey);
|
||||||
HandlePhase2 ();
|
return std::bind(&NTCPSession::HandlePhase2, work->session, work);
|
||||||
#else
|
});
|
||||||
auto s = shared_from_this ();
|
|
||||||
// create AES key in separate thread
|
|
||||||
auto keyCreated = std::async (std::launch::async, [s] ()
|
|
||||||
{
|
|
||||||
s->CreateAESKey (s->m_Establisher->phase2.pubKey);
|
|
||||||
}).share (); // TODO: use move capture in C++ 14 instead shared_future
|
|
||||||
// let other operations execute while a key gets created
|
|
||||||
m_Server.GetService ().post ([s, keyCreated]()
|
|
||||||
{
|
|
||||||
keyCreated.get (); // we might wait if no more pending operations
|
|
||||||
s->HandlePhase2 ();
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::HandlePhase2 ()
|
void NTCPSession::HandlePhase2 (NTCPWork * work)
|
||||||
{
|
{
|
||||||
|
if(work) delete work;
|
||||||
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
|
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
|
||||||
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||||
|
|
||||||
@@ -415,7 +402,7 @@ namespace transport
|
|||||||
uint32_t tsA1 = be32toh (tsA);
|
uint32_t tsA1 = be32toh (tsA);
|
||||||
if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW)
|
if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew");
|
LogPrint (eLogError, "NTCP: Phase3 time difference ", (int)(ts - tsA1), " exceeds clock skew");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -498,7 +485,7 @@ namespace transport
|
|||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW)
|
if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew");
|
LogPrint (eLogError, "NTCP: Phase4 time difference ", (int)(ts - tsB), " exceeds clock skew");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -788,12 +775,14 @@ namespace transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------
|
//-----------------------------------------
|
||||||
NTCPServer::NTCPServer ():
|
NTCPServer::NTCPServer (int workers):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
||||||
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
|
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
|
||||||
m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr),
|
m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr),
|
||||||
m_SoftLimit(0), m_HardLimit(0)
|
m_SoftLimit(0), m_HardLimit(0)
|
||||||
{
|
{
|
||||||
|
if(workers <= 0) workers = 1;
|
||||||
|
m_CryptoPool = std::make_shared<Pool>(workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTCPServer::~NTCPServer ()
|
NTCPServer::~NTCPServer ()
|
||||||
@@ -830,7 +819,7 @@ namespace transport
|
|||||||
for (const auto& address: addresses)
|
for (const auto& address: addresses)
|
||||||
{
|
{
|
||||||
if (!address) continue;
|
if (!address) continue;
|
||||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !address->IsNTCP2 ())
|
||||||
{
|
{
|
||||||
if (address->host.is_v4())
|
if (address->host.is_v4())
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user