mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b97feb89f | ||
|
|
a8135b8d18 | ||
|
|
5cf1961fa4 | ||
|
|
c5cab05a6b | ||
|
|
b855c71891 | ||
|
|
21f41a2b2a | ||
|
|
8319dd6b25 | ||
|
|
d4c47d90cb | ||
|
|
302af823a3 | ||
|
|
69ee6112b3 | ||
|
|
816a58f292 | ||
|
|
43e130ee34 | ||
|
|
8ffc1486a4 | ||
|
|
0e98dd5c70 | ||
|
|
beffdb9fe1 | ||
|
|
05eda2bc9e | ||
|
|
c3429bb1a9 | ||
|
|
53c6b10177 | ||
|
|
c2d7133174 | ||
|
|
9b82265cd8 | ||
|
|
c802c2deb0 | ||
|
|
c215f2e8d1 | ||
|
|
d327533b56 | ||
|
|
94255ebaf4 | ||
|
|
21259204b1 | ||
|
|
8d6eb5b6b2 | ||
|
|
9632e7ba03 | ||
|
|
1a02819187 | ||
|
|
6b33250c59 | ||
|
|
083034fa35 | ||
|
|
0021501d75 | ||
|
|
379be2a29e | ||
|
|
a3f62e1d71 | ||
|
|
a6ee1e648e | ||
|
|
575268d360 | ||
|
|
69b0bef206 | ||
|
|
e1b4feb618 | ||
|
|
3286bdb4a7 | ||
|
|
c8ae15041f | ||
|
|
e090b9052a | ||
|
|
0ef9c08326 | ||
|
|
d04b19d77c | ||
|
|
04adc14b76 | ||
|
|
0dee0609ea | ||
|
|
0a519d8072 | ||
|
|
0cc91dd2d2 | ||
|
|
606e35eec1 | ||
|
|
e926b0392f | ||
|
|
9980bfa0e7 | ||
|
|
efdbe26755 | ||
|
|
bb3ae8f5e4 | ||
|
|
1e6edf06a2 | ||
|
|
0cf656cd76 | ||
|
|
fb420bb563 | ||
|
|
3da5061426 | ||
|
|
dd32f1ed6d | ||
|
|
1857f14be8 | ||
|
|
9c25a88707 | ||
|
|
c599d65307 | ||
|
|
4d573f6655 | ||
|
|
3a4238729a | ||
|
|
df6bb6d9b8 | ||
|
|
918aa556ef | ||
|
|
1e7feae0df | ||
|
|
70829ee79e | ||
|
|
4ed19c05f6 | ||
|
|
4a5e16b994 | ||
|
|
c53ad2012c | ||
|
|
7b6aa41ca8 | ||
|
|
32c5ff23a6 | ||
|
|
c112276eea | ||
|
|
662a59d0fd | ||
|
|
72919ec076 | ||
|
|
627b8dca83 | ||
|
|
7bcc905f05 | ||
|
|
8447822c35 | ||
|
|
411063e3b5 | ||
|
|
9bac680f2a | ||
|
|
38795a41cb | ||
|
|
e170c39dfc | ||
|
|
68f4961f1a | ||
|
|
ae5239de43 | ||
|
|
2064504cce | ||
|
|
4aa631c33f | ||
|
|
d6834d6a9a | ||
|
|
413e25f20e | ||
|
|
b8e19bf5f1 | ||
|
|
c7efd465fa | ||
|
|
6e9a3422e9 | ||
|
|
d3cd8517b7 | ||
|
|
f13cc0b862 | ||
|
|
0754255c1f | ||
|
|
902899ae24 | ||
|
|
c620fc1232 | ||
|
|
e7157cf15e | ||
|
|
940a97db11 | ||
|
|
8e63f8f333 | ||
|
|
5e97b54d1b | ||
|
|
ea7cf1cf69 | ||
|
|
17c4038c60 | ||
|
|
5022a9c610 | ||
|
|
ca8ec6286a | ||
|
|
5142459e12 | ||
|
|
8590dbd3d3 | ||
|
|
c4be5f7fdb | ||
|
|
47dc5591b9 | ||
|
|
2bb48b4546 | ||
|
|
638e9b4d7f | ||
|
|
b8f998f76a | ||
|
|
5f43026986 | ||
|
|
13f263b791 | ||
|
|
07c529173e | ||
|
|
fee940238a | ||
|
|
ca02b5d860 | ||
|
|
fba23a4528 | ||
|
|
a0795d8534 | ||
|
|
03cc6e0524 | ||
|
|
3af1f4bc76 | ||
|
|
52b2d6c393 | ||
|
|
bb52056aec | ||
|
|
75aa9f2c0c | ||
|
|
4e426727e9 | ||
|
|
09f233dbfb | ||
|
|
dfe5df29e1 | ||
|
|
d5ee1f602f | ||
|
|
86173400d5 | ||
|
|
ae439b5385 | ||
|
|
dc6a42c26f | ||
|
|
fdf38f45d9 | ||
|
|
a2726cf206 | ||
|
|
e56d243c3f | ||
|
|
e95fb3ab89 | ||
|
|
c984f89dfb | ||
|
|
5a09c11e90 | ||
|
|
d44be2fd73 | ||
|
|
a158647153 | ||
|
|
623c3f4605 | ||
|
|
8a52295882 | ||
|
|
f2bc2598dc | ||
|
|
1d8a91c5cc | ||
|
|
3bc56ba423 | ||
|
|
e068a3cf22 | ||
|
|
2e2cbe7803 | ||
|
|
1c1452e06b | ||
|
|
c757b6d020 | ||
|
|
8fcab7b0c1 | ||
|
|
7646147ed2 | ||
|
|
b6de474fda | ||
|
|
2f74e670a5 | ||
|
|
c1168c2aa0 | ||
|
|
1bd6390f78 | ||
|
|
a9e9e14c42 | ||
|
|
19471dbb90 | ||
|
|
3b13a3f2a1 | ||
|
|
4ce2ef1d83 | ||
|
|
12d0abda55 | ||
|
|
7418f11651 | ||
|
|
fb83ca42f4 | ||
|
|
dab34e9051 | ||
|
|
ec2297ed9d | ||
|
|
7c535159bc | ||
|
|
2af4a2b58d | ||
|
|
ead6a6dca3 | ||
|
|
0ce15ffc91 | ||
|
|
76adac31c3 | ||
|
|
edfcd23b01 | ||
|
|
f21e1c75d5 | ||
|
|
786c27c8ec | ||
|
|
c34df2090c | ||
|
|
5769a41208 | ||
|
|
dc265367dc | ||
|
|
c22fc75370 |
@@ -34,3 +34,6 @@ trim_trailing_whitespace = false
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.patch]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
4
.github/workflows/build-freebsd.yml
vendored
4
.github/workflows/build-freebsd.yml
vendored
@@ -4,7 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-12
|
||||
runs-on: ubuntu-latest
|
||||
name: with UPnP
|
||||
|
||||
steps:
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
|
||||
- name: Test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v0.3.0
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
mem: 2048
|
||||
|
||||
2
.github/workflows/build-windows-msvc.yml
vendored
2
.github/workflows/build-windows-msvc.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Install Boost
|
||||
uses: crazy-max/ghaction-chocolatey@v2
|
||||
with:
|
||||
args: install boost-msvc-14.3
|
||||
args: install boost-msvc-14.3 --version=1.81.0
|
||||
|
||||
- name: Install OpenSSL
|
||||
uses: crazy-max/ghaction-chocolatey@v2
|
||||
|
||||
10
.github/workflows/docker.yml
vendored
10
.github/workflows/docker.yml
vendored
@@ -5,6 +5,16 @@ on:
|
||||
branches:
|
||||
- openssl
|
||||
- docker
|
||||
paths:
|
||||
- .github/workflows/docker.yml
|
||||
- contrib/docker/**
|
||||
- contrib/certificates/**
|
||||
- daemon/**
|
||||
- i18n/**
|
||||
- libi2pd/**
|
||||
- libi2pd_client/**
|
||||
- Makefile
|
||||
- Makefile.linux
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
|
||||
80
ChangeLog
80
ChangeLog
@@ -1,6 +1,86 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.50.2] - 2024-01-06
|
||||
###Fixed
|
||||
- Crash with OpenSSL 3.2.0
|
||||
- False positive clock skew detection
|
||||
|
||||
## [2.50.1] - 2023-12-23
|
||||
###Fixed
|
||||
- Support for new EdDSA usage behavior in OpenSSL 3.2.0
|
||||
|
||||
## [2.50.0] - 2023-12-18
|
||||
### Added
|
||||
- Support of concurrent ACCEPTs on SAM 3.1
|
||||
- Haiku OS support
|
||||
- Low bandwidth and far routers can expire before 1 hour
|
||||
### Changed
|
||||
- Don't pick too active peer for first hop
|
||||
- Try peer test again if status is Unknown
|
||||
- Send peer tests with random delay
|
||||
- Reseeds list
|
||||
### Fixed
|
||||
- XSS vulnerability in addresshelper
|
||||
- Publishing NAT64 ipv6 addresses
|
||||
- Deadlock in AsyncSend callback
|
||||
|
||||
## [2.49.0] - 2023-09-18
|
||||
### Added
|
||||
- Handle SOCK5 authorization with empty user/password
|
||||
- Drop incoming transport sessions from too old or from future routers
|
||||
- Memory pool for router profiles
|
||||
- Allow 0 hops in explicitPeers
|
||||
### Changed
|
||||
- Separate network and testing status
|
||||
- Remove AVX code
|
||||
- Improve NTCP2 transport session logging
|
||||
- Select router with ipv4 for tunnel endpoint
|
||||
- Consider all addresses non-published for U and H routers even if they have host/port
|
||||
- Don't pick completely unreachable routers for tunnels
|
||||
- Exclude SSU1 introducers from SSU2 addresses
|
||||
- Don't create paired inbound tunnel if length is different
|
||||
- Remove introducer from RouterInfo after 60 minutes
|
||||
- Reduce SSU2 keep alive interval and add keep alive interval variance
|
||||
- Don't pick too old sessions for introducer
|
||||
### Fixed
|
||||
- Version of the subnegotiation in user/password SOCKS5 response
|
||||
- Send keepalive for existing session with introducer
|
||||
- Buffer offset for EVP_EncryptFinal_ex() to include outlen
|
||||
- Termination block size processing for transport sessions
|
||||
- Crash if deleted BOB destination was shared between few BOB sessions
|
||||
- Introducers with zero tag
|
||||
- Padding for SSU2 path response
|
||||
|
||||
## [2.48.0] - 2023-06-12
|
||||
### Added
|
||||
- Allow user/password authentication method for SOCK5 proxy
|
||||
- Publish reject all congestion cap 'G' if transit is not accepted
|
||||
- 'critical' log level
|
||||
- Print b32 on webconsole destination page
|
||||
- Webconsole button to drop a remote LeaseSet
|
||||
- limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup
|
||||
- Recognize real routers if successfully connected or responded to tunnel build request
|
||||
### Changed
|
||||
- Bypass slow transport sessions for first hop selection
|
||||
- Limit AESNI inline asm to x86/x64
|
||||
- Create smaller I2NP packets if possible
|
||||
- Make router unreachable if AEAD tag verification fails in SessionCreated
|
||||
- Don't include a router to floodfills list until it's confirmed as real
|
||||
- Drop LeaseSet store request if not floodfill
|
||||
- Bypass medium congestion('D') routers for client tunnels
|
||||
- Publish encrypted RouterInfo through tunnels
|
||||
- Check if s is valid x25519 public key
|
||||
- Check if socket is open before sending data in SSU2
|
||||
### Fixed
|
||||
- Webconsole empty page if destination is not found
|
||||
- i2p.streaming.answerPings param
|
||||
- Reload tunnels
|
||||
- Address caps for unspecified ipv6 address
|
||||
- Incomplete HTTP headers in I2P tunnels
|
||||
- SSU2 socket network exceptions on Windows
|
||||
- Use of 'server' type tunnel port as inport (#1936)
|
||||
|
||||
## [2.47.0] - 2023-03-11
|
||||
### Added
|
||||
- Congestion caps
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
5
Makefile
5
Makefile
@@ -67,6 +67,9 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifneq (, $(findstring haiku, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.haiku
|
||||
else # not supported
|
||||
$(error Not supported platform)
|
||||
endif
|
||||
@@ -118,7 +121,7 @@ obj/%.o: %.cpp | mk_obj_dir
|
||||
-include $(DEPS)
|
||||
|
||||
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
|
||||
$(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS)
|
||||
$(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
$(SHLIB): $(LIB_OBJS)
|
||||
ifneq ($(USE_STATIC),yes)
|
||||
|
||||
10
Makefile.haiku
Normal file
10
Makefile.haiku
Normal file
@@ -0,0 +1,10 @@
|
||||
CXX = g++
|
||||
CXXFLAGS := -Wall -std=c++11
|
||||
INCFLAGS = -I/system/develop/headers
|
||||
DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||
LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
DEFINES += -DUSE_UPNP
|
||||
LDLIBS += -lminiupnpc
|
||||
endif
|
||||
@@ -5,14 +5,11 @@ WINDRES = windres
|
||||
|
||||
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
|
||||
INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32
|
||||
LDFLAGS := ${LD_DEBUG} -static
|
||||
LDFLAGS := ${LD_DEBUG} -static -fPIC -msse
|
||||
|
||||
NEEDED_CXXFLAGS += -std=c++17
|
||||
DEFINES += -DWIN32_LEAN_AND_MEAN
|
||||
|
||||
# Boost libraries suffix
|
||||
BOOST_SUFFIX = -mt
|
||||
|
||||
# UPNP Support
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB
|
||||
@@ -20,17 +17,18 @@ ifeq ($(USE_UPNP),yes)
|
||||
endif
|
||||
|
||||
LDLIBS += \
|
||||
-lboost_system$(BOOST_SUFFIX) \
|
||||
-lboost_date_time$(BOOST_SUFFIX) \
|
||||
-lboost_filesystem$(BOOST_SUFFIX) \
|
||||
-lboost_program_options$(BOOST_SUFFIX) \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lz \
|
||||
$(MINGW_PREFIX)/lib/libboost_system-mt.a \
|
||||
$(MINGW_PREFIX)/lib/libboost_date_time-mt.a \
|
||||
$(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \
|
||||
$(MINGW_PREFIX)/lib/libboost_program_options-mt.a \
|
||||
$(MINGW_PREFIX)/lib/libssl.a \
|
||||
$(MINGW_PREFIX)/lib/libcrypto.a \
|
||||
$(MINGW_PREFIX)/lib/libz.a \
|
||||
-lwsock32 \
|
||||
-lws2_32 \
|
||||
-lgdi32 \
|
||||
-liphlpapi \
|
||||
-lcrypt32 \
|
||||
-lgdi32 \
|
||||
-lole32 \
|
||||
-luuid \
|
||||
-lpthread
|
||||
@@ -48,6 +46,7 @@ endif
|
||||
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
NEEDED_CXXFLAGS += -maes
|
||||
LDFLAGS += -maes
|
||||
DEFINES += -D__AES__
|
||||
endif
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ DEFINES := -DMAC_OSX
|
||||
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
LDFLAGS += -Wl,-dead_strip
|
||||
LDFLAGS += -Wl,-dead_strip_dylibs
|
||||
LDFLAGS += -Wl,-bind_at_load
|
||||
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||
|
||||
24
README.md
24
README.md
@@ -99,13 +99,23 @@ Current status: [](http
|
||||
Donations
|
||||
---------
|
||||
|
||||
BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f
|
||||
LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59
|
||||
ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d
|
||||
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
|
||||
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
|
||||
GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG
|
||||
XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH
|
||||
**E-Mail**: ```i2porignal at yandex.com```
|
||||
|
||||
**BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f```
|
||||
|
||||
**LTC**: ```LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59```
|
||||
|
||||
**ETH**: ```0x9e5bac70d20d1079ceaa111127f4fb3bccce379d```
|
||||
|
||||
**GST**: ```GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG```
|
||||
|
||||
**DASH**: ```Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF```
|
||||
|
||||
**ZEC**: ```t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ```
|
||||
|
||||
**ANC**: ```AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z```
|
||||
|
||||
**XMR**: ```497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
@@ -145,18 +145,19 @@ namespace win32
|
||||
s << bytes << " Bytes\n";
|
||||
}
|
||||
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case eRouterStatusOK: s << "OK"; break;
|
||||
case eRouterStatusTesting: s << "Test"; break;
|
||||
case eRouterStatusFirewalled: s << "FW"; break;
|
||||
case eRouterStatusUnknown: s << "Unk"; break;
|
||||
case eRouterStatusProxy: s << "Proxy"; break;
|
||||
case eRouterStatusMesh: s << "Mesh"; break;
|
||||
default: s << "Unk";
|
||||
};
|
||||
if (testing)
|
||||
s << " (Test)";
|
||||
if (i2p::context.GetError () != eRouterErrorNone)
|
||||
{
|
||||
switch (i2p::context.GetError ())
|
||||
@@ -179,11 +180,11 @@ namespace win32
|
||||
{
|
||||
s << "\n";
|
||||
s << "Status: ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ());
|
||||
if (i2p::context.SupportsV6 ())
|
||||
{
|
||||
s << " / ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ());
|
||||
}
|
||||
s << "; ";
|
||||
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
|
||||
@@ -348,6 +349,9 @@ namespace win32
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||
[[fallthrough]];
|
||||
#endif
|
||||
}
|
||||
case WM_TRAYICON:
|
||||
{
|
||||
|
||||
BIN
Win32/mask.bmp
BIN
Win32/mask.bmp
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@@ -25,7 +25,7 @@ project(
|
||||
i2pd
|
||||
VERSION ${PROJECT_VERSION}
|
||||
HOMEPAGE_URL "https://i2pd.website/"
|
||||
LANGUAGES CXX
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
|
||||
# configurable options
|
||||
@@ -121,7 +121,7 @@ if(WIN32)
|
||||
)
|
||||
|
||||
file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
|
||||
|
||||
endif()
|
||||
|
||||
@@ -139,6 +139,10 @@ if(APPLE)
|
||||
add_definitions(-DMAC_OSX)
|
||||
endif()
|
||||
|
||||
if(HAIKU)
|
||||
add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-DWINVER=0x0600)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
@@ -197,14 +201,11 @@ endif()
|
||||
|
||||
# Note: AES-NI and AVX is available on x86-based CPU's.
|
||||
# Here also ARM64 implementation, but currently we don't support it.
|
||||
# MSVC is not supported.
|
||||
if(MSVC)
|
||||
message(STATUS "AES-NI is not supported on MSVC, option was disabled")
|
||||
set(WITH_AESNI OFF)
|
||||
endif()
|
||||
|
||||
# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code.
|
||||
if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386"))
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
||||
endif()
|
||||
add_definitions(-D__AES__)
|
||||
endif()
|
||||
|
||||
@@ -329,7 +330,11 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||
if(WITH_GIT_VERSION)
|
||||
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})")
|
||||
else()
|
||||
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
|
||||
endif()
|
||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||
message(STATUS "---------------------------------------")
|
||||
|
||||
42
contrib/apparmor/docker-i2pd
Normal file
42
contrib/apparmor/docker-i2pd
Normal file
@@ -0,0 +1,42 @@
|
||||
# _________________________________________
|
||||
# / Copy this file to the right location \
|
||||
# | then load with: |
|
||||
# | |
|
||||
# | apparmor_parser -r -W |
|
||||
# | /etc/apparmor.d/docker-i2pd |
|
||||
# | |
|
||||
# | docker run --security-opt |
|
||||
# | "apparmor=docker-i2pd" ... |
|
||||
# | purplei2p/i2pd |
|
||||
# | |
|
||||
# \ And "aa-status" to verify it's loaded. /
|
||||
# -----------------------------------------
|
||||
# \ ^__^
|
||||
# \ (oo)\_______
|
||||
# (__)\ )\/\
|
||||
# ||----w |
|
||||
# || ||
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
profile docker-i2pd flags=(attach_disconnected,mediate_deleted) {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/openssl>
|
||||
#include <abstractions/nameservice>
|
||||
|
||||
/bin/busybox ix,
|
||||
/usr/local/bin/i2pd ix,
|
||||
/entrypoint.sh ixr,
|
||||
|
||||
/i2pd_certificates/** r,
|
||||
|
||||
/home/i2pd/data/** rw,
|
||||
|
||||
/home/i2pd/data/i2pd.pid k,
|
||||
|
||||
deny /home/i2pd/data/i2pd.conf w,
|
||||
deny /home/i2pd/data/tunnels.conf w,
|
||||
deny /home/i2pd/data/tunnels.d/** w,
|
||||
deny /home/i2pd/data/certificates/** w,
|
||||
deny /home/i2pd/data/i2pd.log r,
|
||||
}
|
||||
32
contrib/certificates/reseed/ls_at_mail.i2p.crt
Normal file
32
contrib/certificates/reseed/ls_at_mail.i2p.crt
Normal file
@@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFdTCCA12gAwIBAgIEQ5vCxzANBgkqhkiG9w0BAQ0FADBrMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAw
|
||||
HhcNMjMxMDE2MjAwNTA5WhcNMzMxMDEzMjAwNTA5WjBrMQswCQYDVQQGEwJYWDEL
|
||||
MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnltb3Vz
|
||||
IE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAwggIi
|
||||
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPcbKRtf4PzrDa0iRit0XrwnmA
|
||||
2c1fJhkBipdPor7gMOAlkR82H1lkZSizR7kTZnr7vYqjDrOQr7bl5Dy3qo8/YCbZ
|
||||
jsnUCTIIgIJQUxUlR40RjaSXphqzUEiXKHR6b0RahhFisQ3hlbbgzSch5YgSLKws
|
||||
hOLi+eDSXw+HlwHlWFlT1XOKxSTJ/F3Bv40gxqZVC2pbxiPOeRZHQ6Ojw75lxTSF
|
||||
gww2WzgztiWt4X9BO1yepnVqhAVRPmTfGUMfKzq9jkMzZKeQFV4uZSP9nCqzEpYd
|
||||
WNDUfpTWiAQ9F+BwFXGusXXA3tGVwS7s6IEoiJFM5fsoJYfRoWGh3/1eirhBXW7U
|
||||
M6oubMSTADyrvfjLfJBMmMnc2hNblRlKr0ZKUjMfv8cnyT4kQxlXLAHHXY2P89TM
|
||||
TEVODkU48gnv6tC4t1JCb1/Da+3yVMjNX6rCzQfUwnLFrWthrwiI0NivAKFtiZjq
|
||||
w1/ZQcYke2YyeqcfXMn+NTUA22Sm2mJoMo7jUf+rbM9Pi27/DncJgRGj5qwY0D3S
|
||||
gc7829EjuZNPttGBmae1EmO7WQMB32cqdmItnV2FXpMhnn9h0u5H52kYqwn+mdtc
|
||||
dTJRcbfKG1RTr3UjFISaTwL8qigMIkVXIzcpnr/R/sSeEs8xCqfsJ6rb4dCyFx+M
|
||||
hqQcOCL5tumyd4W/LQIDAQABoyEwHzAdBgNVHQ4EFgQUgfaOG5HCnlW82wZ5BahL
|
||||
GRO06igwDQYJKoZIhvcNAQENBQADggIBAKdVpqS9qF7gGotgXaVA1iP5YNsWlTvG
|
||||
daGqeA/87//U21W6gpq82FhzsmsvUtXZfIeVIlDPI7WNDzS+A3K/KKrwM7dLgSie
|
||||
r9eMl3D8WYPU95QF4mAlRyl7PCCsYoVjyvfro0iq3/iudIA5476rjfLdTXRi5hAT
|
||||
qemPj0S+6sRjKEldRtGXrQATFlvLIWVYpgHijdDDx5M2hAz2y0mFxlDZTlA4BhL4
|
||||
DwtGlVKmbc2x5MvIQM4UhbQqkxYS4gXnzf5Qx9QIytHfTr/hmbrkhKR1GCO31BSk
|
||||
x9LhZxdI8LlwKSo6YgwXEB9E0M/tplaK9iZJFv4HPYLZrVJpb4IklMumyLMrgW5P
|
||||
fR0dgKn+R9lk0emJ1Cu+qyyzf1vsLycYBwaEztINn4VK+/HfDFpnVCvJOyNuDmj5
|
||||
KBLIoGdGoVfylmnc+e8zAXe+DY41fgniHMISOO78P8Bx9vTB+rhqnOUr9MzlUxPB
|
||||
sKGjbXy2YynEqiGb+9g344v/+ukTSDenqTPHVzJ5uOi0iedy+3ASzUNN6GJocovP
|
||||
167VOhwaETM0FwiKe0VdZRLLbbZ79CtJC0tmgcgPQPRa9Ldr6KN7u1J3D6lUp6zl
|
||||
byPom10ueKONRb36t7ai79l2SEUZRSMkx6AXIU0JJ1SMtQtav7b5LkpYJfdL7+vO
|
||||
dDx2/Za0VmdD
|
||||
-----END CERTIFICATE-----
|
||||
33
contrib/certificates/reseed/null_at_i2pmail.org.crt
Normal file
33
contrib/certificates/reseed/null_at_i2pmail.org.crt
Normal file
@@ -0,0 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw
|
||||
cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
|
||||
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM
|
||||
EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2
|
||||
WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD
|
||||
VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE
|
||||
AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
|
||||
ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0
|
||||
XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE
|
||||
ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA
|
||||
1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp
|
||||
gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp
|
||||
486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR
|
||||
gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW
|
||||
DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn
|
||||
KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX
|
||||
kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV
|
||||
bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G
|
||||
A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
|
||||
VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG
|
||||
9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss
|
||||
q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj
|
||||
EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39
|
||||
gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV
|
||||
La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH
|
||||
xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6
|
||||
a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8
|
||||
NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK
|
||||
heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO
|
||||
j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU
|
||||
vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,34 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw
|
||||
fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
|
||||
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM
|
||||
HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX
|
||||
DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD
|
||||
VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL
|
||||
EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6
|
||||
MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI
|
||||
Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt
|
||||
4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5
|
||||
UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k
|
||||
P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t
|
||||
3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5
|
||||
zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r
|
||||
Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ
|
||||
lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1
|
||||
sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz
|
||||
euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW
|
||||
MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf
|
||||
BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC
|
||||
AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj
|
||||
tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6
|
||||
ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf
|
||||
xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD
|
||||
UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM
|
||||
XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE
|
||||
Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p
|
||||
Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq
|
||||
NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr
|
||||
QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9
|
||||
0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,2 +1,5 @@
|
||||
This forder contain systemd unit files.
|
||||
To use systemd daemon control, place files from this directory to debian folder before building package.
|
||||
This forder contain files required for building debian packages.
|
||||
|
||||
The trunk repository is contains the packaging files for the latest stable version of Debian (if we not forgot to update them).
|
||||
|
||||
Files in subdirectories contains fixes to make possible to build package on specific versions of Debian/Ubuntu. They are used when building the release package.
|
||||
|
||||
1
contrib/debian/bionic/compat
Normal file
1
contrib/debian/bionic/compat
Normal file
@@ -0,0 +1 @@
|
||||
11
|
||||
18
contrib/debian/bionic/control
Normal file
18
contrib/debian/bionic/control
Normal file
@@ -0,0 +1,18 @@
|
||||
Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
Build-Depends: debhelper (>= 11~), 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.2.0
|
||||
Homepage: http://i2pd.website/
|
||||
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
||||
Vcs-Browser: https://github.com/PurpleI2P/i2pd
|
||||
|
||||
Package: i2pd
|
||||
Architecture: any
|
||||
Pre-Depends: ${misc:Pre-Depends}, adduser
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
|
||||
Description: Full-featured C++ implementation of I2P client.
|
||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
||||
communications over I2P are anonymous and end-to-end encrypted, participants
|
||||
don't reveal their real IP addresses.
|
||||
1
contrib/debian/trusty/compat
Normal file
1
contrib/debian/trusty/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
18
contrib/debian/trusty/control
Normal file
18
contrib/debian/trusty/control
Normal file
@@ -0,0 +1,18 @@
|
||||
Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
Build-Depends: debhelper (>= 9), 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
|
||||
Homepage: http://i2pd.website/
|
||||
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
||||
Vcs-Browser: https://github.com/PurpleI2P/i2pd
|
||||
|
||||
Package: i2pd
|
||||
Architecture: any
|
||||
Pre-Depends: ${misc:Pre-Depends}, adduser
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
|
||||
Description: Full-featured C++ implementation of I2P client.
|
||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
||||
communications over I2P are anonymous and end-to-end encrypted, participants
|
||||
don't reveal their real IP addresses.
|
||||
17
contrib/debian/trusty/patches/01-upnp.patch
Normal file
17
contrib/debian/trusty/patches/01-upnp.patch
Normal file
@@ -0,0 +1,17 @@
|
||||
Description: Enable UPnP usage in package
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2022-03-23
|
||||
|
||||
--- i2pd.orig/Makefile
|
||||
+++ i2pd/Makefile
|
||||
@@ -31,7 +31,7 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
-USE_UPNP := $(or $(USE_UPNP),no)
|
||||
+USE_UPNP := $(or $(USE_UPNP),yes)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
|
||||
19
contrib/debian/trusty/patches/02-service.patch
Normal file
19
contrib/debian/trusty/patches/02-service.patch
Normal file
@@ -0,0 +1,19 @@
|
||||
Description: Disable LogsDirectory and LogsDirectoryMode options in service
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2023-05-17
|
||||
|
||||
--- a/contrib/i2pd.service
|
||||
+++ b/contrib/i2pd.service
|
||||
@@ -8,8 +8,8 @@ User=i2pd
|
||||
Group=i2pd
|
||||
RuntimeDirectory=i2pd
|
||||
RuntimeDirectoryMode=0700
|
||||
-LogsDirectory=i2pd
|
||||
-LogsDirectoryMode=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"
|
||||
2
contrib/debian/trusty/patches/series
Normal file
2
contrib/debian/trusty/patches/series
Normal file
@@ -0,0 +1,2 @@
|
||||
01-upnp.patch
|
||||
02-service.patch
|
||||
18
contrib/debian/trusty/rules
Executable file
18
contrib/debian/trusty/rules
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/make -f
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
|
||||
|
||||
include /usr/share/dpkg/architecture.mk
|
||||
|
||||
ifeq ($(DEB_HOST_ARCH),i386)
|
||||
export DEB_BUILD_OPTIONS=parallel=1
|
||||
endif
|
||||
|
||||
export DEB_CXXFLAGS_MAINT_APPEND=-Wall -pedantic
|
||||
export DEB_LDFLAGS_MAINT_APPEND=
|
||||
|
||||
%:
|
||||
dh $@ --parallel
|
||||
|
||||
override_dh_auto_install:
|
||||
1
contrib/debian/xenial/compat
Normal file
1
contrib/debian/xenial/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
18
contrib/debian/xenial/control
Normal file
18
contrib/debian/xenial/control
Normal file
@@ -0,0 +1,18 @@
|
||||
Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
Build-Depends: debhelper (>= 9), 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
|
||||
Homepage: http://i2pd.website/
|
||||
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
|
||||
Vcs-Browser: https://github.com/PurpleI2P/i2pd
|
||||
|
||||
Package: i2pd
|
||||
Architecture: any
|
||||
Pre-Depends: ${misc:Pre-Depends}, adduser
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
|
||||
Description: Full-featured C++ implementation of I2P client.
|
||||
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
|
||||
communications over I2P are anonymous and end-to-end encrypted, participants
|
||||
don't reveal their real IP addresses.
|
||||
17
contrib/debian/xenial/patches/01-upnp.patch
Normal file
17
contrib/debian/xenial/patches/01-upnp.patch
Normal file
@@ -0,0 +1,17 @@
|
||||
Description: Enable UPnP usage in package
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2022-03-23
|
||||
|
||||
--- i2pd.orig/Makefile
|
||||
+++ i2pd/Makefile
|
||||
@@ -31,7 +31,7 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
-USE_UPNP := $(or $(USE_UPNP),no)
|
||||
+USE_UPNP := $(or $(USE_UPNP),yes)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
|
||||
19
contrib/debian/xenial/patches/02-service.patch
Normal file
19
contrib/debian/xenial/patches/02-service.patch
Normal file
@@ -0,0 +1,19 @@
|
||||
Description: Disable LogsDirectory and LogsDirectoryMode options in service
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2023-05-17
|
||||
|
||||
--- a/contrib/i2pd.service
|
||||
+++ b/contrib/i2pd.service
|
||||
@@ -8,8 +8,8 @@ User=i2pd
|
||||
Group=i2pd
|
||||
RuntimeDirectory=i2pd
|
||||
RuntimeDirectoryMode=0700
|
||||
-LogsDirectory=i2pd
|
||||
-LogsDirectoryMode=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"
|
||||
2
contrib/debian/xenial/patches/series
Normal file
2
contrib/debian/xenial/patches/series
Normal file
@@ -0,0 +1,2 @@
|
||||
01-upnp.patch
|
||||
02-service.patch
|
||||
13
contrib/debian/xenial/rules
Executable file
13
contrib/debian/xenial/rules
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/make -f
|
||||
#export DH_VERBOSE=1
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
include /usr/share/dpkg/architecture.mk
|
||||
|
||||
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
export DEB_LDFLAGS_MAINT_APPEND =
|
||||
|
||||
%:
|
||||
dh $@ --parallel
|
||||
|
||||
override_dh_auto_install:
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: i2pd\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
|
||||
"POT-Creation-Date: 2023-01-19 04:18\n"
|
||||
"POT-Creation-Date: 2023-06-10 01:25\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -18,28 +18,28 @@ msgstr ""
|
||||
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
|
||||
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
|
||||
|
||||
#: daemon/HTTPServer.cpp:106
|
||||
#: daemon/HTTPServer.cpp:107
|
||||
#, c-format
|
||||
msgid "%d day"
|
||||
msgid_plural "%d days"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:110
|
||||
#: daemon/HTTPServer.cpp:111
|
||||
#, c-format
|
||||
msgid "%d hour"
|
||||
msgid_plural "%d hours"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:114
|
||||
#: daemon/HTTPServer.cpp:115
|
||||
#, c-format
|
||||
msgid "%d minute"
|
||||
msgid_plural "%d minutes"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:117
|
||||
#: daemon/HTTPServer.cpp:118
|
||||
#, c-format
|
||||
msgid "%d second"
|
||||
msgid_plural "%d seconds"
|
||||
@@ -47,560 +47,578 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#. tr: Kibibyte
|
||||
#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153
|
||||
#: daemon/HTTPServer.cpp:126
|
||||
#, c-format
|
||||
msgid "%.2f KiB"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Mebibyte
|
||||
#: daemon/HTTPServer.cpp:127
|
||||
#: daemon/HTTPServer.cpp:128
|
||||
#, c-format
|
||||
msgid "%.2f MiB"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Gibibyte
|
||||
#: daemon/HTTPServer.cpp:129
|
||||
#: daemon/HTTPServer.cpp:130
|
||||
#, c-format
|
||||
msgid "%.2f GiB"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:146
|
||||
#: daemon/HTTPServer.cpp:147
|
||||
msgid "building"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:147
|
||||
#: daemon/HTTPServer.cpp:148
|
||||
msgid "failed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:148
|
||||
#: daemon/HTTPServer.cpp:149
|
||||
msgid "expiring"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:149
|
||||
#: daemon/HTTPServer.cpp:150
|
||||
msgid "established"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:150
|
||||
#: daemon/HTTPServer.cpp:151
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:152
|
||||
#: daemon/HTTPServer.cpp:153
|
||||
msgid "exploratory"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Webconsole page title
|
||||
#: daemon/HTTPServer.cpp:183
|
||||
#: daemon/HTTPServer.cpp:185
|
||||
msgid "Purple I2P Webconsole"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:188
|
||||
#: daemon/HTTPServer.cpp:190
|
||||
msgid "<b>i2pd</b> webconsole"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:191
|
||||
#: daemon/HTTPServer.cpp:193
|
||||
msgid "Main page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712
|
||||
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742
|
||||
msgid "Router commands"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387
|
||||
#: daemon/HTTPServer.cpp:399
|
||||
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395
|
||||
#: daemon/HTTPServer.cpp:407
|
||||
msgid "Local Destinations"
|
||||
msgstr ""
|
||||
|
||||
#: 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
|
||||
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:365
|
||||
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:474
|
||||
#: daemon/HTTPServer.cpp:636 daemon/HTTPServer.cpp:682
|
||||
#: daemon/HTTPServer.cpp:686
|
||||
msgid "LeaseSets"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662
|
||||
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692
|
||||
msgid "Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364
|
||||
#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797
|
||||
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372
|
||||
#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830
|
||||
msgid "Transit Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855
|
||||
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898
|
||||
msgid "Transports"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:202
|
||||
#: daemon/HTTPServer.cpp:204
|
||||
msgid "I2P tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884
|
||||
#: daemon/HTTPServer.cpp:894
|
||||
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927
|
||||
#: daemon/HTTPServer.cpp:937
|
||||
msgid "SAM sessions"
|
||||
msgstr ""
|
||||
|
||||
#: 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
|
||||
#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1329
|
||||
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1335
|
||||
#: daemon/HTTPServer.cpp:1362 daemon/HTTPServer.cpp:1365
|
||||
#: daemon/HTTPServer.cpp:1379 daemon/HTTPServer.cpp:1424
|
||||
#: daemon/HTTPServer.cpp:1427 daemon/HTTPServer.cpp:1430
|
||||
msgid "ERROR"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:227
|
||||
#: daemon/HTTPServer.cpp:229
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:228
|
||||
#: daemon/HTTPServer.cpp:230
|
||||
msgid "Testing"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:229
|
||||
#: daemon/HTTPServer.cpp:231
|
||||
msgid "Firewalled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233
|
||||
#: daemon/HTTPServer.cpp:329
|
||||
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235
|
||||
#: daemon/HTTPServer.cpp:336
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374
|
||||
#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952
|
||||
#: daemon/HTTPServer.cpp:961
|
||||
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382
|
||||
#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003
|
||||
#: daemon/HTTPServer.cpp:1011
|
||||
msgid "Proxy"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:232
|
||||
#: daemon/HTTPServer.cpp:234
|
||||
msgid "Mesh"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:240
|
||||
#: daemon/HTTPServer.cpp:242
|
||||
msgid "Clock skew"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:243
|
||||
#: daemon/HTTPServer.cpp:245
|
||||
msgid "Offline"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:246
|
||||
#: daemon/HTTPServer.cpp:248
|
||||
msgid "Symmetric NAT"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:249
|
||||
#: daemon/HTTPServer.cpp:251
|
||||
msgid "Full cone NAT"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:252
|
||||
#: daemon/HTTPServer.cpp:254
|
||||
msgid "No Descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:261
|
||||
#: daemon/HTTPServer.cpp:263
|
||||
msgid "Uptime"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:264
|
||||
#: daemon/HTTPServer.cpp:266
|
||||
msgid "Network status"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:269
|
||||
#: daemon/HTTPServer.cpp:271
|
||||
msgid "Network status v6"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282
|
||||
#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284
|
||||
msgid "Stopping in"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:289
|
||||
#: daemon/HTTPServer.cpp:291
|
||||
msgid "Family"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:290
|
||||
#: daemon/HTTPServer.cpp:292
|
||||
msgid "Tunnel creation success rate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:291
|
||||
#: daemon/HTTPServer.cpp:296
|
||||
msgid "Total tunnel creation success rate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:298
|
||||
msgid "Received"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Kibibyte/s
|
||||
#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296
|
||||
#: daemon/HTTPServer.cpp:299
|
||||
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303
|
||||
#: daemon/HTTPServer.cpp:306
|
||||
#, c-format
|
||||
msgid "%.2f KiB/s"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:294
|
||||
#: daemon/HTTPServer.cpp:301
|
||||
msgid "Sent"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:297
|
||||
#: daemon/HTTPServer.cpp:304
|
||||
msgid "Transit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:300
|
||||
#: daemon/HTTPServer.cpp:307
|
||||
msgid "Data path"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:303
|
||||
#: daemon/HTTPServer.cpp:310
|
||||
msgid "Hidden content. Press on text to see."
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:307
|
||||
#: daemon/HTTPServer.cpp:314
|
||||
msgid "Router Ident"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:309
|
||||
#: daemon/HTTPServer.cpp:316
|
||||
msgid "Router Family"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:310
|
||||
#: daemon/HTTPServer.cpp:317
|
||||
msgid "Router Caps"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:311
|
||||
#: daemon/HTTPServer.cpp:318
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:312
|
||||
#: daemon/HTTPServer.cpp:319
|
||||
msgid "Our external address"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Shown when router doesn't publish itself and have "Firewalled" state
|
||||
#: daemon/HTTPServer.cpp:341
|
||||
#: daemon/HTTPServer.cpp:349
|
||||
msgid "supported"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:355
|
||||
#: daemon/HTTPServer.cpp:363
|
||||
msgid "Routers"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:356
|
||||
#: daemon/HTTPServer.cpp:364
|
||||
msgid "Floodfills"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938
|
||||
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987
|
||||
msgid "Client Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:373
|
||||
#: daemon/HTTPServer.cpp:381
|
||||
msgid "Services"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
|
||||
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
|
||||
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
|
||||
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
|
||||
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
|
||||
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
|
||||
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
|
||||
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
|
||||
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
|
||||
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
|
||||
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:422
|
||||
#: daemon/HTTPServer.cpp:434
|
||||
msgid "Encrypted B33 address"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:431
|
||||
#: daemon/HTTPServer.cpp:442
|
||||
msgid "Address registration line"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:436
|
||||
#: daemon/HTTPServer.cpp:447
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:437
|
||||
#: daemon/HTTPServer.cpp:448
|
||||
msgid "Generate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:438
|
||||
#: daemon/HTTPServer.cpp:449
|
||||
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:444
|
||||
#: daemon/HTTPServer.cpp:457
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:444
|
||||
#: daemon/HTTPServer.cpp:459
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:444
|
||||
#: daemon/HTTPServer.cpp:460
|
||||
msgid "EncType"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667
|
||||
#: daemon/HTTPServer.cpp:467
|
||||
msgid "Expire LeaseSet"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:697
|
||||
msgid "Inbound tunnels"
|
||||
msgstr ""
|
||||
|
||||
#. tr: Milliseconds
|
||||
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489
|
||||
#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701
|
||||
#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514
|
||||
#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731
|
||||
#, c-format
|
||||
msgid "%dms"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686
|
||||
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716
|
||||
msgid "Outbound tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:496
|
||||
#: daemon/HTTPServer.cpp:521
|
||||
msgid "Tags"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:497
|
||||
#: daemon/HTTPServer.cpp:522
|
||||
msgid "Incoming"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
|
||||
#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526
|
||||
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551
|
||||
msgid "Destination"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:507
|
||||
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:515
|
||||
#: daemon/HTTPServer.cpp:540
|
||||
msgid "Incoming Tags"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529
|
||||
#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554
|
||||
msgid "Tags sessions"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:526
|
||||
#: daemon/HTTPServer.cpp:551
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594
|
||||
#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621
|
||||
msgid "Local Destination"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917
|
||||
#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960
|
||||
msgid "Streams"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:570
|
||||
#: daemon/HTTPServer.cpp:595
|
||||
msgid "Close stream"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:599
|
||||
#: daemon/HTTPServer.cpp:613 daemon/HTTPServer.cpp:1430
|
||||
msgid "Such destination is not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:626
|
||||
msgid "I2CP session not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:602
|
||||
#: daemon/HTTPServer.cpp:629
|
||||
msgid "I2CP is not enabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:628
|
||||
#: daemon/HTTPServer.cpp:658
|
||||
msgid "Invalid"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:631
|
||||
#: daemon/HTTPServer.cpp:661
|
||||
msgid "Store type"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:632
|
||||
#: daemon/HTTPServer.cpp:662
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:637
|
||||
#: daemon/HTTPServer.cpp:667
|
||||
msgid "Non Expired Leases"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:640
|
||||
#: daemon/HTTPServer.cpp:670
|
||||
msgid "Gateway"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:641
|
||||
#: daemon/HTTPServer.cpp:671
|
||||
msgid "TunnelID"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:642
|
||||
#: daemon/HTTPServer.cpp:672
|
||||
msgid "EndDate"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:652
|
||||
#: daemon/HTTPServer.cpp:682
|
||||
msgid "floodfill mode is disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:663
|
||||
#: daemon/HTTPServer.cpp:693
|
||||
msgid "Queue size"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:713
|
||||
#: daemon/HTTPServer.cpp:743
|
||||
msgid "Run peer test"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:714
|
||||
#: daemon/HTTPServer.cpp:744
|
||||
msgid "Reload tunnels configuration"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:717
|
||||
#: daemon/HTTPServer.cpp:747
|
||||
msgid "Decline transit tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:719
|
||||
#: daemon/HTTPServer.cpp:749
|
||||
msgid "Accept transit tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728
|
||||
#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758
|
||||
msgid "Cancel graceful shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730
|
||||
#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760
|
||||
msgid "Start graceful shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:733
|
||||
#: daemon/HTTPServer.cpp:763
|
||||
msgid "Force shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:734
|
||||
#: daemon/HTTPServer.cpp:764
|
||||
msgid "Reload external CSS styles"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:737
|
||||
#: daemon/HTTPServer.cpp:767
|
||||
msgid ""
|
||||
"<b>Note:</b> any action done here are not persistent and not changes your "
|
||||
"config files."
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:739
|
||||
#: daemon/HTTPServer.cpp:770
|
||||
msgid "Logging level"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:747
|
||||
#: daemon/HTTPServer.cpp:779
|
||||
msgid "Transit tunnels limit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771
|
||||
#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803
|
||||
msgid "Change"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:759
|
||||
#: daemon/HTTPServer.cpp:791
|
||||
msgid "Change language"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:797
|
||||
#: daemon/HTTPServer.cpp:830
|
||||
msgid "no transit tunnels currently built"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901
|
||||
#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944
|
||||
msgid "SAM disabled"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:894
|
||||
#: daemon/HTTPServer.cpp:937
|
||||
msgid "no sessions currently running"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:907
|
||||
#: daemon/HTTPServer.cpp:950
|
||||
msgid "SAM session not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:912
|
||||
#: daemon/HTTPServer.cpp:955
|
||||
msgid "SAM Session"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:969
|
||||
#: daemon/HTTPServer.cpp:1020
|
||||
msgid "Server Tunnels"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:985
|
||||
#: daemon/HTTPServer.cpp:1036
|
||||
msgid "Client Forwards"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:999
|
||||
#: daemon/HTTPServer.cpp:1050
|
||||
msgid "Server Forwards"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1199
|
||||
#: daemon/HTTPServer.cpp:1250
|
||||
msgid "Unknown page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1218
|
||||
#: daemon/HTTPServer.cpp:1269
|
||||
msgid "Invalid token"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333
|
||||
#: daemon/HTTPServer.cpp:1373
|
||||
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359
|
||||
#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454
|
||||
msgid "SUCCESS"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1276
|
||||
#: daemon/HTTPServer.cpp:1327
|
||||
msgid "Stream closed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1278
|
||||
#: daemon/HTTPServer.cpp:1329
|
||||
msgid "Stream not found or already was closed"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1281
|
||||
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365
|
||||
msgid "Destination not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1284
|
||||
#: daemon/HTTPServer.cpp:1335
|
||||
msgid "StreamID can't be null"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351
|
||||
#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367
|
||||
#: daemon/HTTPServer.cpp:1432
|
||||
msgid "Return to destination page"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300
|
||||
#: daemon/HTTPServer.cpp:1375
|
||||
#: daemon/HTTPServer.cpp:1338 daemon/HTTPServer.cpp:1368
|
||||
#: daemon/HTTPServer.cpp:1381 daemon/HTTPServer.cpp:1456
|
||||
#, c-format
|
||||
msgid "You will be redirected in %d seconds"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1298
|
||||
#: daemon/HTTPServer.cpp:1359
|
||||
msgid "LeaseSet expiration time updated"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1362
|
||||
msgid "LeaseSet is not found or already expired"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1379
|
||||
#, c-format
|
||||
msgid "Transit tunnels count must not exceed %d"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374
|
||||
#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455
|
||||
msgid "Back to commands list"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1335
|
||||
#: daemon/HTTPServer.cpp:1416
|
||||
msgid "Register at reg.i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1336
|
||||
#: daemon/HTTPServer.cpp:1417
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1336
|
||||
#: daemon/HTTPServer.cpp:1417
|
||||
msgid "A bit information about service on domain"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1337
|
||||
#: daemon/HTTPServer.cpp:1418
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1343
|
||||
#: daemon/HTTPServer.cpp:1424
|
||||
msgid "Domain can't end with .b32.i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1346
|
||||
#: daemon/HTTPServer.cpp:1427
|
||||
msgid "Domain must end with .i2p"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1349
|
||||
msgid "Such destination is not found"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1369
|
||||
#: daemon/HTTPServer.cpp:1450
|
||||
msgid "Unknown command"
|
||||
msgstr ""
|
||||
|
||||
#: daemon/HTTPServer.cpp:1373
|
||||
#: daemon/HTTPServer.cpp:1454
|
||||
msgid "Command accepted"
|
||||
msgstr ""
|
||||
|
||||
@@ -624,20 +642,20 @@ msgstr ""
|
||||
msgid "You may try to find this host on jump services below"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324
|
||||
#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435
|
||||
#: libi2pd_client/HTTPProxy.cpp:333 libi2pd_client/HTTPProxy.cpp:348
|
||||
#: libi2pd_client/HTTPProxy.cpp:417 libi2pd_client/HTTPProxy.cpp:460
|
||||
msgid "Invalid request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:309
|
||||
#: libi2pd_client/HTTPProxy.cpp:333
|
||||
msgid "Proxy unable to parse your request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:324
|
||||
#: libi2pd_client/HTTPProxy.cpp:348
|
||||
msgid "Addresshelper is not supported"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:349
|
||||
#: libi2pd_client/HTTPProxy.cpp:373
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Host %s is <font color=red>already in router's addressbook</font>. <b>Be "
|
||||
@@ -645,121 +663,121 @@ msgid ""
|
||||
"<a href=\"%s%s%s&update=true\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:351
|
||||
#: libi2pd_client/HTTPProxy.cpp:375
|
||||
msgid "Addresshelper forced update rejected"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:358
|
||||
#: libi2pd_client/HTTPProxy.cpp:382
|
||||
#, c-format
|
||||
msgid ""
|
||||
"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s"
|
||||
"\">Continue</a>."
|
||||
"To add host <b>%s</b> in router's addressbook, click here: <a "
|
||||
"href=\"%s%s%s\">Continue</a>."
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:360
|
||||
#: libi2pd_client/HTTPProxy.cpp:384
|
||||
msgid "Addresshelper request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:369
|
||||
#: libi2pd_client/HTTPProxy.cpp:393
|
||||
#, 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:370
|
||||
#: libi2pd_client/HTTPProxy.cpp:395
|
||||
msgid "Addresshelper adding"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:377
|
||||
#: libi2pd_client/HTTPProxy.cpp:402
|
||||
#, 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:379
|
||||
#: libi2pd_client/HTTPProxy.cpp:404
|
||||
msgid "Addresshelper update"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:392
|
||||
#: libi2pd_client/HTTPProxy.cpp:417
|
||||
msgid "Invalid request URI"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:435
|
||||
#: libi2pd_client/HTTPProxy.cpp:460
|
||||
msgid "Can't detect destination host from request"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456
|
||||
#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481
|
||||
msgid "Outproxy failure"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:452
|
||||
#: libi2pd_client/HTTPProxy.cpp:477
|
||||
msgid "Bad outproxy settings"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:455
|
||||
#: libi2pd_client/HTTPProxy.cpp:480
|
||||
#, c-format
|
||||
msgid "Host %s is not inside I2P network, but outproxy is not enabled"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:544
|
||||
#: libi2pd_client/HTTPProxy.cpp:569
|
||||
msgid "Unknown outproxy URL"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:550
|
||||
#: libi2pd_client/HTTPProxy.cpp:575
|
||||
msgid "Cannot resolve upstream proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:558
|
||||
#: libi2pd_client/HTTPProxy.cpp:583
|
||||
msgid "Hostname is too long"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:585
|
||||
#: libi2pd_client/HTTPProxy.cpp:610
|
||||
msgid "Cannot connect to upstream SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:591
|
||||
#: libi2pd_client/HTTPProxy.cpp:616
|
||||
msgid "Cannot negotiate with SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:633
|
||||
#: libi2pd_client/HTTPProxy.cpp:658
|
||||
msgid "CONNECT error"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:633
|
||||
#: libi2pd_client/HTTPProxy.cpp:658
|
||||
msgid "Failed to connect"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670
|
||||
#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695
|
||||
msgid "SOCKS proxy error"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:652
|
||||
#: libi2pd_client/HTTPProxy.cpp:677
|
||||
msgid "Failed to send request to upstream"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:673
|
||||
#: libi2pd_client/HTTPProxy.cpp:698
|
||||
msgid "No reply from SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:680
|
||||
#: libi2pd_client/HTTPProxy.cpp:705
|
||||
msgid "Cannot connect"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:680
|
||||
#: libi2pd_client/HTTPProxy.cpp:705
|
||||
msgid "HTTP out proxy not implemented"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:681
|
||||
#: libi2pd_client/HTTPProxy.cpp:706
|
||||
msgid "Cannot connect to upstream HTTP proxy"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:714
|
||||
#: libi2pd_client/HTTPProxy.cpp:739
|
||||
msgid "Host is down"
|
||||
msgstr ""
|
||||
|
||||
#: libi2pd_client/HTTPProxy.cpp:714
|
||||
#: libi2pd_client/HTTPProxy.cpp:739
|
||||
msgid ""
|
||||
"Can't create connection to requested host, it may be down. Please try again "
|
||||
"later."
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
---
|
||||
|
||||
```
|
||||
xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
|
||||
xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
|
||||
```
|
||||
|
||||
Regex for transforming gettext translations to our format:
|
||||
---
|
||||
|
||||
```
|
||||
in: ^(\"|#[:.,]|msgctxt)(.*)$\n
|
||||
out: <to empty line>
|
||||
```
|
||||
|
||||
```
|
||||
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
|
||||
@@ -18,10 +23,6 @@ in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
|
||||
out: {"$1", "$2"},\n
|
||||
```
|
||||
|
||||
```
|
||||
in: ^#[:.,](.*)$\n
|
||||
out: <to empty line>
|
||||
```
|
||||
|
||||
```
|
||||
in: \n\n
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates
|
||||
# certsdir = /var/lib/i2pd/certificates
|
||||
|
||||
## Where to write pidfile (default: i2pd.pid, not used in Windows)
|
||||
## Where to write pidfile (default: /run/i2pd.pid, not used in Windows)
|
||||
# pidfile = /run/i2pd.pid
|
||||
|
||||
## Logging configuration section
|
||||
@@ -31,7 +31,7 @@
|
||||
## * file - log entries to a file
|
||||
## * syslog - use syslog, see man 3 syslog
|
||||
# log = file
|
||||
## Path to logfile (default - autodetect)
|
||||
## Path to logfile (default: autodetect)
|
||||
# logfile = /var/log/i2pd/i2pd.log
|
||||
## Log messages above this level (debug, info, *warn, error, critical, none)
|
||||
## If you set it to none, logging will be disabled
|
||||
@@ -40,6 +40,7 @@
|
||||
# logclftime = true
|
||||
|
||||
## Daemon mode. Router will go to background after start. Ignored on Windows
|
||||
## (default: true)
|
||||
# daemon = true
|
||||
|
||||
## Specify a family, router belongs to (default - none)
|
||||
@@ -70,58 +71,60 @@
|
||||
## don't just uncomment this
|
||||
# port = 4567
|
||||
|
||||
## Enable communication through ipv4
|
||||
## Enable communication through ipv4 (default: true)
|
||||
ipv4 = true
|
||||
## Enable communication through ipv6
|
||||
## Enable communication through ipv6 (default: false)
|
||||
ipv6 = false
|
||||
|
||||
## Enable SSU transport
|
||||
ssu = false
|
||||
|
||||
## Bandwidth configuration
|
||||
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
|
||||
## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec,
|
||||
## X - unlimited
|
||||
## Default is L (regular node) and X if floodfill mode enabled. If you want to
|
||||
## share more bandwidth without floodfill mode, uncomment that line and adjust
|
||||
## value to your possibilities
|
||||
## Default is L (regular node) and X if floodfill mode enabled.
|
||||
## If you want to share more bandwidth without floodfill mode, uncomment
|
||||
## that line and adjust value to your possibilities. Value can be set to
|
||||
## integer in kilobytes, it will apply that limit and flag will be used
|
||||
## from next upper limit (example: if you set 4096 flag will be X, but real
|
||||
## limit will be 4096 KB/s). Same can be done when floodfill mode is used,
|
||||
## but keep in mind that low values may be negatively evaluated by Java
|
||||
## router algorithms.
|
||||
# bandwidth = L
|
||||
## Max % of bandwidth limit for transit. 0-100. 100 by default
|
||||
## Max % of bandwidth limit for transit. 0-100 (default: 100)
|
||||
# share = 100
|
||||
|
||||
## Router will not accept transit tunnels, disabling transit traffic completely
|
||||
## (default = false)
|
||||
## (default: false)
|
||||
# notransit = true
|
||||
|
||||
## Router will be floodfill
|
||||
## Router will be floodfill (default: false)
|
||||
## Note: that mode uses much more network connections and CPU!
|
||||
# floodfill = true
|
||||
|
||||
[ntcp2]
|
||||
## Enable NTCP2 transport (default = true)
|
||||
## Enable NTCP2 transport (default: true)
|
||||
# enabled = true
|
||||
## Publish address in RouterInfo (default = 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
|
||||
## Enable SSU2 transport (default: true)
|
||||
# enabled = true
|
||||
## Publish address in RouterInfo
|
||||
## Publish address in RouterInfo (default: true)
|
||||
# published = true
|
||||
## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled)
|
||||
## Port for incoming connections (default is global port option value)
|
||||
# port = 4567
|
||||
|
||||
[http]
|
||||
## Web Console settings
|
||||
## Uncomment and set to 'false' to disable Web Console
|
||||
## Enable the Web Console (default: true)
|
||||
# enabled = true
|
||||
## Address and port service will listen on
|
||||
address = 127.0.0.1
|
||||
port = 7070
|
||||
## Path to web console, default "/"
|
||||
## Address and port service will listen on (default: 127.0.0.1:7070)
|
||||
# address = 127.0.0.1
|
||||
# port = 7070
|
||||
## Path to web console (default: /)
|
||||
# webroot = /
|
||||
## Uncomment following lines to enable Web Console authentication
|
||||
## Enable Web Console authentication (default: false)
|
||||
## You should not use Web Console via public networks without additional encryption.
|
||||
## HTTP authentication is not encryption layer!
|
||||
# auth = true
|
||||
@@ -134,12 +137,12 @@ port = 7070
|
||||
# lang = english
|
||||
|
||||
[httpproxy]
|
||||
## Uncomment and set to 'false' to disable HTTP Proxy
|
||||
## Enable the HTTP proxy (default: true)
|
||||
# enabled = true
|
||||
## Address and port service will listen on
|
||||
address = 127.0.0.1
|
||||
port = 4444
|
||||
## Optional keys file for proxy local destination
|
||||
## Address and port service will listen on (default: 127.0.0.1:4444)
|
||||
# address = 127.0.0.1
|
||||
# port = 4444
|
||||
## Optional keys file for proxy local destination (default: http-proxy-keys.dat)
|
||||
# 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,
|
||||
@@ -150,15 +153,15 @@ port = 4444
|
||||
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[socksproxy]
|
||||
## Uncomment and set to 'false' to disable SOCKS Proxy
|
||||
## Enable the SOCKS proxy (default: true)
|
||||
# enabled = true
|
||||
## Address and port service will listen on
|
||||
address = 127.0.0.1
|
||||
port = 4447
|
||||
## Optional keys file for proxy local destination
|
||||
## Address and port service will listen on (default: 127.0.0.1:4447)
|
||||
# address = 127.0.0.1
|
||||
# port = 4447
|
||||
## Optional keys file for proxy local destination (default: socks-proxy-keys.dat)
|
||||
# keys = socks-proxy-keys.dat
|
||||
## Socks outproxy. Example below is set to use Tor for all connections except i2p
|
||||
## Uncomment and set to 'true' to enable using of SOCKS outproxy
|
||||
## Enable using of SOCKS outproxy (works only with SOCKS4, default: false)
|
||||
# outproxy.enabled = false
|
||||
## Address and port of outproxy
|
||||
# outproxy = 127.0.0.1
|
||||
@@ -166,34 +169,34 @@ port = 4447
|
||||
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[sam]
|
||||
## Comment or set to 'false' to disable SAM Bridge
|
||||
enabled = true
|
||||
## Address and ports service will listen on
|
||||
## Enable the SAM bridge (default: true)
|
||||
# enabled = false
|
||||
## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655)
|
||||
# address = 127.0.0.1
|
||||
# port = 7656
|
||||
# portudp = 7655
|
||||
|
||||
[bob]
|
||||
## Uncomment and set to 'true' to enable BOB command channel
|
||||
## Enable the BOB command channel (default: false)
|
||||
# enabled = false
|
||||
## Address and port service will listen on
|
||||
## Address and port service will listen on (default: 127.0.0.1:2827)
|
||||
# address = 127.0.0.1
|
||||
# port = 2827
|
||||
|
||||
[i2cp]
|
||||
## Uncomment and set to 'true' to enable I2CP protocol
|
||||
## Enable the I2CP protocol (default: false)
|
||||
# enabled = false
|
||||
## Address and port service will listen on
|
||||
## Address and port service will listen on (default: 127.0.0.1:7654)
|
||||
# address = 127.0.0.1
|
||||
# port = 7654
|
||||
|
||||
[i2pcontrol]
|
||||
## Uncomment and set to 'true' to enable I2PControl protocol
|
||||
## Enable the I2PControl protocol (default: false)
|
||||
# enabled = false
|
||||
## Address and port service will listen on
|
||||
## Address and port service will listen on (default: 127.0.0.1:7650)
|
||||
# address = 127.0.0.1
|
||||
# port = 7650
|
||||
## Authentication password. "itoopie" by default
|
||||
## Authentication password (default: itoopie)
|
||||
# password = itoopie
|
||||
|
||||
[precomputation]
|
||||
@@ -204,11 +207,11 @@ enabled = true
|
||||
[upnp]
|
||||
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
|
||||
# enabled = false
|
||||
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
|
||||
## Name i2pd appears in UPnP forwardings list (default: I2Pd)
|
||||
# name = I2Pd
|
||||
|
||||
[meshnets]
|
||||
## Enable connectivity over the Yggdrasil network
|
||||
## Enable connectivity over the Yggdrasil network (default: false)
|
||||
# yggdrasil = false
|
||||
## You can bind address from your Yggdrasil subnet 300::/64
|
||||
## The address must first be added to the network interface
|
||||
@@ -216,13 +219,13 @@ enabled = true
|
||||
|
||||
[reseed]
|
||||
## Options for bootstrapping into I2P network, aka reseeding
|
||||
## Enable or disable reseed data verification.
|
||||
## Enable reseed data verification (default: true)
|
||||
verify = true
|
||||
## URLs to request reseed data from, separated by comma
|
||||
## Default: "mainline" I2P Network reseeds
|
||||
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
|
||||
## Reseed URLs through the Yggdrasil, separated by comma
|
||||
# yggurls = http://[324:9de3:fea4:f6ac::ace]:7070/
|
||||
# yggurls = http://[324:71e:281a:9ed3::ace]:7070/
|
||||
## Path to local reseed data file (.su3) for manual reseeding
|
||||
# file = /path/to/i2pseeds.su3
|
||||
## or HTTPS URL to reseed from
|
||||
@@ -232,7 +235,7 @@ verify = true
|
||||
## If you run i2pd behind a proxy server, set proxy server for reseeding here
|
||||
## Should be http://address:port or socks://address:port
|
||||
# proxy = http://127.0.0.1:8118
|
||||
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
|
||||
## Minimum number of known routers, below which i2pd triggers reseeding (default: 25)
|
||||
# threshold = 25
|
||||
|
||||
[addressbook]
|
||||
@@ -252,13 +255,13 @@ verify = true
|
||||
# coresize = 0
|
||||
|
||||
[trust]
|
||||
## Enable explicit trust options. false by default
|
||||
## Enable explicit trust options. (default: false)
|
||||
# enabled = true
|
||||
## Make direct I2P connections only to routers in specified Family.
|
||||
# family = MyFamily
|
||||
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
|
||||
# routers =
|
||||
## Should we hide our router from other routers? false by default
|
||||
## Should we hide our router from other routers? (default: false)
|
||||
# hidden = true
|
||||
|
||||
[exploratory]
|
||||
@@ -277,8 +280,6 @@ verify = true
|
||||
[cpuext]
|
||||
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)
|
||||
# aesni = true
|
||||
## Use CPU AVX instructions set when work with cryptography when available (default: true)
|
||||
# avx = true
|
||||
## Force usage of CPU instructions set, even if they not found
|
||||
## Force usage of CPU instructions set, even if they not found (default: false)
|
||||
## DO NOT TOUCH that option if you really don't know what are you doing!
|
||||
# force = false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.47.0
|
||||
Version: 2.50.2
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@@ -28,9 +28,11 @@ Requires: logrotate
|
||||
Requires: systemd
|
||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||
|
||||
|
||||
%description
|
||||
C++ implementation of I2P.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n i2pd-openssl
|
||||
|
||||
@@ -38,72 +40,56 @@ C++ implementation of I2P.
|
||||
%build
|
||||
cd build
|
||||
%if 0%{?rhel} == 7
|
||||
%cmake3 \
|
||||
%cmake3 \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
-DWITH_HARDENING=ON \
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||
%else
|
||||
%cmake \
|
||||
%cmake \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
-DWITH_HARDENING=ON \
|
||||
%if 0%{?fedora} > 29
|
||||
%if 0%{?fedora} > 29
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF \
|
||||
.
|
||||
%else
|
||||
%else
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
pushd redhat-linux-build
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
|
||||
pushd redhat-linux-build
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
%endif
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
pushd build
|
||||
%if 0%{?mageia} > 7
|
||||
pushd build
|
||||
%endif
|
||||
%endif
|
||||
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
popd
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
|
||||
%install
|
||||
pushd build
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
pushd redhat-linux-build
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
|
||||
pushd redhat-linux-build
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
%endif
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia}
|
||||
pushd build
|
||||
%if 0%{?mageia}
|
||||
pushd build
|
||||
%endif
|
||||
%endif
|
||||
|
||||
chrpath -d i2pd
|
||||
@@ -158,6 +144,21 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
|
||||
- update to 2.50.2
|
||||
|
||||
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
|
||||
- update to 2.50.1
|
||||
|
||||
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
|
||||
- update to 2.50.0
|
||||
|
||||
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
|
||||
- update to 2.49.0
|
||||
|
||||
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
|
||||
- update to 2.48.0
|
||||
|
||||
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
|
||||
- update to 2.47.0
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.47.0
|
||||
Version: 2.50.2
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@@ -26,9 +26,11 @@ Requires: logrotate
|
||||
Requires: systemd
|
||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||
|
||||
|
||||
%description
|
||||
C++ implementation of I2P.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
@@ -36,71 +38,56 @@ C++ implementation of I2P.
|
||||
%build
|
||||
cd build
|
||||
%if 0%{?rhel} == 7
|
||||
%cmake3 \
|
||||
%cmake3 \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
-DWITH_HARDENING=ON \
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||
%else
|
||||
%cmake \
|
||||
%cmake \
|
||||
-DWITH_LIBRARY=OFF \
|
||||
-DWITH_UPNP=ON \
|
||||
-DWITH_HARDENING=ON \
|
||||
%if 0%{?fedora} > 29
|
||||
%if 0%{?fedora} > 29
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF \
|
||||
.
|
||||
%else
|
||||
%else
|
||||
-DBUILD_SHARED_LIBS:BOOL=OFF
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
pushd redhat-linux-build
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
|
||||
pushd redhat-linux-build
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
%endif
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
pushd build
|
||||
%if 0%{?mageia} > 7
|
||||
pushd build
|
||||
%endif
|
||||
%endif
|
||||
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
popd
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
|
||||
%install
|
||||
pushd build
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
pushd redhat-linux-build
|
||||
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
|
||||
pushd redhat-linux-build
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
%endif
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia}
|
||||
pushd build
|
||||
%if 0%{?mageia}
|
||||
pushd build
|
||||
%endif
|
||||
%endif
|
||||
|
||||
chrpath -d i2pd
|
||||
@@ -155,6 +142,21 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
|
||||
- update to 2.50.2
|
||||
|
||||
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
|
||||
- update to 2.50.1
|
||||
|
||||
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
|
||||
- update to 2.50.0
|
||||
|
||||
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
|
||||
- update to 2.49.0
|
||||
|
||||
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
|
||||
- update to 2.48.0
|
||||
|
||||
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
|
||||
- update to 2.47.0
|
||||
|
||||
|
||||
@@ -150,12 +150,11 @@ namespace util
|
||||
|
||||
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
||||
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::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
|
||||
|
||||
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace http {
|
||||
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_COMMAND_EXPIRELEASE[] = "expirelease";
|
||||
|
||||
static std::string ConvertTime (uint64_t time)
|
||||
{
|
||||
@@ -221,18 +222,19 @@ namespace http {
|
||||
s << "<b>" << tr("ERROR") << ":</b> " << string << "<br>\r\n";
|
||||
}
|
||||
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error)
|
||||
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case eRouterStatusOK: s << tr("OK"); break;
|
||||
case eRouterStatusTesting: s << tr("Testing"); break;
|
||||
case eRouterStatusFirewalled: s << tr("Firewalled"); break;
|
||||
case eRouterStatusUnknown: s << tr("Unknown"); break;
|
||||
case eRouterStatusProxy: s << tr("Proxy"); break;
|
||||
case eRouterStatusMesh: s << tr("Mesh"); break;
|
||||
default: s << tr("Unknown");
|
||||
}
|
||||
if (testing)
|
||||
s << " (" << tr("Testing") << ")";
|
||||
if (error != eRouterErrorNone)
|
||||
{
|
||||
switch (error)
|
||||
@@ -263,12 +265,12 @@ namespace http {
|
||||
ShowUptime(s, i2p::context.GetUptime ());
|
||||
s << "<br>\r\n";
|
||||
s << "<b>" << tr("Network status") << ":</b> ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
|
||||
s << "<br>\r\n";
|
||||
if (i2p::context.SupportsV6 ())
|
||||
{
|
||||
s << "<b>" << tr("Network status v6") << ":</b> ";
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ());
|
||||
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
|
||||
s << "<br>\r\n";
|
||||
}
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
@@ -421,8 +423,12 @@ namespace http {
|
||||
|
||||
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
|
||||
{
|
||||
s << "<b>Base32:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"1\">";
|
||||
s << dest->GetIdentHash ().ToBase32 () << "</textarea><br>\r\n<br>\r\n";
|
||||
|
||||
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"8\">";
|
||||
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
|
||||
|
||||
if (dest->IsEncryptedLeaseSet ())
|
||||
{
|
||||
i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
|
||||
@@ -434,12 +440,11 @@ namespace http {
|
||||
if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ())
|
||||
{
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
auto base32 = dest->GetIdentHash ().ToBase32 ();
|
||||
s << "<div class='slide'><label for='slide-regaddr'><b>" << tr("Address registration line") << "</b></label>\r\n<input type=\"checkbox\" id=\"slide-regaddr\" />\r\n<div class=\"slidecontent\">\r\n"
|
||||
"<form method=\"get\" action=\"" << webroot << "\">\r\n"
|
||||
" <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_GET_REG_STRING << "\">\r\n"
|
||||
" <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
|
||||
" <input type=\"hidden\" name=\"b32\" value=\"" << base32 << "\">\r\n"
|
||||
" <input type=\"hidden\" name=\"b32\" value=\"" << dest->GetIdentHash ().ToBase32 () << "\">\r\n"
|
||||
" <b>" << tr("Domain") << ":</b>\r\n<input type=\"text\" maxlength=\"67\" name=\"name\" placeholder=\"domain.i2p\" required>\r\n"
|
||||
" <button type=\"submit\">" << tr("Generate") << "</button>\r\n"
|
||||
"</form>\r\n<small>" << tr("<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "</small>\r\n</div>\r\n</div>\r\n<br>\r\n";
|
||||
@@ -448,9 +453,23 @@ namespace http {
|
||||
if (dest->GetNumRemoteLeaseSets())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide-lease'><b>" << tr("LeaseSets") << ":</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
||||
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n<table><thead><th>"<< tr("Address") << "</th><th>" << tr("Type") << "</th><th>" << tr("EncType") << "</th></thead><tbody class=\"tableitem\">";
|
||||
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n"
|
||||
<< "<table><thead>"
|
||||
<< "<th>" << tr("Address") << "</th>"
|
||||
<< "<th style=\"width:5px;\"> </th>" // LeaseSet expiration button column
|
||||
<< "<th>" << tr("Type") << "</th>"
|
||||
<< "<th>" << tr("EncType") << "</th>"
|
||||
<< "</thead><tbody class=\"tableitem\">";
|
||||
for(auto& it: dest->GetLeaseSets ())
|
||||
s << "<tr><td>" << it.first.ToBase32 () << "</td><td>" << (int)it.second->GetStoreType () << "</td><td>" << (int)it.second->GetEncryptionType () <<"</td></tr>\r\n";
|
||||
{
|
||||
s << "<tr>"
|
||||
<< "<td>" << it.first.ToBase32 () << "</td>"
|
||||
<< "<td><a class=\"button\" href=\"/?cmd=" << HTTP_COMMAND_EXPIRELEASE<< "&b32=" << dest->GetIdentHash ().ToBase32 ()
|
||||
<< "&lease=" << it.first.ToBase32 () << "&token=" << token << "\" title=\"" << tr("Expire LeaseSet") << "\"> ✘ </a></td>"
|
||||
<< "<td>" << (int)it.second->GetStoreType () << "</td>"
|
||||
<< "<td>" << (int)it.second->GetEncryptionType () <<"</td>"
|
||||
<< "</tr>\r\n";
|
||||
}
|
||||
s << "</tbody></table>\r\n</div>\r\n</div>\r\n<br>\r\n";
|
||||
} else
|
||||
s << "<b>" << tr("LeaseSets") << ":</b> <i>0</i><br>\r\n<br>\r\n";
|
||||
@@ -591,6 +610,8 @@ namespace http {
|
||||
}
|
||||
s << "</tbody>\r\n</table>";
|
||||
}
|
||||
else
|
||||
ShowError(s, tr("Such destination is not found"));
|
||||
}
|
||||
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
||||
@@ -958,34 +979,42 @@ namespace http {
|
||||
void ShowI2PTunnels (std::stringstream& s)
|
||||
{
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
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;
|
||||
}
|
||||
|
||||
auto& clientTunnels = i2p::client::context.GetClientTunnels ();
|
||||
auto httpProxy = i2p::client::context.GetHttpProxy ();
|
||||
if (httpProxy)
|
||||
{
|
||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << "HTTP " << tr("Proxy") << "</a> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "</div>\r\n"<< std::endl;
|
||||
}
|
||||
auto socksProxy = i2p::client::context.GetSocksProxy ();
|
||||
if (socksProxy)
|
||||
if (!clientTunnels.empty () || httpProxy || socksProxy)
|
||||
{
|
||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << "SOCKS " << tr("Proxy") << "</a> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "</div>\r\n"<< std::endl;
|
||||
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
if (!clientTunnels.empty ())
|
||||
{
|
||||
for (auto& it: clientTunnels)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (httpProxy)
|
||||
{
|
||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << "HTTP " << tr("Proxy") << "</a> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "</div>\r\n"<< std::endl;
|
||||
}
|
||||
if (socksProxy)
|
||||
{
|
||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||
s << "SOCKS " << tr("Proxy") << "</a> ⇐ ";
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||
s << "</div>\r\n"<< std::endl;
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
|
||||
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
|
||||
if (!serverTunnels.empty ()) {
|
||||
@@ -1312,6 +1341,36 @@ namespace http {
|
||||
res.add_header("Refresh", redirect.c_str());
|
||||
return;
|
||||
}
|
||||
else if (cmd == HTTP_COMMAND_EXPIRELEASE)
|
||||
{
|
||||
std::string b32 = params["b32"];
|
||||
std::string lease = params["lease"];
|
||||
|
||||
i2p::data::IdentHash ident, leaseident;
|
||||
ident.FromBase32 (b32);
|
||||
leaseident.FromBase32 (lease);
|
||||
auto dest = i2p::client::context.FindLocalDestination (ident);
|
||||
|
||||
if (dest)
|
||||
{
|
||||
auto leaseset = dest->FindLeaseSet (leaseident);
|
||||
if (leaseset)
|
||||
{
|
||||
leaseset->ExpireLease ();
|
||||
s << "<b>" << tr("SUCCESS") << "</b>: " << tr("LeaseSet expiration time updated") << "<br>\r\n<br>\r\n";
|
||||
}
|
||||
else
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("LeaseSet is not found or already expired") << "<br>\r\n<br>\r\n";
|
||||
}
|
||||
else
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("Destination not found") << "<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 %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);
|
||||
|
||||
30
debian/changelog
vendored
30
debian/changelog
vendored
@@ -1,3 +1,33 @@
|
||||
i2pd (2.50.2) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.50.2/0.9.61
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Sat, 06 Jan 2024 16:00:00 +0000
|
||||
|
||||
i2pd (2.50.1-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.50.1/0.9.61
|
||||
|
||||
-- r4sas <r4sas@i2pmail.org> Sat, 23 Dec 2023 18:30:00 +0000
|
||||
|
||||
i2pd (2.50.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.50.0/0.9.61
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Mon, 18 Dec 2023 16:00:00 +0000
|
||||
|
||||
i2pd (2.49.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.49.0/0.9.60
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Mon, 18 Sep 2023 16:00:00 +0000
|
||||
|
||||
i2pd (2.48.0-1) unstable; urgency=high
|
||||
|
||||
* updated to version 2.48.0/0.9.59
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Mon, 12 Jun 2023 16:00:00 +0000
|
||||
|
||||
i2pd (2.47.0-1) unstable; urgency=high
|
||||
|
||||
* updated to version 2.47.0/0.9.58
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -2,7 +2,7 @@ Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
Build-Depends: debhelper (>= 12~), clang, cmake, 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
|
||||
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
|
||||
|
||||
10
debian/copyright
vendored
10
debian/copyright
vendored
@@ -1,19 +1,23 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: i2pd
|
||||
Source: https://github.com/PurpleI2P/i2pd
|
||||
Source: https://github.com/PurpleI2P
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2023 The PurpleI2P Project
|
||||
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-2023 R4SAS <r4sas@i2pmail.org>
|
||||
2017-2023 Yangfl <mmyangfl@gmail.com>
|
||||
2017-2020 Yangfl <mmyangfl@gmail.com>
|
||||
License: GPL-2+
|
||||
|
||||
License: BSD-3-clause
|
||||
Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
.
|
||||
All rights reserved.
|
||||
.
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
.
|
||||
|
||||
2
debian/i2pd.1
vendored
2
debian/i2pd.1
vendored
@@ -64,7 +64,7 @@ The network interface to bind to for IPv4 connections
|
||||
The network interface to bind to for IPv6 connections
|
||||
.TP
|
||||
\fB\-\-ipv4=\fR
|
||||
Enable communication through ipv6 (\fIenabled\fR by default)
|
||||
Enable communication through ipv4 (\fIenabled\fR by default)
|
||||
.TP
|
||||
\fB\-\-ipv6\fR
|
||||
Enable communication through ipv6 (\fIdisabled\fR by default)
|
||||
|
||||
2
debian/i2pd.install
vendored
2
debian/i2pd.install
vendored
@@ -1,4 +1,4 @@
|
||||
obj-*/i2pd usr/sbin/
|
||||
i2pd usr/sbin/
|
||||
contrib/i2pd.conf etc/i2pd/
|
||||
contrib/tunnels.conf etc/i2pd/
|
||||
contrib/certificates/ usr/share/i2pd/
|
||||
|
||||
17
debian/patches/01-upnp.patch
vendored
Normal file
17
debian/patches/01-upnp.patch
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Description: Enable UPnP usage in package
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2022-03-23
|
||||
|
||||
--- i2pd.orig/Makefile
|
||||
+++ i2pd/Makefile
|
||||
@@ -31,7 +31,7 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
-USE_UPNP := $(or $(USE_UPNP),no)
|
||||
+USE_UPNP := $(or $(USE_UPNP),yes)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
|
||||
1
debian/patches/series
vendored
Normal file
1
debian/patches/series
vendored
Normal file
@@ -0,0 +1 @@
|
||||
01-upnp.patch
|
||||
15
debian/rules
vendored
15
debian/rules
vendored
@@ -7,20 +7,7 @@ include /usr/share/dpkg/architecture.mk
|
||||
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
export DEB_LDFLAGS_MAINT_APPEND =
|
||||
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake
|
||||
|
||||
override_dh_auto_clean:
|
||||
dh_auto_clean --buildsystem=cmake --sourcedirectory=build/
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure --buildsystem=cmake --sourcedirectory=build/ -- \
|
||||
-DWITH_UPNP=ON
|
||||
|
||||
override_dh_auto_build:
|
||||
dh_auto_build --buildsystem=cmake
|
||||
dh $@
|
||||
|
||||
override_dh_auto_install:
|
||||
|
||||
@@ -109,6 +109,7 @@ namespace chinese // language namespace
|
||||
{"Local Destination", "本地目标"},
|
||||
{"Streams", "流"},
|
||||
{"Close stream", "断开流"},
|
||||
{"Such destination is not found", "找不到此目标"},
|
||||
{"I2CP session not found", "未找到 I2CP 会话"},
|
||||
{"I2CP is not enabled", "I2CP 未启用"},
|
||||
{"Invalid", "无效"},
|
||||
@@ -158,7 +159,6 @@ namespace chinese // language namespace
|
||||
{"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", "代理错误"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace french // language namespace
|
||||
{"Stopping in", "Arrêt dans"},
|
||||
{"Family", "Famille"},
|
||||
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
|
||||
{"Total tunnel creation success rate", "Taux de réussite de création de tunnel"},
|
||||
{"Received", "Reçu"},
|
||||
{"%.2f KiB/s", "%.2f Kio/s"},
|
||||
{"Sent", "Envoyé"},
|
||||
@@ -91,10 +92,11 @@ namespace french // language namespace
|
||||
{"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."},
|
||||
{"<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"},
|
||||
{"Type", "Type"},
|
||||
{"EncType", "EncType"},
|
||||
{"Expire LeaseSet", "Expirer le jeu de baux"},
|
||||
{"Inbound tunnels", "Tunnels entrants"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Tunnels sortants"},
|
||||
@@ -109,6 +111,7 @@ namespace french // language namespace
|
||||
{"Local Destination", "Destination locale"},
|
||||
{"Streams", "Flux"},
|
||||
{"Close stream", "Fermer le flux"},
|
||||
{"Such destination is not found", "Cette destination est introuvable"},
|
||||
{"I2CP session not found", "Session I2CP introuvable"},
|
||||
{"I2CP is not enabled", "I2CP est désactivé"},
|
||||
{"Invalid", "Invalide"},
|
||||
@@ -128,7 +131,7 @@ namespace french // language namespace
|
||||
{"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."},
|
||||
{"<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"},
|
||||
@@ -150,6 +153,8 @@ namespace french // language namespace
|
||||
{"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 %d seconds", "Vous serez redirigé dans %d secondes"},
|
||||
{"LeaseSet expiration time updated", "Temps d'expiration du jeu de baux mis à jour"},
|
||||
{"LeaseSet is not found or already expired", "Le jeu de baux est introuvable ou a déjà expiré"},
|
||||
{"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"},
|
||||
{"Back to commands list", "Retour à la liste des commandes"},
|
||||
{"Register at reg.i2p", "Inscription à reg.i2p"},
|
||||
@@ -158,24 +163,23 @@ namespace french // language namespace
|
||||
{"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"},
|
||||
{"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 %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>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
|
||||
{"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>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
|
||||
{"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"},
|
||||
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
|
||||
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
|
||||
{"Addresshelper request", "Demande à l'assistant d'adresse"},
|
||||
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "L'hôte %s a été ajouté au carnet d'adresses du routeur depuis l'assistant. Cliquez ici pour continuer : <a href=\"%s\">Continuer</a>."},
|
||||
{"Addresshelper adding", "Ajout de l'assistant d'adresse"},
|
||||
{"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>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
|
||||
{"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>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
|
||||
{"Addresshelper update", "Mise à jour de l'assistant 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"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace italian // language namespace
|
||||
{"Stopping in", "Arresto in"},
|
||||
{"Family", "Famiglia"},
|
||||
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
|
||||
{"Total tunnel creation success rate", "Percentuale di successo totale nella creazione del tunnel"},
|
||||
{"Received", "Ricevuti"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Inviati"},
|
||||
@@ -95,6 +96,7 @@ namespace italian // language namespace
|
||||
{"Address", "Indirizzo"},
|
||||
{"Type", "Tipologia"},
|
||||
{"EncType", "Tipo di crittografia"},
|
||||
{"Expire LeaseSet", "Scadenza LeaseSet"},
|
||||
{"Inbound tunnels", "Tunnel in entrata"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Tunnel in uscita"},
|
||||
@@ -109,6 +111,7 @@ namespace italian // language namespace
|
||||
{"Local Destination", "Destinazione locale"},
|
||||
{"Streams", "Flussi"},
|
||||
{"Close stream", "Interrompi il flusso"},
|
||||
{"Such destination is not found", "Questa destinazione non è stata trovata"},
|
||||
{"I2CP session not found", "Sessione I2CP non trovata"},
|
||||
{"I2CP is not enabled", "I2CP non è abilitato"},
|
||||
{"Invalid", "Invalido"},
|
||||
@@ -150,6 +153,8 @@ namespace italian // language namespace
|
||||
{"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 %d seconds", "Sarai reindirizzato tra %d secondi"},
|
||||
{"LeaseSet expiration time updated", "Tempo di scadenza LeaseSet aggiornato"},
|
||||
{"LeaseSet is not found or already expired", "LeaseSet non trovato o già scaduto"},
|
||||
{"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"},
|
||||
{"Back to commands list", "Ritorna alla lista dei comandi"},
|
||||
{"Register at reg.i2p", "Registra a reg.i2p"},
|
||||
@@ -158,7 +163,6 @@ namespace italian // language namespace
|
||||
{"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"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace portuguese // language namespace
|
||||
{"Stopping in", "Parando em"},
|
||||
{"Family", "Família"},
|
||||
{"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"},
|
||||
{"Total tunnel creation success rate", "Taxa total de sucesso na criação de túneis"},
|
||||
{"Received", "Recebido"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Enviado"},
|
||||
@@ -95,6 +96,7 @@ namespace portuguese // language namespace
|
||||
{"Address", "Endereço"},
|
||||
{"Type", "Tipo"},
|
||||
{"EncType", "Tipo de Criptografia"},
|
||||
{"Expire LeaseSet", "Expirar LeaseSet"},
|
||||
{"Inbound tunnels", "Túneis de Entrada"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Túneis de Saída"},
|
||||
@@ -109,6 +111,7 @@ namespace portuguese // language namespace
|
||||
{"Local Destination", "Destinos Locais"},
|
||||
{"Streams", "Fluxos"},
|
||||
{"Close stream", "Fechar fluxo"},
|
||||
{"Such destination is not found", "Tal destino não foi encontrado"},
|
||||
{"I2CP session not found", "Sessão do I2CP não encontrada"},
|
||||
{"I2CP is not enabled", "I2CP não está ativado"},
|
||||
{"Invalid", "Inválido"},
|
||||
@@ -150,6 +153,8 @@ namespace portuguese // language namespace
|
||||
{"StreamID can't be null", "StreamID não pode ser nulo"},
|
||||
{"Return to destination page", "Retornar para à página de destino"},
|
||||
{"You will be redirected in %d seconds", "Você será redirecionado em %d segundos"},
|
||||
{"LeaseSet expiration time updated", "Tempo de validade do LeaseSet atualizado"},
|
||||
{"LeaseSet is not found or already expired", "LeaseSet não foi encontrado ou já expirou"},
|
||||
{"Transit tunnels count must not exceed %d", "A contagem de túneis de trânsito não deve exceder %d"},
|
||||
{"Back to commands list", "Voltar para a lista de comandos"},
|
||||
{"Register at reg.i2p", "Registrar na reg.i2p"},
|
||||
@@ -158,7 +163,6 @@ namespace portuguese // language namespace
|
||||
{"Submit", "Enviar"},
|
||||
{"Domain can't end with .b32.i2p", "O domínio não pode terminar com .b32.i2p"},
|
||||
{"Domain must end with .i2p", "O domínio não pode terminar com .i2p"},
|
||||
{"Such destination is not found", "Tal destino não foi encontrado"},
|
||||
{"Unknown command", "Comando desconhecido"},
|
||||
{"Command accepted", "Comando aceito"},
|
||||
{"Proxy error", "Erro no proxy"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace russian // language namespace
|
||||
{"Stopping in", "Остановка через"},
|
||||
{"Family", "Семейство"},
|
||||
{"Tunnel creation success rate", "Успешно построенных туннелей"},
|
||||
{"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"},
|
||||
{"Received", "Получено"},
|
||||
{"%.2f KiB/s", "%.2f КиБ/с"},
|
||||
{"Sent", "Отправлено"},
|
||||
@@ -95,6 +96,7 @@ namespace russian // language namespace
|
||||
{"Address", "Адрес"},
|
||||
{"Type", "Тип"},
|
||||
{"EncType", "ТипШифр"},
|
||||
{"Expire LeaseSet", "Просрочить Лизсет"},
|
||||
{"Inbound tunnels", "Входящие туннели"},
|
||||
{"%dms", "%dмс"},
|
||||
{"Outbound tunnels", "Исходящие туннели"},
|
||||
@@ -109,6 +111,7 @@ namespace russian // language namespace
|
||||
{"Local Destination", "Локальное назначение"},
|
||||
{"Streams", "Стримы"},
|
||||
{"Close stream", "Закрыть стрим"},
|
||||
{"Such destination is not found", "Такая точка назначения не найдена"},
|
||||
{"I2CP session not found", "I2CP сессия не найдена"},
|
||||
{"I2CP is not enabled", "I2CP не включен"},
|
||||
{"Invalid", "Некорректный"},
|
||||
@@ -150,6 +153,8 @@ namespace russian // language namespace
|
||||
{"StreamID can't be null", "StreamID не может быть пустым"},
|
||||
{"Return to destination page", "Вернуться на страницу точки назначения"},
|
||||
{"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"},
|
||||
{"LeaseSet expiration time updated", "Время действия LeaseSet обновлено"},
|
||||
{"LeaseSet is not found or already expired", "Лизсет не найден или время действия уже истекло"},
|
||||
{"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"},
|
||||
{"Back to commands list", "Вернуться к списку команд"},
|
||||
{"Register at reg.i2p", "Зарегистрировать на reg.i2p"},
|
||||
@@ -158,7 +163,6 @@ namespace russian // language namespace
|
||||
{"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", "Ошибка прокси"},
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace swedish // language namespace
|
||||
{"Clock skew", "Tidsförskjutning"},
|
||||
{"Offline", "Nedkopplad"},
|
||||
{"Symmetric NAT", "Symmetrisk NAT"},
|
||||
{"Full cone NAT", "Full kon NAT"},
|
||||
{"No Descriptors", "Inga Beskrivningar"},
|
||||
{"Uptime", "Upptid"},
|
||||
{"Network status", "Nätverkstillstånd"},
|
||||
{"Network status v6", "Nätverkstillstånd v6"},
|
||||
@@ -107,6 +109,7 @@ namespace swedish // language namespace
|
||||
{"Local Destination", "Lokal Plats"},
|
||||
{"Streams", "Strömmar"},
|
||||
{"Close stream", "Stäng strömmen"},
|
||||
{"Such destination is not found", "En sådan plats hittas ej"},
|
||||
{"I2CP session not found", "I2CP-period hittades inte"},
|
||||
{"I2CP is not enabled", "I2CP är inte påslaget"},
|
||||
{"Invalid", "Ogiltig"},
|
||||
@@ -116,8 +119,10 @@ namespace swedish // language namespace
|
||||
{"Gateway", "Gateway"},
|
||||
{"TunnelID", "TunnelID"},
|
||||
{"EndDate", "EndDate"},
|
||||
{"floodfill mode is disabled", "Floodfill läget är inaktiverat"},
|
||||
{"Queue size", "Köstorlek"},
|
||||
{"Run peer test", "Utför utsiktstest"},
|
||||
{"Reload tunnels configuration", "Ladda om tunnelkonfiguration"},
|
||||
{"Decline transit tunnels", "Avvisa förmedlande tunnlar"},
|
||||
{"Accept transit tunnels", "Tillåt förmedlande tunnlar"},
|
||||
{"Cancel graceful shutdown", "Avbryt välvillig avstängning"},
|
||||
@@ -154,7 +159,6 @@ namespace swedish // language namespace
|
||||
{"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"},
|
||||
@@ -165,6 +169,14 @@ namespace swedish // language namespace
|
||||
{"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 %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>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. <b>Var försiktig: källan till denna URL kan vara skadlig!</b> Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
|
||||
{"Addresshelper forced update rejected", "Tvingad uppdatering av adresshjälparen nekad"},
|
||||
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "För att lägga till värd <b>%s</b> i routerns adressbok, klicka här: <a href=\"%s%s%s\">Fortsätt</a>."},
|
||||
{"Addresshelper request", "Adresshjälpare förfrågan"},
|
||||
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Värd %s tillagd i routerns adressbok från hjälparen. Klicka här för att fortsätta: <a href=\"%s\">Fortsätt</a>."},
|
||||
{"Addresshelper adding", "Adresshjälpare tilläggning"},
|
||||
{"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>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
|
||||
{"Addresshelper update", "Adresshjälpare uppdatering"},
|
||||
{"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"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace ukrainian // language namespace
|
||||
{"Stopping in", "Зупинка через"},
|
||||
{"Family", "Сімейство"},
|
||||
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
|
||||
{"Total tunnel creation success rate", "Загальна кількість створених тунелів"},
|
||||
{"Received", "Отримано"},
|
||||
{"%.2f KiB/s", "%.2f КіБ/с"},
|
||||
{"Sent", "Відправлено"},
|
||||
@@ -95,6 +96,7 @@ namespace ukrainian // language namespace
|
||||
{"Address", "Адреса"},
|
||||
{"Type", "Тип"},
|
||||
{"EncType", "ТипШифр"},
|
||||
{"Expire LeaseSet", "Завершити LeaseSet"},
|
||||
{"Inbound tunnels", "Вхідні тунелі"},
|
||||
{"%dms", "%dмс"},
|
||||
{"Outbound tunnels", "Вихідні тунелі"},
|
||||
@@ -109,6 +111,7 @@ namespace ukrainian // language namespace
|
||||
{"Local Destination", "Локальні Призначення"},
|
||||
{"Streams", "Потоки"},
|
||||
{"Close stream", "Закрити потік"},
|
||||
{"Such destination is not found", "Така точка призначення не знайдена"},
|
||||
{"I2CP session not found", "I2CP сесія не знайдена"},
|
||||
{"I2CP is not enabled", "I2CP не увікнуто"},
|
||||
{"Invalid", "Некоректний"},
|
||||
@@ -150,6 +153,8 @@ namespace ukrainian // language namespace
|
||||
{"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"},
|
||||
{"Return to destination page", "Повернутися на сторінку точки призначення"},
|
||||
{"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"},
|
||||
{"LeaseSet expiration time updated", "Час закінчення LeaseSet оновлено"},
|
||||
{"LeaseSet is not found or already expired", "LeaseSet не знайдено або вже закінчився"},
|
||||
{"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"},
|
||||
{"Back to commands list", "Повернутися до списку команд"},
|
||||
{"Register at reg.i2p", "Зареєструвати на reg.i2p"},
|
||||
@@ -158,7 +163,6 @@ namespace ukrainian // language namespace
|
||||
{"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", "Помилка проксі"},
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace uzbek // language namespace
|
||||
{"Stopping in", "Ichida to'xtatish"},
|
||||
{"Family", "Oila"},
|
||||
{"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"},
|
||||
{"Total tunnel creation success rate", "Tunnel yaratishning umumiy muvaffaqiyat darajasi"},
|
||||
{"Received", "Qabul qilindi"},
|
||||
{"%.2f KiB/s", "%.2f KiB/s"},
|
||||
{"Sent", "Yuborilgan"},
|
||||
@@ -95,6 +96,7 @@ namespace uzbek // language namespace
|
||||
{"Address", "Manzil"},
|
||||
{"Type", "Turi"},
|
||||
{"EncType", "ShifrlashTuri"},
|
||||
{"Expire LeaseSet", "LeaseSet muddati tugaydi"},
|
||||
{"Inbound tunnels", "Kirish tunnellari"},
|
||||
{"%dms", "%dms"},
|
||||
{"Outbound tunnels", "Chiquvchi tunnellar"},
|
||||
@@ -109,6 +111,7 @@ namespace uzbek // language namespace
|
||||
{"Local Destination", "Mahalliy joylanish"},
|
||||
{"Streams", "Strim"},
|
||||
{"Close stream", "Strimni o'chirish"},
|
||||
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
|
||||
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
|
||||
{"I2CP is not enabled", "I2CP yoqilmagan"},
|
||||
{"Invalid", "Noto'g'ri"},
|
||||
@@ -150,6 +153,8 @@ namespace uzbek // language namespace
|
||||
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
|
||||
{"Return to destination page", "Manzilgoh sahifasiga qaytish"},
|
||||
{"You will be redirected in %d seconds", "Siz %d soniyadan so‘ng boshqa yo‘nalishga yo‘naltirilasiz"},
|
||||
{"LeaseSet expiration time updated", "LeaseSet amal qilish muddati yangilandi"},
|
||||
{"LeaseSet is not found or already expired", "LeaseSet topilmadi yoki muddati tugagan"},
|
||||
{"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"},
|
||||
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
|
||||
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
|
||||
@@ -158,7 +163,6 @@ namespace uzbek // language namespace
|
||||
{"Submit", "Yuborish"},
|
||||
{"Domain can't end with .b32.i2p", "Domen .b32.i2p bilan tugashi mumkin emas"},
|
||||
{"Domain must end with .i2p", "Domen .i2p bilan tugashi kerak"},
|
||||
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
|
||||
{"Unknown command", "Noma'lum buyruq"},
|
||||
{"Command accepted", "Buyruq qabul qilindi"},
|
||||
{"Proxy error", "Proksi xatosi"},
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -28,6 +28,11 @@ namespace data
|
||||
return T32;
|
||||
}
|
||||
|
||||
bool IsBase32 (char ch)
|
||||
{
|
||||
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
|
||||
}
|
||||
|
||||
static void iT64Build(void);
|
||||
|
||||
/*
|
||||
@@ -55,6 +60,11 @@ namespace data
|
||||
return T64;
|
||||
}
|
||||
|
||||
bool IsBase64 (char ch)
|
||||
{
|
||||
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~';
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse Substitution Table (built in run time)
|
||||
*/
|
||||
@@ -187,6 +197,9 @@ namespace data
|
||||
else
|
||||
return 0;
|
||||
|
||||
if(*InBuffer == P64)
|
||||
return 0;
|
||||
|
||||
ps = (unsigned char *)(InBuffer + InCount - 1);
|
||||
while ( *ps-- == P64 )
|
||||
outCount--;
|
||||
@@ -269,7 +282,7 @@ namespace data
|
||||
|
||||
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen)
|
||||
{
|
||||
int tmp = 0, bits = 0;
|
||||
unsigned int tmp = 0, bits = 0;
|
||||
size_t ret = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
@@ -298,7 +311,7 @@ namespace data
|
||||
size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
|
||||
{
|
||||
size_t ret = 0, pos = 1;
|
||||
int bits = 8, tmp = inBuf[0];
|
||||
unsigned int bits = 8, tmp = inBuf[0];
|
||||
while (ret < outLen && (bits > 0 || pos < len))
|
||||
{
|
||||
if (bits < 5)
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -19,9 +19,11 @@ namespace data {
|
||||
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
|
||||
const char * GetBase32SubstitutionTable ();
|
||||
const char * GetBase64SubstitutionTable ();
|
||||
bool IsBase64 (char ch);
|
||||
|
||||
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
|
||||
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
||||
bool IsBase32 (char ch);
|
||||
|
||||
/**
|
||||
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -7,52 +7,62 @@
|
||||
*/
|
||||
|
||||
#include "CPU.h"
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#include "Log.h"
|
||||
|
||||
#ifndef bit_AES
|
||||
#define bit_AES (1 << 25)
|
||||
#endif
|
||||
#ifndef bit_AVX
|
||||
#define bit_AVX (1 << 28)
|
||||
#define bit_AES (1 << 25)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace cpu
|
||||
{
|
||||
bool aesni = false;
|
||||
bool avx = false;
|
||||
|
||||
void Detect(bool AesSwitch, bool AvxSwitch, bool force)
|
||||
inline bool cpu_support_aes()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
int info[4];
|
||||
__cpuid(0, info[0], info[1], info[2], info[3]);
|
||||
if (info[0] >= 0x00000001) {
|
||||
__cpuid(0x00000001, info[0], info[1], info[2], info[3]);
|
||||
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
|
||||
if (AesSwitch && force) { // only if forced
|
||||
#else
|
||||
if ((info[2] & bit_AES && AesSwitch) || (AesSwitch && force)) {
|
||||
#endif
|
||||
aesni = true;
|
||||
}
|
||||
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
|
||||
if (AvxSwitch && force) { // only if forced
|
||||
#else
|
||||
if ((info[2] & bit_AVX && AvxSwitch) || (AvxSwitch && force)) {
|
||||
#endif
|
||||
avx = true;
|
||||
}
|
||||
#if IS_X86
|
||||
#if defined(__clang__)
|
||||
# if (__clang_major__ >= 6)
|
||||
__builtin_cpu_init();
|
||||
# endif
|
||||
return __builtin_cpu_supports("aes");
|
||||
#elif (defined(__GNUC__) && __GNUC__ >= 6)
|
||||
__builtin_cpu_init();
|
||||
return __builtin_cpu_supports("aes");
|
||||
#elif (defined(__GNUC__) && __GNUC__ < 6)
|
||||
int cpu_info[4];
|
||||
bool flag = false;
|
||||
__cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
|
||||
if (cpu_info[0] >= 0x00000001) {
|
||||
__cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
|
||||
flag = ((cpu_info[2] & bit_AES) != 0);
|
||||
}
|
||||
return flag;
|
||||
#elif defined(_MSC_VER)
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
return ((cpu_info[2] & bit_AES) != 0);
|
||||
#endif
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void Detect(bool AesSwitch, bool force)
|
||||
{
|
||||
if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) {
|
||||
aesni = true;
|
||||
}
|
||||
#endif // defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled"));
|
||||
LogPrint(eLogInfo, "AVX ", (avx ? "enabled" : "disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -9,14 +9,31 @@
|
||||
#ifndef LIBI2PD_CPU_H
|
||||
#define LIBI2PD_CPU_H
|
||||
|
||||
#if defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
|
||||
# define IS_X86 1
|
||||
# if defined(_M_AMD64) || defined(__x86_64__)
|
||||
# define IS_X86_64 1
|
||||
# else
|
||||
# define IS_X86_64 0
|
||||
# endif
|
||||
#else
|
||||
# define IS_X86 0
|
||||
# define IS_X86_64 0
|
||||
#endif
|
||||
|
||||
#if defined(__AES__) && !defined(_MSC_VER) && IS_X86
|
||||
# define SUPPORTS_AES 1
|
||||
#else
|
||||
# define SUPPORTS_AES 0
|
||||
#endif
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace cpu
|
||||
{
|
||||
extern bool aesni;
|
||||
extern bool avx;
|
||||
|
||||
void Detect(bool AesSwitch, bool AvxSwitch, bool force);
|
||||
void Detect(bool AesSwitch, bool force);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace config {
|
||||
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
|
||||
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
|
||||
("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)")
|
||||
("limits.zombies", value<double>()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)")
|
||||
("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")
|
||||
@@ -192,7 +193,7 @@ namespace config {
|
||||
options_description precomputation("Precomputation options");
|
||||
precomputation.add_options()
|
||||
("precomputation.elgamal",
|
||||
#if defined(__x86_64__)
|
||||
#if (defined(_M_AMD64) || defined(__x86_64__))
|
||||
value<bool>()->default_value(false),
|
||||
#else
|
||||
value<bool>()->default_value(true),
|
||||
@@ -220,14 +221,17 @@ namespace config {
|
||||
"https://reseed-pl.i2pd.xyz/,"
|
||||
"https://www2.mk16.de/,"
|
||||
"https://i2p.ghativega.in/,"
|
||||
"https://i2p.novg.net/"
|
||||
"https://i2p.novg.net/,"
|
||||
"https://reseed.is.prestium.org/,"
|
||||
"https://reseed.us.prestium.org/"
|
||||
), "Reseed URLs, separated by comma")
|
||||
("reseed.yggurls", value<std::string>()->default_value(
|
||||
"http://[324:71e:281a:9ed3::ace]:7070/,"
|
||||
"http://[301:65b9:c7cd:9a36::1]:18801/,"
|
||||
"http://[320:8936:ec1a:31f1::216]/,"
|
||||
"http://[306:3834:97b9:a00a::1]/,"
|
||||
"http://[316:f9e0:f22e:a74f::216]/"
|
||||
"http://[316:f9e0:f22e:a74f::216]/,"
|
||||
"http://[300:eaff:7fab:181b::e621]:7170"
|
||||
), "Reseed URLs through the Yggdrasil, separated by comma")
|
||||
;
|
||||
|
||||
@@ -307,7 +311,7 @@ namespace config {
|
||||
options_description cpuext("CPU encryption extensions options");
|
||||
cpuext.add_options()
|
||||
("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used")
|
||||
("cpuext.avx", bool_switch()->default_value(true), "Use auto detection for AVX CPU extensions. If false, AVX will be not used")
|
||||
("cpuext.avx", bool_switch()->default_value(false), "Deprecated option")
|
||||
("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines")
|
||||
;
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "I2PEndian.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace crypto
|
||||
@@ -159,7 +160,7 @@ namespace crypto
|
||||
|
||||
// DH/ElGamal
|
||||
|
||||
#if !defined(__x86_64__)
|
||||
#if !IS_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
|
||||
@@ -361,7 +362,7 @@ namespace crypto
|
||||
BIGNUM * b1 = BN_CTX_get (ctx);
|
||||
BIGNUM * b = BN_CTX_get (ctx);
|
||||
// select random k
|
||||
#if defined(__x86_64__)
|
||||
#if IS_X86_64
|
||||
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
|
||||
#else
|
||||
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
|
||||
@@ -428,7 +429,7 @@ namespace crypto
|
||||
|
||||
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
|
||||
#if IS_X86 || defined(_MSC_VER)
|
||||
RAND_bytes (priv, 256);
|
||||
#else
|
||||
// lower 226 bits (28 bytes and 2 bits) only. short exponent
|
||||
@@ -555,7 +556,7 @@ namespace crypto
|
||||
}
|
||||
|
||||
// AES
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
#define KeyExpansion256(round0,round1) \
|
||||
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
|
||||
"movaps %%xmm1, %%xmm4 \n" \
|
||||
@@ -580,7 +581,7 @@ namespace crypto
|
||||
"movaps %%xmm3, "#round1"(%[sched]) \n"
|
||||
#endif
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
|
||||
{
|
||||
__asm__
|
||||
@@ -621,7 +622,7 @@ namespace crypto
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
#define EncryptAES256(sched) \
|
||||
"pxor (%["#sched"]), %%xmm0 \n" \
|
||||
"aesenc 16(%["#sched"]), %%xmm0 \n" \
|
||||
@@ -642,16 +643,18 @@ namespace crypto
|
||||
|
||||
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
:
|
||||
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -660,7 +663,7 @@ namespace crypto
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
#define DecryptAES256(sched) \
|
||||
"pxor 224(%["#sched"]), %%xmm0 \n" \
|
||||
"aesdec 208(%["#sched"]), %%xmm0 \n" \
|
||||
@@ -681,16 +684,18 @@ namespace crypto
|
||||
|
||||
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
DecryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
DecryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
:
|
||||
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -699,7 +704,7 @@ namespace crypto
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
#define CallAESIMC(offset) \
|
||||
"movaps "#offset"(%[shed]), %%xmm0 \n" \
|
||||
"aesimc %%xmm0, %%xmm0 \n" \
|
||||
@@ -708,7 +713,7 @@ namespace crypto
|
||||
|
||||
void ECBEncryption::SetKey (const AESKey& key)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
ExpandKey (key);
|
||||
@@ -722,28 +727,30 @@ namespace crypto
|
||||
|
||||
void ECBDecryption::SetKey (const AESKey& key)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
ExpandKey (key); // expand encryption key first
|
||||
// then invert it using aesimc
|
||||
__asm__
|
||||
(
|
||||
CallAESIMC(16)
|
||||
CallAESIMC(32)
|
||||
CallAESIMC(48)
|
||||
CallAESIMC(64)
|
||||
CallAESIMC(80)
|
||||
CallAESIMC(96)
|
||||
CallAESIMC(112)
|
||||
CallAESIMC(128)
|
||||
CallAESIMC(144)
|
||||
CallAESIMC(160)
|
||||
CallAESIMC(176)
|
||||
CallAESIMC(192)
|
||||
CallAESIMC(208)
|
||||
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
|
||||
);
|
||||
(
|
||||
CallAESIMC(16)
|
||||
CallAESIMC(32)
|
||||
CallAESIMC(48)
|
||||
CallAESIMC(64)
|
||||
CallAESIMC(80)
|
||||
CallAESIMC(96)
|
||||
CallAESIMC(112)
|
||||
CallAESIMC(128)
|
||||
CallAESIMC(144)
|
||||
CallAESIMC(160)
|
||||
CallAESIMC(176)
|
||||
CallAESIMC(192)
|
||||
CallAESIMC(208)
|
||||
:
|
||||
: [shed]"r"(GetKeySchedule ())
|
||||
: "%xmm0", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -754,28 +761,28 @@ namespace crypto
|
||||
|
||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"1: \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
"movups %%xmm1, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"1: \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
"movups %%xmm1, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -799,22 +806,22 @@ namespace crypto
|
||||
|
||||
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movups %%xmm0, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movups %%xmm0, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -823,29 +830,29 @@ namespace crypto
|
||||
|
||||
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"1: \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
DecryptAES256(sched)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movaps %%xmm2, %%xmm1 \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
"movups %%xmm1, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"1: \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
DecryptAES256(sched)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movaps %%xmm2, %%xmm1 \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
"movups %%xmm1, (%[iv]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -869,22 +876,22 @@ namespace crypto
|
||||
|
||||
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movups %%xmm0, (%[iv]) \n"
|
||||
DecryptAES256(sched)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movups %%xmm0, (%[iv]) \n"
|
||||
DecryptAES256(sched)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
:
|
||||
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -893,34 +900,34 @@ namespace crypto
|
||||
|
||||
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
// encrypt IV
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
EncryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
EncryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// encrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched_l)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
(
|
||||
// encrypt IV
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
EncryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
EncryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// encrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
EncryptAES256(sched_l)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -934,35 +941,35 @@ namespace crypto
|
||||
|
||||
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
// decrypt IV
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
DecryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
DecryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// decrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
DecryptAES256(sched_l)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movaps %%xmm2, %%xmm1 \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
(
|
||||
// decrypt IV
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
DecryptAES256(sched_iv)
|
||||
"movaps %%xmm0, %%xmm1 \n"
|
||||
// double IV encryption
|
||||
DecryptAES256(sched_iv)
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
// decrypt data, IV is xmm1
|
||||
"1: \n"
|
||||
"add $16, %[in] \n"
|
||||
"add $16, %[out] \n"
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
"movaps %%xmm0, %%xmm2 \n"
|
||||
DecryptAES256(sched_l)
|
||||
"pxor %%xmm1, %%xmm0 \n"
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
"movaps %%xmm2, %%xmm1 \n"
|
||||
"dec %[num] \n"
|
||||
"jnz 1b \n"
|
||||
:
|
||||
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -991,7 +998,7 @@ namespace crypto
|
||||
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||
EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
|
||||
EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
|
||||
EVP_EncryptFinal_ex(ctx, buf, &outlen);
|
||||
EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen);
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
|
||||
}
|
||||
else
|
||||
@@ -1285,9 +1292,9 @@ namespace crypto
|
||||
}
|
||||
}*/
|
||||
|
||||
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force)
|
||||
void InitCrypto (bool precomputation, bool aesni, bool force)
|
||||
{
|
||||
i2p::cpu::Detect (aesni, avx, force);
|
||||
i2p::cpu::Detect (aesni, force);
|
||||
#if LEGACY_OPENSSL
|
||||
SSL_library_init ();
|
||||
#endif
|
||||
@@ -1297,7 +1304,7 @@ namespace crypto
|
||||
CRYPTO_set_locking_callback (OpensslLockingCallback);*/
|
||||
if (precomputation)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
#if IS_X86_64
|
||||
g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
|
||||
PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
|
||||
#else
|
||||
@@ -1312,7 +1319,7 @@ namespace crypto
|
||||
if (g_ElggTable)
|
||||
{
|
||||
DestroyElggTable (g_ElggTable,
|
||||
#if defined(__x86_64__)
|
||||
#if IS_X86_64
|
||||
ELGAMAL_FULL_EXPONENT_NUM_BYTES
|
||||
#else
|
||||
ELGAMAL_SHORT_EXPONENT_NUM_BYTES
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -150,7 +150,7 @@ namespace crypto
|
||||
};
|
||||
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
class ECBCryptoAESNI
|
||||
{
|
||||
public:
|
||||
@@ -167,7 +167,7 @@ namespace crypto
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
class ECBEncryption: public ECBCryptoAESNI
|
||||
#else
|
||||
class ECBEncryption
|
||||
@@ -183,7 +183,7 @@ namespace crypto
|
||||
AES_KEY m_Key;
|
||||
};
|
||||
|
||||
#ifdef __AES__
|
||||
#if SUPPORTS_AES
|
||||
class ECBDecryption: public ECBCryptoAESNI
|
||||
#else
|
||||
class ECBDecryption
|
||||
@@ -307,7 +307,7 @@ namespace crypto
|
||||
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
|
||||
|
||||
// init and terminate
|
||||
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force);
|
||||
void InitCrypto (bool precomputation, bool aesni, bool force);
|
||||
void TerminateCrypto ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,17 +262,6 @@ namespace client
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ls = i2p::data::netdb.FindLeaseSet (ident);
|
||||
if (ls && !ls->IsExpired ())
|
||||
{
|
||||
ls->PopulateLeases (); // since we don't store them in netdb
|
||||
std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
|
||||
m_RemoteLeaseSets[ident] = ls;
|
||||
return ls;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1047,11 +1036,15 @@ namespace client
|
||||
|
||||
void ClientDestination::Stop ()
|
||||
{
|
||||
LogPrint(eLogDebug, "Destination: Stopping destination ", GetIdentHash().ToBase32(), ".b32.i2p");
|
||||
LeaseSetDestination::Stop ();
|
||||
m_ReadyChecker.cancel();
|
||||
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination");
|
||||
m_StreamingDestination->Stop ();
|
||||
//m_StreamingDestination->SetOwner (nullptr);
|
||||
m_StreamingDestination = nullptr;
|
||||
|
||||
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination by ports");
|
||||
for (auto& it: m_StreamingDestinationsByPorts)
|
||||
{
|
||||
it.second->Stop ();
|
||||
@@ -1059,11 +1052,14 @@ namespace client
|
||||
}
|
||||
m_StreamingDestinationsByPorts.clear ();
|
||||
m_LastStreamingDestination = nullptr;
|
||||
|
||||
if (m_DatagramDestination)
|
||||
{
|
||||
LogPrint(eLogDebug, "Destination: -> Stopping Datagram Destination");
|
||||
delete m_DatagramDestination;
|
||||
m_DatagramDestination = nullptr;
|
||||
}
|
||||
LogPrint(eLogDebug, "Destination: -> Stopping done");
|
||||
}
|
||||
|
||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||
@@ -1086,10 +1082,10 @@ namespace client
|
||||
if (toPort != m_LastPort || !m_LastStreamingDestination)
|
||||
{
|
||||
m_LastStreamingDestination = GetStreamingDestination (toPort);
|
||||
if (!m_LastStreamingDestination)
|
||||
if (!m_LastStreamingDestination)
|
||||
m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default
|
||||
m_LastPort = toPort;
|
||||
}
|
||||
}
|
||||
if (m_LastStreamingDestination)
|
||||
m_LastStreamingDestination->HandleDataMessagePayload (buf, length);
|
||||
else
|
||||
@@ -1115,7 +1111,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
|
||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port)
|
||||
{
|
||||
if (!streamRequestComplete)
|
||||
{
|
||||
@@ -1145,7 +1141,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
|
||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
|
||||
{
|
||||
if (!streamRequestComplete)
|
||||
{
|
||||
@@ -1164,7 +1160,7 @@ namespace client
|
||||
}
|
||||
|
||||
template<typename Dest>
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, uint16_t port)
|
||||
{
|
||||
volatile bool done = false;
|
||||
std::shared_ptr<i2p::stream::Stream> stream;
|
||||
@@ -1188,17 +1184,17 @@ namespace client
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, uint16_t port)
|
||||
{
|
||||
return CreateStreamSync (dest, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
|
||||
{
|
||||
return CreateStreamSync (dest, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
|
||||
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port)
|
||||
{
|
||||
if (m_StreamingDestination)
|
||||
return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
|
||||
@@ -1235,7 +1231,7 @@ namespace client
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (uint16_t port) const
|
||||
{
|
||||
if (port)
|
||||
{
|
||||
@@ -1273,7 +1269,7 @@ namespace client
|
||||
m_StreamingDestination->AcceptOnce (acceptor);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (uint16_t port, bool gzip)
|
||||
{
|
||||
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
|
||||
if (port)
|
||||
@@ -1283,7 +1279,7 @@ namespace client
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (int port)
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (uint16_t port)
|
||||
{
|
||||
if (port)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
@@ -184,8 +185,8 @@ namespace client
|
||||
|
||||
boost::asio::io_service& m_Service;
|
||||
mutable std::mutex m_RemoteLeaseSetsMutex;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
|
||||
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
|
||||
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
|
||||
|
||||
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
||||
std::mutex m_LeaseSetMutex;
|
||||
@@ -241,15 +242,15 @@ namespace client
|
||||
int GetRefCounter () const { return m_RefCounter; };
|
||||
|
||||
// streaming
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (int port);
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (uint16_t port, bool gzip = true); // additional
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (uint16_t port = 0) const;
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (uint16_t port);
|
||||
// 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 CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0);
|
||||
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0);
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0); // sync
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port = 0);
|
||||
void SendPing (const i2p::data::IdentHash& to);
|
||||
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
|
||||
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||
@@ -285,7 +286,7 @@ namespace client
|
||||
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);
|
||||
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, uint16_t port);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -136,6 +136,14 @@ namespace fs {
|
||||
dataDir = (home != NULL && strlen(home) > 0) ? home : "";
|
||||
dataDir += "/Library/Application Support/" + appName;
|
||||
return;
|
||||
#elif defined(__HAIKU__)
|
||||
char *home = getenv("HOME");
|
||||
if (home != NULL && strlen(home) > 0) {
|
||||
dataDir = std::string(home) + "/config/settings/" + appName;
|
||||
} else {
|
||||
dataDir = "/tmp/" + appName;
|
||||
}
|
||||
return;
|
||||
#else /* other unix */
|
||||
#if defined(ANDROID)
|
||||
const char * ext = getenv("EXTERNAL_STORAGE");
|
||||
|
||||
@@ -588,7 +588,7 @@ namespace garlic
|
||||
auto it = m_ECIESx25519Tags.find (tag);
|
||||
if (it != m_ECIESx25519Tags.end ())
|
||||
{
|
||||
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
|
||||
if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index))
|
||||
m_LastTagset = it->second.tagset;
|
||||
else
|
||||
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace i2p
|
||||
{
|
||||
return std::make_shared<I2NPMessageBuffer<I2NP_MAX_MEDIUM_MESSAGE_SIZE> >();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
|
||||
{
|
||||
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
|
||||
@@ -51,7 +51,7 @@ namespace i2p
|
||||
len += I2NP_HEADER_SIZE + 2;
|
||||
if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage ();
|
||||
if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage ();
|
||||
return NewI2NPMessage ();
|
||||
return NewI2NPMessage ();
|
||||
}
|
||||
|
||||
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum)
|
||||
@@ -424,6 +424,11 @@ namespace i2p
|
||||
{
|
||||
int num = buf[0];
|
||||
LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
|
||||
if (num > i2p::tunnel::MAX_NUM_RECORDS)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num);
|
||||
return;
|
||||
}
|
||||
if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len);
|
||||
@@ -477,6 +482,11 @@ namespace i2p
|
||||
{
|
||||
int num = buf[0];
|
||||
LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
|
||||
if (num > i2p::tunnel::MAX_NUM_RECORDS)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num);
|
||||
return;
|
||||
}
|
||||
size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
|
||||
if (len < num*recordSize + 1)
|
||||
{
|
||||
@@ -508,6 +518,11 @@ namespace i2p
|
||||
{
|
||||
int num = buf[0];
|
||||
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
|
||||
if (num > i2p::tunnel::MAX_NUM_RECORDS)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num);
|
||||
return;
|
||||
}
|
||||
if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len);
|
||||
@@ -733,46 +748,38 @@ namespace i2p
|
||||
return l;
|
||||
}
|
||||
|
||||
void HandleI2NPMessage (uint8_t * msg, size_t len)
|
||||
void HandleTunnelBuildI2NPMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (len < I2NP_HEADER_SIZE)
|
||||
if (msg)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
|
||||
return;
|
||||
}
|
||||
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
|
||||
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
|
||||
LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
|
||||
uint8_t * buf = msg + I2NP_HEADER_SIZE;
|
||||
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
|
||||
len -= I2NP_HEADER_SIZE;
|
||||
if (size > len)
|
||||
{
|
||||
LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
|
||||
size = len;
|
||||
}
|
||||
switch (typeID)
|
||||
{
|
||||
case eI2NPVariableTunnelBuild:
|
||||
HandleVariableTunnelBuildMsg (msgID, buf, size);
|
||||
break;
|
||||
case eI2NPShortTunnelBuild:
|
||||
HandleShortTunnelBuildMsg (msgID, buf, size);
|
||||
break;
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
HandleTunnelBuildReplyMsg (msgID, buf, size, false);
|
||||
break;
|
||||
case eI2NPShortTunnelBuildReply:
|
||||
HandleTunnelBuildReplyMsg (msgID, buf, size, true);
|
||||
break;
|
||||
case eI2NPTunnelBuild:
|
||||
HandleTunnelBuildMsg (buf, size);
|
||||
break;
|
||||
case eI2NPTunnelBuildReply:
|
||||
// TODO:
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID);
|
||||
uint8_t typeID = msg->GetTypeID();
|
||||
uint32_t msgID = msg->GetMsgID();
|
||||
LogPrint (eLogDebug, "I2NP: Handling tunnel build message with len=", msg->GetLength(),", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
|
||||
uint8_t * payload = msg->GetPayload();
|
||||
auto size = msg->GetPayloadLength();
|
||||
switch (typeID)
|
||||
{
|
||||
case eI2NPVariableTunnelBuild:
|
||||
HandleVariableTunnelBuildMsg (msgID, payload, size);
|
||||
break;
|
||||
case eI2NPShortTunnelBuild:
|
||||
HandleShortTunnelBuildMsg (msgID, payload, size);
|
||||
break;
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
HandleTunnelBuildReplyMsg (msgID, payload, size, false);
|
||||
break;
|
||||
case eI2NPShortTunnelBuildReply:
|
||||
HandleTunnelBuildReplyMsg (msgID, payload, size, true);
|
||||
break;
|
||||
case eI2NPTunnelBuild:
|
||||
HandleTunnelBuildMsg (payload, size);
|
||||
break;
|
||||
case eI2NPTunnelBuildReply:
|
||||
// TODO:
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogError, "I2NP: Unexpected message with type", (int)typeID, " during handling TBM; skipping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,10 +792,12 @@ namespace i2p
|
||||
switch (typeID)
|
||||
{
|
||||
case eI2NPTunnelData:
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
if (!msg->from)
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
break;
|
||||
case eI2NPTunnelGateway:
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
if (!msg->from)
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
break;
|
||||
case eI2NPGarlic:
|
||||
{
|
||||
@@ -799,10 +808,16 @@ namespace i2p
|
||||
break;
|
||||
}
|
||||
case eI2NPDatabaseStore:
|
||||
case eI2NPDatabaseSearchReply:
|
||||
case eI2NPDatabaseSearchReply:
|
||||
// forward to netDb if came directly or through exploratory tunnel as response to our request
|
||||
if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ())
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
break;
|
||||
|
||||
case eI2NPDatabaseLookup:
|
||||
// forward to netDb
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
// forward to netDb if floodfill and came directly
|
||||
if (!msg->from && i2p::context.IsFloodfill ())
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
break;
|
||||
case eI2NPDeliveryStatus:
|
||||
{
|
||||
@@ -813,16 +828,20 @@ namespace i2p
|
||||
break;
|
||||
}
|
||||
case eI2NPVariableTunnelBuild:
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
case eI2NPTunnelBuild:
|
||||
case eI2NPTunnelBuildReply:
|
||||
case eI2NPShortTunnelBuild:
|
||||
// forward to tunnel thread
|
||||
if (!msg->from)
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
break;
|
||||
case eI2NPVariableTunnelBuildReply:
|
||||
case eI2NPTunnelBuildReply:
|
||||
case eI2NPShortTunnelBuildReply:
|
||||
// forward to tunnel thread
|
||||
i2p::tunnel::tunnels.PostTunnelData (msg);
|
||||
break;
|
||||
default:
|
||||
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
||||
LogPrint(eLogError, "I2NP: Unexpected I2NP message with type ", int(typeID), " during handling; skipping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace tunnel
|
||||
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
size_t GetI2NPMessageLength (const uint8_t * msg, size_t len);
|
||||
void HandleI2NPMessage (uint8_t * msg, size_t len);
|
||||
void HandleTunnelBuildI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
class I2NPMessagesHandler
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) || defined(__HAIKU__)
|
||||
#include <endian.h>
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
@@ -581,7 +581,7 @@ namespace data
|
||||
if (keyType == SIGNING_KEY_TYPE_DSA_SHA1)
|
||||
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey));
|
||||
else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ())
|
||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
|
||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check
|
||||
else
|
||||
{
|
||||
// public key is not required
|
||||
@@ -803,29 +803,12 @@ namespace data
|
||||
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
||||
{
|
||||
XORMetric m;
|
||||
#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 %1, %%ymm0 \n"
|
||||
"vmovups %2, %%ymm1 \n"
|
||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||
"vmovups %%ymm1, %0 \n"
|
||||
: "=m"(*m.metric)
|
||||
: "m"(*key1), "m"(*key2)
|
||||
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
||||
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
||||
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
||||
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
||||
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
||||
}
|
||||
|
||||
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
||||
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
||||
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
||||
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
||||
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,9 @@ namespace data
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted) const;
|
||||
bool IsDestination () const { return true; };
|
||||
|
||||
// used in webconsole
|
||||
void ExpireLease () { m_ExpirationTime = i2p::util::GetSecondsSinceEpoch (); };
|
||||
|
||||
protected:
|
||||
|
||||
void UpdateLeasesBegin ();
|
||||
|
||||
@@ -374,8 +374,17 @@ namespace transport
|
||||
transports.PeerDisconnected (shared_from_this ());
|
||||
m_Server.RemoveNTCP2Session (shared_from_this ());
|
||||
m_SendQueue.clear ();
|
||||
m_SendQueueSize = 0;
|
||||
LogPrint (eLogDebug, "NTCP2: Session terminated");
|
||||
SetSendQueueSize (0);
|
||||
auto remoteIdentity = GetRemoteIdentity ();
|
||||
if (remoteIdentity)
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), " terminated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +433,7 @@ namespace transport
|
||||
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
|
||||
{
|
||||
if (m_NextReceivedBuffer && !m_IsReceiving &&
|
||||
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
||||
ts > GetLastActivityTimestamp () + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
||||
{
|
||||
delete[] m_NextReceivedBuffer;
|
||||
m_NextReceivedBuffer = nullptr;
|
||||
@@ -566,7 +575,11 @@ namespace transport
|
||||
SendSessionConfirmed ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetRemoteIdentity ())
|
||||
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,16 +700,25 @@ namespace transport
|
||||
i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag
|
||||
if (ri.IsUnreachable ())
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed");
|
||||
LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ());
|
||||
SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail);
|
||||
return;
|
||||
}
|
||||
if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
|
||||
LogPrint(eLogDebug, "NTCP2: SessionConfirmed from ", GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (ri.GetIdentHash ()), ")");
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed");
|
||||
LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds");
|
||||
SendTerminationAndTerminate (eNTCP2Message3Error);
|
||||
return;
|
||||
}
|
||||
if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri.GetTimestamp ()) // 2 minutes
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: RouterInfo is from future for ", (ri.GetTimestamp () - ts)/1000LL, " seconds");
|
||||
SendTerminationAndTerminate (eNTCP2Message3Error);
|
||||
return;
|
||||
}
|
||||
auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () :
|
||||
(i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ());
|
||||
if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32))
|
||||
@@ -767,7 +789,7 @@ namespace transport
|
||||
void NTCP2Session::ServerLogin ()
|
||||
{
|
||||
SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT);
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
SetLastActivityTimestamp (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 (),
|
||||
@@ -850,9 +872,8 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumReceivedBytes += bytes_transferred + 2; // + length
|
||||
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred);
|
||||
UpdateNumReceivedBytes (bytes_transferred + 2);
|
||||
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred + 2);
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
|
||||
@@ -880,7 +901,7 @@ namespace transport
|
||||
auto size = bufbe16toh (frame + offset);
|
||||
offset += 2;
|
||||
LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size);
|
||||
if (size > len)
|
||||
if (offset + size > len)
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: Unexpected block length ", size);
|
||||
break;
|
||||
@@ -1073,11 +1094,10 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumSentBytes += bytes_transferred;
|
||||
UpdateNumSentBytes (bytes_transferred);
|
||||
i2p::transport::transports.UpdateSentBytes (bytes_transferred);
|
||||
LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred);
|
||||
if (m_LastActivityTimestamp > m_NextRouterInfoResendTime)
|
||||
if (GetLastActivityTimestamp () > m_NextRouterInfoResendTime)
|
||||
{
|
||||
m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
|
||||
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
|
||||
@@ -1086,7 +1106,7 @@ namespace transport
|
||||
else
|
||||
{
|
||||
SendQueue ();
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
SetSendQueueSize (m_SendQueue.size ());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1209,7 +1229,7 @@ namespace transport
|
||||
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
||||
Terminate ();
|
||||
}
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
SetSendQueueSize (m_SendQueue.size ());
|
||||
}
|
||||
|
||||
void NTCP2Session::SendLocalRouterInfo (bool update)
|
||||
@@ -1398,7 +1418,8 @@ namespace transport
|
||||
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
|
||||
return;
|
||||
}
|
||||
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ());
|
||||
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")");
|
||||
GetService ().post([this, conn]()
|
||||
{
|
||||
if (this->AddNTCP2Session (conn))
|
||||
@@ -1454,7 +1475,8 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ());
|
||||
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")");
|
||||
conn->ClientLogin ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -59,7 +59,7 @@ namespace data
|
||||
{
|
||||
Reseed ();
|
||||
}
|
||||
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false))
|
||||
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false))
|
||||
Reseed (); // we don't have a router we can connect to. Trying to reseed
|
||||
|
||||
auto it = m_RouterInfos.find (i2p::context.GetIdentHash ());
|
||||
@@ -175,6 +175,7 @@ namespace data
|
||||
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) ||
|
||||
ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup)
|
||||
{
|
||||
m_RouterProfilesPool.CleanUpMt ();
|
||||
if (m_PersistProfiles) PersistProfiles ();
|
||||
DeleteObsoleteProfiles ();
|
||||
lastProfilesCleanup = ts;
|
||||
@@ -245,19 +246,20 @@ namespace data
|
||||
updated = false;
|
||||
m_Requests.RequestComplete (ident, r);
|
||||
return r;
|
||||
}
|
||||
if (r->IsUnreachable ())
|
||||
}
|
||||
if (r->IsUnreachable () ||
|
||||
i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < r->GetTimestamp ())
|
||||
{
|
||||
// delete router as invalid after update
|
||||
// delete router as invalid or from future after update
|
||||
m_RouterInfos.erase (ident);
|
||||
if (wasFloodfill)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||
m_Floodfills.Remove (r->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
m_Requests.RequestComplete (ident, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
||||
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
|
||||
@@ -267,7 +269,12 @@ namespace data
|
||||
if (wasFloodfill)
|
||||
m_Floodfills.Remove (r->GetIdentHash ());
|
||||
else if (r->IsEligibleFloodfill ())
|
||||
m_Floodfills.Insert (r);
|
||||
{
|
||||
if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ())
|
||||
m_Floodfills.Insert (r);
|
||||
else
|
||||
r->ResetFlooldFill ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -292,8 +299,14 @@ namespace data
|
||||
LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
|
||||
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||
m_Floodfills.Insert (r);
|
||||
if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD ||
|
||||
r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||
m_Floodfills.Insert (r);
|
||||
}
|
||||
else
|
||||
r->ResetFlooldFill ();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -413,13 +426,10 @@ namespace data
|
||||
if (r)
|
||||
{
|
||||
r->SetUnreachable (unreachable);
|
||||
if (unreachable)
|
||||
{
|
||||
auto profile = r->GetProfile ();
|
||||
if (profile)
|
||||
profile->Unreachable ();
|
||||
}
|
||||
}
|
||||
auto profile = r->GetProfile ();
|
||||
if (profile)
|
||||
profile->Unreachable (unreachable);
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports)
|
||||
@@ -429,9 +439,9 @@ namespace data
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||
r->ExcludeReachableTransports (transports);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::Reseed ()
|
||||
{
|
||||
if (!m_Reseeder)
|
||||
@@ -607,7 +617,9 @@ 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;
|
||||
double minTunnelCreationSuccessRate;
|
||||
i2p::config::GetOption("limits.zombies", minTunnelCreationSuccessRate);
|
||||
bool isLowRate = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < minTunnelCreationSuccessRate;
|
||||
// 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
|
||||
@@ -617,17 +629,17 @@ namespace data
|
||||
auto own = i2p::context.GetSharedRouterInfo ();
|
||||
for (auto& it: m_RouterInfos)
|
||||
{
|
||||
if (it.second == own) continue; // skip own
|
||||
if (!it.second || it.second == own) continue; // skip own
|
||||
std::string ident = it.second->GetIdentHashBase64();
|
||||
if (it.second->IsUpdated ())
|
||||
{
|
||||
if (it.second->GetBuffer ())
|
||||
{
|
||||
{
|
||||
// we have something to save
|
||||
it.second->SaveToFile (m_Storage.Path(ident));
|
||||
it.second->SetUnreachable (false);
|
||||
it.second->DeleteBuffer ();
|
||||
}
|
||||
}
|
||||
it.second->SetUpdated (false);
|
||||
updatedCount++;
|
||||
continue;
|
||||
@@ -639,20 +651,28 @@ namespace data
|
||||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
||||
it.second->SetUnreachable (false);
|
||||
if (!it.second->IsUnreachable ())
|
||||
{
|
||||
{
|
||||
// find & mark expired routers
|
||||
if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport
|
||||
it.second->SetUnreachable (true);
|
||||
else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout)
|
||||
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);
|
||||
}
|
||||
else if (checkForExpiration)
|
||||
{
|
||||
if (ts > it.second->GetTimestamp () + expirationTimeout)
|
||||
it.second->SetUnreachable (true);
|
||||
else if ((ts > it.second->GetTimestamp () + expirationTimeout/2) && // more than half of expiration
|
||||
total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth() && // low bandwidth
|
||||
!it.second->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill
|
||||
(CreateRoutingKey (it.second->GetIdentHash ()) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits
|
||||
it.second->SetUnreachable (true);
|
||||
}
|
||||
if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ()))
|
||||
it.second->SetUnreachable (false); // don't expire connected router
|
||||
}
|
||||
}
|
||||
|
||||
if (it.second->IsUnreachable ())
|
||||
{
|
||||
@@ -667,7 +687,7 @@ namespace data
|
||||
m_RouterInfoBuffersPool.CleanUpMt ();
|
||||
m_RouterInfoAddressesPool.CleanUpMt ();
|
||||
m_RouterInfoAddressVectorsPool.CleanUpMt ();
|
||||
m_IdentitiesPool.CleanUpMt ();
|
||||
m_IdentitiesPool.CleanUpMt ();
|
||||
|
||||
if (updatedCount > 0)
|
||||
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
|
||||
@@ -679,13 +699,13 @@ namespace data
|
||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||
for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();)
|
||||
{
|
||||
if (it->second->IsUnreachable ())
|
||||
if (!it->second || it->second->IsUnreachable ())
|
||||
it = m_RouterInfos.erase (it);
|
||||
else
|
||||
{
|
||||
{
|
||||
it->second->DropProfile ();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// clean up expired floodfills or not floodfills anymore
|
||||
@@ -722,7 +742,11 @@ namespace data
|
||||
auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
|
||||
auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
|
||||
if (outbound && inbound)
|
||||
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
|
||||
{
|
||||
auto msg = dest->CreateRequestMessage (floodfill, inbound);
|
||||
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
|
||||
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
|
||||
@@ -787,19 +811,22 @@ namespace data
|
||||
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;
|
||||
if (!tunnelID) // send response directly
|
||||
transports.SendMessage (buf + offset, deliveryStatus);
|
||||
else
|
||||
if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW
|
||||
{
|
||||
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
|
||||
if (outbound)
|
||||
outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus);
|
||||
auto deliveryStatus = CreateDeliveryStatusMsg (replyToken);
|
||||
if (!tunnelID) // send response directly
|
||||
transports.SendMessage (buf + offset, deliveryStatus);
|
||||
else
|
||||
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
|
||||
{
|
||||
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
|
||||
if (outbound)
|
||||
outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus);
|
||||
else
|
||||
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
|
||||
}
|
||||
}
|
||||
offset += 32;
|
||||
}
|
||||
@@ -820,7 +847,12 @@ namespace data
|
||||
LogPrint (eLogError, "NetDb: Database store message is too long ", len);
|
||||
return;
|
||||
}
|
||||
if (!m->from) // unsolicited LS must be received directly
|
||||
if (!context.IsFloodfill ())
|
||||
{
|
||||
LogPrint (eLogInfo, "NetDb: Not Floodfill, LeaseSet store request ignored for ", ident.ToBase32());
|
||||
return;
|
||||
}
|
||||
else if (!m->from) // unsolicited LS must be received directly
|
||||
{
|
||||
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
||||
{
|
||||
@@ -988,6 +1020,11 @@ namespace data
|
||||
std::shared_ptr<I2NPMessage> replyMsg;
|
||||
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
||||
{
|
||||
if (!context.IsFloodfill ())
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: Exploratory lookup to non-floodfill dropped");
|
||||
return;
|
||||
}
|
||||
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
|
||||
std::set<IdentHash> excludedRouters;
|
||||
const uint8_t * excluded_ident = excluded;
|
||||
@@ -1013,6 +1050,7 @@ namespace data
|
||||
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
||||
{
|
||||
// try to find router
|
||||
auto router = FindRouter (ident);
|
||||
if (router && !router->IsUnreachable ())
|
||||
{
|
||||
@@ -1025,17 +1063,26 @@ namespace data
|
||||
if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
|
||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
||||
{
|
||||
auto leaseSet = FindLeaseSet (ident);
|
||||
if (!leaseSet)
|
||||
// try to find leaseset
|
||||
if (context.IsFloodfill ())
|
||||
{
|
||||
auto leaseSet = FindLeaseSet (ident);
|
||||
if (!leaseSet)
|
||||
{
|
||||
// no leaseset found
|
||||
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
|
||||
}
|
||||
else if (!leaseSet->IsExpired ()) // we don't send back expired leasesets
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
|
||||
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
|
||||
}
|
||||
}
|
||||
else if (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP)
|
||||
{
|
||||
// no lease set found
|
||||
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
|
||||
}
|
||||
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
|
||||
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
|
||||
}
|
||||
LogPrint (eLogWarning, "NetDb: Explicit LeaseSet lookup to non-floodfill dropped");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!replyMsg)
|
||||
@@ -1174,15 +1221,17 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith,
|
||||
bool reverse, bool endpoint) const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
|
||||
[compatibleWith, reverse, endpoint](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return !router->IsHidden () && router != compatibleWith &&
|
||||
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||
(reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)):
|
||||
router->IsReachableFrom (*compatibleWith)) &&
|
||||
router->IsECIES () && !router->IsHighCongestion (false);
|
||||
router->IsECIES () && !router->IsHighCongestion (false) &&
|
||||
(!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1206,17 +1255,20 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith,
|
||||
bool reverse, bool endpoint) const
|
||||
{
|
||||
return GetRandomRouter (
|
||||
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
|
||||
[compatibleWith, reverse, endpoint](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return !router->IsHidden () && router != compatibleWith &&
|
||||
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||
(reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)) :
|
||||
router->IsReachableFrom (*compatibleWith)) &&
|
||||
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
|
||||
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION &&
|
||||
router->IsECIES () && !router->IsHighCongestion (true);
|
||||
router->IsECIES () && !router->IsHighCongestion (true) &&
|
||||
(!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse)
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1228,7 +1280,9 @@ namespace data
|
||||
uint16_t inds[3];
|
||||
RAND_bytes ((uint8_t *)inds, sizeof (inds));
|
||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||
inds[0] %= m_RouterInfos.size ();
|
||||
auto count = m_RouterInfos.size ();
|
||||
if(count == 0) return nullptr;
|
||||
inds[0] %= count;
|
||||
auto it = m_RouterInfos.begin ();
|
||||
std::advance (it, inds[0]);
|
||||
// try random router
|
||||
@@ -1308,16 +1362,16 @@ namespace data
|
||||
return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () &&
|
||||
!excluded.count (r->GetIdentHash ());
|
||||
});
|
||||
}
|
||||
}
|
||||
if (v.empty ()) return res;
|
||||
|
||||
|
||||
XORMetric ourMetric;
|
||||
if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
|
||||
for (auto& it: v)
|
||||
{
|
||||
if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break;
|
||||
res.push_back (it->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1360,10 +1414,10 @@ namespace data
|
||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||
for (auto& it: m_RouterInfos)
|
||||
it.second->UpdateIntroducers (ts);
|
||||
}
|
||||
}
|
||||
SaveUpdated ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NetDb::ManageLeaseSets ()
|
||||
{
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
|
||||
@@ -38,7 +38,8 @@ 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_NUM_FLOODFILLS_THRESHOLD = 1500;
|
||||
const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD;
|
||||
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
|
||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
||||
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
|
||||
@@ -84,8 +85,8 @@ namespace data
|
||||
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
|
||||
|
||||
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> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
|
||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (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) const;
|
||||
@@ -128,6 +129,7 @@ namespace data
|
||||
};
|
||||
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
|
||||
std::shared_ptr<IdentityEx> NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); };
|
||||
std::shared_ptr<RouterProfile> NewRouterProfile () { return m_RouterProfilesPool.AcquireSharedMt (); };
|
||||
|
||||
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
||||
|
||||
@@ -185,6 +187,7 @@ namespace data
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Addresses> m_RouterInfoAddressVectorsPool;
|
||||
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
|
||||
i2p::util::MemoryPoolMt<IdentityEx> m_IdentitiesPool;
|
||||
i2p::util::MemoryPoolMt<RouterProfile> m_RouterProfilesPool;
|
||||
};
|
||||
|
||||
extern NetDb netdb;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "NetDb.hpp"
|
||||
#include "Profiling.h"
|
||||
|
||||
namespace i2p
|
||||
@@ -30,12 +31,12 @@ namespace data
|
||||
{
|
||||
return boost::posix_time::second_clock::local_time();
|
||||
}
|
||||
|
||||
|
||||
RouterProfile::RouterProfile ():
|
||||
m_LastUpdateTime (GetTime ()), m_IsUpdated (false),
|
||||
m_LastDeclineTime (0), m_LastUnreachableTime (0),
|
||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
|
||||
m_NumTimesTaken (0), m_NumTimesRejected (0)
|
||||
m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ namespace data
|
||||
boost::property_tree::ptree usage;
|
||||
usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken);
|
||||
usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected);
|
||||
usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected);
|
||||
// fill property tree
|
||||
boost::property_tree::ptree pt;
|
||||
pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime));
|
||||
@@ -123,6 +125,7 @@ namespace data
|
||||
auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE);
|
||||
m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0);
|
||||
m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0);
|
||||
m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false);
|
||||
}
|
||||
catch (boost::property_tree::ptree_bad_path& ex)
|
||||
{
|
||||
@@ -148,22 +151,30 @@ namespace data
|
||||
}
|
||||
else
|
||||
{
|
||||
m_NumTunnelsAgreed++;
|
||||
m_NumTunnelsAgreed++;
|
||||
m_LastDeclineTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterProfile::TunnelNonReplied ()
|
||||
{
|
||||
m_NumTunnelsNonReplied++;
|
||||
m_NumTunnelsNonReplied++;
|
||||
UpdateTime ();
|
||||
if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3)
|
||||
{
|
||||
m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
}
|
||||
}
|
||||
|
||||
void RouterProfile::Unreachable ()
|
||||
void RouterProfile::Unreachable (bool unreachable)
|
||||
{
|
||||
m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_LastUnreachableTime = unreachable ? i2p::util::GetSecondsSinceEpoch () : 0;
|
||||
UpdateTime ();
|
||||
}
|
||||
|
||||
void RouterProfile::Connected ()
|
||||
{
|
||||
m_HasConnected = true;
|
||||
UpdateTime ();
|
||||
}
|
||||
|
||||
@@ -214,6 +225,11 @@ namespace data
|
||||
return (bool)m_LastUnreachableTime;
|
||||
}
|
||||
|
||||
bool RouterProfile::IsUseful() const
|
||||
{
|
||||
return IsReal () || m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD;
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash)
|
||||
{
|
||||
{
|
||||
@@ -221,8 +237,8 @@ namespace data
|
||||
auto it = g_Profiles.find (identHash);
|
||||
if (it != g_Profiles.end ())
|
||||
return it->second;
|
||||
}
|
||||
auto profile = std::make_shared<RouterProfile> ();
|
||||
}
|
||||
auto profile = netdb.NewRouterProfile ();
|
||||
profile->Load (identHash); // if possible
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
g_Profiles.emplace (identHash, profile);
|
||||
@@ -242,7 +258,7 @@ namespace data
|
||||
{
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||
{
|
||||
{
|
||||
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL)
|
||||
{
|
||||
if (it->second->IsUpdated ())
|
||||
@@ -251,11 +267,11 @@ namespace data
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& it: tmp)
|
||||
if (it.second) it.second->Save (it.first);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveProfiles ()
|
||||
{
|
||||
@@ -267,24 +283,24 @@ namespace data
|
||||
}
|
||||
auto ts = GetTime ();
|
||||
for (auto& it: tmp)
|
||||
if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
|
||||
if (it.second->IsUseful() && (it.second->IsUpdated () || (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600))
|
||||
it.second->Save (it.first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DeleteObsoleteProfiles ()
|
||||
{
|
||||
{
|
||||
auto ts = GetTime ();
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||
{
|
||||
{
|
||||
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
|
||||
it = g_Profiles.erase (it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct stat st;
|
||||
std::time_t now = std::time(nullptr);
|
||||
|
||||
|
||||
@@ -28,35 +28,40 @@ namespace data
|
||||
const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied";
|
||||
const char PEER_PROFILE_USAGE_TAKEN[] = "taken";
|
||||
const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
|
||||
|
||||
const char PEER_PROFILE_USAGE_CONNECTED[] = "connected";
|
||||
|
||||
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 36; // in hours (1.5 days)
|
||||
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 6 * 3600; // in seconds (6 hours)
|
||||
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 3 * 3600; // in seconds (3 hours)
|
||||
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour)
|
||||
const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes)
|
||||
const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes)
|
||||
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours)
|
||||
const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
|
||||
|
||||
class RouterProfile
|
||||
{
|
||||
public:
|
||||
|
||||
RouterProfile ();
|
||||
RouterProfile& operator= (const RouterProfile& ) = default;
|
||||
|
||||
void Save (const IdentHash& identHash);
|
||||
void Load (const IdentHash& identHash);
|
||||
|
||||
bool IsBad ();
|
||||
bool IsUnreachable ();
|
||||
bool IsReal () const { return m_HasConnected || m_NumTunnelsAgreed > 0 || m_NumTunnelsDeclined > 0; }
|
||||
|
||||
void TunnelBuildResponse (uint8_t ret);
|
||||
void TunnelNonReplied ();
|
||||
|
||||
void Unreachable ();
|
||||
void Unreachable (bool unreachable);
|
||||
void Connected ();
|
||||
|
||||
boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||
bool IsUpdated () const { return m_IsUpdated; };
|
||||
|
||||
bool IsUseful() const;
|
||||
|
||||
private:
|
||||
|
||||
void UpdateTime ();
|
||||
@@ -78,6 +83,7 @@ namespace data
|
||||
// usage
|
||||
uint32_t m_NumTimesTaken;
|
||||
uint32_t m_NumTimesRejected;
|
||||
bool m_HasConnected; // successful trusted(incoming or NTCP2) connection
|
||||
};
|
||||
|
||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
|
||||
|
||||
@@ -31,7 +31,8 @@ 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_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID),
|
||||
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
|
||||
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
|
||||
m_PublishReplyToken (0), m_IsHiddenMode (false)
|
||||
{
|
||||
}
|
||||
@@ -277,8 +278,29 @@ namespace i2p
|
||||
fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
|
||||
}
|
||||
|
||||
void RouterContext::SetTesting (bool testing)
|
||||
{
|
||||
if (testing != m_Testing)
|
||||
{
|
||||
m_Testing = testing;
|
||||
if (m_Testing)
|
||||
m_Error = eRouterErrorNone;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::SetTestingV6 (bool testing)
|
||||
{
|
||||
if (testing != m_TestingV6)
|
||||
{
|
||||
m_TestingV6 = testing;
|
||||
if (m_TestingV6)
|
||||
m_ErrorV6 = eRouterErrorNone;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::SetStatus (RouterStatus status)
|
||||
{
|
||||
SetTesting (false);
|
||||
if (status != m_Status)
|
||||
{
|
||||
m_Status = status;
|
||||
@@ -290,9 +312,6 @@ namespace i2p
|
||||
case eRouterStatusFirewalled:
|
||||
SetUnreachable (true, false); // ipv4
|
||||
break;
|
||||
case eRouterStatusTesting:
|
||||
m_Error = eRouterErrorNone;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -301,6 +320,7 @@ namespace i2p
|
||||
|
||||
void RouterContext::SetStatusV6 (RouterStatus status)
|
||||
{
|
||||
SetTestingV6 (false);
|
||||
if (status != m_StatusV6)
|
||||
{
|
||||
m_StatusV6 = status;
|
||||
@@ -312,9 +332,6 @@ namespace i2p
|
||||
case eRouterStatusFirewalled:
|
||||
SetUnreachable (false, true); // ipv6
|
||||
break;
|
||||
case eRouterStatusTesting:
|
||||
m_ErrorV6 = eRouterErrorNone;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -577,15 +594,15 @@ namespace i2p
|
||||
/* detect parameters */
|
||||
switch (L)
|
||||
{
|
||||
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
|
||||
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = 48; type = low; break;
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break;
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
|
||||
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
|
||||
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
|
||||
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break;
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
|
||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256
|
||||
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048
|
||||
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
|
||||
default:
|
||||
limit = 48; type = low;
|
||||
limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; // 48
|
||||
}
|
||||
/* update caps & flags in RI */
|
||||
auto caps = m_RouterInfo.GetCaps ();
|
||||
@@ -1348,8 +1365,12 @@ namespace i2p
|
||||
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
|
||||
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
|
||||
if (inbound && outbound)
|
||||
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
|
||||
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
|
||||
{
|
||||
// encrypt for floodfill
|
||||
auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound);
|
||||
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
|
||||
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds");
|
||||
}
|
||||
|
||||
@@ -42,11 +42,10 @@ namespace garlic
|
||||
enum RouterStatus
|
||||
{
|
||||
eRouterStatusOK = 0,
|
||||
eRouterStatusTesting = 1,
|
||||
eRouterStatusFirewalled = 2,
|
||||
eRouterStatusUnknown = 3,
|
||||
eRouterStatusProxy = 4,
|
||||
eRouterStatusMesh = 5
|
||||
eRouterStatusFirewalled = 1,
|
||||
eRouterStatusUnknown = 2,
|
||||
eRouterStatusProxy = 3,
|
||||
eRouterStatusMesh = 4
|
||||
};
|
||||
|
||||
enum RouterError
|
||||
@@ -121,10 +120,14 @@ namespace garlic
|
||||
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||
uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; };
|
||||
uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; };
|
||||
bool GetTesting () const { return m_Testing; };
|
||||
void SetTesting (bool testing);
|
||||
RouterStatus GetStatus () const { return m_Status; };
|
||||
void SetStatus (RouterStatus status);
|
||||
RouterError GetError () const { return m_Error; };
|
||||
void SetError (RouterError error) { m_Error = error; };
|
||||
bool GetTestingV6 () const { return m_TestingV6; };
|
||||
void SetTestingV6 (bool testing);
|
||||
RouterStatus GetStatusV6 () const { return m_StatusV6; };
|
||||
void SetStatusV6 (RouterStatus status);
|
||||
RouterError GetErrorV6 () const { return m_ErrorV6; };
|
||||
@@ -231,6 +234,7 @@ namespace garlic
|
||||
int m_ShareRatio;
|
||||
RouterStatus m_Status, m_StatusV6;
|
||||
RouterError m_Error, m_ErrorV6;
|
||||
bool m_Testing, m_TestingV6;
|
||||
int m_NetID;
|
||||
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
|
||||
std::unique_ptr<SSU2PrivateKeys> m_SSU2Keys;
|
||||
|
||||
@@ -293,7 +293,8 @@ namespace data
|
||||
else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key
|
||||
{
|
||||
Base64ToByteStream (value, strlen (value), address->s, 32);
|
||||
isStaticKey = true;
|
||||
if (!(address->s[31] & 0x80)) // check if x25519 public key
|
||||
isStaticKey = true;
|
||||
}
|
||||
else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro
|
||||
{
|
||||
@@ -362,6 +363,7 @@ namespace data
|
||||
}
|
||||
if (!s) return;
|
||||
}
|
||||
|
||||
if (address->transportStyle == eTransportNTCP2)
|
||||
{
|
||||
if (isStaticKey)
|
||||
@@ -387,7 +389,7 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (address->transportStyle == eTransportSSU2 && isV2)
|
||||
else if (address->transportStyle == eTransportSSU2 && isV2 && isStaticKey)
|
||||
{
|
||||
if (address->IsV4 ()) supportedTransports |= eSSU2V4;
|
||||
if (address->IsV6 ()) supportedTransports |= eSSU2V6;
|
||||
@@ -483,7 +485,10 @@ namespace data
|
||||
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value))
|
||||
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed");
|
||||
SetUnreachable (true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s) return;
|
||||
@@ -574,7 +579,7 @@ namespace data
|
||||
int numValid = 0;
|
||||
for (auto& it: address->ssu->introducers)
|
||||
{
|
||||
if (it.iTag && ts < it.iExp)
|
||||
if (it.iTag && ts < it.iExp && !it.iH.IsZero ())
|
||||
numValid++;
|
||||
else
|
||||
it.iTag = 0;
|
||||
@@ -990,6 +995,7 @@ namespace data
|
||||
|
||||
bool RouterInfo::IsPublished (bool v4) const
|
||||
{
|
||||
if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published
|
||||
auto addr = GetAddresses ();
|
||||
if (v4)
|
||||
return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) ||
|
||||
@@ -1315,6 +1321,7 @@ namespace data
|
||||
int i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
if (!introducer.iTag) continue;
|
||||
if (introducer.iExp) // expiration is specified
|
||||
{
|
||||
WriteString ("iexp" + boost::lexical_cast<std::string>(i), properties);
|
||||
@@ -1327,6 +1334,7 @@ namespace data
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
if (!introducer.iTag) continue;
|
||||
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
char value[64];
|
||||
@@ -1339,6 +1347,7 @@ namespace data
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
if (!introducer.iTag) continue;
|
||||
WriteString ("itag" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (boost::lexical_cast<std::string>(introducer.iTag), properties);
|
||||
|
||||
@@ -42,8 +42,12 @@ namespace data
|
||||
const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */
|
||||
const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */
|
||||
const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */
|
||||
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */
|
||||
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */
|
||||
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */
|
||||
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */
|
||||
// bandwidth limits in kBps
|
||||
const uint32_t LOW_BANDWIDTH_LIMIT = 48;
|
||||
const uint32_t HIGH_BANDWIDTH_LIMIT = 256;
|
||||
const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048;
|
||||
// congesion flags
|
||||
const char CAPS_FLAG_MEDIUM_CONGESTION = 'D';
|
||||
const char CAPS_FLAG_HIGH_CONGESTION = 'E';
|
||||
@@ -125,7 +129,7 @@ namespace data
|
||||
|
||||
struct Introducer
|
||||
{
|
||||
Introducer (): iTag (0), iExp (0) {};
|
||||
Introducer (): iTag (0), iExp (0) { iH.Fill(0); };
|
||||
IdentHash iH;
|
||||
uint32_t iTag;
|
||||
uint32_t iExp;
|
||||
@@ -224,6 +228,7 @@ namespace data
|
||||
void UpdateSupportedTransports ();
|
||||
void UpdateIntroducers (uint64_t ts); // ts in seconds
|
||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||
void ResetFlooldFill () { m_Caps &= ~Caps::eFloodfill; };
|
||||
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace transport
|
||||
m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()),
|
||||
m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()),
|
||||
m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()),
|
||||
m_IsPublished (true), m_IsSyncClockFromPeers (true), m_IsThroughProxy (false)
|
||||
m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0),
|
||||
m_IsThroughProxy (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ namespace transport
|
||||
if (address->IsV4 ())
|
||||
{
|
||||
found = true;
|
||||
LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start");
|
||||
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port));
|
||||
m_ReceiveService.GetService ().post(
|
||||
[this]()
|
||||
@@ -89,6 +91,7 @@ namespace transport
|
||||
if (address->IsV6 ())
|
||||
{
|
||||
found = true;
|
||||
LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start");
|
||||
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port));
|
||||
m_ReceiveService.GetService ().post(
|
||||
[this]()
|
||||
@@ -207,6 +210,29 @@ namespace transport
|
||||
return ep.port ();
|
||||
}
|
||||
|
||||
void SSU2Server::AdjustTimeOffset (int64_t offset)
|
||||
{
|
||||
if (offset)
|
||||
{
|
||||
if (m_PendingTimeOffset) // one more
|
||||
{
|
||||
if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW)
|
||||
{
|
||||
offset = (m_PendingTimeOffset + offset)/2; // average
|
||||
LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds");
|
||||
i2p::util::AdjustTimeOffset (offset);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted");
|
||||
m_PendingTimeOffset = 0;
|
||||
}
|
||||
else
|
||||
m_PendingTimeOffset = offset; // first
|
||||
}
|
||||
else
|
||||
m_PendingTimeOffset = 0; // reset
|
||||
}
|
||||
|
||||
boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint)
|
||||
{
|
||||
boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4;
|
||||
@@ -243,10 +269,12 @@ namespace transport
|
||||
if (!ecode
|
||||
|| ecode == boost::asio::error::connection_refused
|
||||
|| ecode == boost::asio::error::connection_reset
|
||||
|| ecode == boost::asio::error::network_reset
|
||||
|| ecode == boost::asio::error::network_unreachable
|
||||
|| ecode == boost::asio::error::host_unreachable
|
||||
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|
||||
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|
||||
|| ecode.value() == boost::winapi::WSAENETRESET_ // 10052
|
||||
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|
||||
#endif
|
||||
@@ -303,7 +331,7 @@ namespace transport
|
||||
else
|
||||
{
|
||||
auto ep = socket.local_endpoint ();
|
||||
socket.close ();
|
||||
LogPrint (eLogCritical, "SSU2: Reopening socket in HandleReceivedFrom: code ", ecode.value(), ": ", ecode.message ());
|
||||
OpenSocket (ep);
|
||||
Receive (socket);
|
||||
}
|
||||
@@ -558,16 +586,25 @@ namespace transport
|
||||
SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<boost::asio::const_buffer> bufs
|
||||
{
|
||||
boost::asio::buffer (header, headerLen),
|
||||
boost::asio::buffer (payload, payloadLen)
|
||||
};
|
||||
|
||||
boost::system::error_code ec;
|
||||
if (to.address ().is_v6 ())
|
||||
{
|
||||
if (!m_SocketV6.is_open ()) return;
|
||||
m_SocketV6.send_to (bufs, to, 0, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_SocketV4.is_open ()) return;
|
||||
m_SocketV4.send_to (bufs, to, 0, ec);
|
||||
}
|
||||
|
||||
if (!ec)
|
||||
i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen);
|
||||
else
|
||||
@@ -582,17 +619,25 @@ namespace transport
|
||||
SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<boost::asio::const_buffer> bufs
|
||||
{
|
||||
boost::asio::buffer (header, headerLen),
|
||||
boost::asio::buffer (headerX, headerXLen),
|
||||
boost::asio::buffer (payload, payloadLen)
|
||||
};
|
||||
|
||||
boost::system::error_code ec;
|
||||
if (to.address ().is_v6 ())
|
||||
{
|
||||
if (!m_SocketV6.is_open ()) return;
|
||||
m_SocketV6.send_to (bufs, to, 0, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_SocketV4.is_open ()) return;
|
||||
m_SocketV4.send_to (bufs, to, 0, ec);
|
||||
}
|
||||
|
||||
if (!ec)
|
||||
i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen);
|
||||
@@ -962,7 +1007,7 @@ namespace transport
|
||||
void SSU2Server::UpdateIntroducers (bool v4)
|
||||
{
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
std::list<i2p::data::IdentHash> newList;
|
||||
std::list<i2p::data::IdentHash> newList, impliedList;
|
||||
auto& introducers = v4 ? m_Introducers : m_IntroducersV6;
|
||||
std::set<i2p::data::IdentHash> excluded;
|
||||
for (const auto& it : introducers)
|
||||
@@ -974,12 +1019,19 @@ namespace transport
|
||||
session = it1->second;
|
||||
excluded.insert (it);
|
||||
}
|
||||
if (session && session->IsEstablished ())
|
||||
if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) // still session with introducer?
|
||||
{
|
||||
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION)
|
||||
{
|
||||
session->SendKeepAlive ();
|
||||
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION)
|
||||
newList.push_back (it);
|
||||
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION)
|
||||
newList.push_back (it);
|
||||
else
|
||||
{
|
||||
impliedList.push_back (it); // keep in introducers list, but not publish
|
||||
session = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
session = nullptr;
|
||||
}
|
||||
@@ -993,20 +1045,18 @@ namespace transport
|
||||
{
|
||||
// bump creation time for previous introducers if no new sessions found
|
||||
LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing");
|
||||
impliedList.clear ();
|
||||
for (auto& it : introducers)
|
||||
{
|
||||
auto it1 = m_SessionsByRouterHash.find (it);
|
||||
if (it1 != m_SessionsByRouterHash.end ())
|
||||
{
|
||||
auto session = it1->second;
|
||||
if (session->IsEstablished ())
|
||||
if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ())
|
||||
{
|
||||
session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION);
|
||||
if (std::find (newList.begin (), newList.end (), it) == newList.end ())
|
||||
{
|
||||
newList.push_back (it);
|
||||
sessions.push_back (session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1014,10 +1064,14 @@ namespace transport
|
||||
|
||||
for (const auto& it : sessions)
|
||||
{
|
||||
uint32_t tag = it->GetRelayTag ();
|
||||
uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION;
|
||||
if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp)
|
||||
continue; // don't pick too old session for introducer
|
||||
i2p::data::RouterInfo::Introducer introducer;
|
||||
introducer.iTag = it->GetRelayTag ();
|
||||
introducer.iTag = tag;
|
||||
introducer.iH = it->GetRemoteIdentity ()->GetIdentHash ();
|
||||
introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION;
|
||||
introducer.iExp = exp;
|
||||
excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ());
|
||||
if (i2p::context.AddSSU2Introducer (introducer, v4))
|
||||
{
|
||||
@@ -1051,13 +1105,15 @@ namespace transport
|
||||
}
|
||||
}
|
||||
}
|
||||
introducers.splice (introducers.end (), impliedList); // insert non-published, but non-expired introducers back
|
||||
}
|
||||
|
||||
void SSU2Server::ScheduleIntroducersUpdateTimer ()
|
||||
{
|
||||
if (m_IsPublished)
|
||||
{
|
||||
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
|
||||
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(
|
||||
SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE));
|
||||
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
|
||||
this, std::placeholders::_1, true));
|
||||
}
|
||||
@@ -1070,7 +1126,8 @@ namespace transport
|
||||
m_IntroducersUpdateTimer.cancel ();
|
||||
i2p::context.ClearSSU2Introducers (true);
|
||||
m_Introducers.clear ();
|
||||
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
|
||||
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(
|
||||
(SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2));
|
||||
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
|
||||
this, std::placeholders::_1, true));
|
||||
}
|
||||
@@ -1080,7 +1137,8 @@ namespace transport
|
||||
{
|
||||
if (m_IsPublished)
|
||||
{
|
||||
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
|
||||
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(
|
||||
SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE));
|
||||
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
|
||||
this, std::placeholders::_1, false));
|
||||
}
|
||||
@@ -1093,7 +1151,8 @@ namespace transport
|
||||
m_IntroducersUpdateTimerV6.cancel ();
|
||||
i2p::context.ClearSSU2Introducers (false);
|
||||
m_IntroducersV6.clear ();
|
||||
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
|
||||
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(
|
||||
(SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2));
|
||||
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
|
||||
this, std::placeholders::_1, false));
|
||||
}
|
||||
@@ -1106,7 +1165,7 @@ namespace transport
|
||||
// timeout expired
|
||||
if (v4)
|
||||
{
|
||||
if (i2p::context.GetStatus () == eRouterStatusTesting)
|
||||
if (i2p::context.GetTesting ())
|
||||
{
|
||||
// we still don't know if we need introducers
|
||||
ScheduleIntroducersUpdateTimer ();
|
||||
@@ -1129,7 +1188,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
|
||||
if (i2p::context.GetTestingV6 ())
|
||||
{
|
||||
// we still don't know if we need introducers
|
||||
ScheduleIntroducersUpdateTimerV6 ();
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace transport
|
||||
const size_t SSU2_MAX_NUM_INTRODUCERS = 3;
|
||||
const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
|
||||
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
|
||||
const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds
|
||||
const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds
|
||||
const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds
|
||||
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
|
||||
|
||||
class SSU2Server: private i2p::util::RunnableServiceWithWork
|
||||
@@ -65,6 +66,7 @@ namespace transport
|
||||
bool IsSupported (const boost::asio::ip::address& addr) const;
|
||||
uint16_t GetPort (bool v4) const;
|
||||
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
|
||||
void AdjustTimeOffset (int64_t offset);
|
||||
|
||||
void AddSession (std::shared_ptr<SSU2Session> session);
|
||||
void RemoveSession (uint64_t connID);
|
||||
@@ -160,6 +162,7 @@ namespace transport
|
||||
std::shared_ptr<SSU2Session> m_LastSession;
|
||||
bool m_IsPublished; // if we maintain introducers
|
||||
bool m_IsSyncClockFromPeers;
|
||||
int64_t m_PendingTimeOffset; // during peer test
|
||||
|
||||
// proxy
|
||||
bool m_IsThroughProxy;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, The PurpleI2P Project
|
||||
* Copyright (c) 2022-2024, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -114,6 +114,8 @@ namespace transport
|
||||
{
|
||||
if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived)
|
||||
{
|
||||
LogPrint(eLogDebug, "SSU2: Connecting to ", GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ")");
|
||||
ScheduleConnectTimer ();
|
||||
auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint);
|
||||
if (token)
|
||||
@@ -243,7 +245,7 @@ namespace transport
|
||||
if (IsEstablished ())
|
||||
{
|
||||
uint8_t payload[20];
|
||||
size_t payloadSize = CreatePaddingBlock (payload, 20, 5);
|
||||
size_t payloadSize = CreatePaddingBlock (payload, 20, 8);
|
||||
SendData (payload, payloadSize);
|
||||
}
|
||||
}
|
||||
@@ -261,7 +263,7 @@ namespace transport
|
||||
m_SessionConfirmedFragment.reset (nullptr);
|
||||
m_PathChallenge.reset (nullptr);
|
||||
m_SendQueue.clear ();
|
||||
m_SendQueueSize = 0;
|
||||
SetSendQueueSize (0);
|
||||
m_SentPackets.clear ();
|
||||
m_IncompleteMessages.clear ();
|
||||
m_RelaySessions.clear ();
|
||||
@@ -269,7 +271,16 @@ namespace transport
|
||||
m_ReceivedI2NPMsgIDs.clear ();
|
||||
m_Server.RemoveSession (m_SourceConnID);
|
||||
transports.PeerDisconnected (shared_from_this ());
|
||||
LogPrint (eLogDebug, "SSU2: Session terminated");
|
||||
auto remoteIdentity = GetRemoteIdentity ();
|
||||
if (remoteIdentity)
|
||||
{
|
||||
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,6 +309,8 @@ namespace transport
|
||||
m_OnEstablished ();
|
||||
m_OnEstablished = nullptr;
|
||||
}
|
||||
LogPrint(eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
|
||||
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") established");
|
||||
}
|
||||
|
||||
void SSU2Session::Done ()
|
||||
@@ -351,7 +364,7 @@ namespace transport
|
||||
RequestTermination (eSSU2TerminationReasonTimeout);
|
||||
}
|
||||
}
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
SetSendQueueSize (m_SendQueue.size ());
|
||||
}
|
||||
|
||||
bool SSU2Session::SendQueue ()
|
||||
@@ -511,7 +524,7 @@ namespace transport
|
||||
LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session");
|
||||
m_SentPackets.clear ();
|
||||
m_SendQueue.clear ();
|
||||
m_SendQueueSize = 0;
|
||||
SetSendQueueSize (0);
|
||||
RequestTermination (eSSU2TerminationReasonTimeout);
|
||||
return resentPackets.size ();
|
||||
}
|
||||
@@ -809,6 +822,8 @@ namespace transport
|
||||
m_NoiseState->m_CK + 32, nonce, decryptedPayload.data (), decryptedPayload.size (), false))
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: SessionCreated AEAD verification failed ");
|
||||
if (GetRemoteIdentity ())
|
||||
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key
|
||||
return false;
|
||||
}
|
||||
m_NoiseState->MixHash (payload, len - 64); // h = SHA256(h || encrypted payload from SessionCreated) for SessionConfirmed
|
||||
@@ -1051,6 +1066,17 @@ namespace transport
|
||||
LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block");
|
||||
return false;
|
||||
}
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||
if (ts > ri->GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
|
||||
{
|
||||
LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is too old for ", (ts - ri->GetTimestamp ())/1000LL, " seconds");
|
||||
return false;
|
||||
}
|
||||
if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri->GetTimestamp ()) // 2 minutes
|
||||
{
|
||||
LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is from future for ", (ri->GetTimestamp () - ts)/1000LL, " seconds");
|
||||
return false;
|
||||
}
|
||||
m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address ();
|
||||
if (!m_Address || memcmp (S, m_Address->s, 32))
|
||||
{
|
||||
@@ -1426,8 +1452,7 @@ namespace transport
|
||||
header.ll[1] ^= CreateHeaderMask (m_KeyDataSend + 32, payload + (len + 4));
|
||||
m_Server.Send (header.buf, 16, payload, len + 16, m_RemoteEndpoint);
|
||||
m_SendPacketNum++;
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumSentBytes += len + 32;
|
||||
UpdateNumSentBytes (len + 32);
|
||||
return m_SendPacketNum - 1;
|
||||
}
|
||||
|
||||
@@ -1468,8 +1493,7 @@ namespace transport
|
||||
LogPrint (eLogWarning, "SSU2: Data AEAD verification failed ");
|
||||
return;
|
||||
}
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumReceivedBytes += len;
|
||||
UpdateNumReceivedBytes (len);
|
||||
if (!packetNum || UpdateReceivePacketNum (packetNum))
|
||||
HandlePayload (payload, payloadSize);
|
||||
}
|
||||
@@ -1484,7 +1508,7 @@ namespace transport
|
||||
auto size = bufbe16toh (buf + offset);
|
||||
offset += 2;
|
||||
LogPrint (eLogDebug, "SSU2: Block type ", (int)blk, " of size ", size);
|
||||
if (size > len)
|
||||
if (offset + size > len)
|
||||
{
|
||||
LogPrint (eLogError, "SSU2: Unexpected block length ", size);
|
||||
break;
|
||||
@@ -1530,16 +1554,21 @@ namespace transport
|
||||
break;
|
||||
case eSSU2BlkTermination:
|
||||
{
|
||||
uint8_t rsn = buf[11]; // reason
|
||||
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
|
||||
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
|
||||
RequestTermination (eSSU2TerminationReasonTerminationReceived);
|
||||
else if (m_State != eSSU2SessionStateTerminated)
|
||||
if (size >= 9)
|
||||
{
|
||||
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
|
||||
m_State = eSSU2SessionStateClosingConfirmed;
|
||||
Done ();
|
||||
uint8_t rsn = buf[offset + 8]; // reason
|
||||
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
|
||||
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
|
||||
RequestTermination (eSSU2TerminationReasonTerminationReceived);
|
||||
else if (m_State != eSSU2SessionStateTerminated)
|
||||
{
|
||||
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
|
||||
m_State = eSSU2SessionStateClosingConfirmed;
|
||||
Done ();
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint(eLogWarning, "SSU2: Unexpected termination block size ", size);
|
||||
break;
|
||||
}
|
||||
case eSSU2BlkRelayRequest:
|
||||
@@ -1633,16 +1662,18 @@ namespace transport
|
||||
break;
|
||||
case eSSU2SessionStateSessionCreatedReceived:
|
||||
case eSSU2SessionStateTokenReceived:
|
||||
if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) ||
|
||||
(m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting))
|
||||
if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetTesting ()) ||
|
||||
(m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetTestingV6 ()))
|
||||
{
|
||||
if (m_Server.IsSyncClockFromPeers ())
|
||||
{
|
||||
if (std::abs (offset) > SSU2_CLOCK_THRESHOLD)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds");
|
||||
i2p::util::AdjustTimeOffset (-offset);
|
||||
}
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint);
|
||||
m_Server.AdjustTimeOffset (-offset);
|
||||
}
|
||||
else
|
||||
m_Server.AdjustTimeOffset (0);
|
||||
}
|
||||
else if (std::abs (offset) > SSU2_CLOCK_SKEW)
|
||||
{
|
||||
@@ -1732,14 +1763,14 @@ namespace transport
|
||||
LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4));
|
||||
if (isV4)
|
||||
{
|
||||
if (i2p::context.GetStatus () == eRouterStatusTesting)
|
||||
if (i2p::context.GetTesting ())
|
||||
i2p::context.SetError (eRouterErrorSymmetricNAT);
|
||||
else if (m_State == eSSU2SessionStatePeerTest)
|
||||
i2p::context.SetError (eRouterErrorFullConeNAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
|
||||
if (i2p::context.GetTestingV6 ())
|
||||
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
|
||||
else if (m_State == eSSU2SessionStatePeerTest)
|
||||
i2p::context.SetErrorV6 (eRouterErrorFullConeNAT);
|
||||
@@ -2212,7 +2243,7 @@ namespace transport
|
||||
if (buf[1] == eSSU2PeerTestCodeAccept)
|
||||
{
|
||||
if (GetRouterStatus () == eRouterStatusUnknown)
|
||||
SetRouterStatus (eRouterStatusTesting);
|
||||
SetTestingState (true);
|
||||
auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie
|
||||
if (r && it->second.first)
|
||||
{
|
||||
@@ -2238,13 +2269,17 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetRouterStatus () == eRouterStatusTesting)
|
||||
if (GetTestingState ())
|
||||
{
|
||||
SetRouterStatus (eRouterStatusFirewalled);
|
||||
if (m_Address->IsV4 ())
|
||||
m_Server.RescheduleIntroducersUpdateTimer ();
|
||||
else
|
||||
m_Server.RescheduleIntroducersUpdateTimerV6 ();
|
||||
SetTestingState (false);
|
||||
if (GetRouterStatus () != eRouterStatusFirewalled)
|
||||
{
|
||||
SetRouterStatus (eRouterStatusFirewalled);
|
||||
if (m_Address->IsV4 ())
|
||||
m_Server.RescheduleIntroducersUpdateTimer ();
|
||||
else
|
||||
m_Server.RescheduleIntroducersUpdateTimerV6 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()),
|
||||
@@ -2273,7 +2308,7 @@ namespace transport
|
||||
{
|
||||
LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ",
|
||||
i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3)));
|
||||
if (GetRouterStatus () == eRouterStatusTesting)
|
||||
if (GetTestingState ())
|
||||
SetRouterStatus (eRouterStatusUnknown);
|
||||
it->second.first->Done ();
|
||||
}
|
||||
@@ -2322,7 +2357,7 @@ namespace transport
|
||||
if (!msg->IsExpired ())
|
||||
{
|
||||
// m_LastActivityTimestamp is updated in ProcessData before
|
||||
if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second)
|
||||
if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)GetLastActivityTimestamp ()).second)
|
||||
m_Handler.PutNextMessage (std::move (msg));
|
||||
else
|
||||
LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received");
|
||||
@@ -2427,6 +2462,31 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
bool SSU2Session::GetTestingState () const
|
||||
{
|
||||
if (m_Address)
|
||||
{
|
||||
if (m_Address->IsV4 ())
|
||||
return i2p::context.GetTesting ();
|
||||
if (m_Address->IsV6 ())
|
||||
return i2p::context.GetTestingV6 ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SSU2Session::SetTestingState (bool testing) const
|
||||
{
|
||||
if (m_Address)
|
||||
{
|
||||
if (m_Address->IsV4 ())
|
||||
i2p::context.SetTesting (testing);
|
||||
else if (m_Address->IsV6 ())
|
||||
i2p::context.SetTestingV6 (testing);
|
||||
}
|
||||
if (!testing)
|
||||
m_Server.AdjustTimeOffset (0); // reset time offset when testing is over
|
||||
}
|
||||
|
||||
size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep)
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
@@ -2839,7 +2899,7 @@ namespace transport
|
||||
|
||||
void SSU2Session::SendPathResponse (const uint8_t * data, size_t len)
|
||||
{
|
||||
if (len < 8 || len > m_MaxPayloadSize - 3)
|
||||
if (len > m_MaxPayloadSize - 3)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len);
|
||||
return;
|
||||
@@ -2848,7 +2908,10 @@ namespace transport
|
||||
payload[0] = eSSU2BlkPathResponse;
|
||||
htobe16buf (payload + 1, len);
|
||||
memcpy (payload + 3, data, len);
|
||||
SendData (payload, len + 3);
|
||||
size_t payloadSize = len + 3;
|
||||
if (payloadSize < m_MaxPayloadSize)
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0);
|
||||
SendData (payload, payloadSize);
|
||||
}
|
||||
|
||||
void SSU2Session::SendPathChallenge ()
|
||||
@@ -2866,7 +2929,7 @@ namespace transport
|
||||
}
|
||||
len += 3;
|
||||
if (len < m_MaxPayloadSize)
|
||||
len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len);
|
||||
len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0);
|
||||
SendData (payload, len);
|
||||
}
|
||||
|
||||
@@ -2882,7 +2945,7 @@ namespace transport
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > m_LastActivityTimestamp + SSU2_DECAY_INTERVAL)
|
||||
if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > GetLastActivityTimestamp () + SSU2_DECAY_INTERVAL)
|
||||
// decay
|
||||
m_ReceivedI2NPMsgIDs.clear ();
|
||||
else
|
||||
@@ -2954,7 +3017,7 @@ namespace transport
|
||||
{
|
||||
bool sent = SendQueue (); // if we have something to send
|
||||
if (sent)
|
||||
m_SendQueueSize = m_SendQueue.size ();
|
||||
SetSendQueueSize (m_SendQueue.size ());
|
||||
if (m_IsDataReceived)
|
||||
{
|
||||
if (!sent) SendQuickAck ();
|
||||
|
||||
@@ -308,6 +308,8 @@ namespace transport
|
||||
void AdjustMaxPayloadSize ();
|
||||
RouterStatus GetRouterStatus () const;
|
||||
void SetRouterStatus (RouterStatus status) const;
|
||||
bool GetTestingState () const;
|
||||
void SetTestingState(bool testing) const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
|
||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||
bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -15,26 +15,35 @@ namespace i2p
|
||||
namespace crypto
|
||||
{
|
||||
#if OPENSSL_EDDSA
|
||||
EDDSA25519Verifier::EDDSA25519Verifier ()
|
||||
EDDSA25519Verifier::EDDSA25519Verifier ():
|
||||
m_Pkey (nullptr)
|
||||
{
|
||||
m_MDCtx = EVP_MD_CTX_create ();
|
||||
}
|
||||
|
||||
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
||||
{
|
||||
EVP_MD_CTX_destroy (m_MDCtx);
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
}
|
||||
|
||||
void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey)
|
||||
{
|
||||
EVP_PKEY * pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
|
||||
EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, pkey);
|
||||
EVP_PKEY_free (pkey);
|
||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||
m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
|
||||
}
|
||||
|
||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||
{
|
||||
return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len);
|
||||
if (m_Pkey)
|
||||
{
|
||||
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
|
||||
EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, m_Pkey);
|
||||
auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len);
|
||||
EVP_MD_CTX_destroy (ctx);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "EdDSA verification key is not set");
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -99,41 +108,45 @@ namespace crypto
|
||||
|
||||
#if OPENSSL_EDDSA
|
||||
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
|
||||
m_MDCtx (nullptr), m_Fallback (nullptr)
|
||||
m_Pkey (nullptr), m_Fallback (nullptr)
|
||||
{
|
||||
EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
|
||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
|
||||
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||
EVP_PKEY_get_raw_public_key (pkey, publicKey, &len);
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
|
||||
if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
||||
{
|
||||
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
|
||||
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
m_Pkey = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MDCtx = EVP_MD_CTX_create ();
|
||||
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, pkey);
|
||||
}
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
EDDSA25519Signer::~EDDSA25519Signer ()
|
||||
{
|
||||
if (m_Fallback) delete m_Fallback;
|
||||
EVP_MD_CTX_destroy (m_MDCtx);
|
||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||
}
|
||||
|
||||
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
{
|
||||
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
|
||||
else
|
||||
if (m_Fallback)
|
||||
return m_Fallback->Sign (buf, len, signature);
|
||||
else if (m_Pkey)
|
||||
{
|
||||
|
||||
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
|
||||
size_t l = 64;
|
||||
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
||||
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
|
||||
EVP_DigestSignInit (ctx, NULL, NULL, NULL, m_Pkey);
|
||||
if (!EVP_DigestSign (ctx, sig, &l, buf, len))
|
||||
LogPrint (eLogError, "EdDSA signing failed");
|
||||
memcpy (signature, sig, 64);
|
||||
EVP_MD_CTX_destroy (ctx);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "EdDSA signing key is not set");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -304,7 +304,7 @@ namespace crypto
|
||||
private:
|
||||
|
||||
#if OPENSSL_EDDSA
|
||||
EVP_MD_CTX * m_MDCtx;
|
||||
EVP_PKEY * m_Pkey;
|
||||
#else
|
||||
EDDSAPoint m_PublicKey;
|
||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
@@ -341,7 +341,7 @@ namespace crypto
|
||||
|
||||
private:
|
||||
|
||||
EVP_MD_CTX * m_MDCtx;
|
||||
EVP_PKEY * m_Pkey;
|
||||
EDDSA25519SignerCompat * m_Fallback;
|
||||
};
|
||||
#else
|
||||
|
||||
@@ -19,11 +19,6 @@ namespace i2p
|
||||
{
|
||||
namespace stream
|
||||
{
|
||||
void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler)
|
||||
{
|
||||
Add (std::make_shared<SendBuffer>(buf, len, handler));
|
||||
}
|
||||
|
||||
void SendBufferQueue::Add (std::shared_ptr<SendBuffer> buf)
|
||||
{
|
||||
if (buf)
|
||||
@@ -115,10 +110,7 @@ namespace stream
|
||||
|
||||
void Stream::CleanUp ()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SendBufferMutex);
|
||||
m_SendBuffer.CleanUp ();
|
||||
}
|
||||
m_SendBuffer.CleanUp ();
|
||||
while (!m_ReceiveQueue.empty ())
|
||||
{
|
||||
auto packet = m_ReceiveQueue.front ();
|
||||
@@ -532,14 +524,18 @@ namespace stream
|
||||
|
||||
void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler)
|
||||
{
|
||||
std::shared_ptr<i2p::stream::SendBuffer> buffer;
|
||||
if (len > 0 && buf)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SendBufferMutex);
|
||||
m_SendBuffer.Add (buf, len, handler);
|
||||
}
|
||||
buffer = std::make_shared<i2p::stream::SendBuffer>(buf, len, handler);
|
||||
else if (handler)
|
||||
handler(boost::system::error_code ());
|
||||
m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
|
||||
auto s = shared_from_this ();
|
||||
m_Service.post ([s, buffer]()
|
||||
{
|
||||
if (buffer)
|
||||
s->m_SendBuffer.Add (buffer);
|
||||
s->SendBuffer ();
|
||||
});
|
||||
}
|
||||
|
||||
void Stream::SendBuffer ()
|
||||
@@ -549,91 +545,88 @@ namespace stream
|
||||
|
||||
bool isNoAck = m_LastReceivedSequenceNumber < 0; // first packet
|
||||
std::vector<Packet *> packets;
|
||||
while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0))
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SendBufferMutex);
|
||||
while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0))
|
||||
Packet * p = m_LocalDestination.NewPacket ();
|
||||
uint8_t * packet = p->GetBuffer ();
|
||||
// TODO: implement setters
|
||||
size_t size = 0;
|
||||
htobe32buf (packet + size, m_SendStreamID);
|
||||
size += 4; // sendStreamID
|
||||
htobe32buf (packet + size, m_RecvStreamID);
|
||||
size += 4; // receiveStreamID
|
||||
htobe32buf (packet + size, m_SequenceNumber++);
|
||||
size += 4; // sequenceNum
|
||||
if (isNoAck)
|
||||
htobuf32 (packet + size, 0);
|
||||
else
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||
size += 4; // ack Through
|
||||
if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity)
|
||||
{
|
||||
Packet * p = m_LocalDestination.NewPacket ();
|
||||
uint8_t * packet = p->GetBuffer ();
|
||||
// TODO: implement setters
|
||||
size_t size = 0;
|
||||
htobe32buf (packet + size, m_SendStreamID);
|
||||
size += 4; // sendStreamID
|
||||
htobe32buf (packet + size, m_RecvStreamID);
|
||||
size += 4; // receiveStreamID
|
||||
htobe32buf (packet + size, m_SequenceNumber++);
|
||||
size += 4; // sequenceNum
|
||||
if (isNoAck)
|
||||
htobuf32 (packet + size, 0);
|
||||
else
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||
size += 4; // ack Through
|
||||
if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity)
|
||||
{
|
||||
// first SYN packet
|
||||
packet[size] = 8;
|
||||
size++; // NACK count
|
||||
memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32);
|
||||
size += 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
}
|
||||
packet[size] = m_RTO/1000;
|
||||
size++; // resend delay
|
||||
if (m_Status == eStreamStatusNew)
|
||||
{
|
||||
// initial packet
|
||||
m_Status = eStreamStatusOpen;
|
||||
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
|
||||
if (m_RemoteLeaseSet)
|
||||
{
|
||||
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
|
||||
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
|
||||
}
|
||||
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
|
||||
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
|
||||
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
||||
bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature ();
|
||||
if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE;
|
||||
htobe16buf (packet + size, flags);
|
||||
size += 2; // flags
|
||||
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
|
||||
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
|
||||
uint8_t * optionsSize = packet + size; // set options size later
|
||||
size += 2; // options size
|
||||
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
|
||||
size += identityLen; // from
|
||||
htobe16buf (packet + size, m_MTU);
|
||||
size += 2; // max packet size
|
||||
if (isOfflineSignature)
|
||||
{
|
||||
const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature ();
|
||||
memcpy (packet + size, offlineSignature.data (), offlineSignature.size ());
|
||||
size += offlineSignature.size (); // offline signature
|
||||
}
|
||||
uint8_t * signature = packet + size; // set it later
|
||||
memset (signature, 0, signatureLen); // zeroes for now
|
||||
size += signatureLen; // signature
|
||||
htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size
|
||||
size += m_SendBuffer.Get (packet + size, m_MTU); // payload
|
||||
m_LocalDestination.GetOwner ()->Sign (packet, size, signature);
|
||||
}
|
||||
else
|
||||
{
|
||||
// follow on packet
|
||||
htobuf16 (packet + size, 0);
|
||||
size += 2; // flags
|
||||
htobuf16 (packet + size, 0); // no options
|
||||
size += 2; // options size
|
||||
size += m_SendBuffer.Get(packet + size, m_MTU); // payload
|
||||
}
|
||||
p->len = size;
|
||||
packets.push_back (p);
|
||||
numMsgs--;
|
||||
// first SYN packet
|
||||
packet[size] = 8;
|
||||
size++; // NACK count
|
||||
memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32);
|
||||
size += 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
}
|
||||
packet[size] = m_RTO/1000;
|
||||
size++; // resend delay
|
||||
if (m_Status == eStreamStatusNew)
|
||||
{
|
||||
// initial packet
|
||||
m_Status = eStreamStatusOpen;
|
||||
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
|
||||
if (m_RemoteLeaseSet)
|
||||
{
|
||||
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
|
||||
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
|
||||
}
|
||||
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
|
||||
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
|
||||
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
||||
bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature ();
|
||||
if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE;
|
||||
htobe16buf (packet + size, flags);
|
||||
size += 2; // flags
|
||||
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
|
||||
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
|
||||
uint8_t * optionsSize = packet + size; // set options size later
|
||||
size += 2; // options size
|
||||
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
|
||||
size += identityLen; // from
|
||||
htobe16buf (packet + size, m_MTU);
|
||||
size += 2; // max packet size
|
||||
if (isOfflineSignature)
|
||||
{
|
||||
const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature ();
|
||||
memcpy (packet + size, offlineSignature.data (), offlineSignature.size ());
|
||||
size += offlineSignature.size (); // offline signature
|
||||
}
|
||||
uint8_t * signature = packet + size; // set it later
|
||||
memset (signature, 0, signatureLen); // zeroes for now
|
||||
size += signatureLen; // signature
|
||||
htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size
|
||||
size += m_SendBuffer.Get (packet + size, m_MTU); // payload
|
||||
m_LocalDestination.GetOwner ()->Sign (packet, size, signature);
|
||||
}
|
||||
else
|
||||
{
|
||||
// follow on packet
|
||||
htobuf16 (packet + size, 0);
|
||||
size += 2; // flags
|
||||
htobuf16 (packet + size, 0); // no options
|
||||
size += 2; // options size
|
||||
size += m_SendBuffer.Get(packet + size, m_MTU); // payload
|
||||
}
|
||||
p->len = size;
|
||||
packets.push_back (p);
|
||||
numMsgs--;
|
||||
}
|
||||
if (packets.size () > 0)
|
||||
{
|
||||
|
||||
@@ -135,7 +135,6 @@ namespace stream
|
||||
SendBufferQueue (): m_Size (0) {};
|
||||
~SendBufferQueue () { CleanUp (); };
|
||||
|
||||
void Add (const uint8_t * buf, size_t len, SendHandler handler);
|
||||
void Add (std::shared_ptr<SendBuffer> buf);
|
||||
size_t Get (uint8_t * buf, size_t len);
|
||||
size_t GetSize () const { return m_Size; };
|
||||
@@ -251,7 +250,6 @@ namespace stream
|
||||
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||
uint16_t m_Port;
|
||||
|
||||
std::mutex m_SendBufferMutex;
|
||||
SendBufferQueue m_SendBuffer;
|
||||
int m_WindowSize, m_RTT, m_RTO, m_AckDelay;
|
||||
uint64_t m_LastWindowSizeIncreaseTime;
|
||||
|
||||
@@ -71,15 +71,17 @@ namespace transport
|
||||
|
||||
const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds
|
||||
const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds
|
||||
const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds
|
||||
class TransportSession
|
||||
{
|
||||
public:
|
||||
|
||||
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
|
||||
m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0),
|
||||
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
|
||||
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()),
|
||||
m_HandshakeInterval (0)
|
||||
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_HandshakeInterval (0),
|
||||
m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0),
|
||||
m_LastBandWidthUpdateNumSentBytes (0), m_LastBandWidthUpdateNumReceivedBytes (0),
|
||||
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()),
|
||||
m_LastBandwidthUpdateTimestamp (m_LastActivityTimestamp), m_InBandwidth (0), m_OutBandwidth (0)
|
||||
{
|
||||
if (router)
|
||||
m_RemoteIdentity = router->GetRouterIdentity ();
|
||||
@@ -103,11 +105,29 @@ namespace transport
|
||||
}
|
||||
|
||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||
void UpdateNumSentBytes (size_t len)
|
||||
{
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumSentBytes += len;
|
||||
UpdateBandwidth ();
|
||||
}
|
||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||
void UpdateNumReceivedBytes (size_t len)
|
||||
{
|
||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||
m_NumReceivedBytes += len;
|
||||
UpdateBandwidth ();
|
||||
}
|
||||
size_t GetSendQueueSize () const { return m_SendQueueSize; };
|
||||
void SetSendQueueSize (size_t s) { m_SendQueueSize = s; };
|
||||
bool IsOutgoing () const { return m_IsOutgoing; };
|
||||
bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD &&
|
||||
m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; };
|
||||
bool IsBandwidthExceeded (bool isHighBandwidth) const
|
||||
{
|
||||
auto limit = isHighBandwidth ? i2p::data::HIGH_BANDWIDTH_LIMIT*1024 : i2p::data::LOW_BANDWIDTH_LIMIT*1024; // convert to bytes
|
||||
return std::max (m_InBandwidth, m_OutBandwidth) > limit;
|
||||
}
|
||||
|
||||
int GetTerminationTimeout () const { return m_TerminationTimeout; };
|
||||
void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; };
|
||||
@@ -120,21 +140,52 @@ namespace transport
|
||||
uint32_t GetCreationTime () const { return m_CreationTime; };
|
||||
void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
|
||||
|
||||
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
|
||||
void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; };
|
||||
|
||||
virtual uint32_t GetRelayTag () const { return 0; };
|
||||
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
|
||||
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
|
||||
virtual bool IsEstablished () const = 0;
|
||||
|
||||
private:
|
||||
|
||||
void UpdateBandwidth ()
|
||||
{
|
||||
int64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp;
|
||||
if (interval < 0 || interval > 60*10) // 10 minutes
|
||||
{
|
||||
// clock was adjusted, copy new values
|
||||
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
|
||||
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
|
||||
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
|
||||
return;
|
||||
}
|
||||
if ((uint64_t)interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL)
|
||||
{
|
||||
m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval;
|
||||
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
|
||||
m_InBandwidth = (m_NumReceivedBytes - m_LastBandWidthUpdateNumReceivedBytes)/interval;
|
||||
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
|
||||
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
||||
mutable std::mutex m_RemoteIdentityMutex;
|
||||
size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize;
|
||||
bool m_IsOutgoing;
|
||||
int m_TerminationTimeout;
|
||||
uint64_t m_LastActivityTimestamp;
|
||||
uint32_t m_CreationTime; // seconds since epoch
|
||||
int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed
|
||||
|
||||
private:
|
||||
|
||||
size_t m_SendQueueSize, m_NumSentBytes, m_NumReceivedBytes,
|
||||
m_LastBandWidthUpdateNumSentBytes, m_LastBandWidthUpdateNumReceivedBytes;
|
||||
uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp;
|
||||
uint32_t m_InBandwidth, m_OutBandwidth;
|
||||
};
|
||||
|
||||
// SOCKS5 proxy
|
||||
|
||||
@@ -591,7 +591,7 @@ namespace transport
|
||||
peer.router->GetCompatibleTransports (true);
|
||||
peer.numAttempts = 0;
|
||||
peer.priority.clear ();
|
||||
bool ssu2 = rand () & 1;
|
||||
bool ssu2 = peer.router->GetProfile ()->IsReal () ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real
|
||||
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
|
||||
for (auto transport: priority)
|
||||
if (transport & compatibleTransports)
|
||||
@@ -645,14 +645,33 @@ namespace transport
|
||||
LogPrint (eLogInfo, "Transports: Started peer test IPv4");
|
||||
std::set<i2p::data::IdentHash> excluded;
|
||||
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
|
||||
int testDelay = 0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4
|
||||
if (router)
|
||||
{
|
||||
if (i2p::context.GetStatus () != eRouterStatusTesting)
|
||||
i2p::context.SetStatus (eRouterStatusTesting);
|
||||
m_SSU2Server->StartPeerTest (router, true);
|
||||
if (!i2p::context.GetTesting ())
|
||||
{
|
||||
i2p::context.SetTesting (true);
|
||||
// send first peer test immediately
|
||||
m_SSU2Server->StartPeerTest (router, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
if (m_Service)
|
||||
{
|
||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||
delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay));
|
||||
delayTimer->async_wait (
|
||||
[this, router, delayTimer](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
m_SSU2Server->StartPeerTest (router, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
excluded.insert (router->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
@@ -664,14 +683,33 @@ namespace transport
|
||||
LogPrint (eLogInfo, "Transports: Started peer test IPv6");
|
||||
std::set<i2p::data::IdentHash> excluded;
|
||||
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
|
||||
int testDelay = 0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6
|
||||
if (router)
|
||||
{
|
||||
if (i2p::context.GetStatusV6 () != eRouterStatusTesting)
|
||||
i2p::context.SetStatusV6 (eRouterStatusTesting);
|
||||
m_SSU2Server->StartPeerTest (router, false);
|
||||
if (!i2p::context.GetTestingV6 ())
|
||||
{
|
||||
i2p::context.SetTestingV6 (true);
|
||||
// send first peer test immediately
|
||||
m_SSU2Server->StartPeerTest (router, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
if (m_Service)
|
||||
{
|
||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||
delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay));
|
||||
delayTimer->async_wait (
|
||||
[this, router, delayTimer](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
m_SSU2Server->StartPeerTest (router, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
excluded.insert (router->GetIdentHash ());
|
||||
}
|
||||
}
|
||||
@@ -709,6 +747,14 @@ namespace transport
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
transports |= it->second.priority[i];
|
||||
i2p::data::netdb.ExcludeReachableTransports (ident, transports);
|
||||
}
|
||||
if (it->second.router && it->second.numAttempts)
|
||||
{
|
||||
auto transport = it->second.priority[it->second.numAttempts-1];
|
||||
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
|
||||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
|
||||
it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real
|
||||
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
|
||||
}
|
||||
it->second.numAttempts = 0;
|
||||
it->second.router = nullptr; // we don't need RouterInfo after successive connect
|
||||
@@ -729,7 +775,7 @@ namespace transport
|
||||
session->SendI2NPMessages (it->second.delayedMessages);
|
||||
it->second.delayedMessages.clear ();
|
||||
}
|
||||
else // incoming connection
|
||||
else // incoming connection or peer test
|
||||
{
|
||||
if(RoutesRestricted() && ! IsRestrictedPeer(ident)) {
|
||||
// not trusted
|
||||
@@ -737,11 +783,15 @@ namespace transport
|
||||
session->Done();
|
||||
return;
|
||||
}
|
||||
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
|
||||
if (!session->IsOutgoing ()) // incoming
|
||||
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
|
||||
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
|
||||
if (r) r->GetProfile ()->Connected ();
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first;
|
||||
auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first;
|
||||
it->second.sessions.push_back (session);
|
||||
it->second.router = nullptr;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -798,12 +848,12 @@ namespace transport
|
||||
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
||||
{
|
||||
LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
|
||||
if (!it->second.router)
|
||||
/* if (!it->second.router)
|
||||
{
|
||||
// if router for ident not found mark it unreachable
|
||||
auto profile = i2p::data::GetRouterProfile (it->first);
|
||||
if (profile) profile->Unreachable ();
|
||||
}
|
||||
} */
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
it = m_Peers.erase (it);
|
||||
}
|
||||
@@ -820,9 +870,13 @@ namespace transport
|
||||
++it;
|
||||
}
|
||||
}
|
||||
bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting;
|
||||
bool ipv6Testing = i2p::context.GetStatusV6 () == eRouterStatusTesting;
|
||||
// if still testing, repeat peer test
|
||||
bool ipv4Testing = i2p::context.GetTesting ();
|
||||
if (!ipv4Testing)
|
||||
ipv4Testing = i2p::context.GetRouterInfo ().IsSSU2V4 () && (i2p::context.GetStatus() == eRouterStatusUnknown);
|
||||
bool ipv6Testing = i2p::context.GetTestingV6 ();
|
||||
if (!ipv6Testing)
|
||||
ipv6Testing = i2p::context.GetRouterInfo ().IsSSU2V6 () && (i2p::context.GetStatusV6() == eRouterStatusUnknown);
|
||||
// if still testing or unknown, repeat peer test
|
||||
if (ipv4Testing || ipv6Testing)
|
||||
PeerTest (ipv4Testing, ipv6Testing);
|
||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT));
|
||||
@@ -850,7 +904,9 @@ namespace transport
|
||||
uint16_t inds[3];
|
||||
RAND_bytes ((uint8_t *)inds, sizeof (inds));
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
inds[0] %= m_Peers.size ();
|
||||
auto count = m_Peers.size ();
|
||||
if(count == 0) return nullptr;
|
||||
inds[0] %= count;
|
||||
auto it = m_Peers.begin ();
|
||||
std::advance (it, inds[0]);
|
||||
// try random peer
|
||||
@@ -933,7 +989,7 @@ namespace transport
|
||||
// connected, not overloaded and not slow
|
||||
return !peer.router && !peer.sessions.empty () && peer.isReachable &&
|
||||
peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE &&
|
||||
!peer.sessions.front ()->IsSlow () &&
|
||||
!peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) &&
|
||||
(!isHighBandwidth || peer.isHighBandwidth);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -105,6 +105,8 @@ namespace transport
|
||||
|
||||
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
|
||||
const int PEER_TEST_INTERVAL = 71; // in minutes
|
||||
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
|
||||
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
|
||||
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
||||
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
|
||||
class Transports
|
||||
|
||||
@@ -516,7 +516,7 @@ namespace tunnel
|
||||
case eI2NPShortTunnelBuildReply:
|
||||
case eI2NPTunnelBuild:
|
||||
case eI2NPTunnelBuildReply:
|
||||
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
||||
HandleTunnelBuildI2NPMessage (msg);
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID);
|
||||
@@ -586,10 +586,17 @@ namespace tunnel
|
||||
auto typeID = msg->GetTypeID ();
|
||||
LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID);
|
||||
|
||||
if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
|
||||
// transit DatabaseStore my contain new/updated RI
|
||||
// or DatabaseSearchReply with new routers
|
||||
if (typeID == eI2NPDatabaseSearchReply)
|
||||
// DatabaseSearchReply with new routers
|
||||
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg));
|
||||
else if (IsRouterInfoMsg (msg))
|
||||
{
|
||||
// transit DatabaseStore might contain new/updated RI
|
||||
auto m = CopyI2NPMessage (msg);
|
||||
if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET))
|
||||
memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply
|
||||
i2p::data::netdb.PostI2NPMsg (m);
|
||||
}
|
||||
tunnel->SendTunnelDataMsg (msg);
|
||||
}
|
||||
|
||||
@@ -702,7 +709,7 @@ namespace tunnel
|
||||
auto inboundTunnel = GetNextInboundTunnel ();
|
||||
auto router = i2p::transport::transports.RoutesRestricted() ?
|
||||
i2p::transport::transports.GetRestrictedPeer() :
|
||||
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us
|
||||
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us
|
||||
if (!inboundTunnel || !router) return;
|
||||
LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel");
|
||||
CreateTunnel<OutboundTunnel> (
|
||||
@@ -774,7 +781,7 @@ namespace tunnel
|
||||
auto router = i2p::transport::transports.RoutesRestricted() ?
|
||||
i2p::transport::transports.GetRestrictedPeer() :
|
||||
// should be reachable by us because we send build request directly
|
||||
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false);
|
||||
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true);
|
||||
if (!router) {
|
||||
LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel");
|
||||
return;
|
||||
@@ -979,6 +986,6 @@ namespace tunnel
|
||||
LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels);
|
||||
m_MaxNumTransitTunnels = maxNumTransitTunnels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace tunnel
|
||||
const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds
|
||||
const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds
|
||||
const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds
|
||||
|
||||
|
||||
const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12
|
||||
const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6
|
||||
|
||||
@@ -232,8 +232,8 @@ namespace tunnel
|
||||
|
||||
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
|
||||
uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
|
||||
bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
|
||||
|
||||
bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
|
||||
|
||||
private:
|
||||
|
||||
template<class TTunnel>
|
||||
@@ -292,7 +292,7 @@ namespace tunnel
|
||||
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
|
||||
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE> > m_I2NPTunnelEndpointMessagesMemoryPool;
|
||||
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_MESSAGE_SIZE> > m_I2NPTunnelMessagesMemoryPool;
|
||||
uint16_t m_MaxNumTransitTunnels;
|
||||
uint16_t m_MaxNumTransitTunnels;
|
||||
// count of tunnels for total TCSR algorithm
|
||||
int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations;
|
||||
double m_TunnelCreationSuccessRate;
|
||||
@@ -311,6 +311,7 @@ namespace tunnel
|
||||
|
||||
int GetQueueSize () { return m_Queue.GetSize (); };
|
||||
int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents
|
||||
double GetPreciseTunnelCreationSuccessRate () const { return m_TunnelCreationSuccessRate * 100; } // in percents
|
||||
int GetTotalTunnelCreationSuccessRate () const // in percents
|
||||
{
|
||||
int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations;
|
||||
|
||||
@@ -323,11 +323,7 @@ namespace tunnel
|
||||
}
|
||||
uint8_t typeID = msg.data->GetTypeID ();
|
||||
LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID);
|
||||
// catch RI or reply with new list of routers
|
||||
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
|
||||
!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal)
|
||||
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data));
|
||||
|
||||
|
||||
switch (msg.deliveryType)
|
||||
{
|
||||
case eDeliveryTypeLocal:
|
||||
|
||||
@@ -296,10 +296,12 @@ namespace tunnel
|
||||
for (const auto& it : m_InboundTunnels)
|
||||
if (it->IsEstablished ()) num++;
|
||||
}
|
||||
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0)
|
||||
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0 &&
|
||||
m_NumInboundHops == m_NumOutboundHops)
|
||||
{
|
||||
for (auto it: m_OutboundTunnels)
|
||||
{
|
||||
// try to create inbound tunnel through the same path as succesive outbound
|
||||
CreatePairedInboundTunnel (it);
|
||||
num++;
|
||||
if (num >= m_NumInboundTunnels) break;
|
||||
@@ -470,13 +472,14 @@ namespace tunnel
|
||||
return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ();
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const
|
||||
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
|
||||
bool reverse, bool endpoint) const
|
||||
{
|
||||
auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse):
|
||||
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse);
|
||||
auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint):
|
||||
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint);
|
||||
|
||||
if (!hop || hop->GetProfile ()->IsBad ())
|
||||
hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse);
|
||||
hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint);
|
||||
return hop;
|
||||
}
|
||||
|
||||
@@ -508,7 +511,7 @@ namespace tunnel
|
||||
|
||||
for(int i = start; i < numHops; i++ )
|
||||
{
|
||||
auto hop = nextHop (prevHop, inbound);
|
||||
auto hop = nextHop (prevHop, inbound, i == numHops - 1);
|
||||
if (!hop && !i) // if no suitable peer found for first hop, try already connected
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected");
|
||||
@@ -520,11 +523,6 @@ namespace tunnel
|
||||
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
|
||||
return false;
|
||||
}
|
||||
if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4
|
||||
{
|
||||
auto hop1 = nextHop (prevHop, true);
|
||||
if (hop1) hop = hop1;
|
||||
}
|
||||
prevHop = hop;
|
||||
path.Add (hop);
|
||||
}
|
||||
@@ -566,14 +564,15 @@ namespace tunnel
|
||||
if (m_CustomPeerSelector)
|
||||
return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound);
|
||||
}
|
||||
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
|
||||
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this,
|
||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
}
|
||||
|
||||
bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound)
|
||||
{
|
||||
if (!m_ExplicitPeers->size ()) return false;
|
||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||
if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size ();
|
||||
if (!numHops) return false;
|
||||
for (int i = 0; i < numHops; i++)
|
||||
{
|
||||
auto& ident = (*m_ExplicitPeers)[i];
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace tunnel
|
||||
|
||||
class TunnelPool: public std::enable_shared_from_this<TunnelPool> // per local destination
|
||||
{
|
||||
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool)> SelectHopFunc;
|
||||
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool, bool)> SelectHopFunc;
|
||||
public:
|
||||
|
||||
TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels,
|
||||
@@ -112,7 +112,7 @@ namespace tunnel
|
||||
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
|
||||
|
||||
// for overriding tunnel peer selection
|
||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse, bool endpoint) const;
|
||||
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop);
|
||||
|
||||
private:
|
||||
|
||||
@@ -38,9 +38,8 @@ namespace api
|
||||
|
||||
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
||||
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
|
||||
bool avx; i2p::config::GetOption("cpuext.avx", avx);
|
||||
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
|
||||
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
|
||||
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
|
||||
|
||||
int netID; i2p::config::GetOption("netid", netID);
|
||||
i2p::context.SetNetID (netID);
|
||||
|
||||
@@ -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,6 +27,17 @@
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__)
|
||||
#include <gnu/pthread.h>
|
||||
#include <posix/pthread.h>
|
||||
#include <posix/sys/sockio.h>
|
||||
#include <posix/sys/ioctl.h>
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#include <bsd/ifaddrs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -201,7 +212,7 @@ namespace net
|
||||
int GetMTUWindowsIpv4 (sockaddr_in inputAddress, int fallback)
|
||||
{
|
||||
typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size);
|
||||
IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
|
||||
IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
|
||||
if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found
|
||||
|
||||
ULONG outBufLen = 0;
|
||||
@@ -262,7 +273,7 @@ namespace net
|
||||
int GetMTUWindowsIpv6 (sockaddr_in6 inputAddress, int fallback)
|
||||
{
|
||||
typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size);
|
||||
IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
|
||||
IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
|
||||
if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found
|
||||
|
||||
ULONG outBufLen = 0;
|
||||
@@ -341,7 +352,7 @@ namespace net
|
||||
#endif
|
||||
|
||||
typedef int (* IPN)(int af, const char *src, void *dst);
|
||||
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
|
||||
IPN inetpton = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
|
||||
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
|
||||
|
||||
if (localAddress.is_v4())
|
||||
@@ -654,6 +665,7 @@ namespace net
|
||||
if (host.is_v6())
|
||||
{
|
||||
static const std::vector< std::pair<boost::asio::ip::address_v6::bytes_type, boost::asio::ip::address_v6::bytes_type> > reservedIPv6Ranges {
|
||||
address_pair_v6("64:ff9b::", "64:ff9b:ffff:ffff:ffff:ffff:ffff:ffff"), // NAT64
|
||||
address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"),
|
||||
address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
|
||||
address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -18,8 +18,8 @@
|
||||
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 47
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_MINOR 50
|
||||
#define I2PD_VERSION_MICRO 2
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#ifdef GITVER
|
||||
#define I2PD_VERSION XSTRINGIZE(GITVER)
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 58
|
||||
#define I2P_VERSION_MICRO 61
|
||||
#define I2P_VERSION_PATCH 0
|
||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
#define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user