mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
447 Commits
webconsole
...
static-bui
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7a882582f | ||
|
|
250696a7b5 | ||
|
|
af7905744e | ||
|
|
db2364e9aa | ||
|
|
067fb45a25 | ||
|
|
ac287a896c | ||
|
|
8baf62eb2c | ||
|
|
e1ec79daf2 | ||
|
|
d4426118c5 | ||
|
|
64fe56aa07 | ||
|
|
47eb49c34e | ||
|
|
cd6d86c8c3 | ||
|
|
84d4e074ce | ||
|
|
a0e71c4173 | ||
|
|
533c8a8a55 | ||
|
|
a57ae4dc56 | ||
|
|
88dfe3ca4e | ||
|
|
d68c7f8ea7 | ||
|
|
e8ace998ba | ||
|
|
e8be39af17 | ||
|
|
7196db09d6 | ||
|
|
b290ee1aa0 | ||
|
|
d105ab11af | ||
|
|
bc888167a7 | ||
|
|
6ca6591c43 | ||
|
|
36cb707e47 | ||
|
|
013d5ff74f | ||
|
|
9af5a90757 | ||
|
|
d8b6f5438c | ||
|
|
10030a4e0d | ||
|
|
993dc72ce6 | ||
|
|
324ace103b | ||
|
|
d530269e4f | ||
|
|
7146a4dbae | ||
|
|
f79900653b | ||
|
|
f172f44f32 | ||
|
|
f34abe60fa | ||
|
|
a3c305032a | ||
|
|
2921eaa055 | ||
|
|
1cc68ea402 | ||
|
|
c18e8f6c78 | ||
|
|
e59ca8420e | ||
|
|
a6f9a56e40 | ||
|
|
4011502f5f | ||
|
|
acd6af709e | ||
|
|
55704ece3a | ||
|
|
0d3ede56cb | ||
|
|
06fae976b3 | ||
|
|
e95035c143 | ||
|
|
55be5c74f0 | ||
|
|
a1c16e129d | ||
|
|
321c7cb7cf | ||
|
|
5f8d45154d | ||
|
|
503f522cc3 | ||
|
|
22179400c7 | ||
|
|
66f82cb43f | ||
|
|
1df67bd43c | ||
|
|
d5b03f214b | ||
|
|
cfb773351d | ||
|
|
6942c20879 | ||
|
|
7b341d5d30 | ||
|
|
e93718456f | ||
|
|
af838196be | ||
|
|
f8ba5b8c63 | ||
|
|
446bbf6b93 | ||
|
|
2c19da9aa7 | ||
|
|
01fc21ffb9 | ||
|
|
3e3e2c41bd | ||
|
|
cb139226df | ||
|
|
84d6028454 | ||
|
|
126dc0ebe0 | ||
|
|
099d9d977f | ||
|
|
5a167316cb | ||
|
|
85e31f84ec | ||
|
|
edb7a0e23c | ||
|
|
f401ccf5dd | ||
|
|
9f9e8bfa14 | ||
|
|
61168d5c9d | ||
|
|
8500aaa26f | ||
|
|
445cff0025 | ||
|
|
99356fd24d | ||
|
|
5ef5f5a170 | ||
|
|
54b7d4ef32 | ||
|
|
6376328c98 | ||
|
|
b6f83dfe9f | ||
|
|
3f728149ab | ||
|
|
36501fe31e | ||
|
|
e4ddc883d2 | ||
|
|
5ac01ddce8 | ||
|
|
d3656fcb3f | ||
|
|
d6c101d261 | ||
|
|
eeea02d834 | ||
|
|
0e0cd555eb | ||
|
|
5dfe483152 | ||
|
|
c210553a39 | ||
|
|
a315e4ce62 | ||
|
|
96cfd9acc2 | ||
|
|
d869bb25ed | ||
|
|
476e6aae35 | ||
|
|
d30ee99cf1 | ||
|
|
84d9c8f1b8 | ||
|
|
df737a65b2 | ||
|
|
c5230ca44b | ||
|
|
3471e6fe16 | ||
|
|
f1437feede | ||
|
|
0d523bd2a6 | ||
|
|
8943200ffa | ||
|
|
a902d68669 | ||
|
|
f6ca7c19af | ||
|
|
3458665df8 | ||
|
|
8320987124 | ||
|
|
648b09d45f | ||
|
|
857df5c734 | ||
|
|
737603e81b | ||
|
|
53ca5dc67a | ||
|
|
8ad5696e50 | ||
|
|
ef9d27e424 | ||
|
|
2bb5ff7184 | ||
|
|
753c7efde8 | ||
|
|
d0d0cd8445 | ||
|
|
410d2c2fa9 | ||
|
|
6a743f66e8 | ||
|
|
709c451400 | ||
|
|
cb73c7c72e | ||
|
|
50abeea82a | ||
|
|
8db352b4d0 | ||
|
|
6589bdf6b5 | ||
|
|
1ac171152a | ||
|
|
629c718527 | ||
|
|
519c0fe81d | ||
|
|
eb0ef80a17 | ||
|
|
9763499dbe | ||
|
|
949c38f5f0 | ||
|
|
2a6f906177 | ||
|
|
b4c226f4b3 | ||
|
|
64c3282aae | ||
|
|
f5d511ae0f | ||
|
|
aa9a9ef18d | ||
|
|
aa5e6400e4 | ||
|
|
61bcfebcc8 | ||
|
|
73b9c0302b | ||
|
|
aead9db971 | ||
|
|
d8230644b2 | ||
|
|
97ef908b0c | ||
|
|
fb8be32c28 | ||
|
|
a298588943 | ||
|
|
ccfeca728e | ||
|
|
7705423c42 | ||
|
|
379075c594 | ||
|
|
6a23153c0b | ||
|
|
9e02c99db5 | ||
|
|
ba3cee1cf1 | ||
|
|
9f59ff2df4 | ||
|
|
8df4082d6f | ||
|
|
cf005821d7 | ||
|
|
39b3996596 | ||
|
|
78357baca4 | ||
|
|
85b78dfb9b | ||
|
|
9fd60b52f1 | ||
|
|
851be41d0d | ||
|
|
c6a6a4e0e8 | ||
|
|
28aeebd4c7 | ||
|
|
c88638afe4 | ||
|
|
7f98a8b972 | ||
|
|
e1e4924592 | ||
|
|
8299f80ea5 | ||
|
|
b8ce0b0838 | ||
|
|
e13f151474 | ||
|
|
4ed4e8708e | ||
|
|
1738d118f7 | ||
|
|
f1f66d7b8f | ||
|
|
4ed5e44de7 | ||
|
|
3e3f92c616 | ||
|
|
5fb1247b87 | ||
|
|
016222463d | ||
|
|
0e477bf938 | ||
|
|
eb75eb0e55 | ||
|
|
2a703e0844 | ||
|
|
2b6d9eaa8b | ||
|
|
f9b0bb0383 | ||
|
|
c6e8873d57 | ||
|
|
b2767304e9 | ||
|
|
3d4d3ce80d | ||
|
|
01ea1854bc | ||
|
|
f3aada9e1a | ||
|
|
08fd32b3bf | ||
|
|
39a86ce5c9 | ||
|
|
fe25260ee2 | ||
|
|
63fd05c7d3 | ||
|
|
6c2aec8854 | ||
|
|
e5553f7528 | ||
|
|
6e3cec653d | ||
|
|
55976fd9dc | ||
|
|
bcbd5201e9 | ||
|
|
c2f91ea63b | ||
|
|
1d9d89b115 | ||
|
|
798dd8b27b | ||
|
|
3544f77e90 | ||
|
|
96c4463d39 | ||
|
|
650b7abef6 | ||
|
|
714b3856a2 | ||
|
|
6b939eba59 | ||
|
|
e82662b389 | ||
|
|
8f9dae8556 | ||
|
|
69ca3bc75d | ||
|
|
3945f34e96 | ||
|
|
549dcbee32 | ||
|
|
0a0c2350f2 | ||
|
|
cef2263a7f | ||
|
|
e338ce7da9 | ||
|
|
638c376e5b | ||
|
|
8eade86624 | ||
|
|
24ae8d5443 | ||
|
|
030af11d86 | ||
|
|
857a2bc399 | ||
|
|
09e6e2940f | ||
|
|
23e18a34d4 | ||
|
|
3bdef5f58d | ||
|
|
cf27581c76 | ||
|
|
cf41df82e2 | ||
|
|
4634bff9f0 | ||
|
|
1a9c658836 | ||
|
|
1a32c55ca3 | ||
|
|
f4e230f1ad | ||
|
|
9abc4cf359 | ||
|
|
c54fc7ee44 | ||
|
|
9df757a3fd | ||
|
|
9b5a885b3b | ||
|
|
f32b288785 | ||
|
|
f378119889 | ||
|
|
8fd466c5a9 | ||
|
|
36eddd48c3 | ||
|
|
2470ba76f0 | ||
|
|
d32475440a | ||
|
|
b4d73683d1 | ||
|
|
95f19a5fb2 | ||
|
|
f98780b1d7 | ||
|
|
150c89e48a | ||
|
|
c85bf82749 | ||
|
|
63227ab2f1 | ||
|
|
5b19237a85 | ||
|
|
150b8f8cbd | ||
|
|
79b97ef2f7 | ||
|
|
e45d68ad3a | ||
|
|
b40f1b67b9 | ||
|
|
4fa7e43162 | ||
|
|
66fcbcae96 | ||
|
|
7f0845dfd3 | ||
|
|
f875823357 | ||
|
|
75611866eb | ||
|
|
c3dd7ed73a | ||
|
|
3ae885d120 | ||
|
|
81f53d313c | ||
|
|
d10c86b849 | ||
|
|
9d123fa5ad | ||
|
|
f4d6a08d57 | ||
|
|
e9e641afbe | ||
|
|
8f5768f85b | ||
|
|
3dd78a2589 | ||
|
|
df92a85159 | ||
|
|
ab606a1121 | ||
|
|
457b3cf168 | ||
|
|
c6f898b8ca | ||
|
|
b9970e1908 | ||
|
|
8bb9a57908 | ||
|
|
53934a470b | ||
|
|
a94ae7d77d | ||
|
|
f43e860998 | ||
|
|
3e40852999 | ||
|
|
df073bb306 | ||
|
|
771c4a0d02 | ||
|
|
cb959ab14c | ||
|
|
34b75dac02 | ||
|
|
fbb590d9a9 | ||
|
|
ed5c533982 | ||
|
|
98d2ce5845 | ||
|
|
9d9d5e3e5d | ||
|
|
eba4626589 | ||
|
|
ff5fa1d137 | ||
|
|
71766ecd16 | ||
|
|
fc63ca6982 | ||
|
|
0e6d888ed3 | ||
|
|
9afe3b5f39 | ||
|
|
3bd40fc8b3 | ||
|
|
01fe642beb | ||
|
|
e70d57dcb4 | ||
|
|
fd41fba069 | ||
|
|
8a6fe0f321 | ||
|
|
ae73e8a305 | ||
|
|
a344c09d0d | ||
|
|
991e37d0bf | ||
|
|
fdeb884fe5 | ||
|
|
4b1f5c9c9b | ||
|
|
6b513a0f95 | ||
|
|
b574aaf99c | ||
|
|
bc0cdaa669 | ||
|
|
f9106b77bb | ||
|
|
a0419e4f34 | ||
|
|
46a549c875 | ||
|
|
f8a609f692 | ||
|
|
987497bb10 | ||
|
|
e537878b8a | ||
|
|
617f45bc59 | ||
|
|
fe744f8f81 | ||
|
|
93d879b297 | ||
|
|
dbb9295063 | ||
|
|
09aa96e486 | ||
|
|
4d0047ae7c | ||
|
|
b860a4799d | ||
|
|
6ff64352d3 | ||
|
|
3683ec6a95 | ||
|
|
454fa9ee9b | ||
|
|
d33aeb4bb2 | ||
|
|
5f9f23eb3f | ||
|
|
5dbc7a8ca4 | ||
|
|
33a5968eb7 | ||
|
|
5ff34b93c0 | ||
|
|
098fdf0596 | ||
|
|
2eb929fe05 | ||
|
|
ea0ed9e844 | ||
|
|
4a3e481a83 | ||
|
|
2197cd8620 | ||
|
|
cf0d3b5f61 | ||
|
|
6f7ab49346 | ||
|
|
000e0358a7 | ||
|
|
a3e19931f0 | ||
|
|
9fec1a86cf | ||
|
|
ffab29890b | ||
|
|
206c068d8e | ||
|
|
dc30cd1112 | ||
|
|
412a245e88 | ||
|
|
16290bf66f | ||
|
|
4f8b0e6484 | ||
|
|
5026dbc1b3 | ||
|
|
014e4b0e1d | ||
|
|
14a6947b02 | ||
|
|
665a914dc3 | ||
|
|
8feac310af | ||
|
|
3394bb4b8d | ||
|
|
1dd2bd0013 | ||
|
|
5c62726992 | ||
|
|
90981f628e | ||
|
|
0c34189d94 | ||
|
|
f1d3d6a7b5 | ||
|
|
b0d962b49a | ||
|
|
c50e453af6 | ||
|
|
efbaf02016 | ||
|
|
3cf809e99d | ||
|
|
8b649aaaf8 | ||
|
|
fdebbc4498 | ||
|
|
3ff3417ff2 | ||
|
|
bb6227281a | ||
|
|
2f44d99a74 | ||
|
|
ca4414d15a | ||
|
|
fbb961b43c | ||
|
|
fa9c174264 | ||
|
|
83f43ab166 | ||
|
|
f7e9e6a1c4 | ||
|
|
aa21748e9a | ||
|
|
a2f4e08b00 | ||
|
|
66bc29d075 | ||
|
|
e3eebe537b | ||
|
|
3ed625f949 | ||
|
|
a1e414c3b7 | ||
|
|
a5a35b1fa6 | ||
|
|
2a24584d45 | ||
|
|
6039cdceb0 | ||
|
|
473159be0f | ||
|
|
0e6ad548b2 | ||
|
|
6143515ac6 | ||
|
|
50419f200d | ||
|
|
455390f121 | ||
|
|
d375299fa9 | ||
|
|
28db337166 | ||
|
|
6ca9a599ff | ||
|
|
83bd3b6f0b | ||
|
|
a68765e021 | ||
|
|
f5ed9129cd | ||
|
|
5e3115a614 | ||
|
|
624c46f925 | ||
|
|
52d1ee161f | ||
|
|
d3bc9eb110 | ||
|
|
72b61a29c2 | ||
|
|
a99fcfe54f | ||
|
|
b5d139f7b2 | ||
|
|
463ed12ce8 | ||
|
|
baf74cb582 | ||
|
|
63d7cffefe | ||
|
|
d7d74666b2 | ||
|
|
078d76c6f3 | ||
|
|
3539ee9be6 | ||
|
|
437282b148 | ||
|
|
5394b747a1 | ||
|
|
dd1dd3b7cf | ||
|
|
ae77d4ad22 | ||
|
|
821987fed7 | ||
|
|
18ddba4332 | ||
|
|
aaad6dece6 | ||
|
|
ed04747b9d | ||
|
|
827a88d772 | ||
|
|
24e325db62 | ||
|
|
38e43bc9c8 | ||
|
|
c3c5c7ae63 | ||
|
|
578a15bbe5 | ||
|
|
6b3d7372ae | ||
|
|
55f7529167 | ||
|
|
bceae244c1 | ||
|
|
5de224d6bf | ||
|
|
694b936f30 | ||
|
|
dda25d431c | ||
|
|
22f9abc2f1 | ||
|
|
c6c3de9164 | ||
|
|
58186f0283 | ||
|
|
0253e2d3f6 | ||
|
|
ee20d5b804 | ||
|
|
3a5295dbb9 | ||
|
|
39f14fd952 | ||
|
|
4d59df9f59 | ||
|
|
b8bc114502 | ||
|
|
74d29770e1 | ||
|
|
e4d5788cdc | ||
|
|
2a5cf3e4a8 | ||
|
|
c348736058 | ||
|
|
5bb20cb039 | ||
|
|
dd602a27b5 | ||
|
|
2067de162a | ||
|
|
2cc106b43e | ||
|
|
b15bfd99b3 | ||
|
|
67252b90b3 | ||
|
|
079f7e515c | ||
|
|
e8c58270c4 | ||
|
|
0c64f278d7 | ||
|
|
03518ec94f | ||
|
|
93b5dc2dff | ||
|
|
3bef6383d9 | ||
|
|
605ccf3e02 | ||
|
|
17892238a9 | ||
|
|
b678c989e2 | ||
|
|
b72d1237d2 | ||
|
|
f7b6db5dad | ||
|
|
b744a0cc38 | ||
|
|
b918499f14 | ||
|
|
2cfd054f2c | ||
|
|
dddc7ab039 | ||
|
|
2e4d8cdc8b | ||
|
|
0640bec026 | ||
|
|
cbcee5fb45 |
32
.editorconfig
Normal file
32
.editorconfig
Normal file
@@ -0,0 +1,32 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Unix style files
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[Makefile,Makefile.*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.cmd]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = crlf
|
||||
|
||||
[*.{h,cpp}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.rc]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{md,markdown}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
32
.github/workflows/build-deb.yml
vendored
Normal file
32
.github/workflows/build-deb.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Build Debian packages
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.dist }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
dist: ['buster', 'bullseye', 'bookworm']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: change debian changelog
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install devscripts
|
||||
debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build"
|
||||
- uses: jtdor/build-deb-action@v1
|
||||
with:
|
||||
docker-image: debian:${{ matrix.dist }}-slim
|
||||
buildpackage-opts: --build=binary --no-sign
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: i2pd_${{ matrix.dist }}
|
||||
path: debian/artifacts/i2pd_*.deb
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: i2pd-dbgsym_${{ matrix.dist }}
|
||||
path: debian/artifacts/i2pd-dbgsym_*.deb
|
||||
11
.github/workflows/build-freebsd.yml
vendored
11
.github/workflows/build-freebsd.yml
vendored
@@ -4,18 +4,25 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-10.15
|
||||
runs-on: macos-12
|
||||
name: with UPnP
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v0.1.5
|
||||
uses: vmactions/freebsd-vm@v0.3.0
|
||||
with:
|
||||
usesh: true
|
||||
mem: 2048
|
||||
sync: rsync
|
||||
copyback: true
|
||||
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
|
||||
run: |
|
||||
cd build
|
||||
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
|
||||
gmake -j2
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: i2pd-freebsd
|
||||
path: build/i2pd
|
||||
1
.github/workflows/build-osx.yml
vendored
1
.github/workflows/build-osx.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: |
|
||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
||||
brew update
|
||||
brew install boost miniupnpc openssl@1.1
|
||||
- name: build application
|
||||
|
||||
64
.github/workflows/build.yml
vendored
64
.github/workflows/build.yml
vendored
@@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
build-make:
|
||||
name: Make with USE_UPNP=${{ matrix.with_upnp }}
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
@@ -14,14 +14,13 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: |
|
||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
sudo apt-get install build-essential libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
- name: build application
|
||||
run: make USE_UPNP=${{ matrix.with_upnp }} -j3
|
||||
build-cmake:
|
||||
name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }}
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
@@ -30,59 +29,26 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: |
|
||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential cmake libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
sudo apt-get install build-essential cmake libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
- name: build application
|
||||
run: |
|
||||
cd build
|
||||
cmake -DWITH_UPNP=${{ matrix.with_upnp }} .
|
||||
make -j3
|
||||
build-deb-stretch:
|
||||
name: Build package for stretch
|
||||
runs-on: ubuntu-latest
|
||||
build-static:
|
||||
name: Static build with UPnP
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: change debian changelog
|
||||
- name: install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install devscripts
|
||||
debchange -v "`git describe --tags`-stretch" -b -M --distribution stretch "trunk build"
|
||||
- uses: singingwolfboy/build-dpkg-stretch@v1
|
||||
id: build
|
||||
sudo apt-get install build-essential libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
- name: build application
|
||||
run: make DEBUG=no USE_STATIC=yes USE_UPNP=yes -j`nproc`
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
args: --unsigned-source --unsigned-changes -b
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ steps.build.outputs.filename }}
|
||||
path: ${{ steps.build.outputs.filename }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ steps.build.outputs.filename-dbgsym }}
|
||||
path: ${{ steps.build.outputs.filename-dbgsym }}
|
||||
build-deb-buster:
|
||||
name: Build package for buster
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: change debian changelog
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install devscripts
|
||||
debchange -v "`git describe --tags`-buster" -b -M --distribution buster "trunk build"
|
||||
- uses: singingwolfboy/build-dpkg-buster@v1
|
||||
id: build
|
||||
with:
|
||||
args: --unsigned-source --unsigned-changes -b
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ steps.build.outputs.filename }}
|
||||
path: ${{ steps.build.outputs.filename }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: ${{ steps.build.outputs.filename-dbgsym }}
|
||||
path: ${{ steps.build.outputs.filename-dbgsym }}
|
||||
name: i2pd-amd64-static
|
||||
path: i2pd
|
||||
|
||||
118
.github/workflows/docker.yml
vendored
118
.github/workflows/docker.yml
vendored
@@ -4,67 +4,137 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- openssl
|
||||
- docker
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
include: [
|
||||
{ platform: 'linux/amd64', archname: 'amd64' },
|
||||
{ platform: 'linux/386', archname: 'i386' },
|
||||
{ platform: 'linux/arm64', archname: 'arm64' },
|
||||
{ platform: 'linux/arm/v7', archname: 'armv7' },
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container registry
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push trunk container
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: docker/build-push-action@v2
|
||||
- name: Build container for ${{ matrix.archname }}
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: ./contrib/docker
|
||||
file: ./contrib/docker/Dockerfile
|
||||
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
|
||||
platforms: ${{ matrix.platform }}
|
||||
push: true
|
||||
tags: |
|
||||
purplei2p/i2pd:latest
|
||||
ghcr.io/purplei2p/i2pd:latest
|
||||
purplei2p/i2pd:latest-${{ matrix.archname }}
|
||||
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
|
||||
|
||||
- name: Set env
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create and push latest manifest image to Docker Hub
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
base-image: purplei2p/i2pd:latest
|
||||
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
|
||||
- name: Create and push latest manifest image to GHCR
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
base-image: ghcr.io/purplei2p/i2pd:latest
|
||||
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
|
||||
- name: Store release version to env
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build and push release container
|
||||
- name: Create and push release manifest image to Docker Hub
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: docker/build-push-action@v2
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
context: ./contrib/docker
|
||||
file: ./contrib/docker/Dockerfile
|
||||
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
|
||||
base-image: purplei2p/i2pd:latest-release
|
||||
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
|
||||
- name: Create and push release manifest image to GHCR
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
base-image: ghcr.io/purplei2p/i2pd:latest-release
|
||||
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
|
||||
- name: Create and push versioned manifest image to Docker Hub
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
base-image: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
|
||||
- name: Create and push versioned manifest image to GHCR
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: Noelware/docker-manifest-action@master
|
||||
with:
|
||||
base-image: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
|
||||
push: true
|
||||
tags: |
|
||||
purplei2p/i2pd:latest
|
||||
purplei2p/i2pd:latest-release
|
||||
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
ghcr.io/purplei2p/i2pd:latest
|
||||
ghcr.io/purplei2p/i2pd:latest-release
|
||||
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,15 +8,12 @@ netDb
|
||||
/libi2pd.a
|
||||
/libi2pdclient.a
|
||||
/libi2pdlang.a
|
||||
/libi2pdwebconsole.a
|
||||
/libi2pd.so
|
||||
/libi2pdclient.so
|
||||
/libi2pdlang.so
|
||||
/libi2pdwebconsole.so
|
||||
/libi2pd.dll
|
||||
/libi2pdclient.dll
|
||||
/libi2pdlang.dll
|
||||
/libi2pdwebconsole.dll
|
||||
*.exe
|
||||
|
||||
|
||||
|
||||
108
ChangeLog
108
ChangeLog
@@ -1,6 +1,110 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.45.1] - 2023-01-11
|
||||
### Added
|
||||
- Full Cone NAT status error
|
||||
### Changed
|
||||
- Drop duplicated I2NP messages in SSU2
|
||||
- Set rejection code 30 if tunnel with id already exists
|
||||
- Network status is always OK if peer test msg 5 received
|
||||
### Fixed
|
||||
- UPnP crash if SSU2 or NTCP2 is disabled
|
||||
- Crash on termination for some platforms
|
||||
|
||||
## [2.45.0] - 2023-01-03
|
||||
### Added
|
||||
- Test for Symmetric NAT with peer test msgs 6 and 7
|
||||
- Webconsole "No Descriptors" router error state
|
||||
- 1 and 15 seconds bandwidth calculation for i2pcontrol
|
||||
- Show non-zero send queue size for transports in web console
|
||||
- Compressible padding for I2P addresses
|
||||
- Localization to Czech
|
||||
- Don't accept incoming session from invalid/reserved addresses for NTCP2 and SSU2
|
||||
- Limit simultaneous tunnel build requests by 4 per pool
|
||||
### Changed
|
||||
- Removed SSU support
|
||||
- Reduced bandwidth calculation interval from 60 to 15 seconds
|
||||
- Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill
|
||||
- Transit tunnels limit is doubled if floodfill mode is enabled
|
||||
- NTCP2 and SSU2 timestamps are rounded to seconds
|
||||
- Drop RouterInfos and LeaseSets with timestamp from future
|
||||
- Don't delete unreachable routers if tunnel creation success rate is too low
|
||||
- Refuse duplicated incoming pending NTCP2 session from same IP
|
||||
- Don't send SSU2 termination again if termination received block received
|
||||
- Handle standard network error for SSU2 without throwing an exception
|
||||
- Don't select overloaded peer for next tunnel
|
||||
- Remove "X-Requested-With" in HTTP Proxy for non-AJAX requests
|
||||
### Fixed
|
||||
- File descriptors leak
|
||||
- Random crash on AddressBook update
|
||||
- Crash if incorrect LeaseSet size
|
||||
- Spamming to log if no descriptors
|
||||
- ::1 address in RouterInfo
|
||||
- SSU2 network error handling (especially for Windows)
|
||||
- Race condition with pending outgoing SSU2 sessions
|
||||
- RTT self-reduction for long-live streams
|
||||
|
||||
## [2.44.0] - 2022-11-20
|
||||
### Added
|
||||
- SSL connection for server I2P tunnels
|
||||
- Localization to Italian and Spanish
|
||||
- SSU2 through SOCKS5 UDP proxy
|
||||
- Reload tunnels through web console
|
||||
- SSU2 send immediate ack request flag
|
||||
- SSU2 send and verify path challenge
|
||||
- Configurable ssu2.mtu4 and ssu2.mtu6
|
||||
### Changed
|
||||
- SSU2 is enabled and SSU is disabled by default
|
||||
- Separate network status and error
|
||||
- Random selection between NTCP2 and SSU2 priority
|
||||
- Added notbob.i2p to jump services
|
||||
- Remove DoNotTrack flag from HTTP Request header
|
||||
- Skip addresshelper page if destination was not changed
|
||||
- SSU2 allow different ports from RelayReponse and HolePunch
|
||||
- SSU2 resend PeerTest msg 1 and msg 2
|
||||
- SSU2 Send Retry instead SessionCreated if clock skew detected
|
||||
### Fixed
|
||||
- Long HTTP headers for HTTP proxy and HTTP server tunnel
|
||||
- SSU2 resends and resend limits
|
||||
- Crash at startup if addressbook is disabled
|
||||
- NTCP2 ipv6 connection through SOCKS5 proxy
|
||||
- SSU2 SessionRequest with zero token
|
||||
- SSU2 MTU less than 1280
|
||||
- SSU2 port=1
|
||||
- Incorrect addresses from network interfaces
|
||||
- Definitions for Darwin PPC; do not use pthread_setname_np
|
||||
|
||||
## [2.43.0] - 2022-08-22
|
||||
### Added
|
||||
- Complete SSU2 implementation
|
||||
- Localization to Chinese
|
||||
- Send RouterInfo update for long live sessions
|
||||
- Explicit ipv6 ranges of known tunnel brokers for MTU detection
|
||||
- Always send "Connection: close" and strip out Keep-Alive for server HTTP tunnel
|
||||
- Show ports for all transports in web console
|
||||
- Translation of webconsole site title
|
||||
- Support for Windows ProgramData path when running as service
|
||||
- Ability to turn off address book
|
||||
- Handle signals TSTP and CONT to stop and resume network
|
||||
### Changed
|
||||
- Case insensitive headers for server HTTP tunnel
|
||||
- Do not show 'Address registration' line if LeaseSet is encrypted
|
||||
- SSU2 transports have higher priority than SSU
|
||||
- Disable ElGamal precalculated table if no SSU
|
||||
- Deprecate limits.ntcpsoft, limits.ntcphard and limits.ntcpthreads config options
|
||||
- SSU2 is enabled and SSU is disabled by default for new installations
|
||||
### Fixed
|
||||
- Typo with Referer header name in HTTP proxy
|
||||
- Can't handle garlic message from an exploratory tunnel
|
||||
- Incorrect encryption key for exploratory lookup reply
|
||||
- Bound checks issues in LeaseSets code
|
||||
- MTU detection on Windows
|
||||
- Crash on stop of active server tunnel
|
||||
- Send datagram to wrong destination in SAM
|
||||
- Incorrect static key in RouterInfo if the keys were regenerated
|
||||
- Duplicated sessions in BOB
|
||||
|
||||
## [2.42.1] - 2022-05-24
|
||||
### Fixed
|
||||
- Incorrect jump link in HTTP Proxy
|
||||
@@ -381,7 +485,7 @@
|
||||
### Added
|
||||
- Client auth flag for b33 address
|
||||
### Changed
|
||||
- Remove incoming NTCP2 session from pending list when established
|
||||
- Remove incoming NTCP2 session from pending list when established
|
||||
- Handle errors for NTCP2 SessionConfrimed send
|
||||
### Fixed
|
||||
- Failure to start on Windows XP
|
||||
@@ -685,7 +789,7 @@
|
||||
### Added
|
||||
- Datagram i2p tunnels
|
||||
- Unique local addresses for server tunnels
|
||||
- Configurable list of reseed servers and initial addressbook
|
||||
- Configurable list of reseed servers and initial addressbook
|
||||
- Configurable netid
|
||||
- Initial iOS support
|
||||
|
||||
|
||||
68
Makefile
68
Makefile
@@ -12,22 +12,19 @@ endif
|
||||
|
||||
SHLIB := libi2pd.$(SHARED_SUFFIX)
|
||||
ARLIB := libi2pd.a
|
||||
SHLIB_CLIENT := libi2pdclient.$(SHARED_SUFFIX)
|
||||
ARLIB_CLIENT := libi2pdclient.a
|
||||
SHLIB_LANG := libi2pdlang.$(SHARED_SUFFIX)
|
||||
ARLIB_LANG := libi2pdlang.a
|
||||
SHLIB_WEBCONSOLE := libi2pdwebconsole.$(SHARED_SUFFIX)
|
||||
ARLIB_WEBCONSOLE := libi2pdwebconsole.a
|
||||
SHLIB_CLIENT := libi2pdclient.$(SHARED_SUFFIX)
|
||||
ARLIB_CLIENT := libi2pdclient.a
|
||||
SHLIB_WRAP := libi2pdwrapper.$(SHARED_SUFFIX)
|
||||
ARLIB_WRAP := libi2pdwrapper.a
|
||||
I2PD := i2pd
|
||||
|
||||
LIB_SRC_DIR := libi2pd
|
||||
LIB_CLIENT_SRC_DIR := libi2pd_client
|
||||
WEBCONSOLE_SRC_DIR := libi2pd_webconsole
|
||||
WRAP_SRC_DIR := libi2pd_wrapper
|
||||
LANG_SRC_DIR := i18n
|
||||
DAEMON_SRC_DIR := daemon
|
||||
WRAP_SRC_DIR := libi2pd_wrapper
|
||||
|
||||
# import source files lists
|
||||
include filelist.mk
|
||||
@@ -50,22 +47,26 @@ else
|
||||
LD_DEBUG = -s
|
||||
endif
|
||||
|
||||
ifneq (, $(DESTDIR))
|
||||
PREFIX = $(DESTDIR)
|
||||
endif
|
||||
|
||||
ifneq (, $(findstring darwin, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
ifeq ($(HOMEBREW),1)
|
||||
include Makefile.homebrew
|
||||
else
|
||||
include Makefile.osx
|
||||
endif
|
||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
|
||||
include Makefile.mingw
|
||||
else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.linux
|
||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
|
||||
include Makefile.mingw
|
||||
else # not supported
|
||||
$(error Not supported platform)
|
||||
endif
|
||||
@@ -75,34 +76,31 @@ ifeq ($(USE_GIT_VERSION),yes)
|
||||
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
|
||||
endif
|
||||
|
||||
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -I$(WEBCONSOLE_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
|
||||
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
|
||||
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
|
||||
LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC))
|
||||
WEBCONSOLE_OBJS += $(patsubst %.cpp,obj/%.o,$(WEBCONSOLE_SRC))
|
||||
DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC))
|
||||
WRAP_LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(WRAP_LIB_SRC))
|
||||
DEPS += $(LIB_OBJS:.o=.d) $(LIB_CLIENT_OBJS:.o=.d) $(LANG_OBJS:.o=.d) $(WEBCONSOLE_OBJS:.o=.d) $(DAEMON_OBJS:.o=.d) $(WRAP_LIB_OBJS:.o=.d)
|
||||
DEPS += $(LIB_OBJS:.o=.d) $(LIB_CLIENT_OBJS:.o=.d) $(LANG_OBJS:.o=.d) $(DAEMON_OBJS:.o=.d) $(WRAP_LIB_OBJS:.o=.d)
|
||||
|
||||
## Build all code (libi2pd, libi2pdclient, libi2pdlang), link it to .a and build binary
|
||||
all: $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(ARLIB_WEBCONSOLE) $(I2PD)
|
||||
all: $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(I2PD)
|
||||
|
||||
mk_obj_dir:
|
||||
@mkdir -p obj/$(LIB_SRC_DIR)
|
||||
@mkdir -p obj/$(LIB_CLIENT_SRC_DIR)
|
||||
@mkdir -p obj/$(LANG_SRC_DIR)
|
||||
@mkdir -p obj/$(WEBCONSOLE_SRC_DIR)
|
||||
@mkdir -p obj/$(DAEMON_SRC_DIR)
|
||||
@mkdir -p obj/$(WRAP_SRC_DIR)
|
||||
@mkdir -p obj/Win32
|
||||
|
||||
api: $(SHLIB) $(ARLIB)
|
||||
client: $(SHLIB_CLIENT) $(ARLIB_CLIENT)
|
||||
lang: $(SHLIB_LANG) $(ARLIB_LANG)
|
||||
webconsole: $(SHLIB_WEBCONSOLE) $(ARLIB_WEBCONSOLE)
|
||||
api_client: api client lang webconsole
|
||||
wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
|
||||
api: $(SHLIB) $(ARLIB)
|
||||
client: $(SHLIB_CLIENT) $(ARLIB_CLIENT)
|
||||
lang: $(SHLIB_LANG) $(ARLIB_LANG)
|
||||
api_client: api client lang
|
||||
wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
|
||||
|
||||
## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
@@ -117,7 +115,7 @@ obj/%.o: %.cpp | mk_obj_dir
|
||||
# '-' is 'ignore if missing' on first run
|
||||
-include $(DEPS)
|
||||
|
||||
$(I2PD): $(DAEMON_OBJS) $(ARLIB_WEBCONSOLE) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
|
||||
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
|
||||
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
|
||||
|
||||
$(SHLIB): $(LIB_OBJS) $(SHLIB_LANG)
|
||||
@@ -130,17 +128,12 @@ ifneq ($(USE_STATIC),yes)
|
||||
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) $(SHLIB_LANG)
|
||||
endif
|
||||
|
||||
$(SHLIB_LANG): $(LANG_OBJS)
|
||||
$(SHLIB_WRAP): $(WRAP_LIB_OBJS)
|
||||
ifneq ($(USE_STATIC),yes)
|
||||
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
|
||||
endif
|
||||
|
||||
$(SHLIB_WEBCONSOLE): $(WEBCONSOLE_OBJS) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
|
||||
ifneq ($(USE_STATIC),yes)
|
||||
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
|
||||
endif
|
||||
|
||||
$(SHLIB_WRAP): $(WRAP_LIB_OBJS)
|
||||
$(SHLIB_LANG): $(LANG_OBJS)
|
||||
ifneq ($(USE_STATIC),yes)
|
||||
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
|
||||
endif
|
||||
@@ -151,21 +144,18 @@ $(ARLIB): $(LIB_OBJS)
|
||||
$(ARLIB_CLIENT): $(LIB_CLIENT_OBJS)
|
||||
$(AR) -r $@ $^
|
||||
|
||||
$(ARLIB_LANG): $(LANG_OBJS)
|
||||
$(AR) -r $@ $^
|
||||
|
||||
$(ARLIB_WEBCONSOLE): $(WEBCONSOLE_OBJS)
|
||||
$(AR) -r $@ $^
|
||||
|
||||
$(ARLIB_WRAP): $(WRAP_LIB_OBJS)
|
||||
$(AR) -r $@ $^
|
||||
|
||||
$(ARLIB_LANG): $(LANG_OBJS)
|
||||
$(AR) -r $@ $^
|
||||
|
||||
clean:
|
||||
$(RM) -r obj
|
||||
$(RM) -r docs/generated
|
||||
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) $(SHLIB_WEBCONSOLE) $(ARLIB_WEBCONSOLE) $(SHLIB_WRAP) $(ARLIB_WRAP)
|
||||
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) $(SHLIB_WRAP) $(ARLIB_WRAP)
|
||||
|
||||
strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG) $(SHLIB_WEBCONSOLE)
|
||||
strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
|
||||
strip $^
|
||||
|
||||
LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl)
|
||||
|
||||
@@ -39,13 +39,18 @@ ifeq ($(USE_AESNI),yes)
|
||||
endif
|
||||
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||
install -d ${PREFIX}/bin
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin
|
||||
install -d ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d
|
||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -d ${PREFIX}/share ${PREFIX}/share/doc ${PREFIX}/share/doc/i2pd
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||
install -d ${PREFIX}/share/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -d ${PREFIX}/share/man ${PREFIX}/share/man/man1
|
||||
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
install -d ${PREFIX}/var ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/certificates
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
|
||||
@@ -20,7 +20,11 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9
|
||||
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
LDLIBS = -latomic
|
||||
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
|
||||
else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9
|
||||
NEEDED_CXXFLAGS += -std=c++17
|
||||
LDLIBS = -latomic
|
||||
else ifeq ($(shell expr match ${CXXVER} "1[0-9]"),2) # gcc 10+
|
||||
# NEEDED_CXXFLAGS += -std=c++20
|
||||
NEEDED_CXXFLAGS += -std=c++17
|
||||
LDLIBS = -latomic
|
||||
else # not supported
|
||||
@@ -29,34 +33,23 @@ endif
|
||||
|
||||
NEEDED_CXXFLAGS += -fPIC
|
||||
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
# NOTE: on glibc you will get this warning:
|
||||
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
||||
# the shared libraries from the glibc version used for linking
|
||||
LIBDIR := /usr/lib/$(SYS)
|
||||
LDLIBS += $(LIBDIR)/libboost_system.a
|
||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||
LDLIBS += $(LIBDIR)/libssl.a
|
||||
LDLIBS += $(LIBDIR)/libcrypto.a
|
||||
LDLIBS += $(LIBDIR)/libz.a
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
LDLIBS += $(LIBDIR)/libminiupnpc.a
|
||||
endif
|
||||
LDLIBS += -lpthread -ldl
|
||||
else
|
||||
LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
LDLIBS += -lminiupnpc
|
||||
endif
|
||||
endif
|
||||
LDLIBS += -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lssl -lcrypto -lz
|
||||
|
||||
# UPNP Support (miniupnpc 1.5 and higher)
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
LDLIBS += -lminiupnpc
|
||||
NEEDED_CXXFLAGS += -DUSE_UPNP
|
||||
endif
|
||||
|
||||
# NOTE: on glibc you will get this warning:
|
||||
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
||||
# the shared libraries from the glibc version used for linking
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS += -static -ldl -lpthread -static-libgcc -static-libstdc++
|
||||
else
|
||||
LDLIBS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
|
||||
NEEDED_CXXFLAGS += -D__AES__ -maes
|
||||
@@ -64,13 +57,18 @@ endif
|
||||
endif
|
||||
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/usr ${PREFIX}/usr/share ${PREFIX}/usr/share/doc/i2pd ${PREFIX}/usr/share/i2pd ${PREFIX}/usr/share/man ${PREFIX}/usr/share/man/man1 ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||
install -d ${PREFIX}/bin
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin
|
||||
install -d ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d
|
||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/usr/share/i2pd/
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/usr/share/doc/i2pd
|
||||
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/usr/share/man/man1
|
||||
@ln -sf ${PREFIX}/usr/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
install -d ${PREFIX}/share ${PREFIX}/share/doc ${PREFIX}/share/doc/i2pd
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||
install -d ${PREFIX}/share/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -d ${PREFIX}/share/man ${PREFIX}/share/man/man1
|
||||
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
||||
install -d ${PREFIX}/var ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/certificates
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
|
||||
@@ -4,7 +4,7 @@ USE_WIN32_APP := yes
|
||||
WINDRES = windres
|
||||
|
||||
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
|
||||
INCFLAGS = -IWin32
|
||||
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
|
||||
LDFLAGS := ${LD_DEBUG} -static
|
||||
|
||||
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
|
||||
|
||||
10
README.md
10
README.md
@@ -69,12 +69,12 @@ Build instructions:
|
||||
|
||||
**Supported systems:**
|
||||
|
||||
* GNU/Linux - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml)
|
||||
* CentOS / Fedora / Mageia - [](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
|
||||
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
|
||||
* GNU/Linux (Debian, Ubuntu, etc) - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml)
|
||||
* CentOS, Fedora, Mageia - [](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
|
||||
* Alpine, ArchLinux, openSUSE, Gentoo, etc.
|
||||
* Windows - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml)
|
||||
* Mac OS X - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml)
|
||||
* Docker image - [](https://hub.docker.com/r/purplei2p/i2pd/builds/) [](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml)
|
||||
* Mac OS - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml)
|
||||
* Docker image - [](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml)
|
||||
* Snap - [](https://snapcraft.io/i2pd) [](https://snapcraft.io/i2pd)
|
||||
* FreeBSD - [](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml)
|
||||
* Android - [](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml)
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <thread>
|
||||
#include <clocale>
|
||||
#include "Config.h"
|
||||
@@ -15,6 +13,7 @@
|
||||
#include "util.h"
|
||||
#include "Log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Win32Service.h"
|
||||
#ifdef WIN32_APP
|
||||
#include <windows.h>
|
||||
@@ -30,7 +29,7 @@ namespace util
|
||||
setlocale(LC_CTYPE, "");
|
||||
SetConsoleCP(1251);
|
||||
SetConsoleOutputCP(1251);
|
||||
setlocale(LC_ALL, "Russian");
|
||||
//setlocale(LC_ALL, "Russian");
|
||||
setlocale(LC_TIME, "C");
|
||||
|
||||
i2p::log::SetThrowFunction ([](const std::string& s)
|
||||
@@ -39,9 +38,6 @@ namespace util
|
||||
}
|
||||
);
|
||||
|
||||
i2p::win32::SetIsGraceful (std::bind (&DaemonWin32::SetIsGraceful, this, std::placeholders::_1));
|
||||
i2p::win32::GetIsGraceful (std::bind (&DaemonWin32::GetIsGraceful, this));
|
||||
|
||||
if (!Daemon_Singleton::init(argc, argv))
|
||||
return false;
|
||||
|
||||
@@ -49,8 +45,6 @@ namespace util
|
||||
{
|
||||
LogPrint(eLogDebug, "Daemon: running as service");
|
||||
I2PService service((PSTR)SERVICE_NAME);
|
||||
service.SetDaemonStart (std::bind (&DaemonWin32::start, this));
|
||||
service.SetDaemonStop (std::bind (&DaemonWin32::stop, this));
|
||||
if (!I2PService::Run(service))
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
|
||||
@@ -67,7 +61,7 @@ namespace util
|
||||
setlocale(LC_CTYPE, "");
|
||||
SetConsoleCP(1251);
|
||||
SetConsoleOutputCP(1251);
|
||||
setlocale(LC_ALL, "Russian");
|
||||
//setlocale(LC_ALL, "Russian");
|
||||
setlocale(LC_TIME, "C");
|
||||
#ifdef WIN32_APP
|
||||
if (!i2p::win32::StartWin32App ()) return false;
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "Tunnel.h"
|
||||
#include "version.h"
|
||||
#include "resource.h"
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "Win32App.h"
|
||||
#include "Win32NetState.h"
|
||||
|
||||
@@ -55,15 +55,13 @@ namespace win32
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
||||
if(!i2p::context.AcceptsTunnels())
|
||||
if(m_getIsGraceful)
|
||||
if(m_getIsGraceful())
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING | MF_GRAYED, ID_ACCEPT_TRANSIT, "Accept &transit");
|
||||
else
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ACCEPT_TRANSIT, "Accept &transit");
|
||||
InsertMenu (hPopup, -1,
|
||||
i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING,
|
||||
ID_ACCEPT_TRANSIT, "Accept &transit");
|
||||
else
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit");
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config");
|
||||
if (!m_getIsGraceful)
|
||||
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
|
||||
else
|
||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown");
|
||||
@@ -156,25 +154,23 @@ namespace win32
|
||||
case eRouterStatusUnknown: s << "Unk"; break;
|
||||
case eRouterStatusProxy: s << "Proxy"; break;
|
||||
case eRouterStatusMesh: s << "Mesh"; break;
|
||||
case eRouterStatusError:
|
||||
{
|
||||
s << "Err";
|
||||
switch (i2p::context.GetError ())
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << " - Clock skew";
|
||||
break;
|
||||
case eRouterErrorOffline:
|
||||
s << " - Offline";
|
||||
break;
|
||||
case eRouterErrorSymmetricNAT:
|
||||
s << " - Symmetric NAT";
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: s << "Unk";
|
||||
};
|
||||
if (i2p::context.GetError () != eRouterErrorNone)
|
||||
{
|
||||
switch (i2p::context.GetError ())
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << " - Clock skew";
|
||||
break;
|
||||
case eRouterErrorOffline:
|
||||
s << " - Offline";
|
||||
break;
|
||||
case eRouterErrorSymmetricNAT:
|
||||
s << " - Symmetric NAT";
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +268,7 @@ namespace win32
|
||||
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
|
||||
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second
|
||||
g_GracefulShutdownEndtime = GetTickCount() + 10*60*1000;
|
||||
if (m_setIsGraceful) m_setIsGraceful(true);
|
||||
i2p::util::DaemonWin32::Instance ().isGraceful = true;
|
||||
return 0;
|
||||
}
|
||||
case ID_STOP_GRACEFUL_SHUTDOWN:
|
||||
@@ -281,7 +277,7 @@ namespace win32
|
||||
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
|
||||
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
|
||||
g_GracefulShutdownEndtime = 0;
|
||||
if (m_setIsGraceful) m_setIsGraceful(false);
|
||||
i2p::util::DaemonWin32::Instance ().isGraceful = false;
|
||||
return 0;
|
||||
}
|
||||
case ID_RELOAD:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -22,15 +22,6 @@ namespace win32
|
||||
int RunWin32App ();
|
||||
bool GracefulShutdown ();
|
||||
bool StopGracefulShutdown ();
|
||||
|
||||
inline typedef std::function<void (bool)> DaemonSetIsGraceful;
|
||||
inline DaemonSetIsGraceful m_setIsGraceful;
|
||||
inline void SetIsGraceful (const DaemonSetIsGraceful& f) { m_setIsGraceful = f; };
|
||||
|
||||
inline typedef std::function<bool ()> DaemonGetIsGraceful;
|
||||
inline DaemonGetIsGraceful m_getIsGraceful;
|
||||
inline void GetIsGraceful (const DaemonGetIsGraceful& f) { m_getIsGraceful = f; };
|
||||
|
||||
}
|
||||
}
|
||||
#endif // WIN32APP_H__
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "Log.h"
|
||||
|
||||
I2PService *I2PService::s_service = NULL;
|
||||
@@ -131,13 +132,7 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
|
||||
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
|
||||
{
|
||||
LogPrint(eLogInfo, "Win32Service: in OnStart (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||
if(m_daemonStart)
|
||||
m_daemonStart();
|
||||
else
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: failed to start: Unable to call callback");
|
||||
SetServiceStatus(SERVICE_STOPPED);
|
||||
}
|
||||
Daemon.start();
|
||||
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
|
||||
}
|
||||
|
||||
@@ -176,11 +171,7 @@ void I2PService::OnStop()
|
||||
{
|
||||
// Log a service stop message to the Application log.
|
||||
LogPrint(eLogInfo, "Win32Service: in OnStop (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||
if(m_daemonStop)
|
||||
m_daemonStop();
|
||||
else
|
||||
LogPrint(eLogError, "Win32Service: failed to stop: Unable to call callback");
|
||||
|
||||
Daemon.stop();
|
||||
m_fStopping = TRUE;
|
||||
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifndef WIN32SERVICE_H__
|
||||
#define WIN32SERVICE_H__
|
||||
#ifndef WIN_32_SERVICE_H__
|
||||
#define WIN_32_SERVICE_H__
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <windows.h>
|
||||
|
||||
@@ -30,13 +29,6 @@ class I2PService
|
||||
static BOOL Run(I2PService &service);
|
||||
void Stop();
|
||||
|
||||
typedef std::function<bool ()> DaemonStart;
|
||||
void SetDaemonStart (const DaemonStart& f) { m_daemonStart = f; };
|
||||
|
||||
typedef std::function<bool ()> DaemonStop;
|
||||
void SetDaemonStop (const DaemonStop& f) { m_daemonStop = f; };
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
||||
@@ -66,11 +58,6 @@ class I2PService
|
||||
HANDLE m_hStoppedEvent;
|
||||
|
||||
std::thread* _worker;
|
||||
|
||||
private:
|
||||
|
||||
DaemonStart m_daemonStart;
|
||||
DaemonStop m_daemonStop;
|
||||
};
|
||||
|
||||
#endif // WIN32SERVICE_H__
|
||||
#endif // WIN_32_SERVICE_H__
|
||||
|
||||
@@ -17,14 +17,20 @@ option(WITH_LIBRARY "Build library" ON)
|
||||
option(WITH_BINARY "Build binary" ON)
|
||||
option(WITH_STATIC "Static build" OFF)
|
||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||
option(WITH_GIT_VERSION "Use git commit info as version" OFF)
|
||||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
||||
option(BUILD_TESTING "Build tests" OFF)
|
||||
|
||||
IF(BUILD_TESTING)
|
||||
enable_testing()
|
||||
ENDIF()
|
||||
|
||||
# paths
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
||||
set(CMAKE_SOURCE_DIR "..")
|
||||
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||
|
||||
#Handle paths nicely
|
||||
# Handle paths nicely
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# architecture
|
||||
@@ -33,13 +39,11 @@ target_architecture(ARCHITECTURE)
|
||||
|
||||
set(LIBI2PD_SRC_DIR ../libi2pd)
|
||||
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
|
||||
set(WEBCONSOLE_SRC_DIR ../libi2pd_webconsole)
|
||||
set(LANG_SRC_DIR ../i18n)
|
||||
set(DAEMON_SRC_DIR ../daemon)
|
||||
|
||||
include_directories(${LIBI2PD_SRC_DIR})
|
||||
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
|
||||
include_directories(${WEBCONSOLE_SRC_DIR})
|
||||
include_directories(${LANG_SRC_DIR})
|
||||
include_directories(${DAEMON_SRC_DIR})
|
||||
|
||||
@@ -70,18 +74,6 @@ if(WITH_LIBRARY)
|
||||
COMPONENT Libraries)
|
||||
endif()
|
||||
|
||||
FILE(GLOB WEBCONSOLE_SRC ${WEBCONSOLE_SRC_DIR}/*.cpp)
|
||||
add_library(libi2pdwebconsole ${WEBCONSOLE_SRC})
|
||||
set_target_properties(libi2pdwebconsole PROPERTIES PREFIX "")
|
||||
|
||||
if(WITH_LIBRARY)
|
||||
install(TARGETS libi2pdwebconsole
|
||||
EXPORT libi2pdwebconsole
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT Libraries)
|
||||
endif()
|
||||
|
||||
FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp)
|
||||
add_library(libi2pdlang ${LANG_SRC})
|
||||
set_target_properties(libi2pdlang PROPERTIES PREFIX "")
|
||||
@@ -96,7 +88,9 @@ endif()
|
||||
|
||||
set(DAEMON_SRC
|
||||
"${DAEMON_SRC_DIR}/Daemon.cpp"
|
||||
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
|
||||
"${DAEMON_SRC_DIR}/I2PControl.cpp"
|
||||
"${DAEMON_SRC_DIR}/I2PControlHandlers.cpp"
|
||||
"${DAEMON_SRC_DIR}/i2pd.cpp"
|
||||
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
||||
)
|
||||
@@ -105,6 +99,12 @@ if(WITH_UPNP)
|
||||
add_definitions(-DUSE_UPNP)
|
||||
endif()
|
||||
|
||||
if(WITH_GIT_VERSION)
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_VERSION)
|
||||
add_definitions(-DGITVER="${GIT_VERSION}")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
add_definitions(-DMAC_OSX)
|
||||
endif()
|
||||
@@ -148,7 +148,7 @@ endif()
|
||||
|
||||
# compiler flags customization(by system)
|
||||
if(UNIX)
|
||||
list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/DaemonUnix.cpp")
|
||||
list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||
if(NOT(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE))
|
||||
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
||||
add_definitions("-D_GLIBCXX_USE_NANOSLEEP=1")
|
||||
@@ -176,6 +176,11 @@ if(WITH_THREADSANITIZER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Use std::atomic instead of GCC builtins on macOS PowerPC:
|
||||
# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
add_definitions(-DBOOST_SP_USE_STD_ATOMIC)
|
||||
endif()
|
||||
|
||||
# libraries
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
@@ -184,6 +189,7 @@ find_package(Threads REQUIRED)
|
||||
if(WITH_STATIC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
set(OPENSSL_USE_STATIC_LIBS ON)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
@@ -198,8 +204,6 @@ else()
|
||||
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
|
||||
endif()
|
||||
|
||||
target_link_libraries(libi2pdwebconsole libi2pdclient libi2pd libi2pdlang)
|
||||
|
||||
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
|
||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
||||
@@ -248,6 +252,7 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
|
||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||
message(STATUS "---------------------------------------")
|
||||
@@ -263,25 +268,23 @@ if(WITH_BINARY)
|
||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
|
||||
endif()
|
||||
|
||||
if(WITH_UPNP)
|
||||
set(UPNP_LIB ${MINIUPNPC_LIBRARY})
|
||||
endif()
|
||||
|
||||
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
||||
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
||||
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
||||
list(REMOVE_AT Boost_LIBRARIES -1)
|
||||
endif()
|
||||
|
||||
|
||||
if(WITH_STATIC)
|
||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
|
||||
target_link_libraries("${PROJECT_NAME}" libi2pdwebconsole libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
||||
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
||||
|
||||
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin")
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||
endif()
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
# atomic builtins are required for threading support.
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
std::atomic<int> x;
|
||||
std::atomic<short> y;
|
||||
std::atomic<char> z;
|
||||
int main() {
|
||||
return x;
|
||||
++z;
|
||||
++y;
|
||||
return ++x;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
@@ -27,6 +32,7 @@ function(check_working_cxx_atomics64 varname)
|
||||
std::atomic<uint64_t> x (0);
|
||||
int main() {
|
||||
uint64_t i = x.load(std::memory_order_relaxed);
|
||||
(void)i;
|
||||
return 0;
|
||||
}
|
||||
" ${varname})
|
||||
@@ -34,15 +40,16 @@ int main() {
|
||||
endfunction(check_working_cxx_atomics64)
|
||||
|
||||
|
||||
# This isn't necessary on MSVC, so avoid command-line switch annoyance
|
||||
# by only running on GCC-like hosts.
|
||||
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
|
||||
# Check for (non-64-bit) atomic operations.
|
||||
if(MSVC)
|
||||
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)
|
||||
else()
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if( HAVE_LIBATOMIC )
|
||||
if(HAVE_LIBATOMIC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
@@ -58,20 +65,20 @@ endif()
|
||||
if(MSVC)
|
||||
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
|
||||
else()
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
endif()
|
||||
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
|
||||
if(HAVE_CXX_LIBATOMICS64)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
|
||||
if(HAVE_CXX_LIBATOMICS64)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -80,7 +87,6 @@ endif()
|
||||
## assumes C++11 <atomic> works.
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifdef _MSC_VER
|
||||
#include <Intrin.h> /* Workaround for PR19898. */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
int main() {
|
||||
|
||||
55
build/cmake_modules/FindCheck.cmake
Normal file
55
build/cmake_modules/FindCheck.cmake
Normal file
@@ -0,0 +1,55 @@
|
||||
# - Try to find the CHECK libraries
|
||||
# Once done this will define
|
||||
#
|
||||
# CHECK_FOUND - system has check
|
||||
# CHECK_INCLUDE_DIRS - the check include directory
|
||||
# CHECK_LIBRARIES - check library
|
||||
#
|
||||
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
|
||||
# Copyright (c) 2007-2009 Bjoern Ricks <bjoern.ricks@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE( FindPkgConfig )
|
||||
|
||||
IF ( Check_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "REQUIRED" )
|
||||
ELSE( Check_FIND_REQUIRED )
|
||||
SET( _pkgconfig_REQUIRED "" )
|
||||
ENDIF ( Check_FIND_REQUIRED )
|
||||
|
||||
IF ( CHECK_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} )
|
||||
ELSE ( CHECK_MIN_VERSION )
|
||||
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check )
|
||||
ENDIF ( CHECK_MIN_VERSION )
|
||||
|
||||
# Look for CHECK include dir and libraries
|
||||
IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
|
||||
FIND_PATH( CHECK_INCLUDE_DIRS check.h )
|
||||
|
||||
FIND_LIBRARY( CHECK_LIBRARIES NAMES check )
|
||||
|
||||
IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
|
||||
SET( CHECK_FOUND 1 )
|
||||
IF ( NOT Check_FIND_QUIETLY )
|
||||
MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" )
|
||||
ENDIF ( NOT Check_FIND_QUIETLY )
|
||||
ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
|
||||
IF ( Check_FIND_REQUIRED )
|
||||
MESSAGE( FATAL_ERROR "Could NOT find CHECK" )
|
||||
ELSE ( Check_FIND_REQUIRED )
|
||||
IF ( NOT Check_FIND_QUIETLY )
|
||||
MESSAGE( STATUS "Could NOT find CHECK" )
|
||||
ENDIF ( NOT Check_FIND_QUIETLY )
|
||||
ENDIF ( Check_FIND_REQUIRED )
|
||||
ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
|
||||
ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||
|
||||
# Hide advanced variables from CMake GUIs
|
||||
MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES )
|
||||
|
||||
284
build/cmake_modules/GetGitRevisionDescription.cmake
Normal file
284
build/cmake_modules/GetGitRevisionDescription.cmake
Normal file
@@ -0,0 +1,284 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the working tree (--dirty option),
|
||||
# and adjusting the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
#
|
||||
# Copyright 2009-2013, Iowa State University.
|
||||
# Copyright 2013-2020, Ryan Pavlik
|
||||
# Copyright 2013-2020, Contributors
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||
# that is part of any directory in the path defined by _start_dir.
|
||||
# The result is returned in the parent scope variable whose name is passed
|
||||
# as variable _git_dir_var. If no .git directory can be found, the
|
||||
# function returns an empty string via _git_dir_var.
|
||||
#
|
||||
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||
# neither foo nor bar contain a file/directory .git. This wil return
|
||||
# C:/bla/.git
|
||||
#
|
||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||
set(cur_dir "${_start_dir}")
|
||||
set(git_dir "${_start_dir}/.git")
|
||||
while(NOT EXISTS "${git_dir}")
|
||||
# .git dir not found, search parent directories
|
||||
set(git_previous_parent "${cur_dir}")
|
||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||
if(cur_dir STREQUAL git_previous_parent)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_git_dir_var}
|
||||
""
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(git_dir "${cur_dir}/.git")
|
||||
endwhile()
|
||||
set(${_git_dir_var}
|
||||
"${git_dir}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||
|
||||
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||
else()
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||
endif()
|
||||
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||
"${GIT_DIR}")
|
||||
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||
# We've gone above the CMake root dir.
|
||||
set(GIT_DIR "")
|
||||
endif()
|
||||
endif()
|
||||
if("${GIT_DIR}" STREQUAL "")
|
||||
set(${_refspecvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if the current source dir is a git submodule or a worktree.
|
||||
# In both cases .git is a file instead of a directory.
|
||||
#
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
# The following git command will return a non empty string that
|
||||
# points to the super project working tree if the current
|
||||
# source dir is inside a git submodule.
|
||||
# Otherwise the command will return an empty string.
|
||||
#
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||
--show-superproject-working-tree
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT "${out}" STREQUAL "")
|
||||
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||
${submodule})
|
||||
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||
ABSOLUTE)
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
else()
|
||||
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||
file(READ ${GIT_DIR} worktree_ref)
|
||||
# The .git directory contains a path to the worktree information directory
|
||||
# inside the parent git repo of the worktree.
|
||||
#
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||
${worktree_ref})
|
||||
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||
endif()
|
||||
else()
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar}
|
||||
"${HEAD_REF}"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"${HEAD_HASH}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe_working_tree _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var}
|
||||
"CLEAN"
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var}
|
||||
"DIRTY"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
43
build/cmake_modules/GetGitRevisionDescription.cmake.in
Normal file
43
build/cmake_modules/GetGitRevisionDescription.cmake.in
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright 2009-2012, Iowa State University
|
||||
# Copyright 2011-2015, Contributors
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
@@ -61,7 +61,7 @@ set(archdetect_c_code "
|
||||
#else
|
||||
#error cmake_ARCH mips
|
||||
#endif
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(__POWERPC__) \\
|
||||
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
||||
|| defined(_M_MPPC) || defined(_M_PPC)
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2017-2022, The PurpleI2P Project
|
||||
#
|
||||
# This file is part of Purple i2pd project and licensed under BSD3
|
||||
#
|
||||
# See full license text in LICENSE file at top of project tree
|
||||
#
|
||||
|
||||
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>"
|
||||
LABEL maintainer="R4SAS <r4sas@i2pmail.org>"
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/PurpleI2P/i2pd
|
||||
LABEL org.opencontainers.image.documentation=https://i2pd.readthedocs.io/en/latest/
|
||||
LABEL org.opencontainers.image.licenses=BSD3
|
||||
|
||||
# Expose git branch, tag and URL variables as arguments
|
||||
ARG GIT_BRANCH="openssl"
|
||||
@@ -11,27 +24,28 @@ ENV REPO_URL=${REPO_URL}
|
||||
|
||||
ENV I2PD_HOME="/home/i2pd"
|
||||
ENV DATA_DIR="${I2PD_HOME}/data"
|
||||
ENV DEFAULT_ARGS=" --datadir=$DATA_DIR --reseed.verify=true --upnp.enabled=false --http.enabled=true --http.address=0.0.0.0 --httpproxy.enabled=true --httpproxy.address=0.0.0.0 --socksproxy.enabled=true --socksproxy.address=0.0.0.0 --sam.enabled=true --sam.address=0.0.0.0"
|
||||
ENV DEFAULT_ARGS=" --datadir=$DATA_DIR"
|
||||
|
||||
RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
|
||||
&& adduser -S -h "$I2PD_HOME" i2pd \
|
||||
&& chown -R i2pd:nobody "$I2PD_HOME"
|
||||
|
||||
#
|
||||
# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the
|
||||
# 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.
|
||||
# 1. Building binary
|
||||
# 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 update \
|
||||
&& apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl miniupnpc-dev git \
|
||||
&& mkdir -p /tmp/build \
|
||||
&& cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \
|
||||
&& cd i2pd \
|
||||
&& if [ -n "${GIT_TAG}" ]; then git checkout tags/${GIT_TAG}; fi \
|
||||
&& make USE_UPNP=yes \
|
||||
&& make -j$(nproc) USE_UPNP=yes \
|
||||
&& cp -R contrib/certificates /i2pd_certificates \
|
||||
&& mkdir -p /usr/local/bin \
|
||||
&& mv i2pd /usr/local/bin \
|
||||
@@ -45,6 +59,9 @@ RUN apk update \
|
||||
# 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 miniupnpc musl-utils libstdc++
|
||||
|
||||
# 3. Copy preconfigured config file and entrypoint
|
||||
COPY i2pd-docker.conf "$DATA_DIR/i2pd.conf"
|
||||
RUN chown i2pd:nobody "$DATA_DIR/i2pd.conf"
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod a+x /entrypoint.sh
|
||||
|
||||
|
||||
52
contrib/docker/i2pd-docker.conf
Normal file
52
contrib/docker/i2pd-docker.conf
Normal file
@@ -0,0 +1,52 @@
|
||||
## Preconfigured i2pd configuration file for a Docker container
|
||||
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
## for more options you can use in this file.
|
||||
|
||||
## Note that for exposing ports outside of container you need to bind all services to 0.0.0.0
|
||||
|
||||
log = file
|
||||
loglevel = none
|
||||
|
||||
ipv4 = true
|
||||
ipv6 = false
|
||||
|
||||
# bandwidth = L
|
||||
# notransit = false
|
||||
# floodfill = false
|
||||
|
||||
[ntcp2]
|
||||
enabled = true
|
||||
published = true
|
||||
|
||||
[ssu2]
|
||||
enabled = true
|
||||
published = true
|
||||
|
||||
[http]
|
||||
enabled = true
|
||||
address = 0.0.0.0
|
||||
port = 7070
|
||||
|
||||
[httpproxy]
|
||||
enabled = true
|
||||
address = 0.0.0.0
|
||||
port = 4444
|
||||
|
||||
[socksproxy]
|
||||
enabled = true
|
||||
address = 0.0.0.0
|
||||
port = 4447
|
||||
|
||||
[sam]
|
||||
enabled = true
|
||||
address = 0.0.0.0
|
||||
port = 7656
|
||||
|
||||
[upnp]
|
||||
enabled = false
|
||||
|
||||
[reseed]
|
||||
verify = true
|
||||
|
||||
[limits]
|
||||
# transittunnels = 2500
|
||||
@@ -1,13 +1,13 @@
|
||||
# i2pd
|
||||
# Copyright (C) 2021 PurpleI2P team
|
||||
# Copyright (C) 2021-2023 PurpleI2P team
|
||||
# This file is distributed under the same license as the i2pd package.
|
||||
# R4SAS <r4sas@i2pmail.org>, 2021.
|
||||
# R4SAS <r4sas@i2pmail.org>, 2021-2023.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: i2pd\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
|
||||
"POT-Creation-Date: 2021-08-06 17:12\n"
|
||||
"POT-Creation-Date: 2023-01-19 04:18\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -18,706 +18,748 @@ msgstr ""
|
||||
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
|
||||
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
|
||||
|
||||
#: daemon/HTTPServer.cpp:177
|
||||
msgid "day"
|
||||
msgid_plural "days"
|
||||
#: daemon/HTTPServer.cpp:106
|
||||
#, c-format
|
||||
msgid "%d day"
|
||||
msgid_plural "%d days"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:181
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
#: daemon/HTTPServer.cpp:110
|
||||
#, c-format
|
||||
msgid "%d hour"
|
||||
msgid_plural "%d hours"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:185
|
||||
msgid "minute"
|
||||
msgid_plural "minutes"
|
||||
#: daemon/HTTPServer.cpp:114
|
||||
#, c-format
|
||||
msgid "%d minute"
|
||||
msgid_plural "%d minutes"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:188
|
||||
msgid "second"
|
||||
msgid_plural "seconds"
|
||||
#: daemon/HTTPServer.cpp:117
|
||||
#, c-format
|
||||
msgid "%d second"
|
||||
msgid_plural "%d seconds"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#. tr: Kibibit
|
||||
#: daemon/HTTPServer.cpp:196 daemon/HTTPServer.cpp:224
|
||||
msgid "KiB"
|
||||
#. tr: Kibibyte
|
||||
#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153
|
||||
#, c-format
|
||||
msgid "%.2f KiB"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Mebibit
|
||||
#: daemon/HTTPServer.cpp:198
|
||||
msgid "MiB"
|
||||
#. tr: Mebibyte
|
||||
#: daemon/HTTPServer.cpp:127
|
||||
#, c-format
|
||||
msgid "%.2f MiB"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Gibibit
|
||||
#: daemon/HTTPServer.cpp:200
|
||||
msgid "GiB"
|
||||
#. tr: Gibibyte
|
||||
#: daemon/HTTPServer.cpp:129
|
||||
#, c-format
|
||||
msgid "%.2f GiB"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:217
|
||||
#: daemon/HTTPServer.cpp:146
|
||||
msgid "building"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:218
|
||||
#: daemon/HTTPServer.cpp:147
|
||||
msgid "failed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:219
|
||||
#: daemon/HTTPServer.cpp:148
|
||||
msgid "expiring"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:220
|
||||
#: daemon/HTTPServer.cpp:149
|
||||
msgid "established"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:221
|
||||
#: daemon/HTTPServer.cpp:150
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:223
|
||||
#: daemon/HTTPServer.cpp:152
|
||||
msgid "exploratory"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:259
|
||||
#. tr: Webconsole page title
|
||||
#: daemon/HTTPServer.cpp:183
|
||||
msgid "Purple I2P Webconsole"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:188
|
||||
msgid "<b>i2pd</b> webconsole"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:262
|
||||
#: daemon/HTTPServer.cpp:191
|
||||
msgid "Main page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:263 daemon/HTTPServer.cpp:725
|
||||
#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712
|
||||
msgid "Router commands"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:264 daemon/HTTPServer.cpp:448
|
||||
#: daemon/HTTPServer.cpp:460
|
||||
#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387
|
||||
#: daemon/HTTPServer.cpp:399
|
||||
msgid "Local Destinations"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:266 daemon/HTTPServer.cpp:418
|
||||
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
|
||||
#: daemon/HTTPServer.cpp:641 daemon/HTTPServer.cpp:684
|
||||
#: daemon/HTTPServer.cpp:688
|
||||
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:357
|
||||
#: daemon/HTTPServer.cpp:443 daemon/HTTPServer.cpp:449
|
||||
#: daemon/HTTPServer.cpp:609 daemon/HTTPServer.cpp:652
|
||||
#: daemon/HTTPServer.cpp:656
|
||||
msgid "LeaseSets"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:268 daemon/HTTPServer.cpp:694
|
||||
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662
|
||||
msgid "Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:269 daemon/HTTPServer.cpp:425
|
||||
#: daemon/HTTPServer.cpp:787 daemon/HTTPServer.cpp:803
|
||||
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364
|
||||
#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797
|
||||
msgid "Transit Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:270 daemon/HTTPServer.cpp:852
|
||||
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855
|
||||
msgid "Transports"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:271
|
||||
#: daemon/HTTPServer.cpp:202
|
||||
msgid "I2P tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:914
|
||||
#: daemon/HTTPServer.cpp:924
|
||||
#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884
|
||||
#: daemon/HTTPServer.cpp:894
|
||||
msgid "SAM sessions"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:289 daemon/HTTPServer.cpp:1306
|
||||
#: daemon/HTTPServer.cpp:1309 daemon/HTTPServer.cpp:1312
|
||||
#: daemon/HTTPServer.cpp:1326 daemon/HTTPServer.cpp:1371
|
||||
#: daemon/HTTPServer.cpp:1374 daemon/HTTPServer.cpp:1377
|
||||
#: daemon/HTTPServer.cpp:220 daemon/HTTPServer.cpp:1278
|
||||
#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1284
|
||||
#: daemon/HTTPServer.cpp:1298 daemon/HTTPServer.cpp:1343
|
||||
#: daemon/HTTPServer.cpp:1346 daemon/HTTPServer.cpp:1349
|
||||
msgid "ERROR"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:296
|
||||
#: daemon/HTTPServer.cpp:227
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:297
|
||||
#: daemon/HTTPServer.cpp:228
|
||||
msgid "Testing"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:298
|
||||
#: daemon/HTTPServer.cpp:229
|
||||
msgid "Firewalled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:299 daemon/HTTPServer.cpp:320
|
||||
#: daemon/HTTPServer.cpp:406
|
||||
#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233
|
||||
#: daemon/HTTPServer.cpp:329
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:435
|
||||
#: daemon/HTTPServer.cpp:436 daemon/HTTPServer.cpp:982
|
||||
#: daemon/HTTPServer.cpp:991
|
||||
#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374
|
||||
#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952
|
||||
#: daemon/HTTPServer.cpp:961
|
||||
msgid "Proxy"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:301
|
||||
#: daemon/HTTPServer.cpp:232
|
||||
msgid "Mesh"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:304
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:308
|
||||
#: daemon/HTTPServer.cpp:240
|
||||
msgid "Clock skew"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:311
|
||||
#: daemon/HTTPServer.cpp:243
|
||||
msgid "Offline"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:314
|
||||
#: daemon/HTTPServer.cpp:246
|
||||
msgid "Symmetric NAT"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:326
|
||||
#: daemon/HTTPServer.cpp:249
|
||||
msgid "Full cone NAT"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:252
|
||||
msgid "No Descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:261
|
||||
msgid "Uptime"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:329
|
||||
#: daemon/HTTPServer.cpp:264
|
||||
msgid "Network status"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:334
|
||||
#: daemon/HTTPServer.cpp:269
|
||||
msgid "Network status v6"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:340 daemon/HTTPServer.cpp:347
|
||||
#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282
|
||||
msgid "Stopping in"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:354
|
||||
#: daemon/HTTPServer.cpp:289
|
||||
msgid "Family"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:355
|
||||
#: daemon/HTTPServer.cpp:290
|
||||
msgid "Tunnel creation success rate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:356
|
||||
#: daemon/HTTPServer.cpp:291
|
||||
msgid "Received"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Kibibit/s
|
||||
#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:361
|
||||
#: daemon/HTTPServer.cpp:364
|
||||
msgid "KiB/s"
|
||||
#. tr: Kibibyte/s
|
||||
#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296
|
||||
#: daemon/HTTPServer.cpp:299
|
||||
#, c-format
|
||||
msgid "%.2f KiB/s"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:359
|
||||
#: daemon/HTTPServer.cpp:294
|
||||
msgid "Sent"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:362
|
||||
#: daemon/HTTPServer.cpp:297
|
||||
msgid "Transit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:365
|
||||
#: daemon/HTTPServer.cpp:300
|
||||
msgid "Data path"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:368
|
||||
#: daemon/HTTPServer.cpp:303
|
||||
msgid "Hidden content. Press on text to see."
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:371
|
||||
#: daemon/HTTPServer.cpp:307
|
||||
msgid "Router Ident"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:373
|
||||
#: daemon/HTTPServer.cpp:309
|
||||
msgid "Router Family"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:374
|
||||
#: daemon/HTTPServer.cpp:310
|
||||
msgid "Router Caps"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:375
|
||||
#: daemon/HTTPServer.cpp:311
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:376
|
||||
#: daemon/HTTPServer.cpp:312
|
||||
msgid "Our external address"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:384
|
||||
#. tr: Shown when router doesn't publish itself and have "Firewalled" state
|
||||
#: daemon/HTTPServer.cpp:341
|
||||
msgid "supported"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:416
|
||||
#: daemon/HTTPServer.cpp:355
|
||||
msgid "Routers"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:417
|
||||
#: daemon/HTTPServer.cpp:356
|
||||
msgid "Floodfills"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:424 daemon/HTTPServer.cpp:968
|
||||
#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938
|
||||
msgid "Client Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:434
|
||||
#: daemon/HTTPServer.cpp:373
|
||||
msgid "Services"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
|
||||
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
|
||||
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
|
||||
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
|
||||
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
|
||||
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
|
||||
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
|
||||
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
|
||||
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
|
||||
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
|
||||
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:483
|
||||
#: daemon/HTTPServer.cpp:422
|
||||
msgid "Encrypted B33 address"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:492
|
||||
#: daemon/HTTPServer.cpp:431
|
||||
msgid "Address registration line"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:497
|
||||
#: daemon/HTTPServer.cpp:436
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:498
|
||||
#: daemon/HTTPServer.cpp:437
|
||||
msgid "Generate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:499
|
||||
#: daemon/HTTPServer.cpp:438
|
||||
msgid ""
|
||||
"<b>Note:</b> result string can be used only for registering 2LD domains "
|
||||
"(example.i2p). For registering subdomains please use i2pd-tools."
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:505
|
||||
#: daemon/HTTPServer.cpp:444
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:505
|
||||
#: daemon/HTTPServer.cpp:444
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:505
|
||||
#: daemon/HTTPServer.cpp:444
|
||||
msgid "EncType"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:515 daemon/HTTPServer.cpp:699
|
||||
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667
|
||||
msgid "Inbound tunnels"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Milliseconds
|
||||
#: daemon/HTTPServer.cpp:520 daemon/HTTPServer.cpp:530
|
||||
#: daemon/HTTPServer.cpp:704 daemon/HTTPServer.cpp:714
|
||||
msgid "ms"
|
||||
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489
|
||||
#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701
|
||||
#, c-format
|
||||
msgid "%dms"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:525 daemon/HTTPServer.cpp:709
|
||||
#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686
|
||||
msgid "Outbound tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:537
|
||||
#: daemon/HTTPServer.cpp:496
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:537
|
||||
#: daemon/HTTPServer.cpp:497
|
||||
msgid "Incoming"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:544 daemon/HTTPServer.cpp:547
|
||||
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:545 daemon/HTTPServer.cpp:561
|
||||
#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526
|
||||
msgid "Destination"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:545
|
||||
#: daemon/HTTPServer.cpp:507
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:552
|
||||
#: daemon/HTTPServer.cpp:515
|
||||
msgid "Incoming Tags"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:560 daemon/HTTPServer.cpp:563
|
||||
#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529
|
||||
msgid "Tags sessions"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:561
|
||||
#: daemon/HTTPServer.cpp:526
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:570 daemon/HTTPServer.cpp:626
|
||||
#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594
|
||||
msgid "Local Destination"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:580 daemon/HTTPServer.cpp:947
|
||||
#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917
|
||||
msgid "Streams"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:602
|
||||
#: daemon/HTTPServer.cpp:570
|
||||
msgid "Close stream"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:631
|
||||
#: daemon/HTTPServer.cpp:599
|
||||
msgid "I2CP session not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:634
|
||||
#: daemon/HTTPServer.cpp:602
|
||||
msgid "I2CP is not enabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:660
|
||||
#: daemon/HTTPServer.cpp:628
|
||||
msgid "Invalid"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:663
|
||||
#: daemon/HTTPServer.cpp:631
|
||||
msgid "Store type"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:664
|
||||
#: daemon/HTTPServer.cpp:632
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:669
|
||||
#: daemon/HTTPServer.cpp:637
|
||||
msgid "Non Expired Leases"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:672
|
||||
#: daemon/HTTPServer.cpp:640
|
||||
msgid "Gateway"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:673
|
||||
#: daemon/HTTPServer.cpp:641
|
||||
msgid "TunnelID"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:674
|
||||
#: daemon/HTTPServer.cpp:642
|
||||
msgid "EndDate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:684
|
||||
msgid "not floodfill"
|
||||
#: daemon/HTTPServer.cpp:652
|
||||
msgid "floodfill mode is disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:695
|
||||
#: daemon/HTTPServer.cpp:663
|
||||
msgid "Queue size"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:726
|
||||
#: daemon/HTTPServer.cpp:713
|
||||
msgid "Run peer test"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:731
|
||||
#: daemon/HTTPServer.cpp:714
|
||||
msgid "Reload tunnels configuration"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:717
|
||||
msgid "Decline transit tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:733
|
||||
#: daemon/HTTPServer.cpp:719
|
||||
msgid "Accept transit tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:737 daemon/HTTPServer.cpp:742
|
||||
#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728
|
||||
msgid "Cancel graceful shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:739 daemon/HTTPServer.cpp:744
|
||||
#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730
|
||||
msgid "Start graceful shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:747
|
||||
#: daemon/HTTPServer.cpp:733
|
||||
msgid "Force shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:748
|
||||
#: daemon/HTTPServer.cpp:734
|
||||
msgid "Reload external CSS styles"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:751
|
||||
#: daemon/HTTPServer.cpp:737
|
||||
msgid ""
|
||||
"<b>Note:</b> any action done here are not persistent and not changes your "
|
||||
"config files."
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:753
|
||||
#: daemon/HTTPServer.cpp:739
|
||||
msgid "Logging level"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:761
|
||||
#: daemon/HTTPServer.cpp:747
|
||||
msgid "Transit tunnels limit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:766 daemon/HTTPServer.cpp:778
|
||||
#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771
|
||||
msgid "Change"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:770
|
||||
#: daemon/HTTPServer.cpp:759
|
||||
msgid "Change language"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:803
|
||||
#: daemon/HTTPServer.cpp:797
|
||||
msgid "no transit tunnels currently built"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:908 daemon/HTTPServer.cpp:931
|
||||
#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901
|
||||
msgid "SAM disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:924
|
||||
#: daemon/HTTPServer.cpp:894
|
||||
msgid "no sessions currently running"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:937
|
||||
#: daemon/HTTPServer.cpp:907
|
||||
msgid "SAM session not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:942
|
||||
#: daemon/HTTPServer.cpp:912
|
||||
msgid "SAM Session"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:999
|
||||
#: daemon/HTTPServer.cpp:969
|
||||
msgid "Server Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1015
|
||||
#: daemon/HTTPServer.cpp:985
|
||||
msgid "Client Forwards"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1029
|
||||
#: daemon/HTTPServer.cpp:999
|
||||
msgid "Server Forwards"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1227
|
||||
#: daemon/HTTPServer.cpp:1199
|
||||
msgid "Unknown page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1246
|
||||
#: daemon/HTTPServer.cpp:1218
|
||||
msgid "Invalid token"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1304 daemon/HTTPServer.cpp:1361
|
||||
#: daemon/HTTPServer.cpp:1401
|
||||
#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333
|
||||
#: daemon/HTTPServer.cpp:1373
|
||||
msgid "SUCCESS"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1304
|
||||
#: daemon/HTTPServer.cpp:1276
|
||||
msgid "Stream closed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1306
|
||||
#: daemon/HTTPServer.cpp:1278
|
||||
msgid "Stream not found or already was closed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1309
|
||||
#: daemon/HTTPServer.cpp:1281
|
||||
msgid "Destination not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1312
|
||||
#: daemon/HTTPServer.cpp:1284
|
||||
msgid "StreamID can't be null"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1314 daemon/HTTPServer.cpp:1379
|
||||
#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351
|
||||
msgid "Return to destination page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1315 daemon/HTTPServer.cpp:1328
|
||||
#: daemon/HTTPServer.cpp:1403
|
||||
msgid "You will be redirected in 5 seconds"
|
||||
#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300
|
||||
#: daemon/HTTPServer.cpp:1375
|
||||
#, c-format
|
||||
msgid "You will be redirected in %d seconds"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1326
|
||||
msgid "Transit tunnels count must not exceed 65535"
|
||||
#: daemon/HTTPServer.cpp:1298
|
||||
#, c-format
|
||||
msgid "Transit tunnels count must not exceed %d"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1402
|
||||
#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374
|
||||
msgid "Back to commands list"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1363
|
||||
#: daemon/HTTPServer.cpp:1335
|
||||
msgid "Register at reg.i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1364
|
||||
#: daemon/HTTPServer.cpp:1336
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1364
|
||||
#: daemon/HTTPServer.cpp:1336
|
||||
msgid "A bit information about service on domain"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1365
|
||||
#: daemon/HTTPServer.cpp:1337
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1371
|
||||
#: daemon/HTTPServer.cpp:1343
|
||||
msgid "Domain can't end with .b32.i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1374
|
||||
#: daemon/HTTPServer.cpp:1346
|
||||
msgid "Domain must end with .i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1377
|
||||
#: daemon/HTTPServer.cpp:1349
|
||||
msgid "Such destination is not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1397
|
||||
#: daemon/HTTPServer.cpp:1369
|
||||
msgid "Unknown command"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1401
|
||||
#: daemon/HTTPServer.cpp:1373
|
||||
msgid "Command accepted"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:157
|
||||
#: libi2pd_client/HTTPProxy.cpp:166
|
||||
msgid "Proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:165
|
||||
#: libi2pd_client/HTTPProxy.cpp:174
|
||||
msgid "Proxy info"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:173
|
||||
#: libi2pd_client/HTTPProxy.cpp:182
|
||||
msgid "Proxy error: Host not found"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:174
|
||||
#: libi2pd_client/HTTPProxy.cpp:183
|
||||
msgid "Remote host not found in router's addressbook"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:175
|
||||
#: libi2pd_client/HTTPProxy.cpp:184
|
||||
msgid "You may try to find this host on jump services below"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:273 libi2pd_client/HTTPProxy.cpp:288
|
||||
#: libi2pd_client/HTTPProxy.cpp:322 libi2pd_client/HTTPProxy.cpp:365
|
||||
#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324
|
||||
#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435
|
||||
msgid "Invalid request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:273
|
||||
#: libi2pd_client/HTTPProxy.cpp:309
|
||||
msgid "Proxy unable to parse your request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:288
|
||||
msgid "addresshelper is not supported"
|
||||
#: libi2pd_client/HTTPProxy.cpp:324
|
||||
msgid "Addresshelper is not supported"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:297 libi2pd_client/HTTPProxy.cpp:306
|
||||
#: libi2pd_client/HTTPProxy.cpp:385
|
||||
msgid "Host"
|
||||
#: libi2pd_client/HTTPProxy.cpp:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Host %s is <font color=red>already in router's addressbook</font>. <b>Be "
|
||||
"careful: source of this URL may be harmful!</b> Click here to update record: "
|
||||
"<a href=\"%s%s%s&update=true\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:297
|
||||
msgid "added to router's addressbook from helper"
|
||||
#: libi2pd_client/HTTPProxy.cpp:351
|
||||
msgid "Addresshelper forced update rejected"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:298
|
||||
msgid "Click here to proceed:"
|
||||
#: libi2pd_client/HTTPProxy.cpp:358
|
||||
#, c-format
|
||||
msgid ""
|
||||
"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s"
|
||||
"\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:298 libi2pd_client/HTTPProxy.cpp:308
|
||||
msgid "Continue"
|
||||
#: libi2pd_client/HTTPProxy.cpp:360
|
||||
msgid "Addresshelper request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:299 libi2pd_client/HTTPProxy.cpp:309
|
||||
msgid "Addresshelper found"
|
||||
#: libi2pd_client/HTTPProxy.cpp:369
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Host %s added to router's addressbook from helper. Click here to proceed: <a "
|
||||
"href=\"%s\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:306
|
||||
msgid "already in router's addressbook"
|
||||
#: libi2pd_client/HTTPProxy.cpp:370
|
||||
msgid "Addresshelper adding"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:307
|
||||
msgid "Click here to update record:"
|
||||
#: libi2pd_client/HTTPProxy.cpp:377
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Host %s is <font color=red>already in router's addressbook</font>. Click "
|
||||
"here to update record: <a href=\"%s%s%s&update=true\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:322
|
||||
msgid "invalid request uri"
|
||||
#: libi2pd_client/HTTPProxy.cpp:379
|
||||
msgid "Addresshelper update"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:365
|
||||
#: libi2pd_client/HTTPProxy.cpp:392
|
||||
msgid "Invalid request URI"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:435
|
||||
msgid "Can't detect destination host from request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:382 libi2pd_client/HTTPProxy.cpp:386
|
||||
#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456
|
||||
msgid "Outproxy failure"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:382
|
||||
msgid "bad outproxy settings"
|
||||
#: libi2pd_client/HTTPProxy.cpp:452
|
||||
msgid "Bad outproxy settings"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:385
|
||||
msgid "not inside I2P network, but outproxy is not enabled"
|
||||
#: libi2pd_client/HTTPProxy.cpp:455
|
||||
#, c-format
|
||||
msgid "Host %s is not inside I2P network, but outproxy is not enabled"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:474
|
||||
msgid "unknown outproxy url"
|
||||
#: libi2pd_client/HTTPProxy.cpp:544
|
||||
msgid "Unknown outproxy URL"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:480
|
||||
msgid "cannot resolve upstream proxy"
|
||||
#: libi2pd_client/HTTPProxy.cpp:550
|
||||
msgid "Cannot resolve upstream proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:488
|
||||
msgid "hostname too long"
|
||||
#: libi2pd_client/HTTPProxy.cpp:558
|
||||
msgid "Hostname is too long"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:515
|
||||
msgid "cannot connect to upstream socks proxy"
|
||||
#: libi2pd_client/HTTPProxy.cpp:585
|
||||
msgid "Cannot connect to upstream SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:521
|
||||
msgid "Cannot negotiate with socks proxy"
|
||||
#: libi2pd_client/HTTPProxy.cpp:591
|
||||
msgid "Cannot negotiate with SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:563
|
||||
#: libi2pd_client/HTTPProxy.cpp:633
|
||||
msgid "CONNECT error"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:563
|
||||
msgid "Failed to Connect"
|
||||
#: libi2pd_client/HTTPProxy.cpp:633
|
||||
msgid "Failed to connect"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:574 libi2pd_client/HTTPProxy.cpp:600
|
||||
msgid "socks proxy error"
|
||||
#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670
|
||||
msgid "SOCKS proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:582
|
||||
msgid "failed to send request to upstream"
|
||||
#: libi2pd_client/HTTPProxy.cpp:652
|
||||
msgid "Failed to send request to upstream"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:603
|
||||
msgid "No Reply From socks proxy"
|
||||
#: libi2pd_client/HTTPProxy.cpp:673
|
||||
msgid "No reply from SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:610
|
||||
msgid "cannot connect"
|
||||
#: libi2pd_client/HTTPProxy.cpp:680
|
||||
msgid "Cannot connect"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:610
|
||||
msgid "http out proxy not implemented"
|
||||
#: libi2pd_client/HTTPProxy.cpp:680
|
||||
msgid "HTTP out proxy not implemented"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:611
|
||||
msgid "cannot connect to upstream http proxy"
|
||||
#: libi2pd_client/HTTPProxy.cpp:681
|
||||
msgid "Cannot connect to upstream HTTP proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:644
|
||||
#: libi2pd_client/HTTPProxy.cpp:714
|
||||
msgid "Host is down"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:644
|
||||
#: libi2pd_client/HTTPProxy.cpp:714
|
||||
msgid ""
|
||||
"Can't create connection to requested host, it may be down. Please try again "
|
||||
"later."
|
||||
|
||||
@@ -9,8 +9,8 @@ Regex for transforming gettext translations to our format:
|
||||
---
|
||||
|
||||
```
|
||||
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\nmsgstr\[1\]\ \"(.*)\"\n(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
|
||||
out: #{"$2", {"$3", "$4", "$6", "$8", "$10"}},\n
|
||||
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
|
||||
out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
@@ -75,8 +75,8 @@ ipv4 = true
|
||||
## Enable communication through ipv6
|
||||
ipv6 = false
|
||||
|
||||
## Enable SSU transport (default = true)
|
||||
# ssu = true
|
||||
## Enable SSU transport
|
||||
ssu = false
|
||||
|
||||
## Bandwidth configuration
|
||||
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
|
||||
@@ -96,6 +96,22 @@ ipv6 = false
|
||||
## Note: that mode uses much more network connections and CPU!
|
||||
# floodfill = true
|
||||
|
||||
[ntcp2]
|
||||
## Enable NTCP2 transport (default = true)
|
||||
# enabled = true
|
||||
## Publish address in RouterInfo (default = true)
|
||||
# published = true
|
||||
## Port for incoming connections (default is global port option value)
|
||||
# port = 4567
|
||||
|
||||
[ssu2]
|
||||
## Enable SSU2 transport
|
||||
# enabled = true
|
||||
## Publish address in RouterInfo
|
||||
# published = true
|
||||
## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled)
|
||||
# port = 4567
|
||||
|
||||
[http]
|
||||
## Web Console settings
|
||||
## Uncomment and set to 'false' to disable Web Console
|
||||
@@ -106,12 +122,14 @@ port = 7070
|
||||
## Path to web console, default "/"
|
||||
# webroot = /
|
||||
## Uncomment following lines to enable Web Console authentication
|
||||
## You should not use Web Console via public networks without additional encryption.
|
||||
## HTTP authentication is not encryption layer!
|
||||
# auth = true
|
||||
# user = i2pd
|
||||
# pass = changeme
|
||||
## Select webconsole language
|
||||
## Currently supported english (default), afrikaans, armenian, french, german,
|
||||
## russian, turkmen, ukrainian and uzbek languages
|
||||
## Currently supported english (default), afrikaans, armenian, chinese, czech, french,
|
||||
## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
|
||||
# lang = english
|
||||
|
||||
[httpproxy]
|
||||
@@ -123,6 +141,8 @@ port = 4444
|
||||
## Optional keys file for proxy local destination
|
||||
# keys = http-proxy-keys.dat
|
||||
## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
|
||||
## You should disable this feature if your i2pd HTTP Proxy is public,
|
||||
## because anyone could spoof the short domain via addresshelper and forward other users to phishing links
|
||||
# addresshelper = true
|
||||
## Address of a proxy server inside I2P, which is used to visit regular Internet
|
||||
# outproxy = http://false.i2p
|
||||
@@ -221,8 +241,9 @@ verify = true
|
||||
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
|
||||
|
||||
[limits]
|
||||
## Maximum active transit sessions (default:2500)
|
||||
# transittunnels = 2500
|
||||
## Maximum active transit sessions (default: 5000)
|
||||
## This value is doubled if floodfill mode is enabled!
|
||||
# transittunnels = 5000
|
||||
## Limit number of open file descriptors (0 - use system limit)
|
||||
# openfiles = 0
|
||||
## Maximum size of corefile in Kb (0 - use system limit)
|
||||
|
||||
@@ -29,7 +29,7 @@ SendSIGKILL=yes
|
||||
#TimeoutStopSec=10m
|
||||
|
||||
# If you have problems with hanging i2pd, you can try increase this
|
||||
LimitNOFILE=4096
|
||||
LimitNOFILE=8192
|
||||
# To enable write of coredump uncomment this
|
||||
#LimitCORE=infinity
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.42.1
|
||||
Version: 2.45.1
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@@ -62,9 +62,7 @@ pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -82,10 +80,8 @@ popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?fedora} < 37
|
||||
popd
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
@@ -99,9 +95,7 @@ pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -164,6 +158,18 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
|
||||
- update to 2.45.1
|
||||
|
||||
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
|
||||
- update to 2.45.0
|
||||
|
||||
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
|
||||
- update to 2.44.0
|
||||
|
||||
* Mon Aug 22 2022 orignal <orignal@i2pmail.org> - 2.43.0
|
||||
- update to 2.43.0
|
||||
|
||||
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
|
||||
- update to 2.42.1
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.42.1
|
||||
Version: 2.45.1
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@@ -59,9 +59,7 @@ pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -79,10 +77,8 @@ popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?fedora} < 37
|
||||
popd
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
@@ -96,9 +92,7 @@ pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -161,6 +155,18 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
|
||||
- update to 2.45.1
|
||||
|
||||
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
|
||||
- update to 2.45.0
|
||||
|
||||
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
|
||||
- update to 2.44.0
|
||||
|
||||
* Mon Aug 22 2022 orignal <orignal@i2pmail.org> - 2.43.0
|
||||
- update to 2.43.0
|
||||
|
||||
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
|
||||
- update to 2.42.1
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2021-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -43,7 +43,7 @@ a, .slide label {
|
||||
color: var(--main-link-color);
|
||||
}
|
||||
|
||||
a:hover, .slide label:hover, button[type=submit]:hover {
|
||||
a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover {
|
||||
color: var(--main-link-hover-color);
|
||||
background: var(--main-link-color);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "Crypto.h"
|
||||
#include "UPnP.h"
|
||||
#include "Timestamp.h"
|
||||
#include "util.h"
|
||||
#include "I18N.h"
|
||||
|
||||
namespace i2p
|
||||
@@ -153,130 +152,34 @@ namespace util
|
||||
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
|
||||
bool avx; i2p::config::GetOption("cpuext.avx", avx);
|
||||
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
|
||||
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
|
||||
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
|
||||
|
||||
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces
|
||||
|
||||
int netID; i2p::config::GetOption("netid", netID);
|
||||
i2p::context.SetNetID (netID);
|
||||
i2p::context.Init ();
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
|
||||
// ifname -> address
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
if (ipv4 && i2p::config::IsDefault ("address4"))
|
||||
{
|
||||
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
|
||||
if (!ifname4.empty ())
|
||||
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
|
||||
else if (!ifname.empty ())
|
||||
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
|
||||
}
|
||||
if (ipv6 && i2p::config::IsDefault ("address6"))
|
||||
{
|
||||
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
|
||||
if (!ifname6.empty ())
|
||||
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
|
||||
else if (!ifname.empty ())
|
||||
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
|
||||
}
|
||||
|
||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||
boost::asio::ip::address_v6 yggaddr;
|
||||
if (ygg)
|
||||
{
|
||||
std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress);
|
||||
if (!yggaddress.empty ())
|
||||
{
|
||||
yggaddr = boost::asio::ip::address_v6::from_string (yggaddress);
|
||||
if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) ||
|
||||
!i2p::util::net::IsLocalAddress (yggaddr))
|
||||
{
|
||||
LogPrint(eLogWarning, "Daemon: Can't find Yggdrasil address ", yggaddress);
|
||||
ygg = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yggaddr = i2p::util::net::GetYggdrasilAddress ();
|
||||
if (yggaddr.is_unspecified ())
|
||||
{
|
||||
LogPrint(eLogWarning, "Daemon: Yggdrasil is not running. Disabled");
|
||||
ygg = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t port; i2p::config::GetOption("port", port);
|
||||
if (!i2p::config::IsDefault("port"))
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: Accepting incoming connections at port ", port);
|
||||
i2p::context.UpdatePort (port);
|
||||
}
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
i2p::context.SetSupportsMesh (ygg, yggaddr);
|
||||
|
||||
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||
if (!ntcp2proxy.empty ()) published = false;
|
||||
}
|
||||
if (published)
|
||||
{
|
||||
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
||||
if (!ntcp2port) ntcp2port = port; // use standard port
|
||||
i2p::context.PublishNTCP2Address (ntcp2port, true, ipv4, ipv6, false); // publish
|
||||
if (ipv6)
|
||||
{
|
||||
std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
|
||||
auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
|
||||
if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
|
||||
i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
|
||||
}
|
||||
}
|
||||
else
|
||||
i2p::context.PublishNTCP2Address (port, false, ipv4, ipv6, false); // unpublish
|
||||
}
|
||||
if (ygg)
|
||||
{
|
||||
i2p::context.PublishNTCP2Address (port, true, false, false, true);
|
||||
i2p::context.UpdateNTCP2V6Address (yggaddr);
|
||||
if (!ipv4 && !ipv6)
|
||||
i2p::context.SetStatus (eRouterStatusMesh);
|
||||
}
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
if (ssu2)
|
||||
{
|
||||
bool published; i2p::config::GetOption("ssu2.published", published);
|
||||
if (published)
|
||||
{
|
||||
uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port);
|
||||
i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish
|
||||
}
|
||||
else
|
||||
i2p::context.PublishSSU2Address (0, false, ipv4, ipv6); // unpublish
|
||||
}
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
|
||||
SetMaxNumTransitTunnels (transitTunnels);
|
||||
i2p::transport::InitTransports ();
|
||||
|
||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||
if (isFloodfill) {
|
||||
if (isFloodfill)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
|
||||
i2p::context.SetFloodfill (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2p::context.SetFloodfill (false);
|
||||
}
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
|
||||
if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels"))
|
||||
transitTunnels *= 2; // double default number of transit tunnels for floodfill
|
||||
SetMaxNumTransitTunnels (transitTunnels);
|
||||
|
||||
/* this section also honors 'floodfill' flag, if set above */
|
||||
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
|
||||
@@ -396,15 +299,14 @@ namespace util
|
||||
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
||||
LogPrint(eLogInfo, "Daemon: Starting Transports");
|
||||
if(!ssu) LogPrint(eLogInfo, "Daemon: SSU disabled");
|
||||
if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled");
|
||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
|
||||
|
||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||
i2p::transport::transports.Start(ntcp2, ssu, ssu2);
|
||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
i2p::transport::transports.Start(ntcp2, ssu2);
|
||||
if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
else
|
||||
{
|
||||
@@ -423,10 +325,6 @@ namespace util
|
||||
try
|
||||
{
|
||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->SetDaemonStop (std::bind (Daemon_Singleton::stop, this));
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
d.httpServer->SetDaemonGracefulTimer (std::bind (gracefulShutdownInterval, this));
|
||||
#endif
|
||||
d.httpServer->Start();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
|
||||
@@ -75,17 +75,14 @@ namespace util
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool init (int argc, char* argv[]);
|
||||
bool start ();
|
||||
bool stop ();
|
||||
bool init(int argc, char* argv[]);
|
||||
bool start();
|
||||
bool stop();
|
||||
void run ();
|
||||
|
||||
void SetIsGraceful (bool state) { m_isGraceful = state; };
|
||||
const bool GetIsGraceful () { return m_isGraceful; };
|
||||
bool isGraceful;
|
||||
|
||||
private:
|
||||
|
||||
bool m_isGraceful;
|
||||
DaemonWin32 ():isGraceful(false) {}
|
||||
};
|
||||
#elif (defined(ANDROID) && !defined(ANDROID_BINARY))
|
||||
#define Daemon i2p::util::DaemonAndroid::Instance()
|
||||
@@ -112,8 +109,8 @@ namespace util
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool start ();
|
||||
bool stop ();
|
||||
bool start();
|
||||
bool stop();
|
||||
void run ();
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -27,16 +27,14 @@
|
||||
#include "RouterContext.h"
|
||||
#include "ClientContext.h"
|
||||
#include "HTTPServer.h"
|
||||
#include "Daemon.h"
|
||||
#include "util.h"
|
||||
#include "ECIESX25519AEADRatchetSession.h"
|
||||
#include "I18N.h"
|
||||
|
||||
//#ifdef WIN32_APP
|
||||
//#include "Win32App.h"
|
||||
//#endif
|
||||
|
||||
// Inja template engine
|
||||
#include "inja/inja.hpp"
|
||||
#ifdef WIN32_APP
|
||||
#include "Win32App.h"
|
||||
#endif
|
||||
|
||||
// For image, style and info
|
||||
#include "version.h"
|
||||
@@ -60,7 +58,7 @@ namespace http {
|
||||
static void GetStyles (std::stringstream& s)
|
||||
{
|
||||
if (externalCSS.length() != 0)
|
||||
s << externalCSS;
|
||||
s << "<style>\r\n" << externalCSS << "</style>\r\n";
|
||||
else
|
||||
s << internalCSS;
|
||||
}
|
||||
@@ -82,15 +80,13 @@ namespace http {
|
||||
const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel";
|
||||
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
|
||||
const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test";
|
||||
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
|
||||
const char HTTP_COMMAND_RELOAD_TUNNELS_CONFIG[] = "reload_tunnels_config";
|
||||
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
|
||||
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
|
||||
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
|
||||
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
|
||||
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
|
||||
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
|
||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||
|
||||
static std::string ConvertTime (uint64_t time)
|
||||
{
|
||||
@@ -107,18 +103,18 @@ namespace http {
|
||||
int num;
|
||||
|
||||
if ((num = seconds / 86400) > 0) {
|
||||
s << num << " " << tr("day", "days", num) << ", ";
|
||||
s << ntr("%d day", "%d days", num, num) << ", ";
|
||||
seconds -= num * 86400;
|
||||
}
|
||||
if ((num = seconds / 3600) > 0) {
|
||||
s << num << " " << tr("hour", "hours", num) << ", ";
|
||||
s << ntr("%d hour", "%d hours", num, num) << ", ";
|
||||
seconds -= num * 3600;
|
||||
}
|
||||
if ((num = seconds / 60) > 0) {
|
||||
s << num << " " << tr("minute", "minutes", num) << ", ";
|
||||
s << ntr("%d minute", "%d minutes", num, num) << ", ";
|
||||
seconds -= num * 60;
|
||||
}
|
||||
s << seconds << " " << tr("second", "seconds", seconds);
|
||||
s << ntr("%d second", "%d seconds", seconds, seconds);
|
||||
}
|
||||
|
||||
static void ShowTraffic (std::stringstream& s, uint64_t bytes)
|
||||
@@ -126,11 +122,11 @@ namespace http {
|
||||
s << std::fixed << std::setprecision(2);
|
||||
auto numKBytes = (double) bytes / 1024;
|
||||
if (numKBytes < 1024)
|
||||
s << numKBytes << " " << tr(/* tr: Kibibit */ "KiB");
|
||||
s << tr(/* tr: Kibibyte */ "%.2f KiB", numKBytes);
|
||||
else if (numKBytes < 1024 * 1024)
|
||||
s << numKBytes / 1024 << " " << tr(/* tr: Mebibit */ "MiB");
|
||||
s << tr(/* tr: Mebibyte */ "%.2f MiB", numKBytes / 1024);
|
||||
else
|
||||
s << numKBytes / 1024 / 1024 << " " << tr(/* tr: Gibibit */ "GiB");
|
||||
s << tr(/* tr: Gibibyte */ "%.2f GiB", numKBytes / 1024 / 1024);
|
||||
}
|
||||
|
||||
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
|
||||
@@ -154,7 +150,8 @@ namespace http {
|
||||
else stateText = tr("unknown");
|
||||
|
||||
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, ";
|
||||
s << " " << (int) (bytes / 1024) << " " << tr(/* tr: Kibibit */ "KiB") << "\r\n";
|
||||
ShowTraffic(s, bytes);
|
||||
s << "\r\n";
|
||||
}
|
||||
|
||||
static void SetLogLevel (const std::string& level)
|
||||
@@ -184,11 +181,9 @@ namespace http {
|
||||
" <meta charset=\"UTF-8\">\r\n"
|
||||
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n"
|
||||
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
||||
" <title>Purple I2P Webconsole</title>\r\n"
|
||||
" <style>";
|
||||
" <title>" << tr(/* tr: Webconsole page title */ "Purple I2P Webconsole") << "</title>\r\n";
|
||||
GetStyles(s);
|
||||
s <<
|
||||
"\r\n</style>\r\n"
|
||||
"</head>\r\n"
|
||||
"<body>\r\n"
|
||||
"<div class=\"header\">" << tr("<b>i2pd</b> webconsole") << "</div>\r\n"
|
||||
@@ -204,7 +199,7 @@ namespace http {
|
||||
if (i2p::context.AcceptsTunnels () || i2p::tunnel::tunnels.CountTransitTunnels())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n";
|
||||
s <<
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr("Transports") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
|
||||
if (i2p::client::context.GetSAMBridge ())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
|
||||
@@ -226,7 +221,7 @@ namespace http {
|
||||
s << "<b>" << tr("ERROR") << ":</b> " << string << "<br>\r\n";
|
||||
}
|
||||
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
@@ -236,26 +231,30 @@ namespace http {
|
||||
case eRouterStatusUnknown: s << tr("Unknown"); break;
|
||||
case eRouterStatusProxy: s << tr("Proxy"); break;
|
||||
case eRouterStatusMesh: s << tr("Mesh"); break;
|
||||
case eRouterStatusError:
|
||||
{
|
||||
s << tr("Error");
|
||||
switch (i2p::context.GetError ())
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << " - " << tr("Clock skew");
|
||||
break;
|
||||
case eRouterErrorOffline:
|
||||
s << " - " << tr("Offline");
|
||||
break;
|
||||
case eRouterErrorSymmetricNAT:
|
||||
s << " - " << tr("Symmetric NAT");
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: s << tr("Unknown");
|
||||
}
|
||||
if (error != eRouterErrorNone)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << " - " << tr("Clock skew");
|
||||
break;
|
||||
case eRouterErrorOffline:
|
||||
s << " - " << tr("Offline");
|
||||
break;
|
||||
case eRouterErrorSymmetricNAT:
|
||||
s << " - " << tr("Symmetric NAT");
|
||||
break;
|
||||
case eRouterErrorFullConeNAT:
|
||||
s << " - " << tr("Full cone NAT");
|
||||
break;
|
||||
case eRouterErrorNoDescriptors:
|
||||
s << " - " << tr("No Descriptors");
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat)
|
||||
@@ -264,85 +263,89 @@ namespace http {
|
||||
ShowUptime(s, i2p::context.GetUptime ());
|
||||
s << "<br>\r\n";
|
||||
s << "<b>" << tr("Network status") << ":</b> ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ());
|
||||
s << "<br>\r\n";
|
||||
if (i2p::context.SupportsV6 ())
|
||||
{
|
||||
s << "<b>" << tr("Network status v6") << ":</b> ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ());
|
||||
s << "<br>\r\n";
|
||||
}
|
||||
|
||||
// TODO: rewrite timer access
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
if (auto remains = m_DaemonGracefulTimer) {
|
||||
if (auto remains = Daemon.gracefulShutdownInterval) {
|
||||
s << "<b>" << tr("Stopping in") << ":</b> ";
|
||||
ShowUptime(s, remains);
|
||||
s << "<br>\r\n";
|
||||
}
|
||||
/*#elif defined(WIN32_APP)
|
||||
#elif defined(WIN32_APP)
|
||||
if (i2p::win32::g_GracefulShutdownEndtime != 0) {
|
||||
uint16_t remains = (i2p::win32::g_GracefulShutdownEndtime - GetTickCount()) / 1000;
|
||||
s << "<b>" << tr("Stopping in") << ":</b> ";
|
||||
ShowUptime(s, remains);
|
||||
s << "<br>\r\n";
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
auto family = i2p::context.GetFamily ();
|
||||
if (family.length () > 0)
|
||||
s << "<b>"<< tr("Family") << ":</b> " << family << "<br>\r\n";
|
||||
s << "<b>" << tr("Tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%<br>\r\n";
|
||||
s << "<b>" << tr("Received") << ":</b> ";
|
||||
ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ());
|
||||
s << " (" << (double) i2p::transport::transports.GetInBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
||||
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")<br>\r\n";
|
||||
s << "<b>" << tr("Sent") << ":</b> ";
|
||||
ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ());
|
||||
s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
||||
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")<br>\r\n";
|
||||
s << "<b>" << tr("Transit") << ":</b> ";
|
||||
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
|
||||
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
||||
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")<br>\r\n";
|
||||
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
|
||||
s << "<div class='slide'>";
|
||||
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
||||
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
||||
}
|
||||
if (includeHiddenContent) {
|
||||
if (includeHiddenContent)
|
||||
{
|
||||
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
||||
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
||||
s << "<b>" << tr("Router Caps") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
|
||||
s << "<b>" << tr("Version") << ":</b> " VERSION "<br>\r\n";
|
||||
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||
auto addresses = i2p::context.GetRouterInfo().GetAddresses ();
|
||||
if (addresses)
|
||||
{
|
||||
s << "<tr>\r\n<td>";
|
||||
switch (address->transportStyle)
|
||||
for (const auto& address : *addresses)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
s << "NTCP2";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
s << "SSU";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
s << "SSU2";
|
||||
break;
|
||||
default:
|
||||
s << tr("Unknown");
|
||||
}
|
||||
if (address->IsV6 ())
|
||||
{
|
||||
if (address->IsV4 ()) s << "v4";
|
||||
s << "v6";
|
||||
}
|
||||
s << "</td>\r\n";
|
||||
if (address->published)
|
||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
||||
else
|
||||
{
|
||||
s << "<td>" << tr("supported");
|
||||
if (address->port)
|
||||
s << " :" << address->port;
|
||||
if (!address) continue;
|
||||
s << "<tr>\r\n<td>";
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||
s << "NTCP2";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
s << "SSU2";
|
||||
break;
|
||||
default:
|
||||
s << tr("Unknown");
|
||||
}
|
||||
if (address->IsV6 ())
|
||||
{
|
||||
if (address->IsV4 ()) s << "v4";
|
||||
s << "v6";
|
||||
}
|
||||
s << "</td>\r\n";
|
||||
if (address->published)
|
||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
||||
else
|
||||
{
|
||||
s << "<td>" << tr(/* tr: Shown when router doesn't publish itself and have "Firewalled" state */ "supported");
|
||||
if (address->port)
|
||||
s << " :" << address->port;
|
||||
s << "</td>\r\n";
|
||||
}
|
||||
s << "</tr>\r\n";
|
||||
}
|
||||
s << "</tr>\r\n";
|
||||
}
|
||||
s << "</tbody></table>\r\n";
|
||||
}
|
||||
@@ -464,7 +467,7 @@ namespace http {
|
||||
}
|
||||
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
|
||||
s << " ( " << tr(/* tr: Milliseconds */ "%dms", it->GetMeanLatency()) << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
@@ -484,22 +487,26 @@ namespace http {
|
||||
);
|
||||
}
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
}
|
||||
s << "<br>\r\n";
|
||||
|
||||
s << "<b>" << tr("Tags") << "</b><br>\r\n" << tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
|
||||
s << "<b>" << tr("Tags") << "</b><br>\r\n"
|
||||
<< tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
|
||||
if (!dest->GetSessions ().empty ()) {
|
||||
std::stringstream tmp_s; uint32_t out_tags = 0;
|
||||
for (const auto& it: dest->GetSessions ()) {
|
||||
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
|
||||
out_tags += it.second->GetNumOutgoingTags ();
|
||||
}
|
||||
s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-tags\" />\r\n"
|
||||
<< "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||
s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n"
|
||||
<< "<input type=\"checkbox\" id=\"slide-tags\" />\r\n"
|
||||
<< "<div class=\"slidecontent\">\r\n"
|
||||
<< "<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n"
|
||||
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||
} else
|
||||
s << tr("Outgoing") << ": <i>0</i><br>\r\n";
|
||||
s << "<br>\r\n";
|
||||
@@ -514,8 +521,11 @@ namespace http {
|
||||
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "</td><td>" << it.second->GetState () << "</td></tr>\r\n";
|
||||
ecies_sessions++;
|
||||
}
|
||||
s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n"
|
||||
<< "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||
s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n"
|
||||
<< "<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n"
|
||||
<< "<div class=\"slidecontent\">\r\n<table>\r\n"
|
||||
<< "<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n"
|
||||
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||
} else
|
||||
s << tr("Tags sessions") << ": <i>0</i><br>\r\n";
|
||||
s << "<br>\r\n";
|
||||
@@ -534,19 +544,21 @@ namespace http {
|
||||
ShowLeaseSetDestination (s, dest, token);
|
||||
|
||||
// Print table with streams information
|
||||
s << "<table>\r\n<caption>" << tr("Streams") << "</caption>\r\n<thead>\r\n<tr>";
|
||||
s << "<th style=\"width:25px;\">StreamID</th>";
|
||||
s << "<th style=\"width:5px;\" \\>"; // Stream closing button column
|
||||
s << "<th class=\"streamdest\">Destination</th>";
|
||||
s << "<th>Sent</th>";
|
||||
s << "<th>Received</th>";
|
||||
s << "<th>Out</th>";
|
||||
s << "<th>In</th>";
|
||||
s << "<th>Buf</th>";
|
||||
s << "<th>RTT</th>";
|
||||
s << "<th>Window</th>";
|
||||
s << "<th>Status</th>";
|
||||
s << "</tr>\r\n</thead>\r\n<tbody class=\"tableitem\">\r\n";
|
||||
s << "<table>\r\n<caption>"
|
||||
<< tr("Streams")
|
||||
<< "</caption>\r\n<thead>\r\n<tr>"
|
||||
<< "<th style=\"width:25px;\">StreamID</th>"
|
||||
<< "<th style=\"width:5px;\" \\>" // Stream closing button column
|
||||
<< "<th class=\"streamdest\">Destination</th>"
|
||||
<< "<th>Sent</th>"
|
||||
<< "<th>Received</th>"
|
||||
<< "<th>Out</th>"
|
||||
<< "<th>In</th>"
|
||||
<< "<th>Buf</th>"
|
||||
<< "<th>RTT</th>"
|
||||
<< "<th>Window</th>"
|
||||
<< "<th>Status</th>"
|
||||
<< "</tr>\r\n</thead>\r\n<tbody class=\"tableitem\">\r\n";
|
||||
|
||||
for (const auto& it: dest->GetAllStreams ())
|
||||
{
|
||||
@@ -638,7 +650,7 @@ namespace http {
|
||||
}
|
||||
else if (!i2p::context.IsFloodfill ())
|
||||
{
|
||||
s << "<b>" << tr("LeaseSets") << ":</b> " << tr("not floodfill") << ".<br>\r\n";
|
||||
s << "<b>" << tr("LeaseSets") << ":</b> " << tr(/* Message on LeaseSets page */ "floodfill mode is disabled") << ".<br>\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -667,7 +679,7 @@ namespace http {
|
||||
}
|
||||
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
@@ -687,7 +699,7 @@ namespace http {
|
||||
);
|
||||
}
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
@@ -700,8 +712,7 @@ namespace http {
|
||||
|
||||
s << "<b>" << tr("Router commands") << "</b><br>\r\n<br>\r\n<div class=\"commands\">\r\n";
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">" << tr("Run peer test") << "</a><br>\r\n";
|
||||
|
||||
// s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RELOAD_TUNNELS_CONFIG << "&token=" << token << "\">" << tr("Reload tunnels configuration") << "</a><br>\r\n";
|
||||
|
||||
if (i2p::context.AcceptsTunnels ())
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">" << tr("Decline transit tunnels") << "</a><br>\r\n";
|
||||
@@ -713,12 +724,11 @@ namespace http {
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">" << tr("Cancel graceful shutdown") << "</a><br>\r\n";
|
||||
else
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">" << tr("Start graceful shutdown") << "</a><br>\r\n";
|
||||
/*#elif defined(WIN32_APP)
|
||||
#elif defined(WIN32_APP)
|
||||
if (i2p::util::DaemonWin32::Instance().isGraceful)
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">" << tr("Cancel graceful shutdown") << "</a><br>\r\n";
|
||||
else
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">" << tr("Start graceful shutdown") << "</a><br>\r\n";
|
||||
*/
|
||||
#endif
|
||||
|
||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">" << tr("Force shutdown") << "</a><br><br>\r\n";
|
||||
@@ -727,33 +737,42 @@ namespace http {
|
||||
|
||||
s << "<br>\r\n<small>" << tr("<b>Note:</b> any action done here are not persistent and not changes your config files.") << "</small>\r\n<br>\r\n";
|
||||
|
||||
auto loglevel = i2p::log::Logger().GetLogLevel();
|
||||
s << "<b>" << tr("Logging level") << "</b><br>\r\n";
|
||||
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
|
||||
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
|
||||
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
|
||||
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
|
||||
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
|
||||
s << " <a class=\"button" << (loglevel == eLogNone ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
|
||||
s << " <a class=\"button" << (loglevel == eLogError ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
|
||||
s << " <a class=\"button" << (loglevel == eLogWarning ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
|
||||
s << " <a class=\"button" << (loglevel == eLogInfo ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
|
||||
s << " <a class=\"button" << (loglevel == eLogDebug ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
|
||||
|
||||
uint16_t maxTunnels = GetMaxNumTransitTunnels ();
|
||||
s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n";
|
||||
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
|
||||
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
|
||||
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
|
||||
s << " <input type=\"number\" min=\"0\" max=\"65535\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
|
||||
s << " <input type=\"number\" min=\"0\" max=\"" << TRANSIT_TUNNELS_LIMIT <<"\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
|
||||
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
|
||||
s << "</form>\r\n<br>\r\n";
|
||||
|
||||
std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage(); // get current used language
|
||||
s << "<b>" << tr("Change language") << "</b><br>\r\n";
|
||||
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
|
||||
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_SETLANGUAGE << "\">\r\n";
|
||||
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
|
||||
s << " <select name=\"lang\" id=\"lang\">\r\n";
|
||||
// get current used language
|
||||
std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage();
|
||||
|
||||
s << "<b>"
|
||||
<< tr("Change language")
|
||||
<< "</b><br>\r\n"
|
||||
<< "<form method=\"get\" action=\"" << webroot << "\">\r\n"
|
||||
<< " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_SETLANGUAGE << "\">\r\n"
|
||||
<< " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
|
||||
<< " <select name=\"lang\" id=\"lang\">\r\n";
|
||||
|
||||
for (const auto& it: i2p::i18n::languages)
|
||||
s << " <option value=\"" << it.first << "\"" << ((it.first.compare(currLang) == 0) ? " selected" : "") << ">" << it.second.LocaleName << "</option>\r\n";
|
||||
s << " </select>\r\n";
|
||||
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
|
||||
s << "</form>\r\n<br>\r\n";
|
||||
|
||||
s << " </select>\r\n"
|
||||
<< " <button type=\"submit\">"
|
||||
<< tr("Change")
|
||||
<< "</button>\r\n"
|
||||
<< "</form>\r\n<br>\r\n";
|
||||
|
||||
}
|
||||
|
||||
@@ -761,23 +780,24 @@ namespace http {
|
||||
{
|
||||
if (i2p::tunnel::tunnels.CountTransitTunnels())
|
||||
{
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n";
|
||||
s << "<table><thead><th>⇒</th><th>ID</th><th>⇒</th><th>" << tr("Amount") << "</th></thead><tbody class=\"tableitem\">";
|
||||
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
|
||||
{
|
||||
s << "<div class=\"listitem\">\r\n";
|
||||
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
|
||||
s << it->GetTunnelID () << " ⇒ ";
|
||||
s << "<tr><td></td><td>" << it->GetTunnelID () << "</td><td>⇒</td><td>";
|
||||
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
|
||||
s << " ⇒ " << it->GetTunnelID ();
|
||||
s << "<tr><td>⇒</td><td>" << it->GetTunnelID () << "</td><td></td><td>";
|
||||
else
|
||||
s << " ⇒ " << it->GetTunnelID () << " ⇒ ";
|
||||
s << " " << it->GetNumTransmittedBytes () << "</div>\r\n";
|
||||
s << "<tr><td>⇒</td><td>" << it->GetTunnelID () << "</td><td>⇒</td><td>";
|
||||
ShowTraffic(s, it->GetNumTransmittedBytes ());
|
||||
s << "</td></tr>\r\n";
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
s << "</tbody></table>\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr("no transit tunnels currently built") << ".<br>\r\n";
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr(/* Message on transit tunnels page */ "no transit tunnels currently built") << ".<br>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,25 +807,34 @@ namespace http {
|
||||
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->GetRemoteEndpoint ().address ().is_v6 ())
|
||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v4 ())
|
||||
{
|
||||
tmp_s << "<div class=\"listitem\">\r\n";
|
||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< it.second->GetRemoteEndpoint ().address ().to_string ();
|
||||
<< endpoint.address ().to_string () << ":" << endpoint.port ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
if (it.second->GetRelayTag ())
|
||||
tmp_s << " [itag:" << it.second->GetRelayTag () << "]";
|
||||
if (it.second->GetSendQueueSize () > 0)
|
||||
tmp_s << " [queue:" << it.second->GetSendQueueSize () << "]";
|
||||
tmp_s << "</div>\r\n" << std::endl;
|
||||
cnt++;
|
||||
}
|
||||
if (it.second && it.second->IsEstablished () && it.second->GetRemoteEndpoint ().address ().is_v6 ())
|
||||
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v6 ())
|
||||
{
|
||||
tmp_s6 << "<div class=\"listitem\">\r\n";
|
||||
if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< "[" << it.second->GetRemoteEndpoint ().address ().to_string () << "]";
|
||||
<< "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
if (it.second->GetRelayTag ())
|
||||
tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]";
|
||||
if (it.second->GetSendQueueSize () > 0)
|
||||
tmp_s6 << " [queue:" << it.second->GetSendQueueSize () << "]";
|
||||
tmp_s6 << "</div>\r\n" << std::endl;
|
||||
cnt6++;
|
||||
}
|
||||
@@ -834,46 +863,6 @@ namespace http {
|
||||
if (!sessions.empty ())
|
||||
ShowTransportSessions (s, sessions, "NTCP2");
|
||||
}
|
||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||
if (ssuServer)
|
||||
{
|
||||
auto sessions = ssuServer->GetSessions ();
|
||||
if (!sessions.empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ssu'><b>SSU</b> ( " << (int) sessions.size() << " )</label>\r\n<input type=\"checkbox\" id=\"slide_ssu\" />\r\n<div class=\"slidecontent list\">";
|
||||
for (const auto& it: sessions)
|
||||
{
|
||||
s << "<div class=\"listitem\">\r\n";
|
||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||
if (it.second->IsOutgoing ()) s << " ⇒ ";
|
||||
s << endpoint.address ().to_string () << ":" << endpoint.port ();
|
||||
if (!it.second->IsOutgoing ()) s << " ⇒ ";
|
||||
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
if (it.second->GetRelayTag ())
|
||||
s << " [itag:" << it.second->GetRelayTag () << "]";
|
||||
s << "</div>\r\n" << std::endl;
|
||||
}
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
}
|
||||
auto sessions6 = ssuServer->GetSessionsV6 ();
|
||||
if (!sessions6.empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ssuv6'><b>SSUv6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type=\"checkbox\" id=\"slide_ssuv6\" />\r\n<div class=\"slidecontent list\">";
|
||||
for (const auto& it: sessions6)
|
||||
{
|
||||
s << "<div class=\"listitem\">\r\n";
|
||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||
if (it.second->IsOutgoing ()) s << " ⇒ ";
|
||||
s << "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
|
||||
if (!it.second->IsOutgoing ()) s << " ⇒ ";
|
||||
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
if (it.second->GetRelayTag ())
|
||||
s << " [itag:" << it.second->GetRelayTag () << "]";
|
||||
s << "</div>\r\n" << std::endl;
|
||||
}
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
auto ssu2Server = i2p::transport::transports.GetSSU2Server ();
|
||||
if (ssu2Server)
|
||||
{
|
||||
@@ -905,7 +894,7 @@ namespace http {
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
else
|
||||
s << "<b>" << tr("SAM sessions") << ":</b> " << tr("no sessions currently running") << ".<br>\r\n";
|
||||
s << "<b>" << tr("SAM sessions") << ":</b> " << tr(/* Message on SAM sessions page */ "no sessions currently running") << ".<br>\r\n";
|
||||
}
|
||||
|
||||
void ShowSAMSession (std::stringstream& s, const std::string& id)
|
||||
@@ -1014,7 +1003,7 @@ namespace http {
|
||||
for (auto& it: serverForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << it.second->GetName () << "</a> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "</div>\r\n"<< std::endl;
|
||||
@@ -1023,8 +1012,8 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket, HTTPServer& server):
|
||||
m_Socket (socket), m_Server (server), m_BufferLen (0), expected_host(hostname)
|
||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||
m_Socket (socket), m_BufferLen (0), expected_host(hostname)
|
||||
{
|
||||
/* cache options */
|
||||
i2p::config::GetOption("http.auth", needAuth);
|
||||
@@ -1224,7 +1213,7 @@ namespace http {
|
||||
url.parse_query(params);
|
||||
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
std::string redirect = "5; url=" + webroot + "?page=commands";
|
||||
std::string redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=commands";
|
||||
std::string token = params["token"];
|
||||
|
||||
if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ())
|
||||
@@ -1236,7 +1225,7 @@ namespace http {
|
||||
std::string cmd = params["cmd"];
|
||||
if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
|
||||
i2p::transport::transports.PeerTest ();
|
||||
else if (cmd == HTTP_COMMAND_RELOAD_CONFIG)
|
||||
else if (cmd == HTTP_COMMAND_RELOAD_TUNNELS_CONFIG)
|
||||
i2p::client::context.ReloadConfig ();
|
||||
else if (cmd == HTTP_COMMAND_ENABLE_TRANSIT)
|
||||
i2p::context.SetAcceptsTunnels (true);
|
||||
@@ -1245,33 +1234,28 @@ namespace http {
|
||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_START)
|
||||
{
|
||||
i2p::context.SetAcceptsTunnels (false);
|
||||
// TODO: rewrite timer access
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
if (m_DaemonGracefulTimer) m_DaemonGracefulTimer = 10 * 60;
|
||||
/*#elif defined(WIN32_APP)
|
||||
Daemon.gracefulShutdownInterval = 10*60;
|
||||
#elif defined(WIN32_APP)
|
||||
i2p::win32::GracefulShutdown ();
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL)
|
||||
{
|
||||
i2p::context.SetAcceptsTunnels (true);
|
||||
// TODO: rewrite timer access
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
if (m_DaemonGracefulTimer) m_DaemonGracefulTimer = 0;
|
||||
/*#elif defined(WIN32_APP)
|
||||
Daemon.gracefulShutdownInterval = 0;
|
||||
#elif defined(WIN32_APP)
|
||||
i2p::win32::StopGracefulShutdown ();
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW)
|
||||
{
|
||||
// TODO: rewrite stop command access
|
||||
//#ifndef WIN32_APP
|
||||
m_Server.GetDaemonStop();
|
||||
//#else
|
||||
// i2p::win32::StopWin32App ();
|
||||
//#endif
|
||||
#ifndef WIN32_APP
|
||||
Daemon.running = false;
|
||||
#else
|
||||
i2p::win32::StopWin32App ();
|
||||
#endif
|
||||
}
|
||||
else if (cmd == HTTP_COMMAND_LOGLEVEL)
|
||||
{
|
||||
@@ -1303,20 +1287,20 @@ namespace http {
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("StreamID can't be null") << "<br>\r\n<br>\r\n";
|
||||
|
||||
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">" << tr("Return to destination page") << "</a><br>\r\n";
|
||||
s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
|
||||
redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32;
|
||||
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
|
||||
redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32;
|
||||
res.add_header("Refresh", redirect.c_str());
|
||||
return;
|
||||
}
|
||||
else if (cmd == HTTP_COMMAND_LIMITTRANSIT)
|
||||
{
|
||||
uint32_t limit = std::stoul(params["limit"], nullptr);
|
||||
if (limit > 0 && limit <= 65535)
|
||||
if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT)
|
||||
SetMaxNumTransitTunnels (limit);
|
||||
else {
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("Transit tunnels count must not exceed 65535") << "\r\n<br>\r\n<br>\r\n";
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("Transit tunnels count must not exceed %d", TRANSIT_TUNNELS_LIMIT) << "\r\n<br>\r\n<br>\r\n";
|
||||
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a>\r\n<br>\r\n";
|
||||
s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
|
||||
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
|
||||
res.add_header("Refresh", redirect.c_str());
|
||||
return;
|
||||
}
|
||||
@@ -1391,7 +1375,7 @@ namespace http {
|
||||
|
||||
s << "<b>" << tr("SUCCESS") << "</b>: " << tr("Command accepted") << "<br><br>\r\n";
|
||||
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a><br>\r\n";
|
||||
s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
|
||||
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
|
||||
res.add_header("Refresh", redirect.c_str());
|
||||
}
|
||||
|
||||
@@ -1505,7 +1489,7 @@ namespace http {
|
||||
|
||||
void HTTPServer::CreateConnection(std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
|
||||
{
|
||||
auto conn = std::make_shared<HTTPConnection> (m_Hostname, newSocket, *this);
|
||||
auto conn = std::make_shared<HTTPConnection> (m_Hostname, newSocket);
|
||||
conn->Receive ();
|
||||
}
|
||||
} // http
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -24,14 +24,14 @@ namespace http
|
||||
{
|
||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
|
||||
|
||||
class HTTPServer;
|
||||
const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds
|
||||
const int TRANSIT_TUNNELS_LIMIT = 65535;
|
||||
|
||||
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
|
||||
{
|
||||
public:
|
||||
|
||||
HTTPConnection (std::string serverhost, std::shared_ptr<boost::asio::ip::tcp::socket> socket, HTTPServer& server);
|
||||
HTTPConnection (std::string serverhost, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||
void Receive ();
|
||||
|
||||
private:
|
||||
@@ -50,7 +50,6 @@ namespace http
|
||||
private:
|
||||
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
||||
HTTPServer& m_Server;
|
||||
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
|
||||
size_t m_BufferLen;
|
||||
std::string m_SendBuffer;
|
||||
@@ -72,13 +71,6 @@ namespace http
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
typedef std::function<void ()> DaemonStop;
|
||||
void SetDaemonStop (const DaemonStop& f) { m_DaemonStop = f; };
|
||||
DaemonStop GetDaemonStop () { return m_DaemonStop; };
|
||||
|
||||
void SetDaemonGracefulTimer (const int& f) { m_DaemonGracefulTimer = f; };
|
||||
int GetDaemonGracefulTimer () { return m_DaemonGracefulTimer; };
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
@@ -95,11 +87,6 @@ namespace http
|
||||
boost::asio::io_service::work m_Work;
|
||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||
std::string m_Hostname;
|
||||
|
||||
private:
|
||||
|
||||
DaemonStop m_DaemonStop;
|
||||
int m_DaemonGracefulTimer;
|
||||
};
|
||||
|
||||
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -33,11 +33,12 @@ namespace http
|
||||
|
||||
// bundled style sheet
|
||||
const std::string internalCSS =
|
||||
"<style>\r\n"
|
||||
":root { --main-bg-color: #fafafa; --main-text-color: #103456; --main-link-color: #894c84; --main-link-hover-color: #fafafa; }\r\n"
|
||||
"@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n"
|
||||
"body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n"
|
||||
"a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n"
|
||||
"a:hover, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
|
||||
"a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
|
||||
"a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n"
|
||||
".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n"
|
||||
".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n"
|
||||
@@ -84,127 +85,12 @@ namespace http
|
||||
" border-radius: 5px; font-size: 12px; }\r\n"
|
||||
" button[type=submit] { padding: 5px 15px; background: transparent; border: 2px solid var(--main-link-color); cursor: pointer;\r\n"
|
||||
" border-radius: 5px; position: relative; height: 36px; display: -webkit-inline-box; margin-top: 10px; }\r\n"
|
||||
"}\r\n";
|
||||
"}\r\n"
|
||||
"</style>\r\n";
|
||||
|
||||
// for external style sheet
|
||||
std::string externalCSS;
|
||||
|
||||
const std::string pageBase =
|
||||
"<!DOCTYPE html> \
|
||||
<html lang=\"{{ langCode }}\"> \
|
||||
<head> \
|
||||
{% block head %} \
|
||||
<meta charset=\"UTF-8\"> \
|
||||
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> \
|
||||
<link rel=\"shortcut icon\" href=\"{% getFavicon() %}\"> \
|
||||
<title>{% block title %}{% endblock %} - Purple I2P Webconsole</title> \
|
||||
<style>{% getStyles() %}</style> \
|
||||
{% endblock %} \
|
||||
</head> \
|
||||
<body> \
|
||||
<div class=\"header\">{% tr(\"<b>i2pd</b> webconsole\") %}</div> \
|
||||
<div class=\"wrapper\"> \
|
||||
<div class=\"menu\"> \
|
||||
<a href=\"{{ webroot }}\">{% tr(\"Main page\") %}</a><br><br> \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_COMMANDS\") %}\">{% tr(\"Router commands\") %}</a><br> \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_LOCAL_DESTINATIONS\") %}\">{% tr(\"Local Destinations\") %}</a><br> \
|
||||
{% if isFloodfill %} \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_LEASESETS\") %}\">{% tr(\"LeaseSets\") %}</a><br> \
|
||||
{% endif %} \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_TUNNELS\") %}\">{% tr(\"Tunnels\") %}</a><br> \
|
||||
{% if (acceptingTunnels || transitTunnels) %} \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_TRANSIT_TUNNELS\") %}\">{% tr(\"Transit Tunnels\") %}</a><br> \
|
||||
{% endif %} \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_TRANSPORTS\") %}\">{% tr(\"Transports\") %}</a><br> \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_I2P_TUNNELS\") %}\">{% tr(\"I2P tunnels\") %}</a><br> \
|
||||
{% if samEnabled %} \
|
||||
<a href=\"{{ webroot }}?page={% getCommand(\"HTTP_PAGE_SAM_SESSIONS\") %}\">{% tr(\"SAM sessions\") %}</a><br> \
|
||||
{% endif %} \
|
||||
</div> \
|
||||
<div class=\"content\">{% block content %}{% endblock %}</div> \
|
||||
</div> \
|
||||
</body> \
|
||||
</html>";
|
||||
|
||||
const std::string pageMain =
|
||||
"{% extends \"base.html\" %} \
|
||||
{% block title %}Main{% endblock %} \
|
||||
{% block content %} \
|
||||
<b>{% tr(\"Uptime\") %}:</b> {% getUptime() %}<br> \
|
||||
<b>{% tr(\"Network status\") %}:</b> {% getNetworkStatus(false) %}<br> \
|
||||
{% if supportsV6 %} \
|
||||
<b>{% tr(\"Network status v6\") %}:</b> {% getNetworkStatus(true) %}<br> \
|
||||
{% endif %} \
|
||||
{% if gracefulShutdown %} \
|
||||
<b>{% tr(\"Stopping in\") %}:</b> {% getShutdownTimer() %}<br> \
|
||||
{% endif %} \
|
||||
<b>{% tr(\"Tunnel creation success rate\") %}:</b> {% getSuccessRate() %}%<br> \
|
||||
<b>{% tr(\"Received\") %}:</b> {% getInBytes() %} ({% getInBW() %} {% tr(/* tr: Kibibit/s */ \"KiB/s\") %})<br> \
|
||||
<b>{% tr(\"Sent\") %}:</b> {% getOutBytes() %} ({% getOutBW() %} {% tr(/* tr: Kibibit/s */ \"KiB/s\") %})<br> \
|
||||
<b>{% tr(\"Transit\") %}:</b> {% getTransitBytes() %} ({% getTransitBW() %} {% tr(/* tr: Kibibit/s */ \"KiB/s\") %})<br> \
|
||||
<b>{% tr(\"Data path\") %}:</b> {% getDataPath() %}<br> \
|
||||
{% if notQt || withHiddenContent %} \
|
||||
<div class=\"slide\"> \
|
||||
<label for=\"slide-info\">{% tr(\"Hidden content. Press on text to see.\") %}</label> \
|
||||
<input type=\"checkbox\" id=\"slide-info\" /> \
|
||||
<div class=\"slidecontent\"> \
|
||||
<b>{% tr(\"Router Ident\") %}:</b> {% getRI() %}<br> \
|
||||
{% if lenght(family) %} \
|
||||
<b>{% tr(\"Family\") %}:</b> {{ family }}<br> \
|
||||
{% endif %} \
|
||||
<b>{% tr(\"Router Caps\") %}:</b> {% getCaps() %}<br> \
|
||||
<b>{% tr(\"Version\") %}:</b> {{ version }}<br> \
|
||||
<b>{% tr(\"Our external address\") %}:</b><br> \
|
||||
<table class=\"extaddr\"> \
|
||||
<tbody> \
|
||||
{% for type, address in addresses %} \
|
||||
<tr><td>{{ type }}</td><td>{{ address }}</td></tr> \
|
||||
{% endfor %} \
|
||||
</tbody> \
|
||||
</table> \
|
||||
</div> \
|
||||
</div> \
|
||||
{% else %} \
|
||||
<br> \
|
||||
{% endif %} \
|
||||
<b>{% tr(\"Routers\") %}:</b> {% getNumRouter() %} \
|
||||
<b>{% tr(\"Floodfills\") %}:</b> {% getNumFloodfills() %} \
|
||||
<b>{% tr(\"LeaseSets\") %}:</b> {% getNumLeaseSets() %}<br> \
|
||||
<b>{% tr(\"Client Tunnels\") %}:</b> {% getClientTunnelsCount() %} \
|
||||
<b>{% tr(\"Transit Tunnels\") %}:</b> {% getTransitTunnelsCount() %}<br> \
|
||||
<br> \
|
||||
{% if notQt == false %} \
|
||||
<table class=\"services\"> \
|
||||
<caption>{% tr(\"Services\") %}</caption> \
|
||||
<tbody> \
|
||||
<tr> \
|
||||
<td>HTTP {% tr(\"Proxy\") %}</td> \
|
||||
<td class=\"{% if httpproxy %}enabled{% else %}disabled{% endif %}\">{% if httpproxy %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
<tr> \
|
||||
<td>SOCKS {% tr(\"Proxy\") %}</td> \
|
||||
<td class=\"{% if socksproxy %}enabled{% else %}disabled{% endif %}\">{% if socksproxy %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
<tr> \
|
||||
<td>BOB</td> \
|
||||
<td class=\"{% if bob %}enabled{% else %}disabled{% endif %}\">{% if bob %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
<tr> \
|
||||
<td>SAM</td> \
|
||||
<td class=\"{% if sam %}enabled{% else %}disabled{% endif %}\">{% if sam %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
<tr> \
|
||||
<td>I2CP</td> \
|
||||
<td class=\"{% if i2cp %}enabled{% else %}disabled{% endif %}\">{% if i2cp %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
<tr> \
|
||||
<td>I2PControl</td> \
|
||||
<td class=\"{% if i2pcontrol %}enabled{% else %}disabled{% endif %}\">{% if i2pcontrol %}{% tr(\"Enabled\") %}{% else %}{% tr(\"Disabled\") %}{% endif %}</td> \
|
||||
</tr> \
|
||||
</tbody> \
|
||||
</table> \
|
||||
{% endblock %}";
|
||||
|
||||
} // http
|
||||
} // i2p
|
||||
|
||||
@@ -14,25 +14,17 @@
|
||||
// Use global placeholders from boost introduced when local_time.hpp is loaded
|
||||
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "Crypto.h"
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
#include "Config.h"
|
||||
#include "NetDb.hpp"
|
||||
#include "RouterContext.h"
|
||||
#include "Daemon.h"
|
||||
#include "Tunnel.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Transports.h"
|
||||
#include "version.h"
|
||||
#include "util.h"
|
||||
#include "ClientContext.h"
|
||||
#include "Daemon.h"
|
||||
#include "I2PControl.h"
|
||||
|
||||
namespace i2p
|
||||
@@ -69,44 +61,18 @@ namespace client
|
||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlHandlers::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlHandlers::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlHandlers::ClientServicesInfoHandler;
|
||||
|
||||
// I2PControl
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
|
||||
// RouterInfo
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
// RouterManager
|
||||
m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler;
|
||||
m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler;
|
||||
m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler;
|
||||
|
||||
// NetworkSetting
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlService::OutboundBandwidthLimit;
|
||||
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@@ -280,37 +246,6 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << value;
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
|
||||
{
|
||||
ss << "\"" << name << "\":";
|
||||
if (value.length () > 0)
|
||||
{
|
||||
if (quotes)
|
||||
ss << "\"" << value << "\"";
|
||||
else
|
||||
ss << value;
|
||||
}
|
||||
else
|
||||
ss << "null";
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, double value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
|
||||
{
|
||||
std::ostringstream buf;
|
||||
boost::property_tree::write_json (buf, value, false);
|
||||
ss << "\"" << name << "\":" << buf.str();
|
||||
}
|
||||
|
||||
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
||||
{
|
||||
@@ -396,91 +331,6 @@ namespace client
|
||||
m_Tokens.clear ();
|
||||
}
|
||||
|
||||
// RouterInfo
|
||||
|
||||
void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
bool first = true;
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
|
||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||
if (it1 != m_RouterInfoHandlers.end ())
|
||||
{
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::UptimeHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
|
||||
}
|
||||
|
||||
void I2PControlService::VersionHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.version", VERSION);
|
||||
}
|
||||
|
||||
void I2PControlService::StatusHandler (std::ostringstream& results)
|
||||
{
|
||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
|
||||
}
|
||||
|
||||
void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetDbActivePeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetStatusHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ());
|
||||
}
|
||||
|
||||
void I2PControlService::TunnelsParticipatingHandler (std::ostringstream& results)
|
||||
{
|
||||
int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size ();
|
||||
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
|
||||
}
|
||||
|
||||
void I2PControlService::TunnelsSuccessRateHandler (std::ostringstream& results)
|
||||
{
|
||||
int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate ();
|
||||
InsertParam (results, "i2p.router.net.tunnels.successrate", rate);
|
||||
}
|
||||
|
||||
void I2PControlService::InboundBandwidth1S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetInBandwidth ();
|
||||
InsertParam (results, "i2p.router.net.bw.inbound.1s", bw);
|
||||
}
|
||||
|
||||
void I2PControlService::OutboundBandwidth1S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetOutBandwidth ();
|
||||
InsertParam (results, "i2p.router.net.bw.outbound.1s", bw);
|
||||
}
|
||||
|
||||
void I2PControlService::NetTotalReceivedBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
|
||||
// RouterManager
|
||||
|
||||
@@ -532,37 +382,6 @@ namespace client
|
||||
i2p::data::netdb.Reseed ();
|
||||
}
|
||||
|
||||
// network setting
|
||||
void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
|
||||
auto it1 = m_NetworkSettingHandlers.find (it->first);
|
||||
if (it1 != m_NetworkSettingHandlers.end ()) {
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(it->second.data (), results);
|
||||
} else
|
||||
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::InboundBandwidthLimit (const std::string& value, std::ostringstream& results)
|
||||
{
|
||||
if (value != "null")
|
||||
i2p::context.SetBandwidth (std::atoi(value.c_str()));
|
||||
int bw = i2p::context.GetBandwidthLimit();
|
||||
InsertParam (results, "i2p.router.net.bw.in", bw);
|
||||
}
|
||||
|
||||
void I2PControlService::OutboundBandwidthLimit (const std::string& value, std::ostringstream& results)
|
||||
{
|
||||
if (value != "null")
|
||||
i2p::context.SetBandwidth (std::atoi(value.c_str()));
|
||||
int bw = i2p::context.GetBandwidthLimit();
|
||||
InsertParam (results, "i2p.router.net.bw.out", bw);
|
||||
}
|
||||
|
||||
// certificate
|
||||
void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path)
|
||||
{
|
||||
@@ -611,178 +430,5 @@ namespace client
|
||||
}
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first);
|
||||
auto it1 = m_ClientServicesInfoHandlers.find (it->first);
|
||||
if (it1 != m_ClientServicesInfoHandlers.end ())
|
||||
{
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::I2PTunnelInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::ptree client_tunnels, server_tunnels;
|
||||
|
||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
|
||||
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
|
||||
if (!serverTunnels.empty ()) {
|
||||
for (auto& it: serverTunnels)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
st.put("port", it.second->GetLocalPort ());
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
auto& clientForwards = i2p::client::context.GetClientForwards ();
|
||||
if (!clientForwards.empty ())
|
||||
{
|
||||
for (auto& it: clientForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
}
|
||||
|
||||
auto& serverForwards = i2p::client::context.GetServerForwards ();
|
||||
if (!serverForwards.empty ())
|
||||
{
|
||||
for (auto& it: serverForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
pt.add_child("client", client_tunnels);
|
||||
pt.add_child("server", server_tunnels);
|
||||
|
||||
InsertParam (results, "I2PTunnel", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::HTTPProxyInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto httpProxy = i2p::client::context.GetHttpProxy ();
|
||||
if (httpProxy)
|
||||
{
|
||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "HTTPProxy", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SOCKSInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto socksProxy = i2p::client::context.GetSocksProxy ();
|
||||
if (socksProxy)
|
||||
{
|
||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "SOCKS", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto sam = i2p::client::context.GetSAMBridge ();
|
||||
if (sam)
|
||||
{
|
||||
pt.put("enabled", true);
|
||||
boost::property_tree::ptree sam_sessions;
|
||||
for (auto& it: sam->GetSessions ())
|
||||
{
|
||||
boost::property_tree::ptree sam_session, sam_session_sockets;
|
||||
auto& name = it.second->GetLocalDestination ()->GetNickname ();
|
||||
auto& ident = it.second->GetLocalDestination ()->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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include "I2PControlHandlers.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@@ -32,7 +33,7 @@ namespace client
|
||||
const char I2P_CONTROL_CERTIFICATE_COMMON_NAME[] = "i2pd.i2pcontrol";
|
||||
const char I2P_CONTROL_CERTIFICATE_ORGANIZATION[] = "Purple I2P";
|
||||
|
||||
class I2PControlService
|
||||
class I2PControlService: public I2PControlHandlers
|
||||
{
|
||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
||||
|
||||
@@ -63,61 +64,24 @@ namespace client
|
||||
|
||||
private:
|
||||
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||
|
||||
// methods
|
||||
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
||||
void AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void I2PControlHandler (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 NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
||||
// I2PControl
|
||||
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
||||
void PasswordHandler (const std::string& value);
|
||||
|
||||
// RouterInfo
|
||||
typedef void (I2PControlService::*RouterInfoRequestHandler)(std::ostringstream& results);
|
||||
void UptimeHandler (std::ostringstream& results);
|
||||
void VersionHandler (std::ostringstream& results);
|
||||
void StatusHandler (std::ostringstream& results);
|
||||
void NetDbKnownPeersHandler (std::ostringstream& results);
|
||||
void NetDbActivePeersHandler (std::ostringstream& results);
|
||||
void NetStatusHandler (std::ostringstream& results);
|
||||
void TunnelsParticipatingHandler (std::ostringstream& results);
|
||||
void TunnelsSuccessRateHandler (std::ostringstream& results);
|
||||
void InboundBandwidth1S (std::ostringstream& results);
|
||||
void OutboundBandwidth1S (std::ostringstream& results);
|
||||
void NetTotalReceivedBytes (std::ostringstream& results);
|
||||
void NetTotalSentBytes (std::ostringstream& results);
|
||||
|
||||
// RouterManager
|
||||
typedef void (I2PControlService::*RouterManagerRequestHandler)(std::ostringstream& results);
|
||||
void ShutdownHandler (std::ostringstream& results);
|
||||
void ShutdownGracefulHandler (std::ostringstream& results);
|
||||
void ReseedHandler (std::ostringstream& results);
|
||||
|
||||
// NetworkSetting
|
||||
typedef void (I2PControlService::*NetworkSettingRequestHandler)(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);
|
||||
|
||||
// ClientServicesInfo
|
||||
typedef void (I2PControlService::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Password;
|
||||
@@ -132,10 +96,7 @@ namespace client
|
||||
|
||||
std::map<std::string, MethodHandler> m_MethodHandlers;
|
||||
std::map<std::string, I2PControlRequestHandler> m_I2PControlHandlers;
|
||||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
|
||||
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
||||
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
390
daemon/I2PControlHandlers.cpp
Normal file
390
daemon/I2PControlHandlers.cpp
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <iomanip>
|
||||
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include "Log.h"
|
||||
#include "RouterContext.h"
|
||||
#include "NetDb.hpp"
|
||||
#include "Tunnel.h"
|
||||
#include "Transports.h"
|
||||
#include "version.h"
|
||||
#include "ClientContext.h"
|
||||
#include "I2PControlHandlers.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
I2PControlHandlers::I2PControlHandlers ()
|
||||
{
|
||||
// RouterInfo
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlHandlers::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlHandlers::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlHandlers::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlHandlers::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlHandlers::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlHandlers::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.15s"] = &I2PControlHandlers::InboundBandwidth15S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlHandlers::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.15s"] = &I2PControlHandlers::OutboundBandwidth15S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlHandlers::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlHandlers::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlHandlers::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlHandlers::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlHandlers::NetTotalSentBytes;
|
||||
|
||||
// NetworkSetting
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit;
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit;
|
||||
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlHandlers::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << value;
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
|
||||
{
|
||||
ss << "\"" << name << "\":";
|
||||
if (value.length () > 0)
|
||||
{
|
||||
if (quotes)
|
||||
ss << "\"" << value << "\"";
|
||||
else
|
||||
ss << value;
|
||||
}
|
||||
else
|
||||
ss << "null";
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, double value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||
}
|
||||
|
||||
void I2PControlHandlers::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();
|
||||
}
|
||||
|
||||
// RouterInfo
|
||||
|
||||
void I2PControlHandlers::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
bool first = true;
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
|
||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||
if (it1 != m_RouterInfoHandlers.end ())
|
||||
{
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlHandlers::UptimeHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::VersionHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.version", VERSION);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::StatusHandler (std::ostringstream& results)
|
||||
{
|
||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
|
||||
}
|
||||
|
||||
void I2PControlHandlers::NetDbKnownPeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ());
|
||||
}
|
||||
|
||||
void I2PControlHandlers::NetDbActivePeersHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ());
|
||||
}
|
||||
|
||||
void I2PControlHandlers::NetStatusHandler (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ());
|
||||
}
|
||||
|
||||
void I2PControlHandlers::TunnelsParticipatingHandler (std::ostringstream& results)
|
||||
{
|
||||
int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size ();
|
||||
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::TunnelsSuccessRateHandler (std::ostringstream& results)
|
||||
{
|
||||
int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate ();
|
||||
InsertParam (results, "i2p.router.net.tunnels.successrate", rate);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InboundBandwidth1S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetInBandwidth ();
|
||||
InsertParam (results, "i2p.router.net.bw.inbound.1s", bw);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InboundBandwidth15S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetInBandwidth15s ();
|
||||
InsertParam (results, "i2p.router.net.bw.inbound.15s", bw);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::OutboundBandwidth1S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetOutBandwidth ();
|
||||
InsertParam (results, "i2p.router.net.bw.outbound.1s", bw);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::OutboundBandwidth15S (std::ostringstream& results)
|
||||
{
|
||||
double bw = i2p::transport::transports.GetOutBandwidth15s ();
|
||||
InsertParam (results, "i2p.router.net.bw.outbound.15s", bw);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::NetTotalReceivedBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ());
|
||||
}
|
||||
|
||||
void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
// network setting
|
||||
void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
|
||||
auto it1 = m_NetworkSettingHandlers.find (it->first);
|
||||
if (it1 != m_NetworkSettingHandlers.end ()) {
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(it->second.data (), results);
|
||||
} else
|
||||
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlHandlers::InboundBandwidthLimit (const std::string& value, std::ostringstream& results)
|
||||
{
|
||||
if (value != "null")
|
||||
i2p::context.SetBandwidth (std::atoi(value.c_str()));
|
||||
int bw = i2p::context.GetBandwidthLimit();
|
||||
InsertParam (results, "i2p.router.net.bw.in", bw);
|
||||
}
|
||||
|
||||
void I2PControlHandlers::OutboundBandwidthLimit (const std::string& value, std::ostringstream& results)
|
||||
{
|
||||
if (value != "null")
|
||||
i2p::context.SetBandwidth (std::atoi(value.c_str()));
|
||||
int bw = i2p::context.GetBandwidthLimit();
|
||||
InsertParam (results, "i2p.router.net.bw.out", bw);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
void I2PControlHandlers::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 I2PControlHandlers::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 I2PControlHandlers::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 I2PControlHandlers::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 I2PControlHandlers::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->GetLocalDestination ()->GetNickname ();
|
||||
auto& ident = it.second->GetLocalDestination ()->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 I2PControlHandlers::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 I2PControlHandlers::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
daemon/I2PControlHandlers.h
Normal file
82
daemon/I2PControlHandlers.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifndef I2P_CONTROL_HANDLERS_H__
|
||||
#define I2P_CONTROL_HANDLERS_H__
|
||||
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
class I2PControlHandlers
|
||||
{
|
||||
public:
|
||||
|
||||
I2PControlHandlers ();
|
||||
|
||||
// methods
|
||||
// TODO: make protected
|
||||
void RouterInfoHandler (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);
|
||||
|
||||
protected:
|
||||
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||
|
||||
private:
|
||||
|
||||
// RouterInfo
|
||||
typedef void (I2PControlHandlers::*RouterInfoRequestHandler)(std::ostringstream& results);
|
||||
void UptimeHandler (std::ostringstream& results);
|
||||
void VersionHandler (std::ostringstream& results);
|
||||
void StatusHandler (std::ostringstream& results);
|
||||
void NetDbKnownPeersHandler (std::ostringstream& results);
|
||||
void NetDbActivePeersHandler (std::ostringstream& results);
|
||||
void NetStatusHandler (std::ostringstream& results);
|
||||
void TunnelsParticipatingHandler (std::ostringstream& results);
|
||||
void TunnelsSuccessRateHandler (std::ostringstream& results);
|
||||
void InboundBandwidth1S (std::ostringstream& results);
|
||||
void InboundBandwidth15S (std::ostringstream& results);
|
||||
void OutboundBandwidth1S (std::ostringstream& results);
|
||||
void OutboundBandwidth15S (std::ostringstream& results);
|
||||
void NetTotalReceivedBytes (std::ostringstream& results);
|
||||
void NetTotalSentBytes (std::ostringstream& results);
|
||||
|
||||
// NetworkSetting
|
||||
typedef void (I2PControlHandlers::*NetworkSettingRequestHandler)(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);
|
||||
|
||||
// ClientServicesInfo
|
||||
typedef void (I2PControlHandlers::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
||||
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -159,10 +159,11 @@ namespace transport
|
||||
|
||||
void UPnP::PortMapping ()
|
||||
{
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
auto a = context.GetRouterInfo().GetAddresses();
|
||||
if (!a) return;
|
||||
for (const auto& address : *a)
|
||||
{
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
if (address && !address->host.is_v6 () && address->port)
|
||||
TryPortMapping (address);
|
||||
}
|
||||
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
|
||||
@@ -210,10 +211,11 @@ namespace transport
|
||||
|
||||
void UPnP::CloseMapping ()
|
||||
{
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
auto a = context.GetRouterInfo().GetAddresses();
|
||||
if (!a) return;
|
||||
for (const auto& address : *a)
|
||||
{
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
if (address && !address->host.is_v6 () && address->port)
|
||||
CloseMapping (address);
|
||||
}
|
||||
}
|
||||
@@ -248,10 +250,10 @@ namespace transport
|
||||
{
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||
return "TCP";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
default:
|
||||
return "UDP";
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "Tunnel.h"
|
||||
#include "RouterContext.h"
|
||||
#include "ClientContext.h"
|
||||
#include "Transports.h"
|
||||
|
||||
void handle_signal(int sig)
|
||||
{
|
||||
@@ -54,6 +55,14 @@ void handle_signal(int sig)
|
||||
case SIGPIPE:
|
||||
LogPrint(eLogInfo, "SIGPIPE received");
|
||||
break;
|
||||
case SIGTSTP:
|
||||
LogPrint(eLogInfo, "Daemon: Got SIGTSTP, disconnecting from network...");
|
||||
i2p::transport::transports.SetOnline(false);
|
||||
break;
|
||||
case SIGCONT:
|
||||
LogPrint(eLogInfo, "Daemon: Got SIGCONT, restoring connection to network...");
|
||||
i2p::transport::transports.SetOnline(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +180,9 @@ namespace i2p
|
||||
}
|
||||
gracefulShutdownInterval = 0; // not specified
|
||||
|
||||
// handle signal TSTP
|
||||
bool handleTSTP; i2p::config::GetOption("unix.handle_sigtstp", handleTSTP);
|
||||
|
||||
// Signal handler
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handle_signal;
|
||||
@@ -182,6 +194,11 @@ namespace i2p
|
||||
sigaction(SIGTERM, &sa, 0);
|
||||
sigaction(SIGINT, &sa, 0);
|
||||
sigaction(SIGPIPE, &sa, 0);
|
||||
if (handleTSTP)
|
||||
{
|
||||
sigaction(SIGTSTP, &sa, 0);
|
||||
sigaction(SIGCONT, &sa, 0);
|
||||
}
|
||||
|
||||
return Daemon_Singleton::start();
|
||||
}
|
||||
29
debian/changelog
vendored
29
debian/changelog
vendored
@@ -1,3 +1,32 @@
|
||||
i2pd (2.45.1-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.45.1/0.9.57
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Wed, 11 Jan 2023 19:00:00 +0000
|
||||
|
||||
i2pd (2.45.0-1) unstable; urgency=high
|
||||
|
||||
* updated to version 2.45.0/0.9.57
|
||||
* compat level 12
|
||||
* standards version 4.3.0
|
||||
* increased nofile limit in service and init.d to 8192
|
||||
* added conffiles
|
||||
* removed #1210 patch
|
||||
|
||||
-- r4sas <r4sas@i2pmail.org> Tue, 3 Jan 2023 18:00:00 +0000
|
||||
|
||||
i2pd (2.44.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.44.0/0.9.56
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Sun, 20 Nov 2022 19:00:00 +0000
|
||||
|
||||
i2pd (2.43.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.43.0/0.9.55
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Mon, 22 Aug 2022 16:00:00 +0000
|
||||
|
||||
i2pd (2.42.1-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.42.1/0.9.54
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
9
|
||||
12
|
||||
|
||||
2
debian/conffiles
vendored
Normal file
2
debian/conffiles
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/etc/i2pd/i2pd.conf
|
||||
/etc/i2pd/tunnels.conf
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -2,8 +2,8 @@ Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
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.8
|
||||
Build-Depends: debhelper (>= 12~), 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: 4.3.0
|
||||
Homepage: http://i2pd.website/
|
||||
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
||||
Vcs-Browser: https://github.com/PurpleI2P/i2pd
|
||||
|
||||
6
debian/copyright
vendored
6
debian/copyright
vendored
@@ -3,18 +3,18 @@ Upstream-Name: i2pd
|
||||
Source: https://github.com/PurpleI2P
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2020 PurpleI2P
|
||||
Copyright: 2013-2023 PurpleI2P
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
|
||||
2014-2016 hagen <hagen@i2pmail.org>
|
||||
2016-2020 R4SAS <r4sas@i2pmail.org>
|
||||
2016-2023 R4SAS <r4sas@i2pmail.org>
|
||||
2017-2020 Yangfl <mmyangfl@gmail.com>
|
||||
License: GPL-2+
|
||||
|
||||
License: BSD-3-clause
|
||||
Copyright (c) 2013-2017, The PurpleI2P Project
|
||||
Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
.
|
||||
All rights reserved.
|
||||
.
|
||||
|
||||
2
debian/i2pd.default
vendored
2
debian/i2pd.default
vendored
@@ -8,4 +8,4 @@ I2PD_ENABLED="yes"
|
||||
DAEMON_OPTS=""
|
||||
|
||||
# If you have problems with hunging i2pd, you can try enable this
|
||||
ulimit -n 4096
|
||||
ulimit -n 8192
|
||||
|
||||
1
debian/i2pd.install
vendored
1
debian/i2pd.install
vendored
@@ -1,7 +1,6 @@
|
||||
i2pd usr/sbin/
|
||||
contrib/i2pd.conf etc/i2pd/
|
||||
contrib/tunnels.conf etc/i2pd/
|
||||
contrib/subscriptions.txt etc/i2pd/
|
||||
contrib/certificates/ usr/share/i2pd/
|
||||
contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/
|
||||
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d
|
||||
|
||||
3
debian/i2pd.links
vendored
3
debian/i2pd.links
vendored
@@ -1,5 +1,4 @@
|
||||
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
|
||||
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
|
||||
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
|
||||
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
|
||||
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d
|
||||
usr/share/i2pd/certificates var/lib/i2pd/certificates
|
||||
|
||||
27
debian/patches/01-fix-1210.patch
vendored
27
debian/patches/01-fix-1210.patch
vendored
@@ -1,27 +0,0 @@
|
||||
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: 2020-05-25
|
||||
|
||||
Index: i2pd/contrib/i2pd.service
|
||||
===================================================================
|
||||
--- i2pd.orig/contrib/i2pd.service
|
||||
+++ i2pd/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 --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||
ExecReload=/bin/sh -c "kill -HUP $MAINPID"
|
||||
3
debian/patches/series
vendored
3
debian/patches/series
vendored
@@ -1,2 +1 @@
|
||||
01-fix-1210.patch
|
||||
02-upnp.patch
|
||||
01-upnp.patch
|
||||
|
||||
3
debian/watch
vendored
3
debian/watch
vendored
@@ -1,3 +1,4 @@
|
||||
version=4 opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
|
||||
version=4
|
||||
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
|
||||
https://github.com/PurpleI2P/i2pd/tags \
|
||||
(?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate
|
||||
|
||||
23
filelist.mk
23
filelist.mk
@@ -1,7 +1,26 @@
|
||||
#LIB_SRC = \
|
||||
# BloomFilter.cpp Gzip.cpp Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \
|
||||
# Log.cpp NTCPSession.cpp NetDb.cpp NetDbRequests.cpp Profiling.cpp \
|
||||
# Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
|
||||
# SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
||||
# Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
|
||||
# Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \
|
||||
# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Gost.cpp
|
||||
|
||||
LIB_SRC = $(wildcard $(LIB_SRC_DIR)/*.cpp)
|
||||
|
||||
#LIB_CLIENT_SRC = \
|
||||
# AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \
|
||||
# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp
|
||||
|
||||
LIB_CLIENT_SRC = $(wildcard $(LIB_CLIENT_SRC_DIR)/*.cpp)
|
||||
|
||||
# also: Daemon{Linux,Win32}.cpp will be added later
|
||||
#DAEMON_SRC = \
|
||||
# HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
|
||||
|
||||
LANG_SRC = $(wildcard $(LANG_SRC_DIR)/*.cpp)
|
||||
WEBCONSOLE_SRC = $(wildcard $(WEBCONSOLE_SRC_DIR)/*.cpp)
|
||||
|
||||
WRAP_LIB_SRC = $(wildcard $(WRAP_SRC_DIR)/*.cpp)
|
||||
DAEMON_SRC = $(DAEMON_SRC_DIR)/Daemon.cpp $(DAEMON_SRC_DIR)/I2PControl.cpp $(DAEMON_SRC_DIR)/i2pd.cpp $(DAEMON_SRC_DIR)/UPnP.cpp
|
||||
|
||||
DAEMON_SRC = $(wildcard $(DAEMON_SRC_DIR)/*.cpp)
|
||||
|
||||
@@ -64,10 +64,10 @@ namespace afrikaans // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"dag", "dae"}},
|
||||
{"hours", {"uur", "ure"}},
|
||||
{"minutes", {"minuut", "minute"}},
|
||||
{"seconds", {"seconde", "sekondes"}},
|
||||
{"%d days", {"%d dag", "%d dae"}},
|
||||
{"%d hours", {"%d uur", "%d ure"}},
|
||||
{"%d minutes", {"%d minuut", "%d minute"}},
|
||||
{"%d seconds", {"%d seconde", "%d sekondes"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace armenian // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "ԿիԲ"},
|
||||
{"MiB", "ՄիԲ"},
|
||||
{"GiB", "ԳիԲ"},
|
||||
{"%.2f KiB", "%.2f ԿիԲ"},
|
||||
{"%.2f MiB", "%.2f ՄիԲ"},
|
||||
{"%.2f GiB", "%.2f ԳիԲ"},
|
||||
{"building", "կառուցվում է"},
|
||||
{"failed", "Անհաջող"},
|
||||
{"expiring", "Լրանում է"},
|
||||
@@ -68,7 +68,7 @@ namespace armenian // language namespace
|
||||
{"Family", "Խմբատեսակ"},
|
||||
{"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"},
|
||||
{"Received", "Ստացվել է"},
|
||||
{"KiB/s", "ԿիԲ/վ"},
|
||||
{"%.2f KiB/s", "%.2f ԿիԲ/վ"},
|
||||
{"Sent", "Ուղարկվել է"},
|
||||
{"Transit", "Տարանցում"},
|
||||
{"Data path", "Տվյալների ուղին"},
|
||||
@@ -94,7 +94,7 @@ namespace armenian // language namespace
|
||||
{"Type", "Տեսակը"},
|
||||
{"EncType", "Գաղտնագրի տեսակը"},
|
||||
{"Inbound tunnels", "Մուտքային թունելներ"},
|
||||
{"ms", "մլվ"},
|
||||
{"%dms", "%dմլվ"},
|
||||
{"Outbound tunnels", "Ելքային թունելներ"},
|
||||
{"Tags", "Թեգեր"},
|
||||
{"Incoming", "Մուտքային"},
|
||||
@@ -198,10 +198,10 @@ namespace armenian // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"օր", "օր"}},
|
||||
{"hours", {"ժամ", "ժամ"}},
|
||||
{"minutes", {"րոպե", "րոպե"}},
|
||||
{"seconds", {"վարկյան", "վարկյան"}},
|
||||
{"%d days", {"%d օր", "%d օր"}},
|
||||
{"%d hours", {"%d ժամ", "%d ժամ"}},
|
||||
{"%d minutes", {"%d րոպե", "%d րոպե"}},
|
||||
{"%d seconds", {"%d վարկյան", "%d վարկյան"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
217
i18n/Chinese.cpp
Normal file
217
i18n/Chinese.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// Simplified Chinese localization file
|
||||
// This is an example translation file without strings in it.
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace chinese // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "chinese";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "正在构建"},
|
||||
{"failed", "连接失败"},
|
||||
{"expiring", "即将过期"},
|
||||
{"established", "连接成功"},
|
||||
{"unknown", "未知"},
|
||||
{"exploratory", "探索"},
|
||||
{"Purple I2P Webconsole", "Purple I2P 网页控制台"},
|
||||
{"<b>i2pd</b> webconsole", "<b>i2pd</b> 网页控制台"},
|
||||
{"Main page", "主页"},
|
||||
{"Router commands", "路由命令"},
|
||||
{"Local Destinations", "本地目标"},
|
||||
{"LeaseSets", "租契集"},
|
||||
{"Tunnels", "隧道"},
|
||||
{"Transit Tunnels", "中转隧道"},
|
||||
{"Transports", "传输"},
|
||||
{"I2P tunnels", "I2P 隧道"},
|
||||
{"SAM sessions", "SAM 会话"},
|
||||
{"ERROR", "错误"},
|
||||
{"OK", "良好"},
|
||||
{"Testing", "测试中"},
|
||||
{"Firewalled", "受到防火墙限制"},
|
||||
{"Unknown", "未知"},
|
||||
{"Proxy", "代理"},
|
||||
{"Mesh", "Mesh组网"},
|
||||
{"Error", "错误"},
|
||||
{"Clock skew", "时钟偏移"},
|
||||
{"Offline", "离线"},
|
||||
{"Symmetric NAT", "对称 NAT"},
|
||||
{"Uptime", "运行时间"},
|
||||
{"Network status", "IPv4 网络状态"},
|
||||
{"Network status v6", "IPv6 网络状态"},
|
||||
{"Stopping in", "距停止还有:"},
|
||||
{"Family", "家族"},
|
||||
{"Tunnel creation success rate", "隧道创建成功率"},
|
||||
{"Received", "已接收"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "已发送"},
|
||||
{"Transit", "中转"},
|
||||
{"Data path", "数据文件路径"},
|
||||
{"Hidden content. Press on text to see.", "隐藏内容 请点击此处查看。"},
|
||||
{"Router Ident", "路由身份"},
|
||||
{"Router Family", "路由器家族"},
|
||||
{"Router Caps", "路由器类型"},
|
||||
{"Version", "版本"},
|
||||
{"Our external address", "外部地址"},
|
||||
{"supported", "支持"},
|
||||
{"Routers", "路由节点"},
|
||||
{"Floodfills", "洪泛节点"},
|
||||
{"Client Tunnels", "客户端隧道"},
|
||||
{"Services", "服务"},
|
||||
{"Enabled", "启用"},
|
||||
{"Disabled", "禁用"},
|
||||
{"Encrypted B33 address", "加密的 B33 地址"},
|
||||
{"Address registration line", "地址域名注册"},
|
||||
{"Domain", "域名"},
|
||||
{"Generate", "生成"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>注意:</b> 结果字符串只能用于注册次级域名(例如:example.i2p)。若需注册子域名,请使用 i2pd-tools。"},
|
||||
{"Address", "地址"},
|
||||
{"Type", "类型"},
|
||||
{"EncType", "加密类型"},
|
||||
{"Inbound tunnels", "入站隧道"},
|
||||
{"%dms", "%d毫秒"},
|
||||
{"Outbound tunnels", "出站隧道"},
|
||||
{"Tags", "标签"},
|
||||
{"Incoming", "传入"},
|
||||
{"Outgoing", "传出"},
|
||||
{"Destination", "目标"},
|
||||
{"Amount", "数量"},
|
||||
{"Incoming Tags", "传入标签"},
|
||||
{"Tags sessions", "标签会话"},
|
||||
{"Status", "状态"},
|
||||
{"Local Destination", "本地目标"},
|
||||
{"Streams", "流"},
|
||||
{"Close stream", "断开流"},
|
||||
{"I2CP session not found", "未找到 I2CP 会话"},
|
||||
{"I2CP is not enabled", "I2CP 未启用"},
|
||||
{"Invalid", "无效"},
|
||||
{"Store type", "存储类型"},
|
||||
{"Expires", "过期时间"},
|
||||
{"Non Expired Leases", "未到期的租约"},
|
||||
{"Gateway", "网关"},
|
||||
{"TunnelID", "隧道 ID"},
|
||||
{"EndDate", "结束日期"},
|
||||
{"not floodfill", "非洪泛"},
|
||||
{"Queue size", "队列大小"},
|
||||
{"Run peer test", "运行节点测试"},
|
||||
{"Decline transit tunnels", "拒绝中转隧道"},
|
||||
{"Accept transit tunnels", "允许中转隧道"},
|
||||
{"Cancel graceful shutdown", "取消平滑关闭"},
|
||||
{"Start graceful shutdown", "平滑关闭"},
|
||||
{"Force shutdown", "强制停止"},
|
||||
{"Reload external CSS styles", "重载外部 CSS 样式"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>注意:</b> 此处完成的任何操作都不是永久的,不会更改您的配置文件。"},
|
||||
{"Logging level", "日志记录级别"},
|
||||
{"Transit tunnels limit", "中转隧道限制"},
|
||||
{"Change", "修改"},
|
||||
{"Change language", "更改语言"},
|
||||
{"no transit tunnels currently built", "目前未构建中转隧道"},
|
||||
{"SAM disabled", "SAM 已禁用"},
|
||||
{"no sessions currently running", "没有正在运行的会话"},
|
||||
{"SAM session not found", "未找到 SAM 会话"},
|
||||
{"SAM Session", "SAM 会话"},
|
||||
{"Server Tunnels", "服务器隧道"},
|
||||
{"Client Forwards", "客户端转发"},
|
||||
{"Server Forwards", "服务器转发"},
|
||||
{"Unknown page", "未知页面"},
|
||||
{"Invalid token", "无效令牌"},
|
||||
{"SUCCESS", "成功"},
|
||||
{"Stream closed", "流已关闭"},
|
||||
{"Stream not found or already was closed", "流未找到或已关闭"},
|
||||
{"Destination not found", "找不到目标"},
|
||||
{"StreamID can't be null", "StreamID 不能为空"},
|
||||
{"Return to destination page", "返回目标页面"},
|
||||
{"You will be redirected in 5 seconds", "您将在5秒内被重定向"},
|
||||
{"Transit tunnels count must not exceed 65535", "中转隧道数量不能超过 65535"},
|
||||
{"Back to commands list", "返回命令列表"},
|
||||
{"Register at reg.i2p", "在 reg.i2p 注册域名"},
|
||||
{"Description", "描述"},
|
||||
{"A bit information about service on domain", "在此域名上运行的服务的一些信息"},
|
||||
{"Submit", "提交"},
|
||||
{"Domain can't end with .b32.i2p", "域名不能以 .b32.i2p 结尾"},
|
||||
{"Domain must end with .i2p", "域名必须以 .i2p 结尾"},
|
||||
{"Such destination is not found", "找不到此目标"},
|
||||
{"Unknown command", "未知指令"},
|
||||
{"Command accepted", "已接受指令"},
|
||||
{"Proxy error", "代理错误"},
|
||||
{"Proxy info", "代理信息"},
|
||||
{"Proxy error: Host not found", "代理错误:未找到主机"},
|
||||
{"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"},
|
||||
{"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到该主机"},
|
||||
{"Invalid request", "无效请求"},
|
||||
{"Proxy unable to parse your request", "代理无法解析您的请求"},
|
||||
{"addresshelper is not supported", "不支持地址助手"},
|
||||
{"Host", "主机"},
|
||||
{"added to router's addressbook from helper", "将此地址从地址助手添加到路由地址簿"},
|
||||
{"Click here to proceed:", "点击此处继续:"},
|
||||
{"Continue", "继续"},
|
||||
{"Addresshelper found", "已找到地址助手"},
|
||||
{"already in router's addressbook", "已在路由地址簿中"},
|
||||
{"Click here to update record:", "点击此处更新地址簿记录"},
|
||||
{"invalid request uri", "无效的 URL 请求"},
|
||||
{"Can't detect destination host from request", "无法从请求中检测到目标主机"},
|
||||
{"Outproxy failure", "出口代理故障"},
|
||||
{"bad outproxy settings", "错误的出口代理设置"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "该地址不在 I2P 网络内,但未启用出口代理"},
|
||||
{"unknown outproxy url", "未知的出口代理地址"},
|
||||
{"cannot resolve upstream proxy", "无法解析上游代理"},
|
||||
{"hostname too long", "主机名过长"},
|
||||
{"cannot connect to upstream socks proxy", "无法连接到上游 socks 代理"},
|
||||
{"Cannot negotiate with socks proxy", "无法与 socks 代理协商"},
|
||||
{"CONNECT error", "连接错误"},
|
||||
{"Failed to Connect", "连接失败"},
|
||||
{"socks proxy error", "socks 代理错误"},
|
||||
{"failed to send request to upstream", "向上游发送请求失败"},
|
||||
{"No Reply From socks proxy", "没有来自 socks 代理的回复"},
|
||||
{"cannot connect", "无法连接"},
|
||||
{"http out proxy not implemented", "http 出口代理未实现"},
|
||||
{"cannot connect to upstream http proxy", "无法连接到上游 http 代理"},
|
||||
{"Host is down", "主机已关闭"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"%d days", {"%d 日"}},
|
||||
{"%d hours", {"%d 时"}},
|
||||
{"%d minutes", {"%d 分"}},
|
||||
{"%d seconds", {"%d 秒"}},
|
||||
{"", {""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
216
i18n/Czech.cpp
Normal file
216
i18n/Czech.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// Czech localization file
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace czech // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "czech";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "vytváří se"},
|
||||
{"failed", "selhalo"},
|
||||
{"expiring", "končící"},
|
||||
{"established", "vytvořeno"},
|
||||
{"unknown", "neznámý"},
|
||||
{"exploratory", "průzkumné"},
|
||||
{"Purple I2P Webconsole", "Purple I2P Webkonsole"},
|
||||
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsole"},
|
||||
{"Main page", "Hlavní stránka"},
|
||||
{"Router commands", "Router příkazy"},
|
||||
{"Local Destinations", "Lokální destinace"},
|
||||
{"LeaseSets", "LeaseSety"},
|
||||
{"Tunnels", "Tunely"},
|
||||
{"Transit Tunnels", "Transitní tunely"},
|
||||
{"Transports", "Transporty"},
|
||||
{"I2P tunnels", "I2P tunely"},
|
||||
{"SAM sessions", "SAM relace"},
|
||||
{"ERROR", "CHYBA"},
|
||||
{"OK", "OK"},
|
||||
{"Testing", "Testuji"},
|
||||
{"Firewalled", "Za Firewallem"},
|
||||
{"Unknown", "Neznámý"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Síť"},
|
||||
{"Error", "Chyba"},
|
||||
{"Clock skew", "Časová nesrovnalost"},
|
||||
{"Offline", "Offline"},
|
||||
{"Symmetric NAT", "Symetrický NAT"},
|
||||
{"Uptime", "Doba provozu"},
|
||||
{"Network status", "Status sítě"},
|
||||
{"Network status v6", "Status sítě v6"},
|
||||
{"Stopping in", "Zastavuji za"},
|
||||
{"Family", "Rodina"},
|
||||
{"Tunnel creation success rate", "Úspěšnost vytváření tunelů"},
|
||||
{"Received", "Přijato"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Odesláno"},
|
||||
{"Transit", "Tranzit"},
|
||||
{"Data path", "Cesta k data souborům"},
|
||||
{"Hidden content. Press on text to see.", "Skrytý kontent. Pro zobrazení, klikni na text."},
|
||||
{"Router Ident", "Routerová Identita"},
|
||||
{"Router Family", "Rodina routerů"},
|
||||
{"Router Caps", "Omezení Routerů"},
|
||||
{"Version", "Verze"},
|
||||
{"Our external address", "Naše externí adresa"},
|
||||
{"supported", "podporováno"},
|
||||
{"Routers", "Routery"},
|
||||
{"Floodfills", "Floodfilly"},
|
||||
{"Client Tunnels", "Klientské tunely"},
|
||||
{"Services", "Služby"},
|
||||
{"Enabled", "Zapnuto"},
|
||||
{"Disabled", "Vypnuto"},
|
||||
{"Encrypted B33 address", "Šifrovaná adresa B33"},
|
||||
{"Address registration line", "Registrační řádek adresy"},
|
||||
{"Domain", "Doména"},
|
||||
{"Generate", "Vygenerovat"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Poznámka:</b> výsledný řetězec může být použit pouze pro registraci 2LD domén (example.i2p). Pro registraci subdomén použijte prosím i2pd-tools."},
|
||||
{"Address", "Adresa"},
|
||||
{"Type", "Typ"},
|
||||
{"EncType", "EncType"},
|
||||
{"Inbound tunnels", "Příchozí tunely"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Odchozí tunely"},
|
||||
{"Tags", "Štítky"},
|
||||
{"Incoming", "Příchozí"},
|
||||
{"Outgoing", "Odchozí"},
|
||||
{"Destination", "Destinace"},
|
||||
{"Amount", "Množství"},
|
||||
{"Incoming Tags", "Příchozí štítky"},
|
||||
{"Tags sessions", "Relace štítků"},
|
||||
{"Status", "Status"},
|
||||
{"Local Destination", "Lokální Destinace"},
|
||||
{"Streams", "Toky"},
|
||||
{"Close stream", "Uzavřít tok"},
|
||||
{"I2CP session not found", "I2CP relace nenalezena"},
|
||||
{"I2CP is not enabled", "I2CP není zapnuto"},
|
||||
{"Invalid", "Neplatný"},
|
||||
{"Store type", "Druh uložení"},
|
||||
{"Expires", "Vyprší"},
|
||||
{"Non Expired Leases", "Nevypršené Leasy"},
|
||||
{"Gateway", "Brána"},
|
||||
{"TunnelID", "ID tunelu"},
|
||||
{"EndDate", "Datum ukončení"},
|
||||
{"not floodfill", "není floodfill"},
|
||||
{"Queue size", "Velikost fronty"},
|
||||
{"Run peer test", "Spustit peer test"},
|
||||
{"Decline transit tunnels", "Odmítnout tranzitní tunely"},
|
||||
{"Accept transit tunnels", "Přijmout tranzitní tunely"},
|
||||
{"Cancel graceful shutdown", "Zrušit hladké vypnutí"},
|
||||
{"Start graceful shutdown", "Zahájit hladké vypnutí"},
|
||||
{"Force shutdown", "Vynutit vypnutí"},
|
||||
{"Reload external CSS styles", "Znovu načíst externí CSS"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Poznámka:</b> žádná vykonaná akce zde není trvalá a nemění konfigurační soubory."},
|
||||
{"Logging level", "Úroveň logování"},
|
||||
{"Transit tunnels limit", "Limit tranzitních tunelů"},
|
||||
{"Change", "Změnit"},
|
||||
{"Change language", "Změnit jazyk"},
|
||||
{"no transit tunnels currently built", "Žádný tranzitní tunel není momentálně vytvořen"},
|
||||
{"SAM disabled", "SAM vypnutý"},
|
||||
{"no sessions currently running", "Momentálně nejsou spuštěné žádné relace"},
|
||||
{"SAM session not found", "SAM relace nenalezena"},
|
||||
{"SAM Session", "SAM Relace"},
|
||||
{"Server Tunnels", "Server Tunely"},
|
||||
{"Client Forwards", "Přesměrování Klienta"},
|
||||
{"Server Forwards", "Přesměrování Serveru"},
|
||||
{"Unknown page", "Neznámá stránka"},
|
||||
{"Invalid token", "Neplatný token"},
|
||||
{"SUCCESS", "ÚSPĚCH"},
|
||||
{"Stream closed", "Tok uzavřen"},
|
||||
{"Stream not found or already was closed", "Tok nenalezen nebo byl již uzavřen"},
|
||||
{"Destination not found", "Destinace nenalezena"},
|
||||
{"StreamID can't be null", "StreamID nemůže být null"},
|
||||
{"Return to destination page", "Zpět na stránku destinací"},
|
||||
{"You will be redirected in 5 seconds", "Budete přesměrováni za 5 vteřin"},
|
||||
{"Transit tunnels count must not exceed 65535", "Počet tranzitních tunelů nesmí přesáhnout 65535"},
|
||||
{"Back to commands list", "Zpět na list příkazů"},
|
||||
{"Register at reg.i2p", "Zaregistrovat na reg.i2p"},
|
||||
{"Description", "Popis"},
|
||||
{"A bit information about service on domain", "Trochu informací o službě na doméně"},
|
||||
{"Submit", "Odeslat"},
|
||||
{"Domain can't end with .b32.i2p", "Doména nesmí končit na .b32.i2p"},
|
||||
{"Domain must end with .i2p", "Doména musí končit s .i2p"},
|
||||
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
|
||||
{"Unknown command", "Neznámý příkaz"},
|
||||
{"Command accepted", "Příkaz přijat"},
|
||||
{"Proxy error", "Chyba proxy serveru"},
|
||||
{"Proxy info", "Proxy informace"},
|
||||
{"Proxy error: Host not found", "Chyba proxy serveru: Hostitel nenalezen"},
|
||||
{"Remote host not found in router's addressbook", "Vzdálený hostitel nebyl nalezen v adresáři routeru"},
|
||||
{"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"},
|
||||
{"Invalid request", "Neplatný požadavek"},
|
||||
{"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"},
|
||||
{"addresshelper is not supported", "Adresshelper není podporován"},
|
||||
{"Host", "Hostitel"},
|
||||
{"added to router's addressbook from helper", "přidáno do adresáře routeru od pomocníka"},
|
||||
{"Click here to proceed:", "Pro pokračování, klikněte zde:"},
|
||||
{"Continue", "Pokračovat"},
|
||||
{"Addresshelper found", "Adresář nalezen"},
|
||||
{"already in router's addressbook", "je již v adresáři routeru"},
|
||||
{"Click here to update record:", "Pro aktualizaci záznamu, klikněte zde:"},
|
||||
{"invalid request uri", "neplatný URI požadavek"},
|
||||
{"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"},
|
||||
{"Outproxy failure", "Outproxy selhání"},
|
||||
{"bad outproxy settings", "špatné outproxy nastavení"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "není uvnitř I2P sítě a outproxy není nastavena"},
|
||||
{"unknown outproxy url", "neznámá outproxy URL"},
|
||||
{"cannot resolve upstream proxy", "nelze rozluštit upstream proxy server"},
|
||||
{"hostname too long", "Název hostitele je příliš dlouhý"},
|
||||
{"cannot connect to upstream socks proxy", "nelze se připojit k upstream socks proxy serveru"},
|
||||
{"Cannot negotiate with socks proxy", "Nelze vyjednávat se socks proxy serverem"},
|
||||
{"CONNECT error", "Chyba PŘIPOJENÍ"},
|
||||
{"Failed to Connect", "Připojení se nezdařilo"},
|
||||
{"socks proxy error", "chyba socks proxy serveru"},
|
||||
{"failed to send request to upstream", "odeslání žádosti upstream serveru se nezdařilo"},
|
||||
{"No Reply From socks proxy", "Žádná odpověď od socks proxy serveru"},
|
||||
{"cannot connect", "nelze se připojit"},
|
||||
{"http out proxy not implemented", "http out proxy není implementován"},
|
||||
{"cannot connect to upstream http proxy", "nelze se připojit k upstream socks proxy serveru"},
|
||||
{"Host is down", "Hostitel je nedostupný"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"%d days", {"%d den", "%d dny", "%d dní", "%d dní"}},
|
||||
{"%d hours", {"%d hodina", "%d hodiny", "%d hodin", "%d hodin"}},
|
||||
{"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}},
|
||||
{"%d seconds", {"%d vteřina", "%d vteřiny", "%d vteřin", "%d vteřin"}},
|
||||
{"", {"", "", "", ""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
133
i18n/French.cpp
133
i18n/French.cpp
@@ -31,28 +31,37 @@ namespace french // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "Kio"},
|
||||
{"MiB", "Mio"},
|
||||
{"GiB", "Gio"},
|
||||
{"%.2f KiB", "%.2f Kio"},
|
||||
{"%.2f MiB", "%.2f Mio"},
|
||||
{"%.2f GiB", "%.2f Gio"},
|
||||
{"building", "En construction"},
|
||||
{"failed", "echoué"},
|
||||
{"failed", "échoué"},
|
||||
{"expiring", "expiré"},
|
||||
{"established", "établi"},
|
||||
{"unknown", "inconnu"},
|
||||
{"exploratory", "exploratoire"},
|
||||
{"Purple I2P Webconsole", "Console web Purple I2P"},
|
||||
{"<b>i2pd</b> webconsole", "Console web <b>i2pd</b>"},
|
||||
{"Main page", "Page principale"},
|
||||
{"Router commands", "Commandes du routeur"},
|
||||
{"Local Destinations", "Destinations locales"},
|
||||
{"LeaseSets", "Jeu de baux"},
|
||||
{"Tunnels", "Tunnels"},
|
||||
{"Transit Tunnels", "Tunnels transitoires"},
|
||||
{"Transports", "Transports"},
|
||||
{"I2P tunnels", "Tunnels I2P"},
|
||||
{"SAM sessions", "Sessions SAM"},
|
||||
{"ERROR", "ERREUR"},
|
||||
{"OK", "OK"},
|
||||
{"Testing", "Test en cours"},
|
||||
{"Firewalled", "Derrière un pare-feu"},
|
||||
{"Unknown", "Inconnu"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Maillé"},
|
||||
{"Error", "Erreur"},
|
||||
{"Clock skew", "Horloge décalée"},
|
||||
{"Offline", "Hors ligne"},
|
||||
{"Symmetric NAT", "NAT symétrique"},
|
||||
{"Uptime", "Temps de fonctionnement"},
|
||||
{"Network status", "État du réseau"},
|
||||
{"Network status v6", "État du réseau v6"},
|
||||
@@ -60,35 +69,135 @@ namespace french // language namespace
|
||||
{"Family", "Famille"},
|
||||
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
|
||||
{"Received", "Reçu"},
|
||||
{"KiB/s", "kio/s"},
|
||||
{"%.2f KiB/s", "%.2f kio/s"},
|
||||
{"Sent", "Envoyé"},
|
||||
{"Transit", "Transit"},
|
||||
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour regarder."},
|
||||
{"Transit", "Transité"},
|
||||
{"Data path", "Emplacement des données"},
|
||||
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour afficher."},
|
||||
{"Router Ident", "Identifiant du routeur"},
|
||||
{"Router Family", "Famille du routeur"},
|
||||
{"Router Caps", "Limiteurs du routeur"},
|
||||
{"Version", "Version"},
|
||||
{"Our external address", "Notre adresse externe"},
|
||||
{"supported", "supporté"},
|
||||
{"Routers", "Routeurs"},
|
||||
{"Client Tunnels", "Tunnels clients"},
|
||||
{"Services", "Services"},
|
||||
{"Enabled", "Activé"},
|
||||
{"Disabled", "Désactivé"},
|
||||
{"Encrypted B33 address", "Adresse B33 chiffrée"},
|
||||
{"Address registration line", "Ligne d'inscription de l'adresse"},
|
||||
{"Domain", "Domaine"},
|
||||
{"Generate", "Générer"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
|
||||
{"Address", "Adresse"},
|
||||
{"ms", "ms"},
|
||||
{"Type", "Type"},
|
||||
{"Inbound tunnels", "Tunnels entrants"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Tunnels sortants"},
|
||||
{"Tags", "Balises"},
|
||||
{"Incoming", "Entrant"},
|
||||
{"Outgoing", "Sortant"},
|
||||
{"Destination", "Destination"},
|
||||
{"Amount", "Quantité"},
|
||||
{"Incoming Tags", "Balises entrantes"},
|
||||
{"Tags sessions", "Sessions des balises"},
|
||||
{"Status", "Statut"},
|
||||
{"Local Destination", "Destination locale"},
|
||||
{"Streams", "Flux"},
|
||||
{"Close stream", "Fermer le flux"},
|
||||
{"I2CP session not found", "Session I2CP introuvable"},
|
||||
{"I2CP is not enabled", "I2CP est désactivé"},
|
||||
{"Invalid", "Invalide"},
|
||||
{"Store type", "Type de stockage"},
|
||||
{"Expires", "Expire"},
|
||||
{"Non Expired Leases", "Baux non expirés"},
|
||||
{"Gateway", "Passerelle"},
|
||||
{"TunnelID", "ID du tunnel"},
|
||||
{"EndDate", "Date de fin"},
|
||||
{"Queue size", "Longueur de la file"},
|
||||
{"Run peer test", "Lancer test des pairs"},
|
||||
{"Decline transit tunnels", "Refuser les tunnels transitoires"},
|
||||
{"Accept transit tunnels", "Accepter les tunnels transitoires"},
|
||||
{"Cancel graceful shutdown", "Annuler l'arrêt gracieux"},
|
||||
{"Start graceful shutdown", "Démarrer l'arrêt gracieux"},
|
||||
{"Force shutdown", "Forcer l'arrêt"},
|
||||
{"Reload external CSS styles", "Rafraîchir les styles CSS externes"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note:</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
|
||||
{"Logging level", "Niveau de journalisation"},
|
||||
{"Transit tunnels limit", "Limite sur les tunnels transitoires"},
|
||||
{"Change", "Changer"},
|
||||
{"Change language", "Changer la langue"},
|
||||
{"no transit tunnels currently built", "aucun tunnel transitoire présentement établi"},
|
||||
{"SAM disabled", "SAM désactivé"},
|
||||
{"no sessions currently running", "aucune session présentement en cours"},
|
||||
{"SAM session not found", "session SAM introuvable"},
|
||||
{"SAM Session", "Session SAM"},
|
||||
{"Server Tunnels", "Tunnels serveurs"},
|
||||
{"Unknown page", "Page inconnue"},
|
||||
{"Invalid token", "Jeton invalide"},
|
||||
{"SUCCESS", "SUCCÈS"},
|
||||
{"Stream closed", "Flux fermé"},
|
||||
{"Stream not found or already was closed", "Flux introuvable ou déjà fermé"},
|
||||
{"Destination not found", "Destination introuvable"},
|
||||
{"StreamID can't be null", "StreamID ne peut pas être vide"},
|
||||
{"Return to destination page", "Retourner à la page de destination"},
|
||||
{"You will be redirected in 5 seconds", "Vous allez être redirigé dans cinq secondes"},
|
||||
{"Transit tunnels count must not exceed 65535", "Le nombre de tunnels transitoires ne doit pas dépasser 65535"},
|
||||
{"Back to commands list", "Retour à la liste des commandes"},
|
||||
{"Register at reg.i2p", "Inscription à reg.i2p"},
|
||||
{"Description", "Description"},
|
||||
{"A bit information about service on domain", "Un peu d'information à propos des services disponibles dans le domaine"},
|
||||
{"Submit", "Soumettre"},
|
||||
{"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"},
|
||||
{"Domain must end with .i2p", "Le domaine doit terminer par .i2p"},
|
||||
{"Such destination is not found", "Cette destination est introuvable"},
|
||||
{"Unknown command", "Commande inconnue"},
|
||||
{"Command accepted", "Commande acceptée"},
|
||||
{"Proxy error", "Erreur de proxy"},
|
||||
{"Proxy info", "Information sur le proxy"},
|
||||
{"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"},
|
||||
{"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"},
|
||||
{"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"},
|
||||
{"Invalid request", "Requête invalide"},
|
||||
{"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"},
|
||||
{"addresshelper is not supported", "Assistant d'adresse non supporté"},
|
||||
{"Host", "Hôte"},
|
||||
{"added to router's addressbook from helper", "Ajouté au carnet d'adresse du routeur par l'assistant"},
|
||||
{"Click here to proceed:", "Cliquez ici pour continuer:"},
|
||||
{"Continue", "Continuer"},
|
||||
{"Addresshelper found", "Assistant d'adresse trouvé"},
|
||||
{"already in router's addressbook", "déjà dans le carnet d'adresses du routeur"},
|
||||
{"Click here to update record:", "Cliquez ici pour mettre à jour le carnet d'adresse:"},
|
||||
{"invalid request uri", "uri de la requête invalide"},
|
||||
{"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"},
|
||||
{"Outproxy failure", "Échec de proxy de sortie"},
|
||||
{"bad outproxy settings", "Mauvaise configuration du proxy de sortie"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"},
|
||||
{"unknown outproxy url", "URL du proxy de sortie inconnu"},
|
||||
{"cannot resolve upstream proxy", "impossible de résoudre l'adresse du proxy en amont"},
|
||||
{"hostname too long", "nom d'hôte trop long"},
|
||||
{"cannot connect to upstream socks proxy", "impossible de se connecter au proxy socks en amont"},
|
||||
{"Cannot negotiate with socks proxy", "Impossible de négocier avec le proxy socks"},
|
||||
{"CONNECT error", "Erreur de connexion"},
|
||||
{"Failed to Connect", "Échec de connexion"},
|
||||
{"socks proxy error", "Erreur de proxy socks"},
|
||||
{"failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"},
|
||||
{"No Reply From socks proxy", "Pas de réponse du proxy socks"},
|
||||
{"cannot connect", "impossible de connecter"},
|
||||
{"http out proxy not implemented", "Proxy de sortie HTTP non implémenté"},
|
||||
{"cannot connect to upstream http proxy", "impossible de se connecter au proxy HTTP en amont"},
|
||||
{"Host is down", "Hôte hors service"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"jour", "jours"}},
|
||||
{"hours", {"heure", "heures"}},
|
||||
{"minutes", {"minute", "minutes"}},
|
||||
{"seconds", {"seconde", "secondes"}},
|
||||
{"%d days", {"%d jour", "%d jours"}},
|
||||
{"%d hours", {"%d heure", "%d heures"}},
|
||||
{"%d minutes", {"%d minute", "%d minutes"}},
|
||||
{"%d seconds", {"%d seconde", "%d secondes"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
@@ -31,19 +31,20 @@ namespace german // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "KiB"},
|
||||
{"MiB", "MiB"},
|
||||
{"GiB", "GiB"},
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "In Bau"},
|
||||
{"failed", "fehlgeschlagen"},
|
||||
{"expiring", "läuft ab in"},
|
||||
{"expiring", "läuft ab"},
|
||||
{"established", "hergestellt"},
|
||||
{"unknown", "Unbekannt"},
|
||||
{"exploratory", "erforschende"},
|
||||
{"<b>i2pd</b> webconsole", "<b>i2pd</b> Webkonsole"},
|
||||
{"exploratory", "erforschend"},
|
||||
{"Purple I2P Webconsole", "Purple I2P-Webkonsole"},
|
||||
{"<b>i2pd</b> webconsole", "<b>i2pd</b>-Webkonsole"},
|
||||
{"Main page", "Startseite"},
|
||||
{"Router commands", "Router Befehle"},
|
||||
{"Local Destinations", "Lokale Destination"},
|
||||
{"Router commands", "Routerbefehle"},
|
||||
{"Local Destinations", "Lokale Ziele"},
|
||||
{"LeaseSets", "LeaseSets"},
|
||||
{"Tunnels", "Tunnel"},
|
||||
{"Transit Tunnels", "Transittunnel"},
|
||||
@@ -53,7 +54,7 @@ namespace german // language namespace
|
||||
{"ERROR", "FEHLER"},
|
||||
{"OK", "OK"},
|
||||
{"Testing", "Testen"},
|
||||
{"Firewalled", "Hinter eine Firewall"},
|
||||
{"Firewalled", "Hinter einer Firewall"},
|
||||
{"Unknown", "Unbekannt"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Mesh"},
|
||||
@@ -68,7 +69,7 @@ namespace german // language namespace
|
||||
{"Family", "Familie"},
|
||||
{"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"},
|
||||
{"Received", "Eingegangen"},
|
||||
{"KiB/s", "KiB/s"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Gesendet"},
|
||||
{"Transit", "Transit"},
|
||||
{"Data path", "Datenpfad"},
|
||||
@@ -81,33 +82,33 @@ namespace german // language namespace
|
||||
{"supported", "unterstützt"},
|
||||
{"Routers", "Router"},
|
||||
{"Floodfills", "Floodfills"},
|
||||
{"Client Tunnels", "Klienttunnel"},
|
||||
{"Client Tunnels", "Clienttunnel"},
|
||||
{"Services", "Services"},
|
||||
{"Enabled", "Aktiviert"},
|
||||
{"Disabled", "Deaktiviert"},
|
||||
{"Encrypted B33 address", "Verschlüsselte B33 Adresse"},
|
||||
{"Address registration line", "Adresseregistrierungszeile"},
|
||||
{"Encrypted B33 address", "Verschlüsselte B33-Adresse"},
|
||||
{"Address registration line", "Adressregistrierungszeile"},
|
||||
{"Domain", "Domain"},
|
||||
{"Generate", "Generieren"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Hinweis:</b> Der resultierende String kann nur für die Registrierung einer 2LD Domain (beispiel.i2p) benutzt werden. Für die Registrierung von Subdomains kann i2pd-tools verwendet werden."},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Hinweis:</b> Der resultierende String kann nur für die Registrierung einer 2LD-Domain (beispiel.i2p) benutzt werden. Für die Registrierung von Subdomains kann i2pd-tools verwendet werden."},
|
||||
{"Address", "Adresse"},
|
||||
{"Type", "Typ"},
|
||||
{"EncType", "Verschlüsselungstyp"},
|
||||
{"Inbound tunnels", "Eingehende Tunnel"},
|
||||
{"ms", "ms"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Ausgehende Tunnel"},
|
||||
{"Tags", "Tags"},
|
||||
{"Incoming", "Eingehend"},
|
||||
{"Outgoing", "Ausgehend"},
|
||||
{"Destination", "Destination"},
|
||||
{"Destination", "Ziel"},
|
||||
{"Amount", "Anzahl"},
|
||||
{"Incoming Tags", "Eingehende Tags"},
|
||||
{"Tags sessions", "Tags Sitzungen"},
|
||||
{"Tags sessions", "Tags-Sitzungen"},
|
||||
{"Status", "Status"},
|
||||
{"Local Destination", "Lokale Destination"},
|
||||
{"Local Destination", "Lokales Ziel"},
|
||||
{"Streams", "Streams"},
|
||||
{"Close stream", "Stream schließen"},
|
||||
{"I2CP session not found", "I2CP Sitzung nicht gefunden"},
|
||||
{"I2CP session not found", "I2CP-Sitzung nicht gefunden"},
|
||||
{"I2CP is not enabled", "I2CP ist nicht aktiviert"},
|
||||
{"Invalid", "Ungültig"},
|
||||
{"Store type", "Speichertyp"},
|
||||
@@ -117,67 +118,67 @@ namespace german // language namespace
|
||||
{"TunnelID", "TunnelID"},
|
||||
{"EndDate", "Enddatum"},
|
||||
{"not floodfill", "kein Floodfill"},
|
||||
{"Queue size", "Warteschlangengröße"},
|
||||
{"Run peer test", "Peer-Test ausführen"},
|
||||
{"Queue size", "Größe der Warteschlange"},
|
||||
{"Run peer test", "Peer-Test durchführen"},
|
||||
{"Decline transit tunnels", "Transittunnel ablehnen"},
|
||||
{"Accept transit tunnels", "Transittunnel akzeptieren"},
|
||||
{"Cancel graceful shutdown", "Beende das kontrollierte herunterfahren"},
|
||||
{"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"},
|
||||
{"Start graceful shutdown", "Starte das kontrollierte Herunterfahren"},
|
||||
{"Force shutdown", "Herunterfahren erzwingen"},
|
||||
{"Reload external CSS styles", "Lade externe CSS-Styles neu"},
|
||||
{"Reload external CSS styles", "Lade externe CSS-Stile neu"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Hinweis:</b> Alle hier durchgeführten Aktionen sind nicht dauerhaft und ändern die Konfigurationsdateien nicht."},
|
||||
{"Logging level", "Protokollierungslevel"},
|
||||
{"Transit tunnels limit", "Limit für Transittunnel"},
|
||||
{"Change", "Verändern"},
|
||||
{"Change", "Ändern"},
|
||||
{"Change language", "Sprache ändern"},
|
||||
{"no transit tunnels currently built", "derzeit keine Transittunnel aufgebaut"},
|
||||
{"SAM disabled", "SAM deaktiviert"},
|
||||
{"no sessions currently running", "Derzeit keine laufenden Sitzungen"},
|
||||
{"SAM session not found", "SAM Sitzung nicht gefunden"},
|
||||
{"SAM Session", "SAM Sitzung"},
|
||||
{"SAM session not found", "SAM-Sitzung nicht gefunden"},
|
||||
{"SAM Session", "SAM-Sitzung"},
|
||||
{"Server Tunnels", "Servertunnel"},
|
||||
{"Client Forwards", "Klient-Weiterleitungen"},
|
||||
{"Client Forwards", "Client-Weiterleitungen"},
|
||||
{"Server Forwards", "Server-Weiterleitungen"},
|
||||
{"Unknown page", "Unbekannte Seite"},
|
||||
{"Invalid token", "Ungültiger Token"},
|
||||
{"SUCCESS", "ERFOLGREICH"},
|
||||
{"Stream closed", "Stream geschlossen"},
|
||||
{"Stream not found or already was closed", "Stream nicht gefunden oder bereits geschlossen"},
|
||||
{"Destination not found", "Destination nicht gefunden"},
|
||||
{"Destination not found", "Ziel nicht gefunden"},
|
||||
{"StreamID can't be null", "StreamID kann nicht null sein"},
|
||||
{"Return to destination page", "Zurück zur Destination-Seite"},
|
||||
{"Return to destination page", "Zurück zur Ziel-Seite"},
|
||||
{"You will be redirected in 5 seconds", "Du wirst in 5 Sekunden weitergeleitet"},
|
||||
{"Transit tunnels count must not exceed 65535", "Es darf maximal 65535 Transittunnel geben"},
|
||||
{"Back to commands list", "Zurück zur Kommandoliste"},
|
||||
{"Back to commands list", "Zurück zur Befehlsliste"},
|
||||
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
|
||||
{"Description", "Beschreibung"},
|
||||
{"A bit information about service on domain", "Ein bisschen Informationen über den Service auf der Domain"},
|
||||
{"Submit", "Einreichen"},
|
||||
{"Domain can't end with .b32.i2p", "Domain kann nicht mit .b32.i2p enden"},
|
||||
{"Domain must end with .i2p", "Domain muss mit .i2p enden"},
|
||||
{"Such destination is not found", "Eine solche Destination konnte nicht gefunden werden"},
|
||||
{"A bit information about service on domain", "Ein paar Informationen über den Service auf der Domain"},
|
||||
{"Submit", "Absenden"},
|
||||
{"Domain can't end with .b32.i2p", "Domain kann nicht auf .b32.i2p enden"},
|
||||
{"Domain must end with .i2p", "Domain muss auf .i2p enden"},
|
||||
{"Such destination is not found", "Ein solches Ziel konnte nicht gefunden werden"},
|
||||
{"Unknown command", "Unbekannter Befehl"},
|
||||
{"Command accepted", "Befehl akzeptiert"},
|
||||
{"Proxy error", "Proxy-Fehler"},
|
||||
{"Proxy info", "Proxy-Info"},
|
||||
{"Proxy error: Host not found", "Proxy-Fehler: Host nicht gefunden"},
|
||||
{"Remote host not found in router's addressbook", "Remote-Host nicht im Router Adressbuch gefunden"},
|
||||
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einen der Jump-Services unten finden"},
|
||||
{"Remote host not found in router's addressbook", "Remote-Host nicht im Router-Adressbuch gefunden"},
|
||||
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"},
|
||||
{"Invalid request", "Ungültige Anfrage"},
|
||||
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht interpretieren"},
|
||||
{"addresshelper is not supported", "addresshelper wird nicht unterstützt"},
|
||||
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"},
|
||||
{"addresshelper is not supported", "Addresshelfer wird nicht unterstützt"},
|
||||
{"Host", "Host"},
|
||||
{"added to router's addressbook from helper", "vom Helfer zum Router Adressbuch hinzugefügt"},
|
||||
{"added to router's addressbook from helper", "vom Helfer zum Router-Adressbuch hinzugefügt"},
|
||||
{"Click here to proceed:", "Klicke hier um fortzufahren:"},
|
||||
{"Continue", "Fortsetzen"},
|
||||
{"Addresshelper found", "Adresshelfer gefunden"},
|
||||
{"already in router's addressbook", "bereits im Adressbuch des Routers"},
|
||||
{"Click here to update record:", "Klicke hier, um den Eintrag zu aktualisieren:"},
|
||||
{"invalid request uri", "ungültige Anfrage-URI"},
|
||||
{"Can't detect destination host from request", "Kann Anhand der Anfrage den Destination-Host nicht erkennen"},
|
||||
{"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"},
|
||||
{"Outproxy failure", "Outproxy-Fehler"},
|
||||
{"bad outproxy settings", "ungültige Outproxy-Einstellungen"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "nicht innerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
|
||||
{"unknown outproxy url", "unbekannte Outproxy-URL"},
|
||||
{"cannot resolve upstream proxy", "kann den Upstream-Proxy nicht auflösen"},
|
||||
{"hostname too long", "Hostname zu lang"},
|
||||
@@ -192,16 +193,16 @@ namespace german // language namespace
|
||||
{"http out proxy not implemented", "HTTP-Outproxy nicht implementiert"},
|
||||
{"cannot connect to upstream http proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"},
|
||||
{"Host is down", "Host ist offline"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbaunen, vielleicht ist es offline. Versuche es später noch einmal."},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"Tag", "Tage"}},
|
||||
{"hours", {"Stunde", "Stunden"}},
|
||||
{"minutes", {"Minute", "Minuten"}},
|
||||
{"seconds", {"Sekunde", "Sekunden"}},
|
||||
{"%d days", {"%d Tag", "%d Tage"}},
|
||||
{"%d hours", {"%d Stunde", "%d Stunden"}},
|
||||
{"%d minutes", {"%d Minute", "%d Minuten"}},
|
||||
{"%d seconds", {"%d Sekunde", "%d Sekunden"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
43
i18n/I18N.cpp
Normal file
43
i18n/I18N.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <clocale>
|
||||
#include "ClientContext.h"
|
||||
#include "I18N_langs.h"
|
||||
#include "I18N.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
void SetLanguage(const std::string &lang)
|
||||
{
|
||||
const auto it = i2p::i18n::languages.find(lang);
|
||||
if (it == i2p::i18n::languages.end()) // fallback
|
||||
{
|
||||
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
|
||||
setlocale(LC_NUMERIC, "english");
|
||||
}
|
||||
else
|
||||
{
|
||||
i2p::client::context.SetLanguage (it->second.LocaleFunc());
|
||||
setlocale(LC_NUMERIC, lang.c_str()); // set decimal point based on language
|
||||
}
|
||||
}
|
||||
|
||||
std::string translate (const std::string& arg)
|
||||
{
|
||||
return i2p::client::context.GetLanguage ()->GetString (arg);
|
||||
}
|
||||
|
||||
std::string translate (const std::string& arg, const std::string& arg2, const int& n)
|
||||
{
|
||||
return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n);
|
||||
}
|
||||
} // i18n
|
||||
} // i2p
|
||||
132
i18n/I18N.h
132
i18n/I18N.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2021-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -9,37 +9,129 @@
|
||||
#ifndef __I18N_H__
|
||||
#define __I18N_H__
|
||||
|
||||
#include "ClientContext.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
inline void SetLanguage(const std::string &lang)
|
||||
class Locale
|
||||
{
|
||||
const auto it = i2p::i18n::languages.find(lang);
|
||||
if (it == i2p::i18n::languages.end()) // fallback
|
||||
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
|
||||
else
|
||||
i2p::client::context.SetLanguage (it->second.LocaleFunc());
|
||||
}
|
||||
public:
|
||||
Locale (
|
||||
const std::string& language,
|
||||
const std::map<std::string, std::string>& strings,
|
||||
const std::map<std::string, std::vector<std::string>>& plurals,
|
||||
std::function<int(int)> formula
|
||||
): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { };
|
||||
|
||||
inline std::string translate (const std::string& arg)
|
||||
{
|
||||
return i2p::client::context.GetLanguage ()->GetString (arg);
|
||||
}
|
||||
// Get activated language name for webconsole
|
||||
std::string GetLanguage() const
|
||||
{
|
||||
return m_Language;
|
||||
}
|
||||
|
||||
inline std::string translate (const std::string& arg, const std::string& arg2, const int& n)
|
||||
{
|
||||
return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n);
|
||||
}
|
||||
std::string GetString (const std::string& arg) const
|
||||
{
|
||||
const auto it = m_Strings.find(arg);
|
||||
if (it == m_Strings.end())
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetPlural (const std::string& arg, const std::string& arg2, const int& n) const
|
||||
{
|
||||
const auto it = m_Plurals.find(arg2);
|
||||
if (it == m_Plurals.end()) // not found, fallback to english
|
||||
{
|
||||
return n == 1 ? arg : arg2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int form = m_Formula(n);
|
||||
return it->second[form];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string m_Language;
|
||||
const std::map<std::string, std::string> m_Strings;
|
||||
const std::map<std::string, std::vector<std::string>> m_Plurals;
|
||||
std::function<int(int)> m_Formula;
|
||||
};
|
||||
|
||||
void SetLanguage(const std::string &lang);
|
||||
std::string translate (const std::string& arg);
|
||||
std::string translate (const std::string& arg, const std::string& arg2, const int& n);
|
||||
} // i18n
|
||||
} // i2p
|
||||
|
||||
template<typename... TArgs>
|
||||
std::string tr (TArgs&&... args)
|
||||
/**
|
||||
* @brief Get translation of string
|
||||
* @param arg String with message
|
||||
*/
|
||||
template<typename TValue>
|
||||
std::string tr (TValue&& arg)
|
||||
{
|
||||
return i2p::i18n::translate(std::forward<TArgs>(args)...);
|
||||
return i2p::i18n::translate(std::forward<TValue>(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get translation of string and format it
|
||||
* @param arg String with message
|
||||
* @param args Array of arguments for string formatting
|
||||
*/
|
||||
template<typename TValue, typename... TArgs>
|
||||
std::string tr (TValue&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg));
|
||||
|
||||
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
|
||||
size = size + 1;
|
||||
std::string str(size, 0);
|
||||
std::snprintf(&str.front(), size, tr_str.c_str(), std::forward<TArgs>(args)...);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get translation of string with plural forms
|
||||
* @param arg String with message in singular form
|
||||
* @param arg2 String with message in plural form
|
||||
* @param n Integer, used for selection of form
|
||||
*/
|
||||
template<typename TValue, typename TValue2>
|
||||
std::string ntr (TValue&& arg, TValue2&& arg2, int& n)
|
||||
{
|
||||
return i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get translation of string with plural forms and format it
|
||||
* @param arg String with message in singular form
|
||||
* @param arg2 String with message in plural form
|
||||
* @param n Integer, used for selection of form
|
||||
* @param args Array of arguments for string formatting
|
||||
*/
|
||||
template<typename TValue, typename TValue2, typename... TArgs>
|
||||
std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args)
|
||||
{
|
||||
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
|
||||
|
||||
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
|
||||
size = size + 1;
|
||||
std::string str(size, 0);
|
||||
std::snprintf(&str.front(), size, tr_str.c_str(), std::forward<TArgs>(args)...);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif // __I18N_H__
|
||||
|
||||
@@ -9,60 +9,12 @@
|
||||
#ifndef __I18N_LANGS_H__
|
||||
#define __I18N_LANGS_H__
|
||||
|
||||
#include "I18N.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
class Locale
|
||||
{
|
||||
public:
|
||||
Locale (
|
||||
const std::string& language,
|
||||
const std::map<std::string, std::string>& strings,
|
||||
const std::map<std::string, std::vector<std::string>>& plurals,
|
||||
std::function<int(int)> formula
|
||||
): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { };
|
||||
|
||||
// Get activated language name for webconsole
|
||||
std::string GetLanguage() const
|
||||
{
|
||||
return m_Language;
|
||||
}
|
||||
|
||||
std::string GetString (const std::string& arg) const
|
||||
{
|
||||
const auto it = m_Strings.find(arg);
|
||||
if (it == m_Strings.end())
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetPlural (const std::string& arg, const std::string& arg2, const int& n) const
|
||||
{
|
||||
const auto it = m_Plurals.find(arg2);
|
||||
if (it == m_Plurals.end()) // not found, fallback to english
|
||||
{
|
||||
return n == 1 ? arg : arg2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int form = m_Formula(n);
|
||||
return it->second[form];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string m_Language;
|
||||
const std::map<std::string, std::string> m_Strings;
|
||||
const std::map<std::string, std::vector<std::string>> m_Plurals;
|
||||
std::function<int(int)> m_Formula;
|
||||
};
|
||||
|
||||
struct langData
|
||||
{
|
||||
std::string LocaleName; // localized name
|
||||
@@ -73,10 +25,15 @@ namespace i18n
|
||||
// Add localization here with language name as namespace
|
||||
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace czech { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace swedish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
@@ -87,13 +44,18 @@ namespace i18n
|
||||
static std::map<std::string, langData> languages
|
||||
{
|
||||
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
|
||||
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
|
||||
{ "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} },
|
||||
{ "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} },
|
||||
{ "czech", {"čeština", "cs", i2p::i18n::czech::GetLocale} },
|
||||
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
|
||||
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
|
||||
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
|
||||
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
|
||||
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
|
||||
{ "ukrainian", {"украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
|
||||
{ "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} },
|
||||
{ "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} },
|
||||
{ "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} },
|
||||
{ "swedish", {"Svenska", "sv", i2p::i18n::swedish::GetLocale} },
|
||||
{ "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
|
||||
{ "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
|
||||
{ "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} },
|
||||
};
|
||||
|
||||
|
||||
216
i18n/Italian.cpp
Normal file
216
i18n/Italian.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// Italian localization file
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace italian // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "italian";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return n != 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "in costruzione"},
|
||||
{"failed", "fallito"},
|
||||
{"expiring", "in scadenza"},
|
||||
{"established", "stabilita"},
|
||||
{"unknown", "sconosciuto"},
|
||||
{"exploratory", "esplorativo"},
|
||||
{"Purple I2P Webconsole", "Terminale web Purple I2P"},
|
||||
{"<b>i2pd</b> webconsole", "Terminal web <b>i2pd</b>"},
|
||||
{"Main page", "Pagina principale"},
|
||||
{"Router commands", "Comandi router"},
|
||||
{"Local Destinations", "Destinazioni locali"},
|
||||
{"LeaseSets", "LeaseSets"},
|
||||
{"Tunnels", "Tunnel"},
|
||||
{"Transit Tunnels", "Tunnel di transito"},
|
||||
{"Transports", "Trasporti"},
|
||||
{"I2P tunnels", "Tunnel I2P"},
|
||||
{"SAM sessions", "Sessioni SAM"},
|
||||
{"ERROR", "ERRORE"},
|
||||
{"OK", "OK"},
|
||||
{"Testing", "Testando"},
|
||||
{"Firewalled", "Protetto da firewall"},
|
||||
{"Unknown", "Sconosciuto"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Mesh"},
|
||||
{"Error", "Errore"},
|
||||
{"Clock skew", "Orologio disallineato"},
|
||||
{"Offline", "Disconnesso"},
|
||||
{"Symmetric NAT", "NAT simmetrico"},
|
||||
{"Uptime", "In funzione da"},
|
||||
{"Network status", "Stato della rete"},
|
||||
{"Network status v6", "Stato della rete v6"},
|
||||
{"Stopping in", "Arresto in"},
|
||||
{"Family", "Famiglia"},
|
||||
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
|
||||
{"Received", "Ricevuti"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Inviati"},
|
||||
{"Transit", "Transitati"},
|
||||
{"Data path", "Percorso dati"},
|
||||
{"Hidden content. Press on text to see.", "Contenuto nascosto. Premi sul testo per vedere."},
|
||||
{"Router Ident", "Identificativo del router"},
|
||||
{"Router Family", "Famiglia del router"},
|
||||
{"Router Caps", "Limiti del router"},
|
||||
{"Version", "Versione"},
|
||||
{"Our external address", "Il nostro indirizzo esterno"},
|
||||
{"supported", "supportato"},
|
||||
{"Routers", "Router"},
|
||||
{"Floodfills", "Floodfill"},
|
||||
{"Client Tunnels", "Tunnel client"},
|
||||
{"Services", "Servizi"},
|
||||
{"Enabled", "Abilitato"},
|
||||
{"Disabled", "Disabilitato"},
|
||||
{"Encrypted B33 address", "Indirizzo criptato B33"},
|
||||
{"Address registration line", "Linea di registrazione indirizzo"},
|
||||
{"Domain", "Dominio"},
|
||||
{"Generate", "Genera"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Nota:</b> la stringa risultante può essere utilizzata solo per registrare domini 2LD (example.i2p). Per registrare i sottodomini, si prega di utilizzare i2pd-tools."},
|
||||
{"Address", "Indirizzo"},
|
||||
{"Type", "Tipologia"},
|
||||
{"EncType", "Tipo di crittografia"},
|
||||
{"Inbound tunnels", "Tunnel in entrata"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Tunnel in uscita"},
|
||||
{"Tags", "Tag"},
|
||||
{"Incoming", "In entrata"},
|
||||
{"Outgoing", "In uscita"},
|
||||
{"Destination", "Destinazione"},
|
||||
{"Amount", "Quantità"},
|
||||
{"Incoming Tags", "Tag in entrata"},
|
||||
{"Tags sessions", "Sessioni dei tag"},
|
||||
{"Status", "Stato"},
|
||||
{"Local Destination", "Destinazione locale"},
|
||||
{"Streams", "Flussi"},
|
||||
{"Close stream", "Interrompi il flusso"},
|
||||
{"I2CP session not found", "Sessione I2CP non trovata"},
|
||||
{"I2CP is not enabled", "I2CP non è abilitato"},
|
||||
{"Invalid", "Invalido"},
|
||||
{"Store type", "Tipologia di archivio"},
|
||||
{"Expires", "Scade"},
|
||||
{"Non Expired Leases", "Lease non scaduti"},
|
||||
{"Gateway", "Gateway"},
|
||||
{"TunnelID", "TunnelID"},
|
||||
{"EndDate", "Data di fine"},
|
||||
{"not floodfill", "no floodfill"},
|
||||
{"Queue size", "Dimensione della coda"},
|
||||
{"Run peer test", "Esegui il test dei peer"},
|
||||
{"Decline transit tunnels", "Rifiuta tunnel di transito"},
|
||||
{"Accept transit tunnels", "Accetta tunnel di transito"},
|
||||
{"Cancel graceful shutdown", "Annulla l'interruzione controllata"},
|
||||
{"Start graceful shutdown", "Avvia l'interruzione controllata"},
|
||||
{"Force shutdown", "Forza l'arresto"},
|
||||
{"Reload external CSS styles", "Ricarica gli stili CSS esterni"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Nota:</b> qualsiasi azione effettuata qui non è persistente e non modifica i file di configurazione."},
|
||||
{"Logging level", "Livello di log"},
|
||||
{"Transit tunnels limit", "Limite di tunnel di transito"},
|
||||
{"Change", "Modifica"},
|
||||
{"Change language", "Modifica linguaggio"},
|
||||
{"no transit tunnels currently built", "Attualmente non ci sono tunnel di transito instaurati"},
|
||||
{"SAM disabled", "SAM disabilitato"},
|
||||
{"no sessions currently running", "Attualmente non ci sono sessioni attive"},
|
||||
{"SAM session not found", "Sessione SAM non trovata"},
|
||||
{"SAM Session", "Sessione SAM"},
|
||||
{"Server Tunnels", "Tunnel server"},
|
||||
{"Client Forwards", "Client di inoltro"},
|
||||
{"Server Forwards", "Server di inoltro"},
|
||||
{"Unknown page", "Pagina sconosciuta"},
|
||||
{"Invalid token", "Token non valido"},
|
||||
{"SUCCESS", "SUCCESSO"},
|
||||
{"Stream closed", "Flusso terminato"},
|
||||
{"Stream not found or already was closed", "Il flusso non è stato trovato oppure è già stato terminato"},
|
||||
{"Destination not found", "Destinazione non trovata"},
|
||||
{"StreamID can't be null", "Lo StreamID non può essere null"},
|
||||
{"Return to destination page", "Ritorna alla pagina di destinazione"},
|
||||
{"You will be redirected in 5 seconds", "Verrai reindirizzato in 5 secondi"},
|
||||
{"Transit tunnels count must not exceed 65535", "Il numero di tunnel di transito non può superare i 65535"},
|
||||
{"Back to commands list", "Ritorna alla lista dei comandi"},
|
||||
{"Register at reg.i2p", "Registra a reg.i2p"},
|
||||
{"Description", "Descrizione"},
|
||||
{"A bit information about service on domain", "Alcune informazioni riguardo il servizio sul dominio"},
|
||||
{"Submit", "Invia"},
|
||||
{"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"},
|
||||
{"Domain must end with .i2p", "I domini devono terminare con .i2p"},
|
||||
{"Such destination is not found", "Questa destinazione non è stata trovata"},
|
||||
{"Unknown command", "Comando sconosciuto"},
|
||||
{"Command accepted", "Comando accettato"},
|
||||
{"Proxy error", "Errore del proxy"},
|
||||
{"Proxy info", "Informazioni del proxy"},
|
||||
{"Proxy error: Host not found", "Errore del proxy: Host non trovato"},
|
||||
{"Remote host not found in router's addressbook", "L'host remoto non è stato trovato nella rubrica del router"},
|
||||
{"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"},
|
||||
{"Invalid request", "Richiesta non valida"},
|
||||
{"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"},
|
||||
{"addresshelper is not supported", "addresshelper non è supportato"},
|
||||
{"Host", "Host"},
|
||||
{"added to router's addressbook from helper", "aggiunto alla rubrica tramite l'helper"},
|
||||
{"Click here to proceed:", "Clicca qui per procedere:"},
|
||||
{"Continue", "Continua"},
|
||||
{"Addresshelper found", "Addresshelper trovato"},
|
||||
{"already in router's addressbook", "già presente nella rubrica del router"},
|
||||
{"Click here to update record:", "Clicca qui per aggiornare l'elemento:"},
|
||||
{"invalid request uri", "uri della richiesta non valido"},
|
||||
{"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"},
|
||||
{"Outproxy failure", "Fallimento del proxy di uscita"},
|
||||
{"bad outproxy settings", "impostazioni errate del proxy di uscita"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "non all'interno della rete I2P, ma il proxy di uscita non è abilitato"},
|
||||
{"unknown outproxy url", "url del proxy di uscita sconosciuto"},
|
||||
{"cannot resolve upstream proxy", "impossibile identificare il flusso a monte del proxy"},
|
||||
{"hostname too long", "il nome dell'host è troppo lungo"},
|
||||
{"cannot connect to upstream socks proxy", "impossibile connettersi al flusso a monte del proxy socks"},
|
||||
{"Cannot negotiate with socks proxy", "Impossibile negoziare con il proxy socks"},
|
||||
{"CONNECT error", "Errore di connessione"},
|
||||
{"Failed to Connect", "Connessione fallita"},
|
||||
{"socks proxy error", "errore del proxy socks"},
|
||||
{"failed to send request to upstream", "invio della richiesta a monte non riuscito"},
|
||||
{"No Reply From socks proxy", "Nessuna risposta dal proxy socks"},
|
||||
{"cannot connect", "impossibile connettersi"},
|
||||
{"http out proxy not implemented", "proxy http di uscita non implementato"},
|
||||
{"cannot connect to upstream http proxy", "impossibile connettersi al proxy http a monte"},
|
||||
{"Host is down", "L'host è offline"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"%d days", {"%d giorno", "%d giorni"}},
|
||||
{"%d hours", {"%d ora", "%d ore"}},
|
||||
{"%d minutes", {"%d minuto", "%d minuti"}},
|
||||
{"%d seconds", {"%d secondo", "%d secondi"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
@@ -31,9 +31,9 @@ namespace russian // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "КиБ"},
|
||||
{"MiB", "МиБ"},
|
||||
{"GiB", "ГиБ"},
|
||||
{"%.2f KiB", "%.2f КиБ"},
|
||||
{"%.2f MiB", "%.2f МиБ"},
|
||||
{"%.2f GiB", "%.2f ГиБ"},
|
||||
{"building", "строится"},
|
||||
{"failed", "неудачный"},
|
||||
{"expiring", "истекает"},
|
||||
@@ -68,7 +68,7 @@ namespace russian // language namespace
|
||||
{"Family", "Семейство"},
|
||||
{"Tunnel creation success rate", "Успешно построенных туннелей"},
|
||||
{"Received", "Получено"},
|
||||
{"KiB/s", "КиБ/с"},
|
||||
{"%.2f KiB/s", "%.2f КиБ/с"},
|
||||
{"Sent", "Отправлено"},
|
||||
{"Transit", "Транзит"},
|
||||
{"Data path", "Путь к данным"},
|
||||
@@ -94,7 +94,7 @@ namespace russian // language namespace
|
||||
{"Type", "Тип"},
|
||||
{"EncType", "ТипШифр"},
|
||||
{"Inbound tunnels", "Входящие туннели"},
|
||||
{"ms", "мс"},
|
||||
{"%dms", "%dмс"},
|
||||
{"Outbound tunnels", "Исходящие туннели"},
|
||||
{"Tags", "Теги"},
|
||||
{"Incoming", "Входящие"},
|
||||
@@ -198,10 +198,10 @@ namespace russian // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"день", "дня", "дней"}},
|
||||
{"hours", {"час", "часа", "часов"}},
|
||||
{"minutes", {"минуту", "минуты", "минут"}},
|
||||
{"seconds", {"секунду", "секунды", "секунд"}},
|
||||
{"%d days", {"%d день", "%d дня", "%d дней"}},
|
||||
{"%d hours", {"%d час", "%d часа", "%d часов"}},
|
||||
{"%d minutes", {"%d минуту", "%d минуты", "%d минут"}},
|
||||
{"%d seconds", {"%d секунду", "%d секунды", "%d секунд"}},
|
||||
{"", {"", "", ""}},
|
||||
};
|
||||
|
||||
|
||||
216
i18n/Spanish.cpp
Normal file
216
i18n/Spanish.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// Spanish localization file
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace spanish // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "spanish";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return n != 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "pendiente"},
|
||||
{"failed", "fallido"},
|
||||
{"expiring", "expiró"},
|
||||
{"established", "establecido"},
|
||||
{"unknown", "desconocido"},
|
||||
{"exploratory", "exploratorio"},
|
||||
{"Purple I2P Webconsole", "Consola web de Purple I2P"},
|
||||
{"<b>i2pd</b> webconsole", "Consola web de <b>i2pd</b>"},
|
||||
{"Main page", "Inicio"},
|
||||
{"Router commands", "Comandos de enrutador"},
|
||||
{"Local Destinations", "Destinos locales"},
|
||||
{"LeaseSets", "LeaseSets"},
|
||||
{"Tunnels", "Túneles"},
|
||||
{"Transit Tunnels", "Túneles de Tránsito"},
|
||||
{"Transports", "Transportes"},
|
||||
{"I2P tunnels", "Túneles I2P"},
|
||||
{"SAM sessions", "Sesiones SAM"},
|
||||
{"ERROR", "ERROR"},
|
||||
{"OK", "VALE"},
|
||||
{"Testing", "Probando"},
|
||||
{"Firewalled", "Con cortafuegos"},
|
||||
{"Unknown", "Desconocido"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Malla"},
|
||||
{"Error", "Error"},
|
||||
{"Clock skew", "Reloj desfasado"},
|
||||
{"Offline", "Desconectado"},
|
||||
{"Symmetric NAT", "NAT simétrico"},
|
||||
{"Uptime", "Tiempo en línea"},
|
||||
{"Network status", "Estado de red"},
|
||||
{"Network status v6", "Estado de red v6"},
|
||||
{"Stopping in", "Parando en"},
|
||||
{"Family", "Familia"},
|
||||
{"Tunnel creation success rate", "Tasa de éxito de creación de túneles"},
|
||||
{"Received", "Recibido"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Enviado"},
|
||||
{"Transit", "Tránsito"},
|
||||
{"Data path", "Ruta de datos"},
|
||||
{"Hidden content. Press on text to see.", "Contenido oculto. Presione para ver."},
|
||||
{"Router Ident", "Ident del Enrutador"},
|
||||
{"Router Family", "Familia de enrutador"},
|
||||
{"Router Caps", "Atributos del Enrutador"},
|
||||
{"Version", "Versión"},
|
||||
{"Our external address", "Nuestra dirección externa"},
|
||||
{"supported", "soportado"},
|
||||
{"Routers", "Enrutadores"},
|
||||
{"Floodfills", "Inundaciones"},
|
||||
{"Client Tunnels", "Túneles de cliente"},
|
||||
{"Services", "Servicios"},
|
||||
{"Enabled", "Activado"},
|
||||
{"Disabled", "Desactivado"},
|
||||
{"Encrypted B33 address", "Dirección encriptada B33"},
|
||||
{"Address registration line", "Línea para registrar direcciones"},
|
||||
{"Domain", "Dominio"},
|
||||
{"Generate", "Generar"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Nota:</b> la cadena resultante solo se puede usar para registrar dominios 2LD (ejemplo.i2p). Para registrar subdominios, por favor utilice i2pd-tools."},
|
||||
{"Address", "Dirección"},
|
||||
{"Type", "Tipo"},
|
||||
{"EncType", "TipoEncrip"},
|
||||
{"Inbound tunnels", "Túneles entrantes"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Túneles salientes"},
|
||||
{"Tags", "Etiquetas"},
|
||||
{"Incoming", "Entrante"},
|
||||
{"Outgoing", "Saliente"},
|
||||
{"Destination", "Destino"},
|
||||
{"Amount", "Cantidad"},
|
||||
{"Incoming Tags", "Etiquetas entrantes"},
|
||||
{"Tags sessions", "Sesiones de etiquetas"},
|
||||
{"Status", "Estado"},
|
||||
{"Local Destination", "Destino Local"},
|
||||
{"Streams", "Flujos"},
|
||||
{"Close stream", "Cerrar flujo"},
|
||||
{"I2CP session not found", "Sesión I2CP no encontrada"},
|
||||
{"I2CP is not enabled", "I2CP no está activado"},
|
||||
{"Invalid", "Inválido"},
|
||||
{"Store type", "Tipo de almacenamiento"},
|
||||
{"Expires", "Caduca"},
|
||||
{"Non Expired Leases", "Sesiones No Expiradas"},
|
||||
{"Gateway", "Puerta de enlace"},
|
||||
{"TunnelID", "TunnelID"},
|
||||
{"EndDate", "FechaVenc"},
|
||||
{"not floodfill", "no inundado"},
|
||||
{"Queue size", "Tamaño de cola"},
|
||||
{"Run peer test", "Ejecutar prueba de par"},
|
||||
{"Decline transit tunnels", "Rechazar túneles de tránsito"},
|
||||
{"Accept transit tunnels", "Aceptar túneles de tránsito"},
|
||||
{"Cancel graceful shutdown", "Cancelar apagado con gracia"},
|
||||
{"Start graceful shutdown", "Iniciar apagado con gracia"},
|
||||
{"Force shutdown", "Forzar apagado"},
|
||||
{"Reload external CSS styles", "Recargar estilos CSS externos"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Nota:</b> cualquier acción hecha aquí no es persistente y no cambia tus archivos de configuración."},
|
||||
{"Logging level", "Nivel de registro de errores"},
|
||||
{"Transit tunnels limit", "Límite de túneles de tránsito"},
|
||||
{"Change", "Cambiar"},
|
||||
{"Change language", "Cambiar idioma"},
|
||||
{"no transit tunnels currently built", "no hay túneles de tránsito actualmente construidos"},
|
||||
{"SAM disabled", "SAM desactivado"},
|
||||
{"no sessions currently running", "no hay sesiones ejecutándose ahora"},
|
||||
{"SAM session not found", "Sesión SAM no encontrada"},
|
||||
{"SAM Session", "Sesión SAM"},
|
||||
{"Server Tunnels", "Túneles de Servidor"},
|
||||
{"Client Forwards", "Redirecciones de Cliente"},
|
||||
{"Server Forwards", "Redirecciones de Servidor"},
|
||||
{"Unknown page", "Página desconocida"},
|
||||
{"Invalid token", "Token inválido"},
|
||||
{"SUCCESS", "ÉXITO"},
|
||||
{"Stream closed", "Transmisión cerrada"},
|
||||
{"Stream not found or already was closed", "No se encontró la transmisión o ya se cerró"},
|
||||
{"Destination not found", "Destino no encontrado"},
|
||||
{"StreamID can't be null", "StreamID no puede ser nulo"},
|
||||
{"Return to destination page", "Volver a la página de destino"},
|
||||
{"You will be redirected in 5 seconds", "Serás redirigido en 5 segundos"},
|
||||
{"Transit tunnels count must not exceed 65535", "La cantidad de túneles de tránsito no puede exceder 65535"},
|
||||
{"Back to commands list", "Volver a lista de comandos"},
|
||||
{"Register at reg.i2p", "Registrar en reg.i2p"},
|
||||
{"Description", "Descripción"},
|
||||
{"A bit information about service on domain", "Un poco de información sobre el servicio en el dominio"},
|
||||
{"Submit", "Enviar"},
|
||||
{"Domain can't end with .b32.i2p", "El dominio no puede terminar con .b32.i2p"},
|
||||
{"Domain must end with .i2p", "El dominio debe terminar con .i2p"},
|
||||
{"Such destination is not found", "No se encontró el destino"},
|
||||
{"Unknown command", "Comando desconocido"},
|
||||
{"Command accepted", "Comando aceptado"},
|
||||
{"Proxy error", "Error de proxy"},
|
||||
{"Proxy info", "Información del proxy"},
|
||||
{"Proxy error: Host not found", "Error de proxy: Host no encontrado"},
|
||||
{"Remote host not found in router's addressbook", "Servidor remoto no encontrado en la libreta de direcciones del enrutador"},
|
||||
{"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"},
|
||||
{"Invalid request", "Solicitud inválida"},
|
||||
{"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"},
|
||||
{"addresshelper is not supported", "ayudante de dirección no soportado"},
|
||||
{"Host", "Dominio"},
|
||||
{"added to router's addressbook from helper", "añadido a la libreta de direcciones desde el ayudante"},
|
||||
{"Click here to proceed:", "Haga clic aquí para continuar:"},
|
||||
{"Continue", "Continuar"},
|
||||
{"Addresshelper found", "Se encontró ayudante de dirección"},
|
||||
{"already in router's addressbook", "ya se encontró en libreta de direcciones"},
|
||||
{"Click here to update record:", "Haga clic aquí para actualizar el registro:"},
|
||||
{"invalid request uri", "uri de solicitud inválida"},
|
||||
{"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"},
|
||||
{"Outproxy failure", "Fallo en el proxy saliente"},
|
||||
{"bad outproxy settings", "configuración de outproxy incorrecta"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "no está dentro de la red I2P, pero el proxy de salida no está activado"},
|
||||
{"unknown outproxy url", "url de proxy outproxy desconocido"},
|
||||
{"cannot resolve upstream proxy", "no se puede resolver el proxy de upstream"},
|
||||
{"hostname too long", "nombre de dominio muy largo"},
|
||||
{"cannot connect to upstream socks proxy", "no se puede conectar al proxy socks principal"},
|
||||
{"Cannot negotiate with socks proxy", "No se puede negociar con el proxy socks"},
|
||||
{"CONNECT error", "Error de CONNECT"},
|
||||
{"Failed to Connect", "Error al Conectar"},
|
||||
{"socks proxy error", "error de proxy socks"},
|
||||
{"failed to send request to upstream", "no se pudo enviar petición al principal"},
|
||||
{"No Reply From socks proxy", "Sin respuesta del proxy socks"},
|
||||
{"cannot connect", "no se puede conectar"},
|
||||
{"http out proxy not implemented", "proxy externo http no implementado"},
|
||||
{"cannot connect to upstream http proxy", "no se puede conectar al proxy http principal"},
|
||||
{"Host is down", "Servidor caído"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"%d days", {"%d día", "%d días"}},
|
||||
{"%d hours", {"%d hora", "%d horas"}},
|
||||
{"%d minutes", {"%d minuto", "%d minutos"}},
|
||||
{"%d seconds", {"%d segundo", "%d segundos"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
217
i18n/Swedish.cpp
Normal file
217
i18n/Swedish.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// Swedish localization file
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace swedish // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "swedish";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return n != 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "bygger"},
|
||||
{"failed", "misslyckad"},
|
||||
{"expiring", "utgår"},
|
||||
{"established", "upprättad"},
|
||||
{"unknown", "okänt"},
|
||||
{"exploratory", "utforskande"},
|
||||
{"Purple I2P Webconsole", "Purple I2P Webbkonsoll"},
|
||||
{"<b>i2pd</b> webbkonsoll", "<b>i2pd</b>-Webbkonsoll"},
|
||||
{"Main page", "Huvudsida"},
|
||||
{"Router commands", "Routerkommandon"},
|
||||
{"Local Destinations", "Lokala Platser"},
|
||||
{"LeaseSets", "Hyresuppsättningar"},
|
||||
{"Tunnels", "Tunnlar"},
|
||||
{"Transit Tunnels", "Förmedlande Tunnlar"},
|
||||
{"Transports", "Transporter"},
|
||||
{"I2P tunnels", "I2P-tunnlar"},
|
||||
{"SAM sessions", "SAM-perioder"},
|
||||
{"ERROR", "FEL"},
|
||||
{"OK", "OK"},
|
||||
{"Testing", "Prövar"},
|
||||
{"Firewalled", "Bakom Brandvägg"},
|
||||
{"Unknown", "Okänt"},
|
||||
{"Proxy", "Proxy"},
|
||||
{"Mesh", "Mesh"},
|
||||
{"Error", "Fel"},
|
||||
{"Clock skew", "Tidsförskjutning"},
|
||||
{"Offline", "Nedkopplad"},
|
||||
{"Symmetric NAT", "Symmetrisk NAT"},
|
||||
{"Uptime", "Upptid"},
|
||||
{"Network status", "Nätverkstillstånd"},
|
||||
{"Network status v6", "Nätverkstillstånd v6"},
|
||||
{"Stopping in", "Avstängd om"},
|
||||
{"Family", "Familj"},
|
||||
{"Tunnel creation success rate", "Andel framgångsrika tunnlar"},
|
||||
{"Received", "Mottaget"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Skickat"},
|
||||
{"Transit", "Förmedlat"},
|
||||
{"Data path", "Sökväg"},
|
||||
{"Hidden content. Press on text to see.", "Dolt innehåll. Tryck för att visa."},
|
||||
{"Router Ident", "Routeridentitet"},
|
||||
{"Router Family", "Routerfamilj"},
|
||||
{"Router Caps", "Routerbegränsningar"},
|
||||
{"Version", "Version"},
|
||||
{"Our external address", "Vår externa adress"},
|
||||
{"supported", "stöds"},
|
||||
{"Routers", "Routrar"},
|
||||
{"Floodfills", "Översvämningsfyllare"},
|
||||
{"Client Tunnels", "Klienttunnlar"},
|
||||
{"Services", "Tjänster"},
|
||||
{"Enabled", "Påslaget"},
|
||||
{"Disabled", "Avslaget"},
|
||||
{"Encrypted B33 address", "Krypterad B33-Adress"},
|
||||
{"Address registration line", "Adressregistreringsrad"},
|
||||
{"Domain", "Domän"},
|
||||
{"Generate", "Skapa"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Uppmärksamma:</b> den resulterande strängen kan enbart användas för att registrera 2LD-domäner (exempel.i2p). För att registrera underdomäner, vänligen använd i2pd-tools."},
|
||||
{"Address", "Adress"},
|
||||
{"Type", "Typ"},
|
||||
{"EncType", "EncTyp"},
|
||||
{"Inbound tunnels", "Ingående Tunnlar"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Utgående Tunnlar"},
|
||||
{"Tags", "Taggar"},
|
||||
{"Incoming", "Ingående"},
|
||||
{"Outgoing", "Utgående"},
|
||||
{"Destination", "Plats"},
|
||||
{"Amount", "Mängd"},
|
||||
{"Incoming Tags", "Ingående Taggar"},
|
||||
{"Tags sessions", "Tagg-perioder"},
|
||||
{"Status", "Tillstånd"},
|
||||
{"Local Destination", "Lokal Plats"},
|
||||
{"Streams", "Strömmar"},
|
||||
{"Close stream", "Stäng strömmen"},
|
||||
{"I2CP session not found", "I2CP-period hittades inte"},
|
||||
{"I2CP is not enabled", "I2CP är inte påslaget"},
|
||||
{"Invalid", "Ogiltig"},
|
||||
{"Store type", "Lagringstyp"},
|
||||
{"Expires", "Utgångsdatum"},
|
||||
{"Non Expired Leases", "Ickeutgångna Hyresuppsättningar"},
|
||||
{"Gateway", "Gateway"},
|
||||
{"TunnelID", "TunnelID"},
|
||||
{"EndDate", "EndDate"},
|
||||
{"not floodfill", "inte Översvämningsfyllare"},
|
||||
{"Queue size", "Köstorlek"},
|
||||
{"Run peer test", "Utför utsiktstest"},
|
||||
{"Decline transit tunnels", "Avvisa förmedlande tunnlar"},
|
||||
{"Accept transit tunnels", "Tillåt förmedlande tunnlar"},
|
||||
{"Cancel graceful shutdown", "Avbryt välvillig avstängning"},
|
||||
{"Start graceful shutdown", "Påbörja välvillig avstängning"},
|
||||
{"Force shutdown", "Tvingad avstängning"},
|
||||
{"Reload external CSS styles", "Ladda om externa CSS-stilar"},
|
||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Uppmärksamma:</b> inga ändringar här är beständiga eller påverkar dina inställningsfiler."},
|
||||
{"Logging level", "Protokollförningsnivå"},
|
||||
{"Transit tunnels limit", "Begränsa förmedlande tunnlar"},
|
||||
{"Change", "Ändra"},
|
||||
{"Change language", "Ändra språk"},
|
||||
{"no transit tunnels currently built", "inga förmedlande tunnlar har byggts"},
|
||||
{"SAM disabled", "SAM avslaget"},
|
||||
{"no sessions currently running", "inga perioder igång"},
|
||||
{"SAM session not found", "SAM-perioder hittades ej"},
|
||||
{"SAM Session", "SAM-period"},
|
||||
{"Server Tunnels", "Värdtunnlar"},
|
||||
{"Client Forwards", "Klientförpassningar"},
|
||||
{"Server Forwards", "Värdförpassningar"},
|
||||
{"Unknown page", "Okänd sida"},
|
||||
{"Invalid token", "Ogiltig polett"},
|
||||
{"SUCCESS", "FRAMGÅNG"},
|
||||
{"Stream closed", "Ström stängd"},
|
||||
{"Stream not found or already was closed", "Strömmen hittades inte eller var redan avslutad"},
|
||||
{"Destination not found", "Plats hittades ej"},
|
||||
{"StreamID can't be null", "Ström-ID kan inte vara null"},
|
||||
{"Return to destination page", "Återvänd till platssidan"},
|
||||
{"You will be redirected in 5 seconds", "Du omdirigeras inom fem sekunder"},
|
||||
{"Transit tunnels count must not exceed 65535", "Förmedlande tunnlar får inte överstiga 65535"},
|
||||
{"Back to commands list", "Tillbaka till kommandolistan"},
|
||||
{"Register at reg.i2p", "Registrera vid reg.i2p"},
|
||||
{"Description", "Beskrivning"},
|
||||
{"A bit information about service on domain", "Ett stycke information om domänens tjänst"},
|
||||
{"Submit", "Skicka"},
|
||||
{"Domain can't end with .b32.i2p", "Domänen får inte sluta med .b32.i2p"},
|
||||
{"Domain must end with .i2p", "Domänen måste sluta med .i2p"},
|
||||
{"Such destination is not found", "En sådan plats hittas ej"},
|
||||
{"Unknown command", "Okänt kommando"},
|
||||
{"Command accepted", "Kommando accepterades"},
|
||||
{"Proxy error", "Proxyfel"},
|
||||
{"Proxy info", "Proxyinfo"},
|
||||
{"Proxy error: Host not found", "Proxyfel: Värden hittades ej"},
|
||||
{"Remote host not found in router's addressbook", "Främmande värd hittades inte i routerns adressbok"},
|
||||
{"You may try to find this host on jump services below", "Du kan försöka att hitta värden genom hopptjänsterna nedan"},
|
||||
{"Invalid request", "Ogiltig förfrågan"},
|
||||
{"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"},
|
||||
{"addresshelper is not supported", "adresshjälparen stöds ej"},
|
||||
{"Host", "Värd"},
|
||||
{"added to router's addressbook from helper", "tillagd i routerns adressbok från adresshjälparen"},
|
||||
{"Click here to proceed:", "Tryck här för att fortsätta:"},
|
||||
{"Continue", "Fortsätt"},
|
||||
{"Addresshelper found", "Adresshjälpare hittad"},
|
||||
{"already in router's addressbook", "finns redan i routerns adressbok"},
|
||||
{"Click here to update record:", "Tryck här för att uppdatera:"},
|
||||
{"invalid request uri", "ogiltig förfrågnings-URI"},
|
||||
{"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"},
|
||||
{"Outproxy failure", "Utproxyfel"},
|
||||
{"bad outproxy settings", "ogiltig utproxyinställning"},
|
||||
{"not inside I2P network, but outproxy is not enabled", "adressen är inte inom I2P-näverket, men utproxy är inte påslaget"},
|
||||
{"unknown outproxy url", "okänt Utproxy-URL"},
|
||||
{"cannot resolve upstream proxy", "hittar inte uppströmsproxyt"},
|
||||
{"hostname too long", "värdnamnet är för långt"},
|
||||
{"cannot connect to upstream socks proxy", "kan inte ansluta till uppströmsproxyt"},
|
||||
{"Cannot negotiate with socks proxy", "Kan inte förhandla med socksproxyt"},
|
||||
{"CONNECT error", "CONNECT-fel"},
|
||||
{"Failed to Connect", "Anslutningen misslyckades"},
|
||||
{"socks proxy error", "Socksproxyfel"},
|
||||
{"failed to send request to upstream", "förfrågan uppströms kunde ej skickas"},
|
||||
{"No Reply From socks proxy", "Fick inget svar från socksproxyt"},
|
||||
{"cannot connect", "kan inte ansluta"},
|
||||
{"http out proxy not implemented", "HTTP-Utproxy ej implementerat"},
|
||||
{"cannot connect to upstream http proxy", "Kan inte ansluta till uppströms HTTP-proxy"},
|
||||
{"Host is down", "Värden är nere"},
|
||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Kan inte ansluta till värden, den kan vara nere. Vänligen försök senare."},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"%d days", {"%d Dag", "%d Dagar"}},
|
||||
{"%d hours", {"%d Timme", "%d Timmar"}},
|
||||
{"%d minutes", {"%d Minut", "%d Minuter"}},
|
||||
{"%d seconds", {"%d Sekund", "%d Sekunder"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace turkmen // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "KiB"},
|
||||
{"MiB", "MiB"},
|
||||
{"GiB", "GiB"},
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "bina"},
|
||||
{"failed", "şowsuz"},
|
||||
{"expiring", "möhleti gutarýar"},
|
||||
@@ -68,7 +68,7 @@ namespace turkmen // language namespace
|
||||
{"Family", "Maşgala"},
|
||||
{"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"},
|
||||
{"Received", "Alnan"},
|
||||
{"KiB/s", "KiB/s"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Ýerleşdirildi"},
|
||||
{"Transit", "Tranzit"},
|
||||
{"Data path", "Maglumat ýoly"},
|
||||
@@ -94,7 +94,7 @@ namespace turkmen // language namespace
|
||||
{"Type", "Görnüş"},
|
||||
{"EncType", "Şifrlemek görnüşi"},
|
||||
{"Inbound tunnels", "Gelýän tuneller"},
|
||||
{"ms", "ms"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Çykýan tuneller"},
|
||||
{"Tags", "Bellikler"},
|
||||
{"Incoming", "Gelýän"},
|
||||
@@ -198,10 +198,10 @@ namespace turkmen // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"gün", "gün"}},
|
||||
{"hours", {"sagat", "sagat"}},
|
||||
{"minutes", {"minut", "minut"}},
|
||||
{"seconds", {"sekunt", "sekunt"}},
|
||||
{"%d days", {"%d gün", "%d gün"}},
|
||||
{"%d hours", {"%d sagat", "%d sagat"}},
|
||||
{"%d minutes", {"%d minut", "%d minut"}},
|
||||
{"%d seconds", {"%d sekunt", "%d sekunt"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace ukrainian // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "КіБ"},
|
||||
{"MiB", "МіБ"},
|
||||
{"GiB", "ГіБ"},
|
||||
{"%.2f KiB", "%.2f КіБ"},
|
||||
{"%.2f MiB", "%.2f МіБ"},
|
||||
{"%.2f GiB", "%.2f ГіБ"},
|
||||
{"building", "будується"},
|
||||
{"failed", "невдалий"},
|
||||
{"expiring", "завершується"},
|
||||
@@ -68,7 +68,7 @@ namespace ukrainian // language namespace
|
||||
{"Family", "Сімейство"},
|
||||
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
|
||||
{"Received", "Отримано"},
|
||||
{"KiB/s", "КіБ/с"},
|
||||
{"%.2f KiB/s", "%.2f КіБ/с"},
|
||||
{"Sent", "Відправлено"},
|
||||
{"Transit", "Транзит"},
|
||||
{"Data path", "Шлях до даних"},
|
||||
@@ -94,7 +94,7 @@ namespace ukrainian // language namespace
|
||||
{"Type", "Тип"},
|
||||
{"EncType", "ТипШифр"},
|
||||
{"Inbound tunnels", "Вхідні тунелі"},
|
||||
{"ms", "мс"},
|
||||
{"%dms", "%dмс"},
|
||||
{"Outbound tunnels", "Вихідні тунелі"},
|
||||
{"Tags", "Теги"},
|
||||
{"Incoming", "Вхідні"},
|
||||
@@ -198,10 +198,10 @@ namespace ukrainian // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"день", "дня", "днів"}},
|
||||
{"hours", {"годину", "години", "годин"}},
|
||||
{"minutes", {"хвилину", "хвилини", "хвилин"}},
|
||||
{"seconds", {"секунду", "секунди", "секунд"}},
|
||||
{"%d days", {"%d день", "%d дня", "%d днів"}},
|
||||
{"%d hours", {"%d годину", "%d години", "%d годин"}},
|
||||
{"%d minutes", {"%d хвилину", "%d хвилини", "%d хвилин"}},
|
||||
{"%d seconds", {"%d секунду", "%d секунди", "%d секунд"}},
|
||||
{"", {"", "", ""}},
|
||||
};
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace uzbek // language namespace
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "KiB"},
|
||||
{"MiB", "MiB"},
|
||||
{"GiB", "GiB"},
|
||||
{"%.2f KiB", "%.2f KiB"},
|
||||
{"%.2f MiB", "%.2f MiB"},
|
||||
{"%.2f GiB", "%.2f GiB"},
|
||||
{"building", "yaratilmoqda"},
|
||||
{"failed", "muvaffaqiyatsiz"},
|
||||
{"expiring", "muddati tugaydi"},
|
||||
@@ -68,7 +68,7 @@ namespace uzbek // language namespace
|
||||
{"Family", "Oila"},
|
||||
{"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"},
|
||||
{"Received", "Qabul qilindi"},
|
||||
{"KiB/s", "KiB/s"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Yuborilgan"},
|
||||
{"Transit", "Tranzit"},
|
||||
{"Data path", "Ma'lumotlar joylanishi"},
|
||||
@@ -94,7 +94,7 @@ namespace uzbek // language namespace
|
||||
{"Type", "Turi"},
|
||||
{"EncType", "ShifrlashTuri"},
|
||||
{"Inbound tunnels", "Kirish tunnellari"},
|
||||
{"ms", "ms"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Chiquvchi tunnellar"},
|
||||
{"Tags", "Teglar"},
|
||||
{"Incoming", "Kiruvchi"},
|
||||
@@ -198,10 +198,10 @@ namespace uzbek // language namespace
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"kun", "kun"}},
|
||||
{"hours", {"soat", "soat"}},
|
||||
{"minutes", {"daqiqa", "daqiqa"}},
|
||||
{"seconds", {"soniya", "soniya"}},
|
||||
{"%d days", {"%d kun", "%d kun"}},
|
||||
{"%d hours", {"%d soat", "%d soat"}},
|
||||
{"%d minutes", {"%d daqiqa", "%d daqiqa"}},
|
||||
{"%d seconds", {"%d soniya", "%d soniya"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace data
|
||||
//----------------------------------------------------------
|
||||
|
||||
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
|
||||
const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
|
||||
// const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
|
||||
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
|
||||
|
||||
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include "BloomFilter.h"
|
||||
#include "I2PEndian.h"
|
||||
#include <array>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
/** @brief decaying bloom filter implementation */
|
||||
class DecayingBloomFilter : public IBloomFilter
|
||||
{
|
||||
public:
|
||||
|
||||
DecayingBloomFilter(const std::size_t size)
|
||||
{
|
||||
m_Size = size;
|
||||
m_Data = new uint8_t[size];
|
||||
}
|
||||
|
||||
/** @brief implements IBloomFilter::~IBloomFilter */
|
||||
~DecayingBloomFilter()
|
||||
{
|
||||
delete [] m_Data;
|
||||
}
|
||||
|
||||
/** @brief implements IBloomFilter::Add */
|
||||
bool Add(const uint8_t * data, std::size_t len)
|
||||
{
|
||||
std::size_t idx;
|
||||
uint8_t mask;
|
||||
Get(data, len, idx, mask);
|
||||
if(m_Data[idx] & mask) return false; // filter hit
|
||||
m_Data[idx] |= mask;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief implements IBloomFilter::Decay */
|
||||
void Decay()
|
||||
{
|
||||
// reset bloom filter buffer
|
||||
memset(m_Data, 0, m_Size);
|
||||
}
|
||||
|
||||
private:
|
||||
/** @brief get bit index for for data */
|
||||
void Get(const uint8_t * data, std::size_t len, std::size_t & idx, uint8_t & bm)
|
||||
{
|
||||
bm = 1;
|
||||
uint8_t digest[32];
|
||||
// TODO: use blake2 because it's faster
|
||||
SHA256(data, len, digest);
|
||||
uint64_t i = buf64toh(digest);
|
||||
idx = i % m_Size;
|
||||
bm <<= (i % 8);
|
||||
}
|
||||
|
||||
uint8_t * m_Data;
|
||||
std::size_t m_Size;
|
||||
};
|
||||
|
||||
|
||||
BloomFilterPtr BloomFilter(std::size_t capacity)
|
||||
{
|
||||
return std::make_shared<DecayingBloomFilter>(capacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifndef BLOOM_FILTER_H_
|
||||
#define BLOOM_FILTER_H_
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
/** @brief interface for bloom filter */
|
||||
struct IBloomFilter
|
||||
{
|
||||
|
||||
/** @brief destructor */
|
||||
virtual ~IBloomFilter() {};
|
||||
/** @brief add entry to bloom filter, return false if filter hit otherwise return true */
|
||||
virtual bool Add(const uint8_t * data, std::size_t len) = 0;
|
||||
/** @brief optionally decay old entries */
|
||||
virtual void Decay() = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<IBloomFilter> BloomFilterPtr;
|
||||
|
||||
/** @brief create bloom filter */
|
||||
BloomFilterPtr BloomFilter(std::size_t capacity = 1024 * 8);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -64,7 +64,7 @@ namespace config {
|
||||
("bandwidth", value<std::string>()->default_value(""), "Transit traffic bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
||||
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
|
||||
("ntcp", bool_switch()->default_value(false), "Ignored. Always false")
|
||||
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||
("ssu", bool_switch()->default_value(false), "Ignored. Always false")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Ignored")
|
||||
@@ -77,7 +77,7 @@ namespace config {
|
||||
limits.add_options()
|
||||
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
|
||||
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
|
||||
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
|
||||
("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)")
|
||||
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
|
||||
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
|
||||
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
|
||||
@@ -274,9 +274,12 @@ namespace config {
|
||||
|
||||
options_description ssu2("SSU2 Options");
|
||||
ssu2.add_options()
|
||||
("ssu2.enabled", value<bool>()->default_value(false), "Enable SSU2 (default: disabled)")
|
||||
("ssu2.published", value<bool>()->default_value(false), "Publish SSU2 (default: disabled)")
|
||||
("ssu2.enabled", value<bool>()->default_value(true), "Enable SSU2 (default: enabled)")
|
||||
("ssu2.published", value<bool>()->default_value(true), "Publish SSU2 (default: enabled)")
|
||||
("ssu2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming SSU2 packets (default: auto)")
|
||||
("ssu2.mtu4", value<uint16_t>()->default_value(0), "MTU for ipv4 address (default: detect)")
|
||||
("ssu2.mtu6", value<uint16_t>()->default_value(0), "MTU for ipv6 address (default: detect)")
|
||||
("ssu2.proxy", value<std::string>()->default_value(""), "Socks5 proxy URL for SSU2 transport")
|
||||
;
|
||||
|
||||
options_description nettime("Time sync options");
|
||||
@@ -311,6 +314,13 @@ namespace config {
|
||||
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
|
||||
;
|
||||
|
||||
#ifdef __linux__
|
||||
options_description unix_specific("UNIX-specific options");
|
||||
unix_specific.add_options()
|
||||
("unix.handle_sigtstp", bool_switch()->default_value(false), "Handle SIGTSTP and SIGCONT signals (default: disabled)")
|
||||
;
|
||||
#endif
|
||||
|
||||
m_OptionsDesc
|
||||
.add(general)
|
||||
.add(limits)
|
||||
@@ -334,6 +344,9 @@ namespace config {
|
||||
.add(persist)
|
||||
.add(cpuext)
|
||||
.add(meshnets)
|
||||
#ifdef __linux__
|
||||
.add(unix_specific)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -159,8 +159,10 @@ namespace crypto
|
||||
|
||||
// DH/ElGamal
|
||||
|
||||
#if !defined(__x86_64__)
|
||||
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
|
||||
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
|
||||
#endif
|
||||
const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
|
||||
const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;
|
||||
|
||||
@@ -239,55 +241,6 @@ namespace crypto
|
||||
|
||||
static BIGNUM * (* g_ElggTable)[255] = nullptr;
|
||||
|
||||
// DH
|
||||
|
||||
DHKeys::DHKeys ()
|
||||
{
|
||||
m_DH = DH_new ();
|
||||
DH_set0_pqg (m_DH, BN_dup (elgp), NULL, BN_dup (elgg));
|
||||
DH_set0_key (m_DH, NULL, NULL);
|
||||
}
|
||||
|
||||
DHKeys::~DHKeys ()
|
||||
{
|
||||
DH_free (m_DH);
|
||||
}
|
||||
|
||||
void DHKeys::GenerateKeys ()
|
||||
{
|
||||
BIGNUM * priv_key = NULL, * pub_key = NULL;
|
||||
#if !defined(__x86_64__) // use short exponent for non x64
|
||||
priv_key = BN_new ();
|
||||
BN_rand (priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1);
|
||||
#endif
|
||||
if (g_ElggTable)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
priv_key = BN_new ();
|
||||
BN_rand (priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1);
|
||||
#endif
|
||||
auto ctx = BN_CTX_new ();
|
||||
pub_key = ElggPow (priv_key, g_ElggTable, ctx);
|
||||
DH_set0_key (m_DH, pub_key, priv_key);
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
DH_set0_key (m_DH, NULL, priv_key);
|
||||
DH_generate_key (m_DH);
|
||||
DH_get0_key (m_DH, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key);
|
||||
}
|
||||
|
||||
bn2buf (pub_key, m_PublicKey, 256);
|
||||
}
|
||||
|
||||
void DHKeys::Agree (const uint8_t * pub, uint8_t * shared)
|
||||
{
|
||||
BIGNUM * pk = BN_bin2bn (pub, 256, NULL);
|
||||
DH_compute_key (shared, pk, m_DH);
|
||||
BN_free (pk);
|
||||
}
|
||||
|
||||
// x25519
|
||||
X25519Keys::X25519Keys ()
|
||||
{
|
||||
@@ -601,77 +554,6 @@ namespace crypto
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
|
||||
// HMAC
|
||||
const uint64_t IPAD = 0x3636363636363636;
|
||||
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
|
||||
|
||||
|
||||
static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD };
|
||||
static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD };
|
||||
|
||||
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
|
||||
// key is 32 bytes
|
||||
// digest is 16 bytes
|
||||
// block size is 64 bytes
|
||||
{
|
||||
uint64_t buf[256];
|
||||
uint64_t hash[12]; // 96 bytes
|
||||
#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600)
|
||||
if(i2p::cpu::avx)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"vmovups %[key], %%ymm0 \n"
|
||||
"vmovups %[ipad], %%ymm1 \n"
|
||||
"vmovups %%ymm1, 32(%[buf]) \n"
|
||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||
"vmovups %%ymm1, (%[buf]) \n"
|
||||
"vmovups %[opad], %%ymm1 \n"
|
||||
"vmovups %%ymm1, 32(%[hash]) \n"
|
||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||
"vmovups %%ymm1, (%[hash]) \n"
|
||||
"vzeroall \n" // end of AVX
|
||||
"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
|
||||
:
|
||||
: [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads),
|
||||
[buf]"r"(buf), [hash]"r"(hash)
|
||||
: "memory", "%xmm0" // TODO: change to %ymm0 later
|
||||
);
|
||||
}
|
||||
else
|
||||
#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
|
||||
memcpy (buf + 8, msg, len);
|
||||
// calculate first hash
|
||||
MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes
|
||||
|
||||
// calculate digest
|
||||
MD5((uint8_t *)hash, 96, digest);
|
||||
}
|
||||
|
||||
// AES
|
||||
#ifdef __AES__
|
||||
#define KeyExpansion256(round0,round1) \
|
||||
|
||||
@@ -62,24 +62,6 @@ namespace crypto
|
||||
// RSA
|
||||
const BIGNUM * GetRSAE ();
|
||||
|
||||
// DH
|
||||
class DHKeys
|
||||
{
|
||||
public:
|
||||
|
||||
DHKeys ();
|
||||
~DHKeys ();
|
||||
|
||||
void GenerateKeys ();
|
||||
const uint8_t * GetPublicKey () const { return m_PublicKey; };
|
||||
void Agree (const uint8_t * pub, uint8_t * shared);
|
||||
|
||||
private:
|
||||
|
||||
DH * m_DH;
|
||||
uint8_t m_PublicKey[256];
|
||||
};
|
||||
|
||||
// x25519
|
||||
class X25519Keys
|
||||
{
|
||||
@@ -121,10 +103,6 @@ namespace crypto
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data
|
||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||
|
||||
// HMAC
|
||||
typedef i2p::data::Tag<32> MACKey;
|
||||
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest);
|
||||
|
||||
// AES
|
||||
struct ChipherBlock
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "Base.h"
|
||||
#include "Gzip.h"
|
||||
#include "Identity.h"
|
||||
#include "LeaseSet.h"
|
||||
#include "I2NPProtocol.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -1096,7 +1096,13 @@ namespace client
|
||||
}
|
||||
auto leaseSet = FindLeaseSet (dest);
|
||||
if (leaseSet)
|
||||
streamRequestComplete(CreateStream (leaseSet, port));
|
||||
{
|
||||
auto stream = CreateStream (leaseSet, port);
|
||||
GetService ().post ([streamRequestComplete, stream]()
|
||||
{
|
||||
streamRequestComplete(stream);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto s = GetSharedFromThis ();
|
||||
@@ -1129,6 +1135,41 @@ namespace client
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Dest>
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
|
||||
{
|
||||
volatile bool done = false;
|
||||
std::shared_ptr<i2p::stream::Stream> stream;
|
||||
std::condition_variable streamRequestComplete;
|
||||
std::mutex streamRequestCompleteMutex;
|
||||
CreateStream (
|
||||
[&done, &streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
|
||||
{
|
||||
stream = s;
|
||||
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
|
||||
streamRequestComplete.notify_all ();
|
||||
done = true;
|
||||
},
|
||||
dest, port);
|
||||
while (!done)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
|
||||
if (!done)
|
||||
streamRequestComplete.wait (l);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
|
||||
{
|
||||
return CreateStreamSync (dest, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
|
||||
{
|
||||
return CreateStreamSync (dest, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
|
||||
{
|
||||
if (m_StreamingDestination)
|
||||
|
||||
@@ -247,6 +247,8 @@ namespace client
|
||||
// following methods operate with default streaming destination
|
||||
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
|
||||
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0);
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0); // sync
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
|
||||
void SendPing (const i2p::data::IdentHash& to);
|
||||
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
|
||||
@@ -282,6 +284,9 @@ namespace client
|
||||
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
|
||||
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
||||
|
||||
template<typename Dest>
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port);
|
||||
|
||||
private:
|
||||
|
||||
i2p::data::PrivateKeys m_Keys;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -57,7 +57,8 @@ namespace data
|
||||
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
|
||||
return outLen - m_Inflator.avail_out;
|
||||
// else
|
||||
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||
if (err)
|
||||
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -128,7 +129,8 @@ namespace data
|
||||
return outLen - m_Deflator.avail_out;
|
||||
}
|
||||
// else
|
||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||
if (err)
|
||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,7 +160,8 @@ namespace data
|
||||
offset = outLen - m_Deflator.avail_out;
|
||||
}
|
||||
// else
|
||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||
if (err)
|
||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -135,6 +135,7 @@ namespace http
|
||||
? url.substr(pos_p, std::string::npos)
|
||||
: url.substr(pos_p, pos_c - pos_p);
|
||||
/* stoi throws exception on failure, we don't need it */
|
||||
port = 0;
|
||||
for (char c : port_str) {
|
||||
if (c < '0' || c > '9')
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -392,7 +392,8 @@ namespace i2p
|
||||
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
|
||||
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
||||
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
||||
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
|
||||
if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel))
|
||||
retCode = 30;
|
||||
}
|
||||
else
|
||||
retCode = 30; // always reject with bandwidth reason (30)
|
||||
@@ -558,7 +559,8 @@ namespace i2p
|
||||
return;
|
||||
}
|
||||
auto& noiseState = i2p::context.GetCurrentNoiseState ();
|
||||
uint8_t replyKey[32], layerKey[32], ivKey[32];
|
||||
uint8_t replyKey[32]; // AEAD/Chacha20/Poly1305
|
||||
i2p::crypto::AESKey layerKey, ivKey; // AES
|
||||
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
|
||||
memcpy (replyKey, noiseState.m_CK + 32, 32);
|
||||
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);
|
||||
@@ -589,7 +591,8 @@ namespace i2p
|
||||
layerKey, ivKey,
|
||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
||||
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
|
||||
if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel))
|
||||
retCode = 30;
|
||||
}
|
||||
|
||||
// encrypt reply
|
||||
|
||||
@@ -309,7 +309,7 @@ namespace tunnel
|
||||
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs;
|
||||
};
|
||||
|
||||
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500;
|
||||
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000;
|
||||
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
|
||||
uint16_t GetMaxNumTransitTunnels ();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -49,13 +49,22 @@ namespace data
|
||||
|
||||
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
|
||||
{
|
||||
uint8_t randomPaddingBlock[32];
|
||||
RAND_bytes (randomPaddingBlock, 32);
|
||||
if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
{
|
||||
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
|
||||
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
|
||||
memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32);
|
||||
for (int i = 0; i < 7; i++) // 224 bytes
|
||||
memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32);
|
||||
}
|
||||
else
|
||||
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
|
||||
{
|
||||
if (publicKey)
|
||||
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
|
||||
else
|
||||
for (int i = 0; i < 8; i++) // 256 bytes
|
||||
memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32);
|
||||
}
|
||||
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
|
||||
{
|
||||
size_t excessLen = 0;
|
||||
@@ -93,7 +102,8 @@ namespace data
|
||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||
{
|
||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||
RAND_bytes (m_StandardIdentity.signingKey, padding);
|
||||
for (int i = 0; i < 3; i++) // 96 bytes
|
||||
memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32);
|
||||
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||
break;
|
||||
}
|
||||
@@ -695,7 +705,7 @@ namespace data
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType)
|
||||
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType, bool isDestination)
|
||||
{
|
||||
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
|
||||
{
|
||||
@@ -705,9 +715,12 @@ namespace data
|
||||
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, signingPublicKey);
|
||||
// encryption
|
||||
uint8_t publicKey[256];
|
||||
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
|
||||
if (isDestination)
|
||||
RAND_bytes (keys.m_PrivateKey, 256);
|
||||
else
|
||||
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
|
||||
// identity
|
||||
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type, cryptoType);
|
||||
keys.m_Public = std::make_shared<IdentityEx> (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType);
|
||||
|
||||
keys.CreateSigner ();
|
||||
return keys;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -171,7 +171,7 @@ namespace data
|
||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (const uint8_t * key) const;
|
||||
|
||||
static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
|
||||
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
|
||||
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL, bool isDestination = false);
|
||||
static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub);
|
||||
static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
|
||||
static i2p::crypto::Signer * CreateSigner (SigningKeyType keyType, const uint8_t * priv);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -37,14 +37,7 @@ namespace data
|
||||
|
||||
void LeaseSet::Update (const uint8_t * buf, size_t len, bool verifySignature)
|
||||
{
|
||||
if (len > m_BufferLen)
|
||||
{
|
||||
auto oldBuffer = m_Buffer;
|
||||
m_Buffer = new uint8_t[len];
|
||||
delete[] oldBuffer;
|
||||
}
|
||||
memcpy (m_Buffer, buf, len);
|
||||
m_BufferLen = len;
|
||||
SetBuffer (buf, len);
|
||||
ReadFromBuffer (false, verifySignature);
|
||||
}
|
||||
|
||||
@@ -59,9 +52,9 @@ namespace data
|
||||
if (readIdentity || !m_Identity)
|
||||
m_Identity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
|
||||
size_t size = m_Identity->GetFullLen ();
|
||||
if (size > m_BufferLen)
|
||||
if (size + 256 > m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", m_BufferLen);
|
||||
LogPrint (eLogError, "LeaseSet: Identity length ", int(size), " exceeds buffer size ", int(m_BufferLen));
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
@@ -74,7 +67,7 @@ namespace data
|
||||
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
|
||||
if (size + 1 > m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
|
||||
LogPrint (eLogError, "LeaseSet: ", int(size), " exceeds buffer size ", int(m_BufferLen));
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
@@ -89,7 +82,7 @@ namespace data
|
||||
}
|
||||
if (size + num*LEASE_SIZE > m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
|
||||
LogPrint (eLogError, "LeaseSet: ", int(size), " exceeds buffer size ", int(m_BufferLen));
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
@@ -125,7 +118,7 @@ namespace data
|
||||
auto signedSize = leases - m_Buffer;
|
||||
if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen);
|
||||
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", int(m_BufferLen));
|
||||
m_IsValid = false;
|
||||
}
|
||||
else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
|
||||
@@ -172,7 +165,7 @@ namespace data
|
||||
m_ExpirationTime = lease.endDate;
|
||||
if (m_StoreLeases)
|
||||
{
|
||||
auto ret = m_Leases.insert (std::make_shared<Lease>(lease));
|
||||
auto ret = m_Leases.insert (i2p::data::netdb.NewLease (lease));
|
||||
if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing
|
||||
(*ret.first)->isUpdated = true;
|
||||
}
|
||||
@@ -264,8 +257,18 @@ namespace data
|
||||
|
||||
void LeaseSet::SetBuffer (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_Buffer) delete[] m_Buffer;
|
||||
m_Buffer = new uint8_t[len];
|
||||
if (len > MAX_LS_BUFFER_SIZE)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: Buffer is too long ", len);
|
||||
len = MAX_LS_BUFFER_SIZE;
|
||||
}
|
||||
if (m_Buffer && len > m_BufferLen)
|
||||
{
|
||||
delete[] m_Buffer;
|
||||
m_Buffer = nullptr;
|
||||
}
|
||||
if (!m_Buffer)
|
||||
m_Buffer = new uint8_t[len];
|
||||
m_BufferLen = len;
|
||||
memcpy (m_Buffer, buf, len);
|
||||
}
|
||||
@@ -274,7 +277,7 @@ namespace data
|
||||
{
|
||||
if (len <= m_BufferLen) m_BufferLen = len;
|
||||
else
|
||||
LogPrint (eLogError, "LeaseSet2: Actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
|
||||
LogPrint (eLogError, "LeaseSet2: Actual buffer size ", int(len) , " exceeds full buffer size ", int(m_BufferLen));
|
||||
}
|
||||
|
||||
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
|
||||
@@ -320,7 +323,7 @@ namespace data
|
||||
else
|
||||
identity = GetIdentity ();
|
||||
size_t offset = identity->GetFullLen ();
|
||||
if (offset + 8 >= len) return;
|
||||
if (offset + 8 > len) return;
|
||||
m_PublishedTimestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
|
||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
||||
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
|
||||
@@ -364,6 +367,10 @@ namespace data
|
||||
SetIsValid (verified);
|
||||
}
|
||||
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen ();
|
||||
if (offset > len) {
|
||||
LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len));
|
||||
return;
|
||||
}
|
||||
SetBufferLen (offset);
|
||||
}
|
||||
|
||||
@@ -388,17 +395,17 @@ namespace data
|
||||
// properties
|
||||
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
||||
offset += propertiesLen; // skip for now. TODO: implement properties
|
||||
if (offset + 1 >= len) return 0;
|
||||
// key sections
|
||||
CryptoKeyType preferredKeyType = m_EncryptionType;
|
||||
bool preferredKeyFound = false;
|
||||
if (offset + 1 > len) return 0;
|
||||
int numKeySections = buf[offset]; offset++;
|
||||
for (int i = 0; i < numKeySections; i++)
|
||||
{
|
||||
if (offset + 4 > len) return 0;
|
||||
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type
|
||||
if (offset + 2 >= len) return 0;
|
||||
uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2;
|
||||
if (offset + encryptionKeyLen >= len) return 0;
|
||||
if (offset + encryptionKeyLen > len) return 0;
|
||||
if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only
|
||||
{
|
||||
// we pick first valid key if preferred not found
|
||||
@@ -413,7 +420,7 @@ namespace data
|
||||
offset += encryptionKeyLen;
|
||||
}
|
||||
// leases
|
||||
if (offset + 1 >= len) return 0;
|
||||
if (offset + 1 > len) return 0;
|
||||
int numLeases = buf[offset]; offset++;
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
if (IsStoreLeases ())
|
||||
@@ -432,7 +439,8 @@ namespace data
|
||||
}
|
||||
else
|
||||
offset += numLeases*LEASE2_SIZE; // 40 bytes per lease
|
||||
return offset;
|
||||
|
||||
return (offset > len ? 0 : offset);
|
||||
}
|
||||
|
||||
size_t LeaseSet2::ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len)
|
||||
@@ -442,18 +450,18 @@ namespace data
|
||||
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
||||
offset += propertiesLen; // skip for now. TODO: implement properties
|
||||
// entries
|
||||
if (offset + 1 >= len) return 0;
|
||||
if (offset + 1 > len) return 0;
|
||||
int numEntries = buf[offset]; offset++;
|
||||
for (int i = 0; i < numEntries; i++)
|
||||
{
|
||||
if (offset + 40 >= len) return 0;
|
||||
if (offset + LEASE2_SIZE > len) return 0;
|
||||
offset += 32; // hash
|
||||
offset += 3; // flags
|
||||
offset += 1; // cost
|
||||
offset += 4; // expires
|
||||
}
|
||||
// revocations
|
||||
if (offset + 1 >= len) return 0;
|
||||
if (offset + 1 > len) return 0;
|
||||
int numRevocations = buf[offset]; offset++;
|
||||
for (int i = 0; i < numRevocations; i++)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -18,11 +18,11 @@ namespace log {
|
||||
/**
|
||||
* @brief Maps our loglevel to their symbolic name
|
||||
*/
|
||||
static const char * g_LogLevelStr[eNumLogLevels] =
|
||||
static const char *g_LogLevelStr[eNumLogLevels] =
|
||||
{
|
||||
"none", // eLogNone
|
||||
"error", // eLogError
|
||||
"warn", // eLogWarn
|
||||
"warn", // eLogWarning
|
||||
"info", // eLogInfo
|
||||
"debug" // eLogDebug
|
||||
};
|
||||
@@ -35,12 +35,12 @@ namespace log {
|
||||
static const char *LogMsgColors[] = { "", "", "", "", "", "" };
|
||||
#else /* UNIX */
|
||||
static const char *LogMsgColors[] = {
|
||||
[eLogNone] = "\033[0m", /* reset */
|
||||
[eLogError] = "\033[1;31m", /* red */
|
||||
[eLogWarning] = "\033[1;33m", /* yellow */
|
||||
[eLogInfo] = "\033[1;36m", /* cyan */
|
||||
[eLogDebug] = "\033[1;34m", /* blue */
|
||||
[eNumLogLevels] = "\033[0m", /* reset */
|
||||
"\033[1;32m", /* none: green */
|
||||
"\033[1;31m", /* error: red */
|
||||
"\033[1;33m", /* warning: yellow */
|
||||
"\033[1;36m", /* info: cyan */
|
||||
"\033[1;34m", /* debug: blue */
|
||||
"\033[0m" /* reset */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace log {
|
||||
if (level == "none") { m_MinLevel = eLogNone; }
|
||||
else if (level == "error") { m_MinLevel = eLogError; }
|
||||
else if (level == "warn") { m_MinLevel = eLogWarning; }
|
||||
else if (level == "info") { m_MinLevel = eLogInfo; }
|
||||
else if (level == "info") { m_MinLevel = eLogInfo; }
|
||||
else if (level == "debug") { m_MinLevel = eLogDebug; }
|
||||
else {
|
||||
LogPrint(eLogError, "Log: Unknown loglevel: ", level);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -139,7 +139,7 @@ namespace transport
|
||||
m3p2[3] = 0; // flag
|
||||
memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex
|
||||
// 2 bytes reserved
|
||||
htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA
|
||||
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds
|
||||
// 4 bytes reserved
|
||||
// sign and encrypt options, use m_H as AD
|
||||
uint8_t nonce[12];
|
||||
@@ -162,7 +162,7 @@ namespace transport
|
||||
uint8_t options[16];
|
||||
memset (options, 0, 16);
|
||||
htobe16buf (options + 2, paddingLen); // padLen
|
||||
htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsB
|
||||
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds
|
||||
// sign and encrypt options, use m_H as AD
|
||||
uint8_t nonce[12];
|
||||
memset (nonce, 0, 12); // set nonce to zero
|
||||
@@ -309,7 +309,7 @@ namespace transport
|
||||
|
||||
KDF3Bob ();
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
||||
// caclulate new h again for KDF data
|
||||
// calculate new h again for KDF data
|
||||
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
||||
else
|
||||
{
|
||||
@@ -374,10 +374,16 @@ namespace transport
|
||||
transports.PeerDisconnected (shared_from_this ());
|
||||
m_Server.RemoveNTCP2Session (shared_from_this ());
|
||||
m_SendQueue.clear ();
|
||||
m_SendQueueSize = 0;
|
||||
LogPrint (eLogDebug, "NTCP2: Session terminated");
|
||||
}
|
||||
}
|
||||
|
||||
void NTCP2Session::Close ()
|
||||
{
|
||||
m_Socket.close ();
|
||||
}
|
||||
|
||||
void NTCP2Session::TerminateByTimeout ()
|
||||
{
|
||||
SendTerminationAndTerminate (eNTCP2IdleTimeout);
|
||||
@@ -746,6 +752,8 @@ namespace transport
|
||||
|
||||
void NTCP2Session::ServerLogin ()
|
||||
{
|
||||
SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT);
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_Establisher->CreateEphemeralKey ();
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (),
|
||||
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
|
||||
@@ -1050,7 +1058,10 @@ namespace transport
|
||||
SendRouterInfo ();
|
||||
}
|
||||
else
|
||||
{
|
||||
SendQueue ();
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1158,7 +1169,7 @@ namespace transport
|
||||
{
|
||||
if (m_IsTerminated) return;
|
||||
for (auto it: msgs)
|
||||
m_SendQueue.push_back (it);
|
||||
m_SendQueue.push_back (std::move (it));
|
||||
if (!m_IsSending)
|
||||
SendQueue ();
|
||||
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
|
||||
@@ -1167,11 +1178,12 @@ namespace transport
|
||||
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
||||
Terminate ();
|
||||
}
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
}
|
||||
|
||||
void NTCP2Session::SendLocalRouterInfo ()
|
||||
void NTCP2Session::SendLocalRouterInfo (bool update)
|
||||
{
|
||||
if (!IsOutgoing ()) // we send it in SessionConfirmed
|
||||
if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session
|
||||
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
|
||||
}
|
||||
|
||||
@@ -1210,8 +1222,9 @@ namespace transport
|
||||
else
|
||||
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
||||
// start acceptors
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (const auto& address: addresses)
|
||||
auto addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
if (!addresses) return;
|
||||
for (const auto& address: *addresses)
|
||||
{
|
||||
if (!address) continue;
|
||||
if (address->IsPublishedNTCP2 () && address->port)
|
||||
@@ -1288,7 +1301,7 @@ namespace transport
|
||||
for (auto& it: ntcpSessions)
|
||||
it.second->Terminate ();
|
||||
for (auto& it: m_PendingIncomingSessions)
|
||||
it->Terminate ();
|
||||
it.second->Terminate ();
|
||||
}
|
||||
m_NTCP2Sessions.clear ();
|
||||
|
||||
@@ -1304,20 +1317,32 @@ namespace transport
|
||||
{
|
||||
if (!session) return false;
|
||||
if (incoming)
|
||||
m_PendingIncomingSessions.remove (session);
|
||||
if (!session->GetRemoteIdentity ()) return false;
|
||||
m_PendingIncomingSessions.erase (session->GetRemoteEndpoint ().address ());
|
||||
if (!session->GetRemoteIdentity ())
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: Unknown identity for ", session->GetRemoteEndpoint ());
|
||||
session->Terminate ();
|
||||
return false;
|
||||
}
|
||||
auto& ident = session->GetRemoteIdentity ()->GetIdentHash ();
|
||||
auto it = m_NTCP2Sessions.find (ident);
|
||||
if (it != m_NTCP2Sessions.end ())
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists");
|
||||
LogPrint (eLogWarning, "NTCP2: Session with ", ident.ToBase64 (), " already exists. ", incoming ? "Replaced" : "Dropped");
|
||||
if (incoming)
|
||||
{
|
||||
// replace by new session
|
||||
it->second->Terminate ();
|
||||
auto s = it->second;
|
||||
m_NTCP2Sessions.erase (it);
|
||||
s->Terminate ();
|
||||
}
|
||||
else
|
||||
{
|
||||
session->Terminate ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_NTCP2Sessions.insert (std::make_pair (ident, session));
|
||||
m_NTCP2Sessions.emplace (ident, session);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1412,19 +1437,35 @@ namespace transport
|
||||
if (!ec)
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Connected from ", ep);
|
||||
if (conn)
|
||||
if (!i2p::util::net::IsInReservedRange(ep.address ()))
|
||||
{
|
||||
conn->SetRemoteEndpoint (ep);
|
||||
conn->ServerLogin ();
|
||||
m_PendingIncomingSessions.push_back (conn);
|
||||
conn = nullptr;
|
||||
if (conn)
|
||||
{
|
||||
if (m_PendingIncomingSessions.emplace (ep.address (), conn).second)
|
||||
{
|
||||
conn->SetRemoteEndpoint (ep);
|
||||
conn->ServerLogin ();
|
||||
conn = nullptr;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending");
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ());
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: Accept error ", error.message ());
|
||||
if (error == boost::asio::error::no_descriptors)
|
||||
{
|
||||
i2p::context.SetError (eRouterErrorNoDescriptors);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::operation_aborted)
|
||||
{
|
||||
@@ -1446,20 +1487,43 @@ namespace transport
|
||||
if (!ec)
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Connected from ", ep);
|
||||
if (conn)
|
||||
if (!i2p::util::net::IsInReservedRange(ep.address ()) ||
|
||||
i2p::util::net::IsYggdrasilAddress (ep.address ()))
|
||||
{
|
||||
conn->SetRemoteEndpoint (ep);
|
||||
conn->ServerLogin ();
|
||||
m_PendingIncomingSessions.push_back (conn);
|
||||
if (conn)
|
||||
{
|
||||
if (m_PendingIncomingSessions.emplace (ep.address (), conn).second)
|
||||
{
|
||||
conn->SetRemoteEndpoint (ep);
|
||||
conn->ServerLogin ();
|
||||
conn = nullptr;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending");
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ());
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ());
|
||||
if (error == boost::asio::error::no_descriptors)
|
||||
{
|
||||
i2p::context.SetErrorV6 (eRouterErrorNoDescriptors);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (error != boost::asio::error::operation_aborted)
|
||||
{
|
||||
conn = std::make_shared<NTCP2Session> (*this);
|
||||
if (!conn) // connection is used, create new one
|
||||
conn = std::make_shared<NTCP2Session> (*this);
|
||||
else // reuse failed
|
||||
conn->Close ();
|
||||
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this,
|
||||
conn, std::placeholders::_1));
|
||||
}
|
||||
@@ -1490,18 +1554,34 @@ namespace transport
|
||||
// pending
|
||||
for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();)
|
||||
{
|
||||
if ((*it)->IsEstablished () || (*it)->IsTerminationTimeoutExpired (ts))
|
||||
if (it->second->IsEstablished () || it->second->IsTerminationTimeoutExpired (ts))
|
||||
{
|
||||
(*it)->Terminate ();
|
||||
it->second->Terminate ();
|
||||
it = m_PendingIncomingSessions.erase (it); // established of expired
|
||||
}
|
||||
else if ((*it)->IsTerminated ())
|
||||
else if (it->second->IsTerminated ())
|
||||
it = m_PendingIncomingSessions.erase (it); // already terminated
|
||||
else
|
||||
it++;
|
||||
}
|
||||
|
||||
ScheduleTermination ();
|
||||
|
||||
// try to restart acceptors if no description
|
||||
// we do it after timer to let timer take descriptor first
|
||||
if (i2p::context.GetError () == eRouterErrorNoDescriptors)
|
||||
{
|
||||
i2p::context.SetError (eRouterErrorNone);
|
||||
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this,
|
||||
conn, std::placeholders::_1));
|
||||
}
|
||||
if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors)
|
||||
{
|
||||
i2p::context.SetErrorV6 (eRouterErrorNone);
|
||||
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this,
|
||||
conn, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1558,7 +1638,7 @@ namespace transport
|
||||
case eSocksProxy:
|
||||
{
|
||||
// TODO: support username/password auth etc
|
||||
static const uint8_t buff[3] = {0x05, 0x01, 0x00};
|
||||
static const uint8_t buff[3] = {SOCKS5_VER, 0x01, 0x00};
|
||||
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(),
|
||||
[] (const boost::system::error_code & ec, std::size_t transferred)
|
||||
{
|
||||
@@ -1672,21 +1752,21 @@ namespace transport
|
||||
size_t sz = 6; // header + port
|
||||
auto buff = std::make_shared<std::vector<int8_t> >(256);
|
||||
auto readbuff = std::make_shared<std::vector<int8_t> >(256);
|
||||
(*buff)[0] = 0x05;
|
||||
(*buff)[1] = 0x01;
|
||||
(*buff)[0] = SOCKS5_VER;
|
||||
(*buff)[1] = SOCKS5_CMD_CONNECT;
|
||||
(*buff)[2] = 0x00;
|
||||
|
||||
auto& ep = conn->GetRemoteEndpoint ();
|
||||
if(ep.address ().is_v4 ())
|
||||
{
|
||||
(*buff)[3] = 0x01;
|
||||
(*buff)[3] = SOCKS5_ATYP_IPV4;
|
||||
auto addrbytes = ep.address ().to_v4().to_bytes();
|
||||
sz += 4;
|
||||
memcpy(buff->data () + 4, addrbytes.data(), 4);
|
||||
}
|
||||
else if (ep.address ().is_v6 ())
|
||||
{
|
||||
(*buff)[3] = 0x04;
|
||||
(*buff)[3] = SOCKS5_ATYP_IPV6;
|
||||
auto addrbytes = ep.address ().to_v6().to_bytes();
|
||||
sz += 16;
|
||||
memcpy(buff->data () + 4, addrbytes.data(), 16);
|
||||
@@ -1708,22 +1788,24 @@ namespace transport
|
||||
}
|
||||
});
|
||||
|
||||
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 10),
|
||||
[timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred)
|
||||
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size
|
||||
boost::asio::transfer_all(),
|
||||
[timer, conn, readbuff](const boost::system::error_code & e, std::size_t transferred)
|
||||
{
|
||||
if(e)
|
||||
{
|
||||
if (e)
|
||||
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
|
||||
}
|
||||
else if(transferred == sz)
|
||||
else if (!(*readbuff)[1]) // succeeded
|
||||
{
|
||||
if((*readbuff)[1] == 0x00)
|
||||
{
|
||||
timer->cancel();
|
||||
conn->ClientLogin();
|
||||
return;
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
size_t moreBytes = conn->GetSocket ().available(ec);
|
||||
if (moreBytes) // read remaining portion of reply if ipv6 received
|
||||
boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec);
|
||||
timer->cancel();
|
||||
conn->ClientLogin();
|
||||
return;
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "NTCP2: Proxy reply error ", (int)(*readbuff)[1]);
|
||||
timer->cancel();
|
||||
conn->Terminate();
|
||||
});
|
||||
|
||||
@@ -134,22 +134,22 @@ namespace transport
|
||||
~NTCP2Session ();
|
||||
void Terminate ();
|
||||
void TerminateByTimeout ();
|
||||
void Done ();
|
||||
void Close () { m_Socket.close (); }; // for accept
|
||||
void Done () override;
|
||||
void Close (); // for accept
|
||||
void DeleteNextReceiveBuffer (uint64_t ts);
|
||||
|
||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||
const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
||||
void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; };
|
||||
|
||||
bool IsEstablished () const { return m_IsEstablished; };
|
||||
bool IsEstablished () const override { 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);
|
||||
void SendLocalRouterInfo (bool update) override; // after handshake or by update
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace transport
|
||||
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;
|
||||
std::map<boost::asio::ip::address, std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
||||
|
||||
ProxyType m_ProxyType;
|
||||
std::string m_ProxyAddress, m_ProxyAuthorization;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -240,11 +240,10 @@ namespace data
|
||||
m_HiddenMode = hide;
|
||||
}
|
||||
|
||||
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||
{
|
||||
bool updated;
|
||||
AddRouterInfo (buf, len, updated);
|
||||
return updated;
|
||||
return AddRouterInfo (buf, len, updated);
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated)
|
||||
@@ -272,7 +271,10 @@ namespace data
|
||||
if (r->IsNewer (buf, len))
|
||||
{
|
||||
bool wasFloodfill = r->IsFloodfill ();
|
||||
r->Update (buf, len);
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||
r->Update (buf, len);
|
||||
}
|
||||
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
||||
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
|
||||
{
|
||||
@@ -293,7 +295,8 @@ namespace data
|
||||
else
|
||||
{
|
||||
r = std::make_shared<RouterInfo> (buf, len);
|
||||
if (!r->IsUnreachable () && r->HasValidAddresses ())
|
||||
if (!r->IsUnreachable () && r->HasValidAddresses () &&
|
||||
i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ())
|
||||
{
|
||||
bool inserted = false;
|
||||
{
|
||||
@@ -363,15 +366,16 @@ namespace data
|
||||
|
||||
bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
|
||||
auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb
|
||||
if (leaseSet->IsValid ())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
|
||||
auto it = m_LeaseSets.find(ident);
|
||||
if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType ||
|
||||
leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ())
|
||||
{
|
||||
if (leaseSet->IsPublic () && !leaseSet->IsExpired ())
|
||||
if (leaseSet->IsPublic () && !leaseSet->IsExpired () &&
|
||||
i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ())
|
||||
{
|
||||
// TODO: implement actual update
|
||||
LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32());
|
||||
@@ -380,7 +384,7 @@ namespace data
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: Unpublished or expired LeaseSet2 received: ", ident.ToBase32());
|
||||
LogPrint (eLogWarning, "NetDb: Unpublished or expired or future LeaseSet2 received: ", ident.ToBase32());
|
||||
m_LeaseSets.erase (ident);
|
||||
}
|
||||
}
|
||||
@@ -436,12 +440,15 @@ namespace data
|
||||
|
||||
// try reseeding from floodfill first if specified
|
||||
std::string riPath;
|
||||
if(i2p::config::GetOption("reseed.floodfill", riPath)) {
|
||||
if(i2p::config::GetOption("reseed.floodfill", riPath))
|
||||
{
|
||||
auto ri = std::make_shared<RouterInfo>(riPath);
|
||||
if (ri->IsFloodfill()) {
|
||||
if (ri->IsFloodfill())
|
||||
{
|
||||
const uint8_t * riData = ri->GetBuffer();
|
||||
int riLen = ri->GetBufferLen();
|
||||
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
|
||||
if (!i2p::data::netdb.AddRouterInfo(riData, riLen))
|
||||
{
|
||||
// bad router info
|
||||
LogPrint(eLogError, "NetDb: Bad router info");
|
||||
return;
|
||||
@@ -489,7 +496,7 @@ namespace data
|
||||
{
|
||||
auto r = std::make_shared<RouterInfo>(path);
|
||||
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
|
||||
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
|
||||
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL) // too old
|
||||
{
|
||||
r->DeleteBuffer ();
|
||||
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
||||
@@ -598,6 +605,7 @@ namespace data
|
||||
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||
auto uptime = i2p::context.GetUptime ();
|
||||
bool isLowRate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE;
|
||||
// routers don't expire if less than 90 or uptime is less than 1 hour
|
||||
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
|
||||
if (checkForExpiration && uptime > 3600) // 1 hour
|
||||
@@ -619,18 +627,24 @@ namespace data
|
||||
continue;
|
||||
}
|
||||
// make router reachable back if too few routers or floodfills
|
||||
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
|
||||
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate ||
|
||||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
||||
it.second->SetUnreachable (false);
|
||||
// find & mark expired routers
|
||||
if (!it.second->IsReachable () && it.second->IsSSU (false))
|
||||
if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4))
|
||||
// non-reachable router, but reachable by ipv4 SSU2 means introducers
|
||||
{
|
||||
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
|
||||
// RouterInfo expires after 1 hour if uses introducer
|
||||
it.second->SetUnreachable (true);
|
||||
}
|
||||
else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout)
|
||||
it.second->SetUnreachable (true);
|
||||
it.second->SetUnreachable (true);
|
||||
else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ())
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds");
|
||||
it.second->SetUnreachable (true);
|
||||
}
|
||||
|
||||
if (it.second->IsUnreachable ())
|
||||
{
|
||||
@@ -643,6 +657,8 @@ namespace data
|
||||
} // m_RouterInfos iteration
|
||||
|
||||
m_RouterInfoBuffersPool.CleanUpMt ();
|
||||
m_RouterInfoAddressesPool.CleanUpMt ();
|
||||
m_RouterInfoAddressVectorsPool.CleanUpMt ();
|
||||
|
||||
if (updatedCount > 0)
|
||||
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
|
||||
@@ -743,6 +759,11 @@ namespace data
|
||||
{
|
||||
const uint8_t * buf = m->GetPayload ();
|
||||
size_t len = m->GetSize ();
|
||||
if (len < DATABASE_STORE_HEADER_SIZE)
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: Database store msg is too short ", len, ". Dropped");
|
||||
return;
|
||||
}
|
||||
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
|
||||
if (ident.IsZero ())
|
||||
{
|
||||
@@ -753,6 +774,11 @@ namespace data
|
||||
size_t offset = DATABASE_STORE_HEADER_SIZE;
|
||||
if (replyToken)
|
||||
{
|
||||
if (len < offset + 36) // 32 + 4
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped");
|
||||
return;
|
||||
}
|
||||
auto deliveryStatus = CreateDeliveryStatusMsg (replyToken);
|
||||
uint32_t tunnelID = bufbe32toh (buf + offset);
|
||||
offset += 4;
|
||||
@@ -781,6 +807,11 @@ namespace data
|
||||
uint8_t storeType = buf[DATABASE_STORE_TYPE_OFFSET];
|
||||
if (storeType) // LeaseSet or LeaseSet2
|
||||
{
|
||||
if (len > MAX_LS_BUFFER_SIZE + offset)
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: Database store message is too long ", len);
|
||||
return;
|
||||
}
|
||||
if (!m->from) // unsolicited LS must be received directly
|
||||
{
|
||||
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
||||
@@ -940,9 +971,9 @@ namespace data
|
||||
}
|
||||
uint16_t numExcluded = bufbe16toh (excluded);
|
||||
excluded += 2;
|
||||
if (numExcluded > 512)
|
||||
if (numExcluded > 512 || (excluded - buf) + numExcluded*32 > (int)msg->GetPayloadLength ())
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " exceeds 512");
|
||||
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " is too much");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -951,10 +982,11 @@ namespace data
|
||||
{
|
||||
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
|
||||
std::set<IdentHash> excludedRouters;
|
||||
const uint8_t * excluded_ident = excluded;
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
{
|
||||
excludedRouters.insert (excluded);
|
||||
excluded += 32;
|
||||
excludedRouters.insert (excluded_ident);
|
||||
excluded_ident += 32;
|
||||
}
|
||||
std::vector<IdentHash> routers;
|
||||
for (int i = 0; i < 3; i++)
|
||||
@@ -977,8 +1009,7 @@ namespace data
|
||||
if (router)
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found");
|
||||
if (!router->GetBuffer ())
|
||||
router->LoadBuffer (m_Storage.Path (router->GetIdentHashBase64 ()));
|
||||
PopulateRouterInfoBuffer (router);
|
||||
if (router->GetBuffer ())
|
||||
replyMsg = CreateDatabaseStoreMsg (router);
|
||||
}
|
||||
@@ -1013,7 +1044,7 @@ namespace data
|
||||
if (closestFloodfills.empty ())
|
||||
LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded");
|
||||
replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills);
|
||||
}
|
||||
}
|
||||
}
|
||||
excluded += numExcluded * 32;
|
||||
if (replyMsg)
|
||||
@@ -1193,16 +1224,6 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomPeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return !router->IsHidden () && router->IsECIES () &&
|
||||
router->IsPeerTesting (v4) && !excluded.count (router->GetIdentHash ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
@@ -1213,22 +1234,13 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
[](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return !router->IsHidden () && router->IsECIES () && router->IsSSUV6 ();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return !router->IsHidden () && router->IsECIES () && !router->IsFloodfill () && // floodfills don't send relay tag
|
||||
router->IsIntroducer (v4) && !excluded.count (router->GetIdentHash ());
|
||||
return !router->IsHidden () && router->IsSSU2Introducer (v4) &&
|
||||
!excluded.count (router->GetIdentHash ());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1432,6 +1444,13 @@ namespace data
|
||||
else
|
||||
++it;
|
||||
}
|
||||
m_LeasesPool.CleanUpMt ();
|
||||
}
|
||||
|
||||
void NetDb::PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r)
|
||||
{
|
||||
if (!r || r->GetBuffer ()) return;
|
||||
r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,13 @@ namespace data
|
||||
{
|
||||
const int NETDB_MIN_ROUTERS = 90;
|
||||
const int NETDB_MIN_FLOODFILLS = 5;
|
||||
const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents
|
||||
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
|
||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
||||
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
|
||||
const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days
|
||||
const int NETDB_EXPIRATION_TIMEOUT_THRESHOLD = 2*60; // 2 minutes
|
||||
const int NETDB_PUBLISH_INTERVAL = 60 * 40;
|
||||
const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
||||
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
||||
@@ -69,7 +71,7 @@ namespace data
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
bool AddRouterInfo (const uint8_t * buf, int len);
|
||||
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len);
|
||||
bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
|
||||
bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len);
|
||||
bool AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType);
|
||||
@@ -89,10 +91,8 @@ namespace data
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
|
||||
std::shared_ptr<const RouterInfo> GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||
@@ -124,6 +124,16 @@ namespace data
|
||||
|
||||
void ClearRouterInfos () { m_RouterInfos.clear (); };
|
||||
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
|
||||
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
|
||||
std::shared_ptr<RouterInfo::Address> NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); };
|
||||
boost::shared_ptr<RouterInfo::Addresses> NewRouterInfoAddresses ()
|
||||
{
|
||||
return boost::shared_ptr<RouterInfo::Addresses>(m_RouterInfoAddressVectorsPool.AcquireMt (),
|
||||
std::bind <void (i2p::util::MemoryPoolMt<RouterInfo::Addresses>::*)(RouterInfo::Addresses *)>
|
||||
(&i2p::util::MemoryPoolMt<RouterInfo::Addresses>::ReleaseMt,
|
||||
&m_RouterInfoAddressVectorsPool, std::placeholders::_1));
|
||||
};
|
||||
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
|
||||
|
||||
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
||||
|
||||
@@ -180,6 +190,9 @@ namespace data
|
||||
uint32_t m_PublishReplyToken = 0;
|
||||
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Addresses> m_RouterInfoAddressVectorsPool;
|
||||
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
|
||||
};
|
||||
|
||||
extern NetDb netdb;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Base.h"
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Profiling.h"
|
||||
|
||||
namespace i2p
|
||||
@@ -22,6 +23,7 @@ namespace data
|
||||
|
||||
RouterProfile::RouterProfile ():
|
||||
m_LastUpdateTime (boost::posix_time::second_clock::local_time()),
|
||||
m_LastDeclineTime (0),
|
||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
|
||||
m_NumTimesTaken (0), m_NumTimesRejected (0)
|
||||
{
|
||||
@@ -131,15 +133,23 @@ namespace data
|
||||
{
|
||||
UpdateTime ();
|
||||
if (ret > 0)
|
||||
{
|
||||
m_NumTunnelsDeclined++;
|
||||
m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_NumTunnelsAgreed++;
|
||||
m_LastDeclineTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterProfile::TunnelNonReplied ()
|
||||
{
|
||||
m_NumTunnelsNonReplied++;
|
||||
UpdateTime ();
|
||||
if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3)
|
||||
m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
}
|
||||
|
||||
bool RouterProfile::IsLowPartcipationRate () const
|
||||
@@ -153,8 +163,18 @@ namespace data
|
||||
return m_NumTunnelsNonReplied > 10*(total + 1);
|
||||
}
|
||||
|
||||
bool RouterProfile::IsDeclinedRecently ()
|
||||
{
|
||||
if (!m_LastDeclineTime) return false;
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (ts > m_LastDeclineTime + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL)
|
||||
m_LastDeclineTime = 0;
|
||||
return m_LastDeclineTime;
|
||||
}
|
||||
|
||||
bool RouterProfile::IsBad ()
|
||||
{
|
||||
if (IsDeclinedRecently ()) return true;
|
||||
auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/;
|
||||
if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -31,6 +31,7 @@ namespace data
|
||||
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days)
|
||||
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day)
|
||||
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours)
|
||||
const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes)
|
||||
|
||||
class RouterProfile
|
||||
{
|
||||
@@ -55,10 +56,12 @@ namespace data
|
||||
bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; };
|
||||
bool IsLowPartcipationRate () const;
|
||||
bool IsLowReplyRate () const;
|
||||
bool IsDeclinedRecently ();
|
||||
|
||||
private:
|
||||
|
||||
boost::posix_time::ptime m_LastUpdateTime;
|
||||
boost::posix_time::ptime m_LastUpdateTime; // TODO: use std::chrono
|
||||
uint64_t m_LastDeclineTime; // in seconds
|
||||
// participation
|
||||
uint32_t m_NumTunnelsAgreed;
|
||||
uint32_t m_NumTunnelsDeclined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -29,7 +29,7 @@ namespace i2p
|
||||
RouterContext::RouterContext ():
|
||||
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
|
||||
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
|
||||
m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID)
|
||||
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -60,14 +60,9 @@ namespace i2p
|
||||
i2p::data::LocalRouterInfo routerInfo;
|
||||
routerInfo.SetRouterIdentity (GetIdentity ());
|
||||
uint16_t port; i2p::config::GetOption("port", port);
|
||||
if (!port)
|
||||
{
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
if (port == 9150) port = 9151; // Tor browser
|
||||
}
|
||||
if (!port) port = SelectRandomPort ();
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||
@@ -113,15 +108,14 @@ namespace i2p
|
||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||
}
|
||||
}
|
||||
if (ssu)
|
||||
{
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
|
||||
caps |= i2p::data::RouterInfo::eReachable; // R
|
||||
}
|
||||
if (ssu2)
|
||||
{
|
||||
if (ssu2Published)
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), port);
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
if (!ssu2Port) ssu2Port = port;
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
|
||||
@@ -131,7 +125,7 @@ namespace i2p
|
||||
}
|
||||
if (ipv6)
|
||||
{
|
||||
std::string host = "::1";
|
||||
std::string host;
|
||||
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
|
||||
i2p::config::GetOption("host", host);
|
||||
else
|
||||
@@ -142,6 +136,7 @@ namespace i2p
|
||||
|
||||
if (ntcp2)
|
||||
{
|
||||
bool added = false;
|
||||
if (ntcp2Published)
|
||||
{
|
||||
std::string ntcp2Host;
|
||||
@@ -149,25 +144,33 @@ namespace i2p
|
||||
i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host);
|
||||
else
|
||||
ntcp2Host = host;
|
||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
|
||||
if (!ntcp2Host.empty () && port)
|
||||
{
|
||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!added)
|
||||
{
|
||||
if (!ipv4) // no other ntcp2 addresses yet
|
||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||
}
|
||||
}
|
||||
if (ssu)
|
||||
{
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
|
||||
caps |= i2p::data::RouterInfo::eReachable; // R
|
||||
}
|
||||
if (ssu2)
|
||||
{
|
||||
bool added = false;
|
||||
if (ssu2Published)
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), port);
|
||||
else
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
if (!ssu2Port) ssu2Port = port;
|
||||
if (!host.empty () && ssu2Port)
|
||||
{
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
if (!ipv4) // no other ssu2 addresses yet
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
|
||||
@@ -192,6 +195,13 @@ namespace i2p
|
||||
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
|
||||
}
|
||||
|
||||
uint16_t RouterContext::SelectRandomPort () const
|
||||
{
|
||||
uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
if (port == 9150) port = 9151; // Tor browser
|
||||
return port;
|
||||
}
|
||||
|
||||
void RouterContext::UpdateRouterInfo ()
|
||||
{
|
||||
m_RouterInfo.CreateBuffer (m_Keys);
|
||||
@@ -230,7 +240,6 @@ namespace i2p
|
||||
if (status != m_Status)
|
||||
{
|
||||
m_Status = status;
|
||||
m_Error = eRouterErrorNone;
|
||||
switch (m_Status)
|
||||
{
|
||||
case eRouterStatusOK:
|
||||
@@ -239,6 +248,9 @@ namespace i2p
|
||||
case eRouterStatusFirewalled:
|
||||
SetUnreachable (true, false); // ipv4
|
||||
break;
|
||||
case eRouterStatusTesting:
|
||||
m_Error = eRouterErrorNone;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -258,6 +270,9 @@ namespace i2p
|
||||
case eRouterStatusFirewalled:
|
||||
SetUnreachable (false, true); // ipv6
|
||||
break;
|
||||
case eRouterStatusTesting:
|
||||
m_ErrorV6 = eRouterErrorNone;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -266,10 +281,12 @@ namespace i2p
|
||||
|
||||
void RouterContext::UpdatePort (int port)
|
||||
{
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
for (auto& address : *addresses)
|
||||
{
|
||||
if (!address->IsNTCP2 () && !address->IsSSU2 () && address->port != port)
|
||||
if (address && address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
|
||||
{
|
||||
address->port = port;
|
||||
updated = true;
|
||||
@@ -282,10 +299,12 @@ namespace i2p
|
||||
void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg)
|
||||
{
|
||||
if (!m_NTCP2Keys) return;
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
for (auto& address : *addresses)
|
||||
{
|
||||
if (address->IsNTCP2 () && (address->port != port || address->published != publish))
|
||||
if (address && address->IsNTCP2 () && (address->port != port || address->published != publish))
|
||||
{
|
||||
bool isAddr = v4 && address->IsV4 ();
|
||||
if (!isAddr && (v6 || ygg))
|
||||
@@ -297,12 +316,7 @@ namespace i2p
|
||||
}
|
||||
if (isAddr)
|
||||
{
|
||||
if (!port && !address->port)
|
||||
{
|
||||
// select random port only if address's port is not set
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
if (port == 9150) port = 9151; // Tor browser
|
||||
}
|
||||
if (!port && !address->port) port = SelectRandomPort ();
|
||||
if (port) address->port = port;
|
||||
address->published = publish;
|
||||
memcpy (address->i, m_NTCP2Keys->iv, 16);
|
||||
@@ -316,19 +330,22 @@ namespace i2p
|
||||
|
||||
void RouterContext::UpdateNTCP2Address (bool enable)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
bool found = false, updated = false;
|
||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||
for (auto& it: *addresses)
|
||||
{
|
||||
if ((*it)->IsNTCP2 ())
|
||||
if (it && it->IsNTCP2 ())
|
||||
{
|
||||
found = true;
|
||||
if (!enable)
|
||||
if (enable)
|
||||
{
|
||||
addresses.erase (it);
|
||||
updated= true;
|
||||
it->s = m_NTCP2Keys->staticPublicKey;
|
||||
memcpy (it->i, m_NTCP2Keys->iv, 16);
|
||||
}
|
||||
break;
|
||||
else
|
||||
it.reset ();
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (enable && !found)
|
||||
@@ -342,19 +359,33 @@ namespace i2p
|
||||
|
||||
void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
|
||||
{
|
||||
if (!m_SSU2Keys || (publish && !port)) return;
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
if (!m_SSU2Keys) return;
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
int newPort = 0;
|
||||
if (!port)
|
||||
{
|
||||
if (address->IsSSU2 () && (address->port != port || address->published != publish) &&
|
||||
for (const auto& address : *addresses)
|
||||
if (address && address->port)
|
||||
{
|
||||
newPort = address->port;
|
||||
break;
|
||||
}
|
||||
if (!newPort) newPort = SelectRandomPort ();
|
||||
}
|
||||
bool updated = false;
|
||||
for (auto& address : *addresses)
|
||||
{
|
||||
if (address && address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
|
||||
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
|
||||
{
|
||||
address->port = port;
|
||||
if (port) address->port = port;
|
||||
else if (!address->port) address->port = newPort;
|
||||
address->published = publish;
|
||||
if (publish)
|
||||
address->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||
address->caps |= (i2p::data::RouterInfo::eSSUIntroducer | i2p::data::RouterInfo::eSSUTesting);
|
||||
else
|
||||
address->caps &= ~i2p::data::RouterInfo::eSSUIntroducer;
|
||||
address->caps &= ~(i2p::data::RouterInfo::eSSUIntroducer | i2p::data::RouterInfo::eSSUTesting);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@@ -364,29 +395,41 @@ namespace i2p
|
||||
|
||||
void RouterContext::UpdateSSU2Address (bool enable)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
bool found = false, updated = false;
|
||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||
for (auto& it : *addresses)
|
||||
{
|
||||
if ((*it)->IsSSU2 ())
|
||||
if (it && it->IsSSU2 ())
|
||||
{
|
||||
found = true;
|
||||
if (!enable)
|
||||
if (enable)
|
||||
{
|
||||
addresses.erase (it);
|
||||
updated= true;
|
||||
it->s = m_SSU2Keys->staticPublicKey;
|
||||
it->i = m_SSU2Keys->intro;
|
||||
}
|
||||
break;
|
||||
else
|
||||
it.reset ();
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (enable && !found)
|
||||
{
|
||||
uint8_t addressCaps = 0;
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
|
||||
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
|
||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
if (ipv4) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV4);
|
||||
if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t addressCaps = 0;
|
||||
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
|
||||
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
if (updated)
|
||||
@@ -395,49 +438,85 @@ namespace i2p
|
||||
|
||||
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
||||
{
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
if (host.is_v4 ())
|
||||
{
|
||||
if (address->host != host && address->IsCompatible (host) &&
|
||||
!i2p::util::net::IsYggdrasilAddress (address->host))
|
||||
auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx];
|
||||
if (addr && addr->host != host)
|
||||
{
|
||||
address->host = host;
|
||||
if (host.is_v6 () && address->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
addr->host = host;
|
||||
updated = true;
|
||||
}
|
||||
addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx];
|
||||
if (addr && addr->host != host)
|
||||
{
|
||||
addr->host = host;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
else if (host.is_v6 ())
|
||||
{
|
||||
auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx];
|
||||
if (addr && addr->host != host)
|
||||
{
|
||||
addr->host = host;
|
||||
updated = true;
|
||||
}
|
||||
addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx];
|
||||
if (addr && (addr->host != host || !addr->ssu->mtu))
|
||||
{
|
||||
addr->host = host;
|
||||
if (m_StatusV6 != eRouterStatusProxy)
|
||||
{
|
||||
// update MTU
|
||||
auto mtu = i2p::util::net::GetMTU (host);
|
||||
if (mtu)
|
||||
{
|
||||
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
|
||||
if (mtu > 1472) { // TODO: magic constant
|
||||
mtu = 1472;
|
||||
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of 1472 bytes");
|
||||
int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ());
|
||||
if (mtu > maxMTU)
|
||||
{
|
||||
mtu = maxMTU;
|
||||
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
|
||||
}
|
||||
if (address->ssu) address->ssu->mtu = mtu;
|
||||
addr->ssu->mtu = mtu;
|
||||
}
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
bool RouterContext::AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer)
|
||||
bool RouterContext::AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4)
|
||||
{
|
||||
bool ret = m_RouterInfo.AddIntroducer (introducer);
|
||||
bool ret = m_RouterInfo.AddSSU2Introducer (introducer, v4);
|
||||
if (ret)
|
||||
UpdateRouterInfo ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RouterContext::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e)
|
||||
void RouterContext::RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4)
|
||||
{
|
||||
if (m_RouterInfo.RemoveIntroducer (e))
|
||||
if (m_RouterInfo.RemoveSSU2Introducer (h, v4))
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::ClearSSU2Introducers (bool v4)
|
||||
{
|
||||
auto addr = m_RouterInfo.GetSSU2Address (v4);
|
||||
if (addr && !addr->ssu->introducers.empty ())
|
||||
{
|
||||
addr->ssu->introducers.clear ();
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::SetFloodfill (bool floodfill)
|
||||
{
|
||||
m_IsFloodfill = floodfill;
|
||||
@@ -536,22 +615,6 @@ namespace i2p
|
||||
return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
|
||||
}
|
||||
|
||||
void RouterContext::RemoveNTCPAddress (bool v4only)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
||||
{
|
||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
||||
(!v4only || (*it)->host.is_v4 ()))
|
||||
{
|
||||
it = addresses.erase (it);
|
||||
if (v4only) break; // otherwise might be more than one address
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::SetUnreachable (bool v4, bool v6)
|
||||
{
|
||||
if (v4 || (v6 && !SupportsV4 ()))
|
||||
@@ -566,15 +629,18 @@ namespace i2p
|
||||
}
|
||||
uint16_t port = 0;
|
||||
// delete previous introducers
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr : addresses)
|
||||
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = false;
|
||||
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (addresses)
|
||||
{
|
||||
for (auto& addr : *addresses)
|
||||
if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = false;
|
||||
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
}
|
||||
// unpublish NTCP2 addreeses
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
@@ -598,15 +664,19 @@ namespace i2p
|
||||
}
|
||||
uint16_t port = 0;
|
||||
// delete previous introducers
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr : addresses)
|
||||
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = true;
|
||||
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published);
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (addresses)
|
||||
{
|
||||
for (auto& addr : *addresses)
|
||||
if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = true;
|
||||
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||
addr->ssu->introducers.clear ();
|
||||
if (addr->port) port = addr->port;
|
||||
}
|
||||
}
|
||||
// publish NTCP2
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
@@ -629,39 +699,33 @@ namespace i2p
|
||||
if (supportsV6)
|
||||
{
|
||||
// insert v6 addresses if necessary
|
||||
bool foundSSU = false, foundNTCP2 = false, foundSSU2 = false;
|
||||
bool foundNTCP2 = false, foundSSU2 = false;
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (addresses)
|
||||
{
|
||||
if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
for (auto& addr: *addresses)
|
||||
{
|
||||
switch (addr->transportStyle)
|
||||
if (addr && addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
foundSSU = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
switch (addr->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if (addr) port = addr->port;
|
||||
}
|
||||
port = addr->port;
|
||||
}
|
||||
if (!port) i2p::config::GetOption("port", port);
|
||||
// SSU
|
||||
if (!foundSSU)
|
||||
if (!port)
|
||||
{
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
if (ssu)
|
||||
{
|
||||
std::string host = "::1"; // TODO: read host
|
||||
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
|
||||
}
|
||||
i2p::config::GetOption("port", port);
|
||||
if (!port) port = SelectRandomPort ();
|
||||
}
|
||||
// NTCP2
|
||||
if (!foundNTCP2)
|
||||
@@ -695,6 +759,7 @@ namespace i2p
|
||||
if (ssu2Published)
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
if (!ssu2Port) ssu2Port = port;
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("::1"), ssu2Port);
|
||||
}
|
||||
else
|
||||
@@ -716,37 +781,34 @@ namespace i2p
|
||||
// update
|
||||
if (supportsV4)
|
||||
{
|
||||
bool foundSSU = false, foundNTCP2 = false, foundSSU2 = false;
|
||||
bool foundNTCP2 = false, foundSSU2 = false;
|
||||
std::string host = "127.0.0.1";
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (addresses)
|
||||
{
|
||||
if (addr->IsV4 ())
|
||||
for (auto& addr: *addresses)
|
||||
{
|
||||
switch (addr->transportStyle)
|
||||
if (addr && addr->IsV4 ())
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
foundSSU = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
switch (addr->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if (addr && addr->port) port = addr->port;
|
||||
}
|
||||
if (addr->port) port = addr->port;
|
||||
}
|
||||
if (!port) i2p::config::GetOption("port", port);
|
||||
// SSU
|
||||
if (!foundSSU)
|
||||
if (!port)
|
||||
{
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
if (ssu)
|
||||
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
|
||||
i2p::config::GetOption("port", port);
|
||||
if (!port) port = SelectRandomPort ();
|
||||
}
|
||||
// NTCP2
|
||||
if (!foundNTCP2)
|
||||
@@ -775,10 +837,11 @@ namespace i2p
|
||||
if (ssu2Published)
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
if (!ssu2Port) ssu2Port = port;
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("127.0.0.1"), ssu2Port);
|
||||
}
|
||||
else
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6);
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV4);
|
||||
}
|
||||
}
|
||||
m_RouterInfo.EnableV4 ();
|
||||
@@ -792,37 +855,56 @@ namespace i2p
|
||||
{
|
||||
if (supportsmesh)
|
||||
{
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
m_RouterInfo.EnableMesh ();
|
||||
if ((*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]) return; // we have mesh address already
|
||||
uint16_t port = 0;
|
||||
i2p::config::GetOption ("ntcp2.port", port);
|
||||
if (!port) i2p::config::GetOption("port", port);
|
||||
bool foundMesh = false;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
if (!port)
|
||||
{
|
||||
if (!port) port = addr->port;
|
||||
if (i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
for (auto& addr: *addresses)
|
||||
{
|
||||
foundMesh = true;
|
||||
break;
|
||||
if (addr && addr->port)
|
||||
{
|
||||
port = addr->port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundMesh)
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
|
||||
if (!port) port = SelectRandomPort ();
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
|
||||
}
|
||||
else
|
||||
m_RouterInfo.DisableMesh ();
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::SetMTU (int mtu, bool v4)
|
||||
{
|
||||
if (mtu < 1280 || mtu > 1500) return;
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
for (auto& addr: *addresses)
|
||||
{
|
||||
if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
||||
{
|
||||
addr->ssu->mtu = mtu;
|
||||
LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
|
||||
bool updated = false;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
auto addresses = m_RouterInfo.GetAddresses ();
|
||||
if (!addresses) return;
|
||||
for (auto& addr: *addresses)
|
||||
{
|
||||
if (addr->IsPublishedNTCP2 ())
|
||||
if (addr && addr->IsPublishedNTCP2 ())
|
||||
{
|
||||
bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host);
|
||||
if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1)))
|
||||
|
||||
@@ -37,10 +37,9 @@ namespace garlic
|
||||
eRouterStatusOK = 0,
|
||||
eRouterStatusTesting = 1,
|
||||
eRouterStatusFirewalled = 2,
|
||||
eRouterStatusError = 3,
|
||||
eRouterStatusUnknown = 4,
|
||||
eRouterStatusProxy = 5,
|
||||
eRouterStatusMesh = 6
|
||||
eRouterStatusUnknown = 3,
|
||||
eRouterStatusProxy = 4,
|
||||
eRouterStatusMesh = 5
|
||||
};
|
||||
|
||||
enum RouterError
|
||||
@@ -48,7 +47,9 @@ namespace garlic
|
||||
eRouterErrorNone = 0,
|
||||
eRouterErrorClockSkew = 1,
|
||||
eRouterErrorOffline = 2,
|
||||
eRouterErrorSymmetricNAT = 3
|
||||
eRouterErrorSymmetricNAT = 3,
|
||||
eRouterErrorFullConeNAT = 4,
|
||||
eRouterErrorNoDescriptors = 5
|
||||
};
|
||||
|
||||
class RouterContext: public i2p::garlic::GarlicDestination
|
||||
@@ -104,9 +105,11 @@ namespace garlic
|
||||
RouterStatus GetStatus () const { return m_Status; };
|
||||
void SetStatus (RouterStatus status);
|
||||
RouterError GetError () const { return m_Error; };
|
||||
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
|
||||
void SetError (RouterError error) { m_Error = error; };
|
||||
RouterStatus GetStatusV6 () const { return m_StatusV6; };
|
||||
void SetStatusV6 (RouterStatus status);
|
||||
RouterError GetErrorV6 () const { return m_ErrorV6; };
|
||||
void SetErrorV6 (RouterError error) { m_ErrorV6 = error; };
|
||||
int GetNetID () const { return m_NetID; };
|
||||
void SetNetID (int netID) { m_NetID = netID; };
|
||||
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data);
|
||||
@@ -118,9 +121,9 @@ namespace garlic
|
||||
void UpdateNTCP2Address (bool enable);
|
||||
void PublishSSU2Address (int port, bool publish, bool v4, bool v6);
|
||||
void UpdateSSU2Address (bool enable);
|
||||
void RemoveNTCPAddress (bool v4only = true); // delete NTCP address for older routers. TODO: remove later
|
||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
bool AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4);
|
||||
void RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4);
|
||||
void ClearSSU2Introducers (bool v4);
|
||||
bool IsUnreachable () const;
|
||||
void SetUnreachable (bool v4, bool v6);
|
||||
void SetReachable (bool v4, bool v6);
|
||||
@@ -139,6 +142,7 @@ namespace garlic
|
||||
void SetSupportsV6 (bool supportsV6);
|
||||
void SetSupportsV4 (bool supportsV4);
|
||||
void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host);
|
||||
void SetMTU (int mtu, bool v4);
|
||||
i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; };
|
||||
|
||||
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove
|
||||
@@ -173,8 +177,10 @@ namespace garlic
|
||||
void UpdateRouterInfo ();
|
||||
void NewNTCP2Keys ();
|
||||
void NewSSU2Keys ();
|
||||
bool IsSSU2Only () const; // SSU2 and no SSU
|
||||
bool Load ();
|
||||
void SaveKeys ();
|
||||
uint16_t SelectRandomPort () const;
|
||||
|
||||
bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize);
|
||||
|
||||
@@ -190,7 +196,7 @@ namespace garlic
|
||||
uint64_t m_BandwidthLimit; // allowed bandwidth
|
||||
int m_ShareRatio;
|
||||
RouterStatus m_Status, m_StatusV6;
|
||||
RouterError m_Error;
|
||||
RouterError m_Error, m_ErrorV6;
|
||||
int m_NetID;
|
||||
std::mutex m_GarlicMutex;
|
||||
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -206,26 +206,24 @@ namespace data
|
||||
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
|
||||
m_Timestamp = be64toh (m_Timestamp);
|
||||
// read addresses
|
||||
auto addresses = boost::make_shared<Addresses>();
|
||||
auto addresses = NewAddresses ();
|
||||
uint8_t numAddresses;
|
||||
s.read ((char *)&numAddresses, sizeof (numAddresses));
|
||||
addresses->reserve (numAddresses);
|
||||
for (int i = 0; i < numAddresses; i++)
|
||||
{
|
||||
uint8_t supportedTransports = 0;
|
||||
auto address = std::make_shared<Address> ();
|
||||
auto address = NewAddress ();
|
||||
uint8_t cost; // ignore
|
||||
s.read ((char *)&cost, sizeof (cost));
|
||||
s.read ((char *)&address->date, sizeof (address->date));
|
||||
bool isHost = false, isIntroKey = false, isStaticKey = false, isV2 = false;
|
||||
Tag<32> iV2; // for 'i' field in SSU, TODO: remove later
|
||||
bool isHost = false, isStaticKey = false, isV2 = false;
|
||||
char transportStyle[6];
|
||||
ReadString (transportStyle, 6, s);
|
||||
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
||||
address->transportStyle = eTransportNTCP;
|
||||
address->transportStyle = eTransportNTCP2;
|
||||
else if (!strncmp (transportStyle, "SSU", 3)) // SSU or SSU2
|
||||
{
|
||||
address->transportStyle = (transportStyle[3] == '2') ? eTransportSSU2 : eTransportSSU;
|
||||
address->transportStyle = eTransportSSU2;
|
||||
address->ssu.reset (new SSUExt ());
|
||||
address->ssu->mtu = 0;
|
||||
}
|
||||
@@ -257,20 +255,31 @@ namespace data
|
||||
if (!ecode && !address->host.is_unspecified ()) isHost = true;
|
||||
}
|
||||
else if (!strcmp (key, "port"))
|
||||
address->port = boost::lexical_cast<int>(value);
|
||||
{
|
||||
try
|
||||
{
|
||||
address->port = boost::lexical_cast<int>(value);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "mtu"))
|
||||
{
|
||||
if (address->ssu)
|
||||
address->ssu->mtu = boost::lexical_cast<int>(value);
|
||||
{
|
||||
try
|
||||
{
|
||||
address->ssu->mtu = boost::lexical_cast<int>(value);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP");
|
||||
}
|
||||
else if (!strcmp (key, "key"))
|
||||
{
|
||||
if (address->ssu)
|
||||
isIntroKey = (Base64ToByteStream (value, strlen (value), address->i, 32) == 32);
|
||||
else
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP");
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2");
|
||||
}
|
||||
else if (!strcmp (key, "caps"))
|
||||
address->caps = ExtractAddressCaps (value);
|
||||
@@ -288,8 +297,6 @@ namespace data
|
||||
}
|
||||
else if (address->IsSSU2 ())
|
||||
Base64ToByteStream (value, strlen (value), address->i, 32);
|
||||
else
|
||||
Base64ToByteStream (value, strlen (value), iV2, 32);
|
||||
}
|
||||
else if (!strcmp (key, "v"))
|
||||
{
|
||||
@@ -322,22 +329,40 @@ namespace data
|
||||
}
|
||||
Introducer& introducer = address->ssu->introducers.at (index);
|
||||
if (!strcmp (key, "ihost"))
|
||||
{
|
||||
boost::system::error_code ecode;
|
||||
introducer.iHost = boost::asio::ip::address::from_string (value, ecode);
|
||||
}
|
||||
introducer.isH = false; // SSU1
|
||||
else if (!strcmp (key, "iport"))
|
||||
introducer.iPort = boost::lexical_cast<int>(value);
|
||||
introducer.isH = false; // SSU1
|
||||
else if (!strcmp (key, "itag"))
|
||||
introducer.iTag = boost::lexical_cast<uint32_t>(value);
|
||||
else if (!strcmp (key, "ikey") || !strcmp (key, "ih"))
|
||||
Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
|
||||
{
|
||||
try
|
||||
{
|
||||
introducer.iTag = boost::lexical_cast<uint32_t>(value);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "ih"))
|
||||
{
|
||||
Base64ToByteStream (value, strlen (value), introducer.iH, 32);
|
||||
introducer.isH = true;
|
||||
}
|
||||
else if (!strcmp (key, "iexp"))
|
||||
introducer.iExp = boost::lexical_cast<uint32_t>(value);
|
||||
{
|
||||
try
|
||||
{
|
||||
introducer.iExp = boost::lexical_cast<uint32_t>(value);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!s) return;
|
||||
}
|
||||
if (address->transportStyle == eTransportNTCP)
|
||||
if (address->transportStyle == eTransportNTCP2)
|
||||
{
|
||||
if (isStaticKey)
|
||||
{
|
||||
@@ -361,46 +386,7 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (address->transportStyle == eTransportSSU)
|
||||
{
|
||||
if (isIntroKey)
|
||||
{
|
||||
if (isHost)
|
||||
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
|
||||
else if (address->caps & AddressCaps::eV6)
|
||||
{
|
||||
supportedTransports |= eSSUV6;
|
||||
if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6
|
||||
}
|
||||
else
|
||||
supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4
|
||||
if (address->ssu && !address->ssu->introducers.empty ())
|
||||
{
|
||||
// exclude invalid introducers
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
int numValid = 0;
|
||||
for (auto& it: address->ssu->introducers)
|
||||
{
|
||||
if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT;
|
||||
if (ts <= it.iExp && it.iPort > 0 &&
|
||||
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
|
||||
numValid++;
|
||||
else
|
||||
it.iPort = 0;
|
||||
}
|
||||
if (numValid)
|
||||
m_ReachableTransports |= supportedTransports;
|
||||
else
|
||||
address->ssu->introducers.resize (0);
|
||||
}
|
||||
else if (isHost && address->port)
|
||||
{
|
||||
address->published = true;
|
||||
m_ReachableTransports |= supportedTransports;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (address->transportStyle == eTransportSSU2 || (isV2 && address->transportStyle == eTransportSSU))
|
||||
else if (address->transportStyle == eTransportSSU2 && isV2)
|
||||
{
|
||||
if (address->IsV4 ()) supportedTransports |= eSSU2V4;
|
||||
if (address->IsV6 ()) supportedTransports |= eSSU2V6;
|
||||
@@ -408,32 +394,38 @@ namespace data
|
||||
{
|
||||
if (address->host.is_v4 ()) m_ReachableTransports |= eSSU2V4;
|
||||
if (address->host.is_v6 ()) m_ReachableTransports |= eSSU2V6;
|
||||
address->published = true;
|
||||
}
|
||||
if (address->ssu && !address->ssu->introducers.empty ())
|
||||
{
|
||||
// exclude invalid introducers
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
int numValid = 0;
|
||||
for (auto& it: address->ssu->introducers)
|
||||
{
|
||||
if (it.iTag && ts < it.iExp && it.isH)
|
||||
numValid++;
|
||||
else
|
||||
it.iTag = 0;
|
||||
}
|
||||
if (numValid)
|
||||
m_ReachableTransports |= supportedTransports;
|
||||
else
|
||||
address->ssu->introducers.resize (0);
|
||||
}
|
||||
}
|
||||
if (supportedTransports)
|
||||
{
|
||||
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
|
||||
{
|
||||
addresses->push_back(address);
|
||||
if (address->transportStyle == eTransportSSU && isV2)
|
||||
{
|
||||
// create additional SSU2 address. TODO: remove later
|
||||
auto ssu2addr = std::make_shared<Address> ();
|
||||
ssu2addr->transportStyle = eTransportSSU2;
|
||||
ssu2addr->host = address->host; ssu2addr->port = address->port;
|
||||
ssu2addr->s = address->s; ssu2addr->i = iV2;
|
||||
ssu2addr->date = address->date; ssu2addr->caps = address->caps;
|
||||
ssu2addr->published = address->published;
|
||||
ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu;
|
||||
for (const auto& introducer: address->ssu->introducers)
|
||||
if (!introducer.iPort) // SSU2
|
||||
ssu2addr->ssu->introducers.push_back (introducer);
|
||||
addresses->push_back(ssu2addr);
|
||||
}
|
||||
for (uint8_t i = 0; i < eNumTransports; i++)
|
||||
if ((1 << i) & supportedTransports)
|
||||
(*addresses)[i] = address;
|
||||
}
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
}
|
||||
}
|
||||
// update addresses
|
||||
#if (BOOST_VERSION >= 105300)
|
||||
boost::atomic_store (&m_Addresses, addresses);
|
||||
#else
|
||||
@@ -562,10 +554,10 @@ namespace data
|
||||
case CAPS_FLAG_V6:
|
||||
caps |= AddressCaps::eV6;
|
||||
break;
|
||||
case CAPS_FLAG_SSU_TESTING:
|
||||
case CAPS_FLAG_SSU2_TESTING:
|
||||
caps |= AddressCaps::eSSUTesting;
|
||||
break;
|
||||
case CAPS_FLAG_SSU_INTRODUCER:
|
||||
case CAPS_FLAG_SSU2_INTRODUCER:
|
||||
caps |= AddressCaps::eSSUIntroducer;
|
||||
break;
|
||||
default: ;
|
||||
@@ -628,36 +620,13 @@ namespace data
|
||||
return l+1;
|
||||
}
|
||||
|
||||
|
||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportSSU;
|
||||
addr->published = true;
|
||||
addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC;
|
||||
addr->date = 0;
|
||||
addr->ssu.reset (new SSUExt ());
|
||||
addr->ssu->mtu = mtu;
|
||||
if (key)
|
||||
memcpy (addr->i, key, 32);
|
||||
else
|
||||
RAND_bytes (addr->i, 32);
|
||||
for (const auto& it: *m_Addresses) // don't insert same address twice
|
||||
if (*it == *addr) return;
|
||||
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
|
||||
m_ReachableTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
|
||||
const boost::asio::ip::address& host, int port, uint8_t caps)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->host = host;
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->transportStyle = eTransportNTCP2;
|
||||
addr->caps = caps;
|
||||
addr->date = 0;
|
||||
if (port) addr->published = true;
|
||||
@@ -667,28 +636,46 @@ namespace data
|
||||
{
|
||||
m_SupportedTransports |= eNTCP2V4;
|
||||
if (addr->published) m_ReachableTransports |= eNTCP2V4;
|
||||
(*m_Addresses)[eNTCP2V4Idx] = addr;
|
||||
}
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
m_SupportedTransports |= eNTCP2V6;
|
||||
if (addr->published) m_ReachableTransports |= eNTCP2V6;
|
||||
if (i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
{
|
||||
m_SupportedTransports |= eNTCP2V6Mesh;
|
||||
m_ReachableTransports |= eNTCP2V6Mesh;
|
||||
(*m_Addresses)[eNTCP2V6MeshIdx] = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SupportedTransports |= eNTCP2V6;
|
||||
if (addr->published) m_ReachableTransports |= eNTCP2V6;
|
||||
(*m_Addresses)[eNTCP2V6Idx] = addr;
|
||||
}
|
||||
}
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->transportStyle = eTransportSSU2;
|
||||
addr->port = 0;
|
||||
addr->caps = caps;
|
||||
addr->date = 0;
|
||||
addr->ssu.reset (new SSUExt ());
|
||||
addr->ssu->mtu = 0;
|
||||
memcpy (addr->s, staticKey, 32);
|
||||
memcpy (addr->i, introKey, 32);
|
||||
if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4;
|
||||
if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6;
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
if (addr->IsV4 ())
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V4;
|
||||
(*m_Addresses)[eSSU2V4Idx] = addr;
|
||||
}
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V6;
|
||||
(*m_Addresses)[eSSU2V6Idx] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
|
||||
@@ -699,7 +686,7 @@ namespace data
|
||||
addr->host = host;
|
||||
addr->port = port;
|
||||
addr->published = true;
|
||||
addr->caps = 0;
|
||||
addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC;
|
||||
addr->date = 0;
|
||||
addr->ssu.reset (new SSUExt ());
|
||||
addr->ssu->mtu = 0;
|
||||
@@ -709,58 +696,14 @@ namespace data
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V4;
|
||||
m_ReachableTransports |= eSSU2V4;
|
||||
(*m_Addresses)[eSSU2V4Idx] = addr;
|
||||
}
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V6;
|
||||
m_ReachableTransports |= eSSU2V6;
|
||||
(*m_Addresses)[eSSU2V6Idx] = addr;
|
||||
}
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
bool RouterInfo::AddIntroducer (const Introducer& introducer)
|
||||
{
|
||||
for (auto& addr : *m_Addresses)
|
||||
{
|
||||
if (addr->transportStyle == eTransportSSU &&
|
||||
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
|
||||
{
|
||||
for (auto& intro: addr->ssu->introducers)
|
||||
if (intro.iTag == introducer.iTag) return false; // already presented
|
||||
addr->ssu->introducers.push_back (introducer);
|
||||
m_ReachableTransports |= (addr->IsV4 () ? eSSUV4 : eSSUV6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e)
|
||||
{
|
||||
for (auto& addr: *m_Addresses)
|
||||
{
|
||||
if (addr->transportStyle == eTransportSSU &&
|
||||
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
|
||||
{
|
||||
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
|
||||
if (boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
|
||||
{
|
||||
addr->ssu->introducers.erase (it);
|
||||
if (addr->ssu->introducers.empty ())
|
||||
m_ReachableTransports &= ~(addr->IsV4 () ? eSSUV4 : eSSUV6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RouterInfo::IsSSU (bool v4only) const
|
||||
{
|
||||
if (v4only)
|
||||
return m_SupportedTransports & eSSUV4;
|
||||
else
|
||||
return m_SupportedTransports & (eSSUV4 | eSSUV6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsNTCP2 (bool v4only) const
|
||||
@@ -799,21 +742,17 @@ namespace data
|
||||
{
|
||||
if (IsV6 ())
|
||||
{
|
||||
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
||||
if ((*m_Addresses)[eNTCP2V6Idx])
|
||||
{
|
||||
auto addr = *it;
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
if (addr->IsV4 ())
|
||||
{
|
||||
addr->caps &= ~AddressCaps::eV6;
|
||||
++it;
|
||||
}
|
||||
else
|
||||
it = m_Addresses->erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 ())
|
||||
(*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV6;
|
||||
(*m_Addresses)[eNTCP2V6Idx].reset ();
|
||||
}
|
||||
if ((*m_Addresses)[eSSU2V6Idx])
|
||||
{
|
||||
if ((*m_Addresses)[eSSU2V6Idx]->IsV4 ())
|
||||
(*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV6;
|
||||
(*m_Addresses)[eSSU2V6Idx].reset ();
|
||||
}
|
||||
UpdateSupportedTransports ();
|
||||
}
|
||||
@@ -823,21 +762,17 @@ namespace data
|
||||
{
|
||||
if (IsV4 ())
|
||||
{
|
||||
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
||||
if ((*m_Addresses)[eNTCP2V4Idx])
|
||||
{
|
||||
auto addr = *it;
|
||||
if (addr->IsV4 ())
|
||||
{
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
addr->caps &= ~AddressCaps::eV4;
|
||||
++it;
|
||||
}
|
||||
else
|
||||
it = m_Addresses->erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 ())
|
||||
(*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV4;
|
||||
(*m_Addresses)[eNTCP2V4Idx].reset ();
|
||||
}
|
||||
if ((*m_Addresses)[eSSU2V4Idx])
|
||||
{
|
||||
if ((*m_Addresses)[eSSU2V4Idx]->IsV6 ())
|
||||
(*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV4;
|
||||
(*m_Addresses)[eSSU2V4Idx].reset ();
|
||||
}
|
||||
UpdateSupportedTransports ();
|
||||
}
|
||||
@@ -858,51 +793,42 @@ namespace data
|
||||
{
|
||||
m_SupportedTransports &= ~eNTCP2V6Mesh;
|
||||
m_ReachableTransports &= ~eNTCP2V6Mesh;
|
||||
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
||||
{
|
||||
auto addr = *it;
|
||||
if (i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
it = m_Addresses->erase (it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
(*m_Addresses)[eNTCP2V6MeshIdx].reset ();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (
|
||||
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && (!v4only || address->IsV4 ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUV6Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && address->IsV6();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU2) && address->IsV4();
|
||||
});
|
||||
return (*GetAddresses ())[eSSU2V4Idx];
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU2) && address->IsV6();
|
||||
});
|
||||
return (*GetAddresses ())[eSSU2V6Idx];
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const
|
||||
{
|
||||
if (v4)
|
||||
{
|
||||
if (m_SupportedTransports & eSSU2V4)
|
||||
return GetSSU2V4Address ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_SupportedTransports & eSSU2V6)
|
||||
return GetSSU2V6Address ();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
boost::shared_ptr<RouterInfo::Addresses> RouterInfo::GetAddresses () const
|
||||
{
|
||||
#if (BOOST_VERSION >= 105300)
|
||||
return boost::atomic_load (&m_Addresses);
|
||||
#else
|
||||
return m_Addresses;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Filter>
|
||||
@@ -915,7 +841,7 @@ namespace data
|
||||
auto addresses = m_Addresses;
|
||||
#endif
|
||||
for (const auto& address : *addresses)
|
||||
if (filter (address)) return address;
|
||||
if (address && filter (address)) return address;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -933,39 +859,29 @@ namespace data
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const
|
||||
{
|
||||
if (!key) return nullptr;
|
||||
return GetAddress (
|
||||
[key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsSSU2 () && !memcmp (address->s, key, 32) && address->IsV6 () == isV6;
|
||||
});
|
||||
auto addr = (*GetAddresses ())[isV6 ? eSSU2V6Idx : eSSU2V4Idx];
|
||||
if (addr && !memcmp (addr->s, key, 32))
|
||||
return addr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsPublishedNTCP2 () && address->host.is_v4 ();
|
||||
});
|
||||
auto addr = (*GetAddresses ())[eNTCP2V4Idx];
|
||||
if (addr && addr->IsPublishedNTCP2 ()) return addr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
|
||||
!i2p::util::net::IsYggdrasilAddress (address->host);
|
||||
});
|
||||
auto addr = (*GetAddresses ())[eNTCP2V6Idx];
|
||||
if (addr && addr->IsPublishedNTCP2 ()) return addr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
|
||||
});
|
||||
return (*GetAddresses ())[eNTCP2V6MeshIdx];
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const
|
||||
@@ -985,49 +901,29 @@ namespace data
|
||||
bool RouterInfo::IsEligibleFloodfill () const
|
||||
{
|
||||
// floodfill must be reachable by ipv4, >= 0.9.38 and not DSA
|
||||
return IsReachableBy (eNTCP2V4 | eSSUV4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION &&
|
||||
return IsReachableBy (eNTCP2V4 | eSSU2V4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION &&
|
||||
GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1;
|
||||
}
|
||||
|
||||
bool RouterInfo::IsPeerTesting (bool v4) const
|
||||
{
|
||||
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
|
||||
return (bool)GetAddress (
|
||||
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && address->IsPeerTesting () &&
|
||||
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
|
||||
});
|
||||
}
|
||||
|
||||
bool RouterInfo::IsSSU2PeerTesting (bool v4) const
|
||||
{
|
||||
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
|
||||
return (bool)GetAddress (
|
||||
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->IsSSU2 ()) && address->IsPeerTesting () &&
|
||||
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
|
||||
});
|
||||
auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx];
|
||||
return addr && addr->IsPeerTesting () && addr->IsReachableSSU ();
|
||||
}
|
||||
|
||||
bool RouterInfo::IsIntroducer (bool v4) const
|
||||
bool RouterInfo::IsSSU2Introducer (bool v4) const
|
||||
{
|
||||
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
|
||||
return (bool)GetAddress (
|
||||
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && address->IsIntroducer () &&
|
||||
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified ();
|
||||
});
|
||||
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
|
||||
auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx];
|
||||
return addr && addr->IsIntroducer () && !addr->host.is_unspecified () && addr->port;
|
||||
}
|
||||
|
||||
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
|
||||
{
|
||||
for (auto& addr: *m_Addresses)
|
||||
{
|
||||
// TODO: implement SSU
|
||||
if (!addr->published && (addr->transportStyle == eTransportNTCP || addr->transportStyle == eTransportSSU2))
|
||||
if (addr && !addr->published)
|
||||
{
|
||||
addr->caps &= ~(eV4 | eV6);
|
||||
addr->caps |= transports;
|
||||
@@ -1041,21 +937,24 @@ namespace data
|
||||
m_ReachableTransports = 0;
|
||||
for (const auto& addr: *m_Addresses)
|
||||
{
|
||||
if (!addr) continue;
|
||||
uint8_t transports = 0;
|
||||
if (addr->transportStyle == eTransportNTCP)
|
||||
switch (addr->transportStyle)
|
||||
{
|
||||
if (addr->IsV4 ()) transports |= eNTCP2V4;
|
||||
if (addr->IsV6 ())
|
||||
transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6);
|
||||
if (addr->IsPublishedNTCP2 ())
|
||||
m_ReachableTransports |= transports;
|
||||
}
|
||||
else if (addr->transportStyle == eTransportSSU)
|
||||
{
|
||||
if (addr->IsV4 ()) transports |= eSSUV4;
|
||||
if (addr->IsV6 ()) transports |= eSSUV6;
|
||||
if (addr->IsReachableSSU ())
|
||||
m_ReachableTransports |= transports;
|
||||
case eTransportNTCP2:
|
||||
if (addr->IsV4 ()) transports |= eNTCP2V4;
|
||||
if (addr->IsV6 ())
|
||||
transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6);
|
||||
if (addr->IsPublishedNTCP2 ())
|
||||
m_ReachableTransports |= transports;
|
||||
break;
|
||||
case eTransportSSU2:
|
||||
if (addr->IsV4 ()) transports |= eSSU2V4;
|
||||
if (addr->IsV6 ()) transports |= eSSU2V6;
|
||||
if (addr->IsReachableSSU ())
|
||||
m_ReachableTransports |= transports;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
m_SupportedTransports |= transports;
|
||||
}
|
||||
@@ -1075,6 +974,16 @@ namespace data
|
||||
return netdb.NewRouterInfoBuffer ();
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterInfo::Address> RouterInfo::NewAddress () const
|
||||
{
|
||||
return netdb.NewRouterInfoAddress ();
|
||||
}
|
||||
|
||||
boost::shared_ptr<RouterInfo::Addresses> RouterInfo::NewAddresses () const
|
||||
{
|
||||
return netdb.NewRouterInfoAddresses ();
|
||||
}
|
||||
|
||||
void RouterInfo::RefreshTimestamp ()
|
||||
{
|
||||
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
@@ -1136,29 +1045,42 @@ namespace data
|
||||
|
||||
void LocalRouterInfo::WriteToStream (std::ostream& s) const
|
||||
{
|
||||
auto addresses = GetAddresses ();
|
||||
if (!addresses) return;
|
||||
|
||||
uint64_t ts = htobe64 (GetTimestamp ());
|
||||
s.write ((const char *)&ts, sizeof (ts));
|
||||
|
||||
// addresses
|
||||
const Addresses& addresses = GetAddresses ();
|
||||
uint8_t numAddresses = addresses.size ();
|
||||
s.write ((char *)&numAddresses, sizeof (numAddresses));
|
||||
for (const auto& addr_ptr : addresses)
|
||||
uint8_t numAddresses = 0;
|
||||
for (size_t idx = 0; idx < addresses->size(); idx++)
|
||||
{
|
||||
auto addr_ptr = (*addresses)[idx];
|
||||
if (!addr_ptr) continue;
|
||||
if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
|
||||
if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
|
||||
numAddresses++;
|
||||
}
|
||||
s.write ((char *)&numAddresses, sizeof (numAddresses));
|
||||
for (size_t idx = 0; idx < addresses->size(); idx++)
|
||||
{
|
||||
auto addr_ptr = (*addresses)[idx];
|
||||
if (!addr_ptr) continue;
|
||||
if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
|
||||
if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
|
||||
const Address& address = *addr_ptr;
|
||||
// calculate cost
|
||||
uint8_t cost = 0x7f;
|
||||
if (address.transportStyle == eTransportNTCP)
|
||||
if (address.transportStyle == eTransportNTCP2)
|
||||
cost = address.published ? COST_NTCP2_PUBLISHED : COST_NTCP2_NON_PUBLISHED;
|
||||
else if (address.transportStyle == eTransportSSU)
|
||||
cost = address.published ? COST_SSU_DIRECT : COST_SSU_THROUGH_INTRODUCERS;
|
||||
else if (address.transportStyle == eTransportSSU2)
|
||||
cost = address.published ? COST_SSU2_DIRECT : COST_SSU2_NON_PUBLISHED;
|
||||
else
|
||||
continue; // skip unknown address
|
||||
s.write ((const char *)&cost, sizeof (cost));
|
||||
s.write ((const char *)&address.date, sizeof (address.date));
|
||||
std::stringstream properties;
|
||||
bool isPublished = false;
|
||||
if (address.transportStyle == eTransportNTCP)
|
||||
if (address.transportStyle == eTransportNTCP2)
|
||||
{
|
||||
if (address.IsNTCP2 ())
|
||||
{
|
||||
@@ -1180,43 +1102,6 @@ namespace data
|
||||
else
|
||||
continue; // don't write NTCP address
|
||||
}
|
||||
else if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
WriteString ("SSU", s);
|
||||
// caps
|
||||
WriteString ("caps", properties);
|
||||
properties << '=';
|
||||
std::string caps;
|
||||
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
|
||||
if (address.host.is_v4 ())
|
||||
{
|
||||
if (address.published)
|
||||
{
|
||||
isPublished = true;
|
||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
||||
}
|
||||
else
|
||||
caps += CAPS_FLAG_V4;
|
||||
}
|
||||
else if (address.host.is_v6 ())
|
||||
{
|
||||
if (address.published)
|
||||
{
|
||||
isPublished = true;
|
||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
||||
}
|
||||
else
|
||||
caps += CAPS_FLAG_V6;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (address.IsV4 ()) caps += CAPS_FLAG_V4;
|
||||
if (address.IsV6 ()) caps += CAPS_FLAG_V6;
|
||||
if (caps.empty ()) caps += CAPS_FLAG_V4;
|
||||
}
|
||||
WriteString (caps, properties);
|
||||
properties << ';';
|
||||
}
|
||||
else if (address.transportStyle == eTransportSSU2)
|
||||
{
|
||||
WriteString ("SSU2", s);
|
||||
@@ -1225,7 +1110,8 @@ namespace data
|
||||
if (address.published)
|
||||
{
|
||||
isPublished = true;
|
||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
||||
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU2_TESTING;
|
||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU2_INTRODUCER;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1244,7 +1130,7 @@ namespace data
|
||||
else
|
||||
WriteString ("", s);
|
||||
|
||||
if (isPublished)
|
||||
if (isPublished && !address.host.is_unspecified ())
|
||||
{
|
||||
WriteString ("host", properties);
|
||||
properties << '=';
|
||||
@@ -1258,7 +1144,7 @@ namespace data
|
||||
size_t len = address.IsSSU2 () ? 32 : 16;
|
||||
WriteString (address.i.ToBase64 (len), properties); properties << ';';
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
|
||||
if (address.transportStyle == eTransportSSU2)
|
||||
{
|
||||
// write introducers if any
|
||||
if (address.ssu && !address.ssu->introducers.empty())
|
||||
@@ -1275,45 +1161,18 @@ namespace data
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (introducer.iHost.to_string (), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
if (address.IsSSU2 ())
|
||||
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
|
||||
else
|
||||
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
|
||||
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
char value[64];
|
||||
size_t l = ByteStreamToBase64 (introducer.iKey, 32, value, 64);
|
||||
size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64);
|
||||
value[l] = 0;
|
||||
WriteString (value, properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
WriteString ("iport" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (boost::lexical_cast<std::string>(introducer.iPort), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
@@ -1325,18 +1184,8 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
// write intro key
|
||||
WriteString ("key", properties);
|
||||
properties << '=';
|
||||
char value[64];
|
||||
size_t l = ByteStreamToBase64 (address.i, 32, value, 64);
|
||||
value[l] = 0;
|
||||
WriteString (value, properties);
|
||||
properties << ';';
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
|
||||
|
||||
if (address.transportStyle == eTransportSSU2)
|
||||
{
|
||||
// write mtu
|
||||
if (address.ssu && address.ssu->mtu)
|
||||
@@ -1347,7 +1196,7 @@ namespace data
|
||||
properties << ';';
|
||||
}
|
||||
}
|
||||
if (isPublished || (address.ssu && !address.IsSSU2 ()))
|
||||
if (isPublished && address.port)
|
||||
{
|
||||
WriteString ("port", properties);
|
||||
properties << '=';
|
||||
@@ -1415,5 +1264,50 @@ namespace data
|
||||
{
|
||||
return std::make_shared<Buffer> ();
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterInfo::Address> LocalRouterInfo::NewAddress () const
|
||||
{
|
||||
return std::make_shared<Address> ();
|
||||
}
|
||||
|
||||
boost::shared_ptr<RouterInfo::Addresses> LocalRouterInfo::NewAddresses () const
|
||||
{
|
||||
return boost::make_shared<Addresses> ();
|
||||
}
|
||||
|
||||
bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4)
|
||||
{
|
||||
auto addresses = GetAddresses ();
|
||||
if (!addresses) return false;
|
||||
auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx];
|
||||
if (addr)
|
||||
{
|
||||
for (auto& intro: addr->ssu->introducers)
|
||||
if (intro.iTag == introducer.iTag) return false; // already presented
|
||||
addr->ssu->introducers.push_back (introducer);
|
||||
SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4)
|
||||
{
|
||||
auto addresses = GetAddresses ();
|
||||
if (!addresses) return false;
|
||||
auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx];
|
||||
if (addr)
|
||||
{
|
||||
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
|
||||
if (h == it->iH)
|
||||
{
|
||||
addr->ssu->introducers.erase (it);
|
||||
if (addr->ssu->introducers.empty ())
|
||||
SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -47,14 +47,12 @@ namespace data
|
||||
|
||||
const char CAPS_FLAG_V4 = '4';
|
||||
const char CAPS_FLAG_V6 = '6';
|
||||
const char CAPS_FLAG_SSU_TESTING = 'B';
|
||||
const char CAPS_FLAG_SSU_INTRODUCER = 'C';
|
||||
const char CAPS_FLAG_SSU2_TESTING = 'B';
|
||||
const char CAPS_FLAG_SSU2_INTRODUCER = 'C';
|
||||
|
||||
const uint8_t COST_NTCP2_PUBLISHED = 3;
|
||||
const uint8_t COST_NTCP2_NON_PUBLISHED = 14;
|
||||
const uint8_t COST_SSU2_DIRECT = 8;
|
||||
const uint8_t COST_SSU_DIRECT = 9;
|
||||
const uint8_t COST_SSU_THROUGH_INTRODUCERS = 11;
|
||||
const uint8_t COST_SSU2_NON_PUBLISHED = 15;
|
||||
|
||||
const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later
|
||||
@@ -62,15 +60,25 @@ namespace data
|
||||
{
|
||||
public:
|
||||
|
||||
enum SupportedTransportsIdx
|
||||
{
|
||||
eNTCP2V4Idx = 0,
|
||||
eNTCP2V6Idx,
|
||||
eSSU2V4Idx,
|
||||
eSSU2V6Idx,
|
||||
eNTCP2V6MeshIdx,
|
||||
eNumTransports
|
||||
};
|
||||
|
||||
#define TransportBit(tr) e##tr = (1 << e##tr##Idx)
|
||||
|
||||
enum SupportedTransports
|
||||
{
|
||||
eNTCP2V4 = 0x01,
|
||||
eNTCP2V6 = 0x02,
|
||||
eSSUV4 = 0x04,
|
||||
eSSUV6 = 0x08,
|
||||
eNTCP2V6Mesh = 0x10,
|
||||
eSSU2V4 = 0x20,
|
||||
eSSU2V6 = 0x40,
|
||||
TransportBit(NTCP2V4), // 0x01
|
||||
TransportBit(NTCP2V6), // 0x02
|
||||
TransportBit(SSU2V4), // 0x04
|
||||
TransportBit(SSU2V6), // 0x08
|
||||
TransportBit(NTCP2V6Mesh), // 0x10
|
||||
eAllTransports = 0xFF
|
||||
};
|
||||
typedef uint8_t CompatibleTransports;
|
||||
@@ -96,20 +104,17 @@ namespace data
|
||||
enum TransportStyle
|
||||
{
|
||||
eTransportUnknown = 0,
|
||||
eTransportNTCP,
|
||||
eTransportSSU,
|
||||
eTransportNTCP2,
|
||||
eTransportSSU2
|
||||
};
|
||||
|
||||
typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey
|
||||
struct Introducer
|
||||
{
|
||||
Introducer (): iPort (0), iExp (0) {};
|
||||
boost::asio::ip::address iHost;
|
||||
int iPort;
|
||||
IntroKey iKey; // or ih for SSU2
|
||||
Introducer (): iTag (0), iExp (0), isH (false) {};
|
||||
IdentHash iH;
|
||||
uint32_t iTag;
|
||||
uint32_t iExp;
|
||||
bool isH; // TODO: remove later
|
||||
};
|
||||
|
||||
struct SSUExt
|
||||
@@ -146,7 +151,7 @@ namespace data
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
|
||||
bool IsNTCP2 () const { return transportStyle == eTransportNTCP2; };
|
||||
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
|
||||
bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; };
|
||||
bool IsReachableSSU () const { return (bool)ssu && (published || UsesIntroducer ()); };
|
||||
@@ -167,7 +172,7 @@ namespace data
|
||||
Buffer (const uint8_t * buf, size_t len);
|
||||
};
|
||||
|
||||
typedef std::vector<std::shared_ptr<Address> > Addresses;
|
||||
typedef std::array<std::shared_ptr<Address>, eNumTransports> Addresses;
|
||||
|
||||
RouterInfo (const std::string& fullPath);
|
||||
RouterInfo (const RouterInfo& ) = default;
|
||||
@@ -183,38 +188,32 @@ namespace data
|
||||
int GetVersion () const { return m_Version; };
|
||||
virtual void SetProperty (const std::string& key, const std::string& value) {};
|
||||
virtual void ClearProperties () {};
|
||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
||||
boost::shared_ptr<Addresses> GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr
|
||||
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
|
||||
std::shared_ptr<const Address> GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const;
|
||||
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
|
||||
std::shared_ptr<const Address> GetPublishedNTCP2V6Address () const;
|
||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||
std::shared_ptr<const Address> GetYggdrasilAddress () const;
|
||||
std::shared_ptr<const Address> GetSSU2V4Address () const;
|
||||
std::shared_ptr<const Address> GetSSU2V6Address () const;
|
||||
std::shared_ptr<const Address> GetSSU2Address (bool v4) const;
|
||||
|
||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
|
||||
const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0);
|
||||
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps = 0); // non published
|
||||
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
|
||||
const boost::asio::ip::address& host, int port); // published
|
||||
bool AddIntroducer (const Introducer& introducer);
|
||||
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
|
||||
void UpdateSupportedTransports ();
|
||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsSSUV6 () const { return m_SupportedTransports & eSSUV6; };
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };
|
||||
bool IsSSU2V4 () const { return m_SupportedTransports & eSSU2V4; };
|
||||
bool IsSSU2V6 () const { return m_SupportedTransports & eSSU2V6; };
|
||||
bool IsV6 () const { return m_SupportedTransports & (eSSUV6 | eNTCP2V6 | eSSU2V6); };
|
||||
bool IsV4 () const { return m_SupportedTransports & (eSSUV4 | eNTCP2V4 | eSSU2V4); };
|
||||
bool IsV6 () const { return m_SupportedTransports & (eNTCP2V6 | eSSU2V6); };
|
||||
bool IsV4 () const { return m_SupportedTransports & (eNTCP2V4 | eSSU2V4); };
|
||||
bool IsMesh () const { return m_SupportedTransports & eNTCP2V6Mesh; };
|
||||
void EnableV6 ();
|
||||
void DisableV6 ();
|
||||
@@ -231,9 +230,8 @@ namespace data
|
||||
bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; };
|
||||
bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; };
|
||||
bool IsEligibleFloodfill () const;
|
||||
bool IsPeerTesting (bool v4) const;
|
||||
bool IsSSU2PeerTesting (bool v4) const;
|
||||
bool IsIntroducer (bool v4) const;
|
||||
bool IsSSU2Introducer (bool v4) const;
|
||||
|
||||
uint8_t GetCaps () const { return m_Caps; };
|
||||
void SetCaps (uint8_t caps) { m_Caps = caps; };
|
||||
@@ -272,7 +270,8 @@ namespace data
|
||||
void UpdateBuffer (const uint8_t * buf, size_t len);
|
||||
void SetBufferLen (size_t len) { m_BufferLen = len; };
|
||||
void RefreshTimestamp ();
|
||||
const Addresses& GetAddresses () const { return *m_Addresses; };
|
||||
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
|
||||
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
|
||||
|
||||
private:
|
||||
|
||||
@@ -286,6 +285,8 @@ namespace data
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const Address> GetAddress (Filter filter) const;
|
||||
virtual std::shared_ptr<Buffer> NewBuffer () const;
|
||||
virtual std::shared_ptr<Address> NewAddress () const;
|
||||
virtual boost::shared_ptr<Addresses> NewAddresses () const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -307,6 +308,7 @@ namespace data
|
||||
public:
|
||||
|
||||
LocalRouterInfo () = default;
|
||||
LocalRouterInfo (const std::string& fullPath): RouterInfo (fullPath) {};
|
||||
void CreateBuffer (const PrivateKeys& privateKeys);
|
||||
void UpdateCaps (uint8_t caps);
|
||||
|
||||
@@ -315,12 +317,17 @@ namespace data
|
||||
std::string GetProperty (const std::string& key) const;
|
||||
void ClearProperties () override { m_Properties.clear (); };
|
||||
|
||||
bool AddSSU2Introducer (const Introducer& introducer, bool v4);
|
||||
bool RemoveSSU2Introducer (const IdentHash& h, bool v4);
|
||||
|
||||
private:
|
||||
|
||||
void WriteToStream (std::ostream& s) const;
|
||||
void UpdateCapsProperty ();
|
||||
void WriteString (const std::string& str, std::ostream& s) const;
|
||||
std::shared_ptr<Buffer> NewBuffer () const override;
|
||||
std::shared_ptr<Address> NewAddress () const override;
|
||||
boost::shared_ptr<Addresses> NewAddresses () const override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user