mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-13 19:37:51 +00:00
Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl
This commit is contained in:
commit
005581ef62
29
.github/workflows/build-windows.yml
vendored
Normal file
29
.github/workflows/build-windows.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
name: Build on Windows
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Building for ${{ matrix.arch }}
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64 },
|
||||
{ msystem: MINGW32, arch: i686 }
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
|
||||
update: true
|
||||
- name: build application
|
||||
run: make USE_UPNP=yes DEBUG=no -j3
|
21
.github/workflows/build.yml
vendored
Normal file
21
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Build on Ubuntu with make
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Building with USE_UPNP=${{ matrix.with_upnp }} flag
|
||||
runs-on: ubuntu-16.04
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
with_upnp: ['yes', 'no']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install packages
|
||||
run: |
|
||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
|
||||
- name: build application
|
||||
run: make USE_AVX=no USE_AESNI=no USE_UPNP=${{ matrix.with_upnp }} -j3
|
25
ChangeLog
25
ChangeLog
@ -1,6 +1,31 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.33.0] - 2020-08-24
|
||||
### Added
|
||||
- Shared transient addresses
|
||||
- crypto.ratchet.inboundTags paramater
|
||||
- Multiple encryption keys through I2CP
|
||||
- Pre-calculated x25519 ephemeral keys
|
||||
- Change datagram routing path if nothing comes back in 10 seconds
|
||||
- Shared routing path for datagram session
|
||||
### Changed
|
||||
- UDP tunnels send mix of repliable and raw datagrams in bulk
|
||||
- Encrypt SSU packet again upon resend
|
||||
- Start new tunnel message if remaining buffer is too small
|
||||
- Use LeaseSet2 for ECIES-X25519-AEAD-Ratchet automatically
|
||||
- Save new ECIES-X25519-AEAD-Ratchet session with NSR tagset
|
||||
- Generate random padding lengths for ECIES-X25519-AEAD-Ratchet in bulk
|
||||
- Webconsole layout
|
||||
- Reseed servers list
|
||||
### Fixed
|
||||
- Don't connect through terminated SAM destination
|
||||
- Differentiate UDP server sessions by port
|
||||
- ECIES-X25519-AEAD-Ratchet through I2CP
|
||||
- Don't save invalid address to AddressBook
|
||||
- ECDSA signatures names in SAM
|
||||
- AppArmor profile
|
||||
|
||||
## [2.32.1] - 2020-06-02
|
||||
### Added
|
||||
- Read explicit peers in tunnels config
|
||||
|
@ -15,7 +15,7 @@ ifeq ($(shell expr match $(CXX) 'clang'),5)
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # gcc 4.7 - 4.9
|
||||
else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9
|
||||
NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
} else {
|
||||
Result = E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -90,4 +91,4 @@ void SubscribeToEvents() { }
|
||||
void UnSubscribeFromEvents() { }
|
||||
|
||||
#endif // WINVER
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
#define I2Pd_AppName "i2pd"
|
||||
#define I2Pd_ver "2.32.1"
|
||||
#define I2Pd_ver "2.33.0"
|
||||
#define I2Pd_Publisher "PurpleI2P"
|
||||
|
||||
[Setup]
|
||||
|
@ -30,8 +30,8 @@ android {
|
||||
applicationId "org.purplei2p.i2pd"
|
||||
targetSdkVersion 29
|
||||
minSdkVersion 14
|
||||
versionCode 2321
|
||||
versionName "2.32.1"
|
||||
versionCode 2330
|
||||
versionName "2.33.0"
|
||||
setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a'
|
||||
|
41
appveyor.yml
41
appveyor.yml
@ -1,4 +1,4 @@
|
||||
version: 2.32.1.{build}
|
||||
version: 2.33.0.{build}
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
branches:
|
||||
@ -9,32 +9,49 @@ os: Visual Studio 2015
|
||||
shallow_clone: true
|
||||
clone_depth: 1
|
||||
|
||||
# avoid building 32-bit if 64-bit failed already
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
environment:
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
MSYS2_PATH_TYPE: inherit
|
||||
CHERE_INVOKING: enabled_from_arguments
|
||||
matrix:
|
||||
- MSYSTEM: MINGW64
|
||||
MSYS_PACKAGES: mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc
|
||||
MSYS_BITNESS: 64
|
||||
- MSYSTEM: MINGW32
|
||||
MSYS_PACKAGES: mingw-w64-i686-boost mingw-w64-i686-miniupnpc
|
||||
MSYS_BITNESS: 32
|
||||
|
||||
cache:
|
||||
- c:\msys64\var\cache\pacman\pkg\
|
||||
|
||||
install:
|
||||
# install new signing keyring
|
||||
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||
- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||
# remove packages which can break build
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
|
||||
# TODO: revert that change when appveyor's images will be updated
|
||||
- c:\msys64\usr\bin\bash -l "build/appveyor-msys2-upgrade.bash"
|
||||
# update runtime
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||
# Kill bash before next try
|
||||
- taskkill /T /F /IM bash.exe /IM gpg.exe /IM gpg-agent.exe | exit /B 0
|
||||
# update packages and install required
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}"
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu $MINGW_PACKAGE_PREFIX-boost $MINGW_PACKAGE_PREFIX-miniupnpc"
|
||||
|
||||
build_script:
|
||||
- echo MSYSTEM = %MSYSTEM%, bitness = %MSYS_BITNESS%
|
||||
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes -j3"
|
||||
- 7z a -tzip -mx9 -mmt i2pd-mingw-win%MSYS_BITNESS%.zip i2pd.exe
|
||||
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes DEBUG=no -j3"
|
||||
# prepare archive for uploading
|
||||
- set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
|
||||
- echo This is development build, use it carefully! For running in portable mode, move all files from contrib directory here. > README.txt
|
||||
- 7z a -tzip -mx9 -mmt i2pd-%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,7%-mingw-win%MSYSTEM:~-2%.zip %FILELIST%
|
||||
|
||||
after_build:
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sc"
|
||||
|
||||
test: off
|
||||
|
||||
deploy: off
|
||||
|
||||
artifacts:
|
||||
- path: i2pd-mingw-win*.zip
|
||||
- path: i2pd-*.zip
|
||||
|
@ -68,7 +68,6 @@ set(LIBI2PD_SRC
|
||||
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
||||
|
@ -1,10 +0,0 @@
|
||||
set -e -x
|
||||
|
||||
base_url='http://repo.msys2.org/msys/x86_64/'
|
||||
packages="libzstd-1.4.4-2-x86_64.pkg.tar.xz pacman-5.2.1-6-x86_64.pkg.tar.xz zstd-1.4.4-2-x86_64.pkg.tar.xz"
|
||||
for p in $packages
|
||||
do
|
||||
curl "${base_url}$p" -o "$p"
|
||||
done
|
||||
pacman -U --noconfirm $packages
|
||||
rm -f $packages
|
@ -1,32 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFezCCA2OgAwIBAgIEUQYyQjANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOYnVnbWVAbWFpbC5p
|
||||
MnAwHhcNMTQxMTA2MDkxMTE0WhcNMjQxMTA1MDkxMTE0WjBuMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOYnVnbWVAbWFpbC5p
|
||||
MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCrThOH0eSDT0VnCSBC
|
||||
sqYmAydWH+O8eNttDXr2mSvZLhvAW+6/xHTkKhaWvkIvvS0Vh8hujMnD90Cgp4Fk
|
||||
TKCxMj9K527o5xIZwWW05OevbjlBwIpVLO1PjmsfsoD1nIX14eEzJSEoAulKsv7V
|
||||
jGUC/6hC11mmVvH9buQLSRv6sCjuAcMszmw3TAD+XYBIs+z57KuwYXtX3+OA543c
|
||||
l1/ZKLYkkwY8cwzZqWDVWqTKP5TfVae58t40HhJk3bOsr21FZsaOjlmao3GO+d/3
|
||||
exKuUGJRcolSqskL3sZ1ovFqko81obvvx0upI0YA0iMr/NRGl3VPuf/LJvRppYGc
|
||||
LsJHgy9TIgtHvaXRi5Nt4CbKl9sZh/7WkkTTI5YGvevu00btlabAN+DSAZZqdsB3
|
||||
wY8HhM1MHiA9SWsqwU65TwErcRrjNna2FiDHEu0xk5+/iAGl6CSKHZBmNcYKXSv8
|
||||
cwShB0jjmciK0a05nC638RPgj0fng7KRrSglyzfjXRrljmZ40LSBL/GGMZMWpOM7
|
||||
mEsBH5UZJ/2BEmjc9X9257zBdx8BK8y1TXpAligpNBsERcTw1WP1PJ35einZvlXW
|
||||
qI3GwMf0sl26sn+evcK0gDl27jVDZ45MtNQEq64M4NV3Tn9zq0eg/39YvjVeqrI5
|
||||
l7sxmYqYGR6BuSncwdc4x+t6swIDAQABoyEwHzAdBgNVHQ4EFgQU/REZ7NMbVZHr
|
||||
Xkao6Q8Ccqv2kAMwDQYJKoZIhvcNAQENBQADggIBACc2YjLVNbl1kJUdg2klCLJt
|
||||
5LjNTiIZa2Cha5GStlC/lyoRRge6+q/y9TN3tTptlzLPS9pI9EE1GfIQaE+HAk+e
|
||||
/bC3KUOAHgVuETvsNAbfpaVsPCdWpFuXmp/4b9iDN7qZy4afTKUPA/Ir/cLfNp14
|
||||
JULfP4z2yFOsCQZ5viNFAs1u99FrwobV2LBzUSIJQewsksuOwj96zIyau0Y629oJ
|
||||
k+og88Tifd9EH3MVZNGhdpojQDDdwHQSITnCDgfRP5yER1WIA4jg6l+mM90QkvLY
|
||||
5NjWTna5kJ3X6UizvgCk365yzT2sbN3R9UGXfCJa9GBcnnviJtJF3+/gC0abwY2f
|
||||
NtVYp32Xky45NY/NdRhDg0bjHP3psxmX+Sc0M9NuQcDQ+fUR+CzM0IGeiszkzXOs
|
||||
RG+bOou2cZ81G4oxWdAALHIRrn7VvLGlkFMxiIZyhYcTGQZzsTPT6n18dY99+DAV
|
||||
yQWZfIRdm8DOnt0G+cwfeohc/9ZwDmj4jJAAi0aeTXdY6NEGIVydk6MAycEhg2Hx
|
||||
9EV96kRwZNIW0AGY8CozECFL3Eyo2ClQVV4Q35SsBibsitDjM03usc2DJ/qjynXA
|
||||
C8HoOSWgbddiBvqZueqK8GdhykOy3J3ysr+MNN/lbG48LqkQr1OWxev9rGGQ6RJT
|
||||
wpBgPyAFAwouPy1whmnx
|
||||
-----END CERTIFICATE-----
|
34
contrib/certificates/reseed/reseed_at_diva.exchange.crt
Normal file
34
contrib/certificates/reseed/reseed_at_diva.exchange.crt
Normal file
@ -0,0 +1,34 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIF0zCCA7ugAwIBAgIQWjHyC+NRh3emuuAwcEnKSjANBgkqhkiG9w0BAQsFADB0
|
||||
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
|
||||
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsGA1UEAwwU
|
||||
cmVzZWVkQGRpdmEuZXhjaGFuZ2UwHhcNMjAwNjA5MDUzNjQ1WhcNMzAwNjA5MDUz
|
||||
NjQ1WjB0MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4w
|
||||
HAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEdMBsG
|
||||
A1UEAwwUcmVzZWVkQGRpdmEuZXhjaGFuZ2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC
|
||||
DwAwggIKAoICAQC6BJGeMEgoXk9dlzKVfmwHrT2VpwTT+wRJvh3eAM746u4uDT2y
|
||||
NPHXhdGcQ9dRRZ63T98IshWCwOmWSlm1kdWkmKkVVb93GUoMQ3gziCi0apLJMAau
|
||||
gEu/sPCbORS2dPsQeAPW2eIsJO7dSjTRiQAuquW//NcIXG4gnxDA52lgke1BvpKr
|
||||
83SJlCrqECAy6OKtZ49yn75CqmPPWFn0b/E8bxruN5ffeipTTospvdEtT41gXUqk
|
||||
hOz3k8ang+QTWiP//jOjk31KXZ2dbh0LOlNJOvRxCqQmBZafNxxCR4DH8RewfPlL
|
||||
qOiOJVzbLSP9RjqPLwnny5BOjbLWXcaybN5Qv2Pyd4mKtN3EpqBwRu7VnzXpsuuG
|
||||
gRbxNmfKJ/vBEGrZAHAxi0NkHHEEne3B7pPDc2dVZHOfTfCu31m9uDHZ4eHEsNOJ
|
||||
SJRiGjq74l0chCSlBGLrD1Y9LPyqadjdwuB9bzM0tMFC1wPflanQCflhhnEzAfbN
|
||||
BaU2GRXo/I1UCDW/dH1FIkqEe61eMW1Lwqr5tdlrUpdr5VIddTyNJRBJogbZ+HZE
|
||||
8mcoJW2lXRAkYi7KEm4b4EQNe7sbRNTF0j+fAJ+3ZOZ3O3SMHss6ignlSa+giVim
|
||||
VvL+Joc6wpSzxpeNPf6m82cEO/UvifFYeOC9TpiRriSt+vvgQVzQtfQ+fQIDAQAB
|
||||
o2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
|
||||
BwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHJlc2VlZEBkaXZhLmV4Y2hh
|
||||
bmdlMA0GCSqGSIb3DQEBCwUAA4ICAQCFGOb1dHlwjmgFHEER6oMiGWl1mI3Hb7GX
|
||||
NNI6QUhZQ+iEWGYtsOTk3Q8xejL8t6AG/ZLXfZviLIJXZc5XZfPXk0ezDSC2cYxQ
|
||||
ZAyYPw2dRP14brI86sCSqNAFIax/U5SM3zXhCbBiTfaEoBPfDpvKjx+VliaITUnc
|
||||
sHTRn+C5ID5M8cZIqUSGECPEMU/bDtuRNJLTKYaJ98yXtYuS2CWsMEM4o0GGcnYQ
|
||||
5HOZT/lbbwfq1Ks7IyJpeIpRaS5qckGcfgkxFY4eGujDuaFeWC+HCIh9RzBJrqZR
|
||||
73Aly4Pyu7Jjg8xCCf9MswDjtqAjEHgWCmRLWL7p3H6cPipFKNMY6yomYZl5urE7
|
||||
q6DUAZFKwPqlZpyeaY4/SVvaHTxuPp7484s3db4kPhdmuQS/DOB/7d+cn/S580Vy
|
||||
ALqlFQjtjLEaT16upceAV0gYktDInE6Rtym/OsqilrtYks/Sc0GROSz8lJhDDWbr
|
||||
W3t92muSXDh0rYrEUYWl+xl1gSTpbIP75zzU+cUr1E/qlRY9qZn66FsJpOuN0I0q
|
||||
UXsQS/bPDcA+IW48Hd9LfO9gtTWZslwFTimjEvQ2nJAnUlUQP6OfuPUKHoYX/CwY
|
||||
2LCN8+pv2bKPDVHvp0lf6xrbbZNvFtzfR0G3AprZjYpuu2XgjVB5nJnwmbH74b9w
|
||||
LD8d2z2Lgg==
|
||||
-----END CERTIFICATE-----
|
@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.32.1
|
||||
Version: 2.33.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@ -124,6 +124,9 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Aug 24 2020 orignal <i2porignal@yandex.ru> - 2.33.0
|
||||
- update to 2.33.0
|
||||
|
||||
* Tue Jun 02 2020 r4sas <r4sas@i2pmail.org> - 2.32.1
|
||||
- update to 2.32.1
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.32.1
|
||||
Version: 2.33.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@ -122,6 +122,9 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Aug 24 2020 orignal <i2porignal@yandex.ru> - 2.33.0
|
||||
- update to 2.33.0
|
||||
|
||||
* Tue Jun 02 2020 r4sas <r4sas@i2pmail.org> - 2.32.1
|
||||
- update to 2.32.1
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "Base.h"
|
||||
#include "version.h"
|
||||
#include "Transports.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Tunnel.h"
|
||||
@ -135,8 +134,8 @@ namespace i2p
|
||||
i2p::context.SetNetID (netID);
|
||||
i2p::context.Init ();
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
#ifdef MESHNET
|
||||
// manual override for meshnet
|
||||
ipv4 = false;
|
||||
@ -151,8 +150,7 @@ namespace i2p
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
|
||||
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
@ -160,7 +158,7 @@ namespace i2p
|
||||
if (published)
|
||||
{
|
||||
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
||||
if (!ntcp && !ntcp2port) ntcp2port = port; // use standard port
|
||||
if (!ntcp2port) ntcp2port = port; // use standard port
|
||||
i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
|
||||
if (ipv6)
|
||||
{
|
||||
@ -180,13 +178,10 @@ namespace i2p
|
||||
SetMaxNumTransitTunnels (transitTunnels);
|
||||
|
||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||
if (isFloodfill)
|
||||
{
|
||||
if (isFloodfill) {
|
||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||
i2p::context.SetFloodfill (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
i2p::context.SetFloodfill (false);
|
||||
}
|
||||
|
||||
@ -254,8 +249,7 @@ namespace i2p
|
||||
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
||||
restricted = fams.size() > 0;
|
||||
}
|
||||
if (routers.length() > 0)
|
||||
{
|
||||
if (routers.length() > 0) {
|
||||
std::set<i2p::data::IdentHash> idents;
|
||||
size_t pos = 0, comma;
|
||||
do
|
||||
@ -291,8 +285,7 @@ namespace i2p
|
||||
i2p::data::netdb.Start();
|
||||
|
||||
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
||||
if (upnp)
|
||||
{
|
||||
if (upnp) {
|
||||
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
||||
d.UPnP->Start ();
|
||||
}
|
||||
@ -304,14 +297,16 @@ namespace i2p
|
||||
d.m_NTPSync->Start ();
|
||||
}
|
||||
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
||||
|
||||
i2p::transport::transports.Start(ntcp, ssu);
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||
i2p::transport::transports.Start(ntcp2, ssu);
|
||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
else
|
||||
{
|
||||
@ -323,23 +318,23 @@ namespace i2p
|
||||
}
|
||||
|
||||
bool http; i2p::config::GetOption("http.enabled", http);
|
||||
if (http)
|
||||
{
|
||||
if (http) {
|
||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
||||
try
|
||||
try
|
||||
{
|
||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->Start();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
||||
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||
i2p::tunnel::tunnels.Start();
|
||||
|
||||
@ -352,12 +347,12 @@ namespace i2p
|
||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||
try
|
||||
try
|
||||
{
|
||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||
d.m_I2PControlService->Start ();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||
@ -374,7 +369,7 @@ namespace i2p
|
||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
||||
i2p::tunnel::tunnels.Stop();
|
||||
|
||||
if (d.UPnP)
|
||||
if (d.UPnP)
|
||||
{
|
||||
d.UPnP->Stop ();
|
||||
d.UPnP = nullptr;
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Base.h"
|
||||
@ -83,17 +82,18 @@ namespace http {
|
||||
" .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n"
|
||||
" .enabled:after { color: #56B734; content: \"Enabled\" }\r\n"
|
||||
" @media screen and (max-width: 980px) {\r\n" /* adaptive style */
|
||||
" body { padding: 1.5em 0 0 0; }\r\n"
|
||||
" .menu { width: 100%; display: block; float: none; position: unset; font-size: 16px;\r\n"
|
||||
" text-align: center; }\r\n"
|
||||
" .menu a, .commands a { padding: 2px; }\r\n"
|
||||
" .content { float: none; margin: 0; margin-top: 16px; max-width: 100%; width: 100%;\r\n"
|
||||
" .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%;\r\n"
|
||||
" text-align: center; }\r\n"
|
||||
" a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n"
|
||||
" .header { margin: unset; font-size: 1.5em; } small {display: block}\r\n"
|
||||
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n"
|
||||
" color: initial; margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n"
|
||||
" input { width: 35%; text-align: center; padding: 5px;\r\n"
|
||||
" border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 24px; }\r\n"
|
||||
" border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 18px; }\r\n"
|
||||
" textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n"
|
||||
" -webkit-border-radius: 5px; border-radius: 5px; font-size: 12px; }\r\n"
|
||||
" button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n"
|
||||
@ -257,7 +257,10 @@ namespace http {
|
||||
switch (i2p::context.GetError ())
|
||||
{
|
||||
case eRouterErrorClockSkew:
|
||||
s << "<br>Clock skew";
|
||||
s << " - Clock skew";
|
||||
break;
|
||||
case eRouterErrorOffline:
|
||||
s << " - Offline";
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
@ -732,13 +735,6 @@ namespace http {
|
||||
void ShowTransports (std::stringstream& s)
|
||||
{
|
||||
s << "<b>Transports:</b><br>\r\n";
|
||||
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
|
||||
if (ntcpServer)
|
||||
{
|
||||
auto sessions = ntcpServer->GetNTCPSessions ();
|
||||
if (!sessions.empty ())
|
||||
ShowNTCPTransports (s, sessions, "NTCP");
|
||||
}
|
||||
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
||||
if (ntcp2Server)
|
||||
{
|
||||
@ -933,7 +929,7 @@ namespace http {
|
||||
time_t t = divTime.quot;
|
||||
struct tm *tm = localtime(&t);
|
||||
char date[128];
|
||||
snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem);
|
||||
snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03lld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem);
|
||||
return date;
|
||||
}
|
||||
|
||||
@ -1320,8 +1316,8 @@ namespace http {
|
||||
void HTTPServer::Accept ()
|
||||
{
|
||||
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
||||
m_Acceptor.async_accept (*newSocket, boost::bind (&HTTPServer::HandleAccept, this,
|
||||
boost::asio::placeholders::error, newSocket));
|
||||
m_Acceptor.async_accept (*newSocket, std::bind (&HTTPServer::HandleAccept, this,
|
||||
std::placeholders::_1, newSocket));
|
||||
}
|
||||
|
||||
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
|
||||
|
@ -1,11 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <openssl/x509.h>
|
||||
@ -14,12 +6,7 @@
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
// There is bug in boost 1.49 with gcc 4.7 coming with Debian Wheezy
|
||||
#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
|
||||
#if !GCC47_BOOST149
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#endif
|
||||
|
||||
#include "Crypto.h"
|
||||
#include "FS.h"
|
||||
@ -67,28 +54,29 @@ namespace client
|
||||
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
||||
|
||||
// handlers
|
||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
|
||||
// I2PControl
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
|
||||
// RouterInfo
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
||||
&I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
@ -104,10 +92,10 @@ namespace client
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@ -242,12 +230,6 @@ namespace client
|
||||
}
|
||||
}
|
||||
std::ostringstream response;
|
||||
#if GCC47_BOOST149
|
||||
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
|
||||
response << "{\"id\":null,\"error\":";
|
||||
response << "{\"code\":-32603,\"message\":\"JSON requests is not supported with this version of boost\"},";
|
||||
response << "\"jsonrpc\":\"2.0\"}";
|
||||
#else
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_json (ss, pt);
|
||||
|
||||
@ -267,7 +249,6 @@ namespace client
|
||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
||||
response << "\"jsonrpc\":\"2.0\"}";
|
||||
}
|
||||
#endif
|
||||
SendResponse (socket, buf, response, isHtml);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
@ -408,8 +389,8 @@ namespace client
|
||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||
if (it1 != m_RouterInfoHandlers.end ())
|
||||
{
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
@ -507,7 +488,7 @@ namespace client
|
||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
||||
m_ShutdownTimer.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
@ -521,7 +502,7 @@ namespace client
|
||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||
m_ShutdownTimer.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
|
@ -1,18 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef USE_UPNP
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
@ -88,10 +79,10 @@ namespace transport
|
||||
void UPnP::Discover ()
|
||||
{
|
||||
bool isError;
|
||||
int err;
|
||||
int err;
|
||||
|
||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||
err = UPNPDISCOVER_SUCCESS;
|
||||
err = UPNPDISCOVER_SUCCESS;
|
||||
|
||||
#if (MINIUPNPC_API_VERSION >= 14)
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
||||
@ -100,9 +91,9 @@ namespace transport
|
||||
#endif
|
||||
|
||||
isError = err != UPNPDISCOVER_SUCCESS;
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
err = 0;
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
err = 0;
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||
isError = m_Devlist == NULL;
|
||||
#endif // MINIUPNPC_API_VERSION >= 8
|
||||
{
|
||||
@ -113,15 +104,15 @@ namespace transport
|
||||
|
||||
if (isError)
|
||||
{
|
||||
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
||||
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
||||
return;
|
||||
}
|
||||
|
||||
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||
m_upnpUrlsInitialized = err != 0;
|
||||
m_upnpUrlsInitialized=err!=0;
|
||||
if (err == UPNP_IGD_VALID_CONNECTED)
|
||||
{
|
||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||
if(err != UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
||||
@ -132,14 +123,14 @@ namespace transport
|
||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
||||
if (!m_externalIPAddress[0])
|
||||
{
|
||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
||||
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -190,7 +181,7 @@ namespace transport
|
||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
||||
{
|
||||
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
||||
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
||||
|
||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
||||
@ -210,7 +201,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
||||
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -227,14 +218,14 @@ namespace transport
|
||||
|
||||
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||
{
|
||||
if(!m_upnpUrlsInitialized) {
|
||||
return;
|
||||
}
|
||||
if(!m_upnpUrlsInitialized) {
|
||||
return;
|
||||
}
|
||||
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
||||
int err = UPNPCOMMAND_SUCCESS;
|
||||
|
||||
|
||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||
if (err == UPNPCOMMAND_SUCCESS)
|
||||
if (err == UPNPCOMMAND_SUCCESS)
|
||||
{
|
||||
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
|
||||
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
||||
@ -245,11 +236,11 @@ namespace transport
|
||||
{
|
||||
freeUPNPDevlist (m_Devlist);
|
||||
m_Devlist = 0;
|
||||
if(m_upnpUrlsInitialized){
|
||||
FreeUPNPUrls (&m_upnpUrls);
|
||||
m_upnpUrlsInitialized=false;
|
||||
}
|
||||
}
|
||||
if(m_upnpUrlsInitialized){
|
||||
FreeUPNPUrls (&m_upnpUrls);
|
||||
m_upnpUrlsInitialized=false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||
{
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
i2pd (2.33.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.33.0/0.9.47
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Mon, 24 Aug 2020 16:00:00 +0000
|
||||
|
||||
i2pd (2.32.1-1) unstable; urgency=high
|
||||
|
||||
* updated to version 2.32.1
|
||||
|
@ -51,6 +51,7 @@ namespace config {
|
||||
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
|
||||
("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4 (default: enabled)")
|
||||
("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)")
|
||||
("reservedrange", value<bool>()->default_value(true), "Check remote RI for being in blacklist of reserved IP ranges (default: enabled)")
|
||||
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
|
||||
("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)")
|
||||
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
|
||||
@ -58,9 +59,9 @@ namespace config {
|
||||
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
||||
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
||||
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
|
||||
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
|
||||
("ntcp", value<bool>()->default_value(false), "Ignored. Always false")
|
||||
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||
@ -96,7 +97,7 @@ namespace config {
|
||||
("httpproxy.enabled", value<bool>()->default_value(true), "Enable or disable HTTP Proxy")
|
||||
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
||||
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
||||
("httpproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist HTTP Proxy keys. Transient by default")
|
||||
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
||||
@ -116,7 +117,7 @@ namespace config {
|
||||
("socksproxy.enabled", value<bool>()->default_value(true), "Enable or disable SOCKS Proxy")
|
||||
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
||||
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
||||
("socksproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist SOCKS Proxy keys. Transient by default")
|
||||
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
||||
@ -152,6 +153,7 @@ namespace config {
|
||||
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
|
||||
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
|
||||
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port")
|
||||
("i2cp.singlethread", value<bool>()->default_value(true), "Destinations run in the I2CP server's thread")
|
||||
;
|
||||
|
||||
options_description i2pcontrol("I2PControl options");
|
||||
@ -195,7 +197,7 @@ namespace config {
|
||||
("reseed.proxy", value<std::string>()->default_value(""), "url for reseed proxy, supports http/socks")
|
||||
("reseed.urls", value<std::string>()->default_value(
|
||||
"https://reseed.i2p-projekt.de/,"
|
||||
"https://i2p.mooo.com/netDb/,"
|
||||
"https://reseed.diva.exchange/,"
|
||||
"https://reseed.i2p2.no/,"
|
||||
"https://reseed-fr.i2pd.xyz/,"
|
||||
"https://reseed.memcpy.io/,"
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <vector>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Crypto.h"
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "FS.h"
|
||||
#include "Timestamp.h"
|
||||
@ -464,14 +465,14 @@ namespace client
|
||||
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
|
||||
{
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
i2p::data::IdentHash peerHash (buf + 33 + i*32);
|
||||
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
|
||||
{
|
||||
LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message
|
||||
i2p::data::netdb.RequestDestination (peerHash);
|
||||
i2p::data::IdentHash peerHash (buf + 33 + i*32);
|
||||
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
|
||||
{
|
||||
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
|
||||
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
|
||||
if (floodfill)
|
||||
@ -603,9 +604,8 @@ namespace client
|
||||
return;
|
||||
}
|
||||
auto s = shared_from_this ();
|
||||
// we must capture this for gcc 4.7 due the bug
|
||||
RequestLeaseSet (ls->GetStoreHash (),
|
||||
[s, ls, this](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
|
||||
[s, ls](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
|
||||
{
|
||||
if (leaseSet)
|
||||
{
|
||||
@ -744,14 +744,19 @@ namespace client
|
||||
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
||||
request->requestTimeoutTimer.cancel ();
|
||||
|
||||
bool isECIES = SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) &&
|
||||
nextFloodfill->GetVersion () >= MAKE_VERSION_NUMBER(0, 9, 46); // >= 0.9.46;
|
||||
uint8_t replyKey[32], replyTag[32];
|
||||
RAND_bytes (replyKey, 32); // random session key
|
||||
RAND_bytes (replyTag, 32); // random session tag
|
||||
AddSessionKey (replyKey, replyTag);
|
||||
RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag
|
||||
if (isECIES)
|
||||
AddECIESx25519Key (replyKey, replyTag);
|
||||
else
|
||||
AddSessionKey (replyKey, replyTag);
|
||||
|
||||
auto msg = WrapMessage (nextFloodfill,
|
||||
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||
request->replyTunnel, replyKey, replyTag));
|
||||
request->replyTunnel, replyKey, replyTag, isECIES));
|
||||
request->outboundTunnel->SendTunnelDataMsg (
|
||||
{
|
||||
i2p::tunnel::TunnelMessageBlock
|
||||
@ -845,8 +850,9 @@ namespace client
|
||||
|
||||
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||
bool isPublic, const std::map<std::string, std::string> * params):
|
||||
LeaseSetDestination (service, isPublic, params),
|
||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||
LeaseSetDestination (service, isPublic, params),
|
||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
|
||||
m_DatagramDestination (nullptr), m_RefCounter (0),
|
||||
m_ReadyChecker(service)
|
||||
{
|
||||
@ -855,8 +861,7 @@ namespace client
|
||||
|
||||
// extract encryption type params for LS2
|
||||
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
||||
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
||||
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
||||
if (params)
|
||||
{
|
||||
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
||||
if (it != params->end ())
|
||||
@ -915,7 +920,10 @@ namespace client
|
||||
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
|
||||
if (it != params->end ())
|
||||
m_StreamingAckDelay = std::stoi(it->second);
|
||||
|
||||
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
||||
if (it != params->end ())
|
||||
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
|
||||
|
||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||
{
|
||||
// authentication for encrypted LeaseSet
|
||||
|
@ -78,6 +78,8 @@ namespace client
|
||||
// streaming
|
||||
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
|
||||
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
||||
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
|
||||
const int DEFAULT_ANSWER_PINGS = true;
|
||||
|
||||
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
||||
|
||||
@ -242,7 +244,8 @@ namespace client
|
||||
bool IsAcceptingStreams () const;
|
||||
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
||||
|
||||
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
||||
|
||||
// datagram
|
||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
||||
@ -275,6 +278,7 @@ namespace client
|
||||
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
||||
|
||||
int m_StreamingAckDelay;
|
||||
bool m_IsStreamingAnswerPings;
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||
|
@ -88,12 +88,67 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
|
||||
void RatchetTagSet::DeleteSymmKey (int index)
|
||||
{
|
||||
m_ItermediateSymmKeys.erase (index);
|
||||
}
|
||||
|
||||
void RatchetTagSet::Expire ()
|
||||
{
|
||||
if (!m_ExpirationTimestamp)
|
||||
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
|
||||
}
|
||||
|
||||
bool RatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
|
||||
{
|
||||
auto session = GetSession ();
|
||||
if (!session) return false;
|
||||
return session->HandleNextMessage (buf, len, shared_from_this (), index);
|
||||
}
|
||||
|
||||
DatabaseLookupTagSet::DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key):
|
||||
RatchetTagSet (nullptr), m_Destination (destination)
|
||||
{
|
||||
memcpy (m_Key, key, 32);
|
||||
Expire ();
|
||||
}
|
||||
|
||||
bool DatabaseLookupTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
|
||||
{
|
||||
if (len < 24) return false;
|
||||
uint8_t nonce[12];
|
||||
memset (nonce, 0, 12); // n = 0
|
||||
size_t offset = 8; // first 8 bytes is reply tag used as AD
|
||||
len -= 16; // poly1305
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Lookup reply AEAD decryption failed");
|
||||
return false;
|
||||
}
|
||||
// we assume 1 I2NP block with delivery type local
|
||||
if (offset + 3 > len)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Lookup reply is too short ", len);
|
||||
return false;
|
||||
}
|
||||
if (buf[offset] != eECIESx25519BlkGalicClove)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Lookup reply unexpected block ", (int)buf[offset]);
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
auto size = bufbe16toh (buf + offset);
|
||||
offset += 2;
|
||||
if (offset + size > len)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Lookup reply block is too long ", size);
|
||||
return false;
|
||||
}
|
||||
if (m_Destination)
|
||||
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
|
||||
GarlicRoutingSession (owner, attachLeaseSet)
|
||||
{
|
||||
@ -657,7 +712,12 @@ namespace garlic
|
||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||
}
|
||||
if (moreTags > 0)
|
||||
{
|
||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||
index -= (moreTags >> 1); // /2
|
||||
if (index > 0)
|
||||
receiveTagset->SetTrimBehind (index);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -739,8 +799,11 @@ namespace garlic
|
||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
size_t payloadLen = 0;
|
||||
if (first) payloadLen += 7;// datatime
|
||||
if (msg && m_Destination)
|
||||
payloadLen += msg->GetPayloadLength () + 13 + 32;
|
||||
if (msg)
|
||||
{
|
||||
payloadLen += msg->GetPayloadLength () + 13;
|
||||
if (m_Destination) payloadLen += 32;
|
||||
}
|
||||
auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated ||
|
||||
(GetLeaseSetUpdateStatus () == eLeaseSetSubmitted &&
|
||||
ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
|
||||
@ -816,7 +879,7 @@ namespace garlic
|
||||
}
|
||||
// msg
|
||||
if (msg && m_Destination)
|
||||
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
|
||||
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset);
|
||||
// ack
|
||||
if (m_AckRequests.size () > 0)
|
||||
{
|
||||
@ -875,16 +938,16 @@ namespace garlic
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination)
|
||||
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len)
|
||||
{
|
||||
if (!msg) return 0;
|
||||
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
|
||||
if (isDestination) cloveSize += 32;
|
||||
if (m_Destination) cloveSize += 32;
|
||||
if ((int)len < cloveSize + 3) return 0;
|
||||
buf[0] = eECIESx25519BlkGalicClove; // clove type
|
||||
htobe16buf (buf + 1, cloveSize); // size
|
||||
buf += 3;
|
||||
if (isDestination)
|
||||
if (m_Destination)
|
||||
{
|
||||
*buf = (eGarlicDeliveryTypeDestination << 5);
|
||||
memcpy (buf + 1, *m_Destination, 32); buf += 32;
|
||||
|
@ -40,7 +40,7 @@ namespace garlic
|
||||
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
||||
|
||||
class ECIESX25519AEADRatchetSession;
|
||||
class RatchetTagSet
|
||||
class RatchetTagSet: public std::enable_shared_from_this<RatchetTagSet>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -52,14 +52,19 @@ namespace garlic
|
||||
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
||||
int GetNextIndex () const { return m_NextIndex; };
|
||||
void GetSymmKey (int index, uint8_t * key);
|
||||
void DeleteSymmKey (int index);
|
||||
|
||||
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
||||
int GetTagSetID () const { return m_TagSetID; };
|
||||
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
|
||||
void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
|
||||
|
||||
void Expire ();
|
||||
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
||||
virtual bool IsIndexExpired (int index) const { return m_Session.expired () || index < m_TrimBehindIndex; };
|
||||
|
||||
virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
|
||||
|
||||
private:
|
||||
|
||||
union
|
||||
@ -73,7 +78,7 @@ namespace garlic
|
||||
|
||||
} m_KeyData;
|
||||
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
||||
int m_NextIndex, m_NextSymmKeyIndex;
|
||||
int m_NextIndex, m_NextSymmKeyIndex, m_TrimBehindIndex = 0;
|
||||
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
||||
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
||||
int m_TagSetID = 0;
|
||||
@ -91,6 +96,21 @@ namespace garlic
|
||||
|
||||
std::shared_ptr<ECIESX25519AEADRatchetSession> m_DummySession; // we need a strong pointer for NS
|
||||
};
|
||||
|
||||
class DatabaseLookupTagSet: public RatchetTagSet
|
||||
{
|
||||
public:
|
||||
|
||||
DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key);
|
||||
|
||||
bool IsIndexExpired (int index) const { return false; };
|
||||
bool HandleNextMessage (uint8_t * buf, size_t len, int index);
|
||||
|
||||
private:
|
||||
|
||||
GarlicDestination * m_Destination;
|
||||
uint8_t m_Key[32];
|
||||
};
|
||||
|
||||
enum ECIESx25519BlockType
|
||||
{
|
||||
@ -171,7 +191,7 @@ namespace garlic
|
||||
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||
|
||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
||||
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
|
||||
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
|
||||
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
||||
|
||||
void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
|
||||
|
@ -460,6 +460,14 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
|
||||
void GarlicDestination::AddECIESx25519Key (const uint8_t * key, const uint8_t * tag)
|
||||
{
|
||||
uint64_t t;
|
||||
memcpy (&t, tag, 8);
|
||||
auto tagset = std::make_shared<DatabaseLookupTagSet>(this, key);
|
||||
m_ECIESx25519Tags.emplace (t, ECIESX25519AEADRatchetIndexTagset{0, tagset});
|
||||
}
|
||||
|
||||
bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
||||
{
|
||||
AddSessionKey (key, tag);
|
||||
@ -507,8 +515,7 @@ namespace garlic
|
||||
if (it1 != m_ECIESx25519Tags.end ())
|
||||
{
|
||||
found = true;
|
||||
auto session = it1->second.tagset->GetSession ();
|
||||
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
||||
if (!it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
|
||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||
m_ECIESx25519Tags.erase (it1);
|
||||
}
|
||||
@ -802,14 +809,6 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
// ECIESx25519
|
||||
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
||||
{
|
||||
if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||
it = m_ECIESx25519Tags.erase (it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();)
|
||||
{
|
||||
if (it->second->CheckExpired (ts))
|
||||
@ -820,6 +819,20 @@ namespace garlic
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
numExpiredTags = 0;
|
||||
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
||||
{
|
||||
if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index))
|
||||
{
|
||||
it->second.tagset->DeleteSymmKey (it->second.index);
|
||||
it = m_ECIESx25519Tags.erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (numExpiredTags > 0)
|
||||
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
|
||||
}
|
||||
|
||||
void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID)
|
||||
@ -1009,7 +1022,7 @@ namespace garlic
|
||||
{
|
||||
auto index = tagset->GetNextIndex ();
|
||||
uint64_t tag = tagset->GetNextSessionTag ();
|
||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
|
||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset});
|
||||
}
|
||||
|
||||
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
||||
|
@ -220,7 +220,6 @@ namespace garlic
|
||||
{
|
||||
int index;
|
||||
RatchetTagSetPtr tagset;
|
||||
uint64_t creationTime; // seconds since epoch
|
||||
};
|
||||
|
||||
class GarlicDestination: public i2p::data::LocalDestination
|
||||
@ -242,6 +241,7 @@ namespace garlic
|
||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
||||
|
||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
|
||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||
|
@ -16,8 +16,8 @@
|
||||
namespace i2p {
|
||||
namespace http {
|
||||
const std::vector<std::string> HTTP_METHODS = {
|
||||
"GET", "HEAD", "POST", "PUT", "PATCH",
|
||||
"DELETE", "OPTIONS", "CONNECT", "PROPFIND"
|
||||
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
|
||||
"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323
|
||||
};
|
||||
const std::vector<std::string> HTTP_VERSIONS = {
|
||||
"HTTP/1.0", "HTTP/1.1"
|
||||
|
@ -171,7 +171,8 @@ namespace i2p
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag)
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
|
||||
const uint8_t * replyTag, bool replyECIES)
|
||||
{
|
||||
int cnt = excludedFloodfills.size ();
|
||||
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||
@ -180,7 +181,8 @@ namespace i2p
|
||||
buf += 32;
|
||||
memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
|
||||
buf += 32;
|
||||
*buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_ENCRYPTION_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
|
||||
*buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
|
||||
*buf |= (replyECIES ? DATABASE_LOOKUP_ECIES_FLAG : DATABASE_LOOKUP_ENCRYPTION_FLAG);
|
||||
buf ++;
|
||||
htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
|
||||
buf += 4;
|
||||
@ -204,8 +206,16 @@ namespace i2p
|
||||
// encryption
|
||||
memcpy (buf, replyKey, 32);
|
||||
buf[32] = 1; // 1 tag
|
||||
memcpy (buf + 33, replyTag, 32);
|
||||
buf += 65;
|
||||
if (replyECIES)
|
||||
{
|
||||
memcpy (buf + 33, replyTag, 8); // 8 bytes tag
|
||||
buf += 41;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (buf + 33, replyTag, 32); // 32 bytes tag
|
||||
buf += 65;
|
||||
}
|
||||
|
||||
m->len += (buf - m->GetPayload ());
|
||||
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
||||
|
@ -251,8 +251,9 @@ namespace tunnel
|
||||
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
||||
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag);
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
|
||||
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
|
||||
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0);
|
||||
|
@ -338,11 +338,8 @@ namespace transport
|
||||
|
||||
KDF3Bob ();
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
||||
{
|
||||
// caclulate new h again for KDF data
|
||||
memcpy (m_SessionConfirmedBuffer + 16, m_H, 32); // h || ciphertext
|
||||
SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_H); //h = SHA256(h || ciphertext);
|
||||
}
|
||||
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed ");
|
||||
@ -1438,7 +1435,7 @@ namespace transport
|
||||
{
|
||||
|
||||
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService());
|
||||
auto timeout = NTCP_CONNECT_TIMEOUT * 5;
|
||||
auto timeout = NTCP2_CONNECT_TIMEOUT * 5;
|
||||
conn->SetTerminationTimeout(timeout * 2);
|
||||
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
||||
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,242 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifndef NTCP_SESSION_H__
|
||||
#define NTCP_SESSION_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Crypto.h"
|
||||
#include "Identity.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "TransportSession.h"
|
||||
#include "CryptoWorker.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace transport
|
||||
{
|
||||
struct NTCPPhase1
|
||||
{
|
||||
uint8_t pubKey[256];
|
||||
uint8_t HXxorHI[32];
|
||||
};
|
||||
|
||||
struct NTCPPhase2
|
||||
{
|
||||
uint8_t pubKey[256];
|
||||
struct
|
||||
{
|
||||
uint8_t hxy[32];
|
||||
uint8_t timestamp[4];
|
||||
uint8_t filler[12];
|
||||
} encrypted;
|
||||
};
|
||||
|
||||
struct NTCPWork;
|
||||
|
||||
const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
|
||||
const size_t NTCP_BUFFER_SIZE = 1028; // fits 1 tunnel data message
|
||||
const int NTCP_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||
const int NTCP_ESTABLISH_TIMEOUT = 10; // 10 seconds
|
||||
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||
const int NTCP_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||
const size_t NTCP_DEFAULT_PHASE3_SIZE = 2/*size*/ + i2p::data::DEFAULT_IDENTITY_SIZE/*387*/ + 4/*ts*/ + 15/*padding*/ + 40/*signature*/; // 448
|
||||
const int NTCP_CLOCK_SKEW = 60; // in seconds
|
||||
const int NTCP_MAX_OUTGOING_QUEUE_SIZE = 200; // how many messages we can queue up
|
||||
|
||||
class NTCPServer;
|
||||
class NTCPSession: public TransportSession, public std::enable_shared_from_this<NTCPSession>
|
||||
{
|
||||
public:
|
||||
|
||||
NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
||||
~NTCPSession ();
|
||||
void Terminate ();
|
||||
void Done ();
|
||||
|
||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||
boost::asio::io_service & GetService();
|
||||
bool IsEstablished () const { return m_IsEstablished; };
|
||||
bool IsTerminated () const { return m_IsTerminated; };
|
||||
|
||||
void ClientLogin ();
|
||||
void ServerLogin ();
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
|
||||
private:
|
||||
|
||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
void Connected ();
|
||||
void SendTimeSyncMessage ();
|
||||
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
|
||||
|
||||
void CreateAESKey (uint8_t * pubKey);
|
||||
|
||||
// client
|
||||
void SendPhase3 ();
|
||||
void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandlePhase2 (NTCPWork * work=nullptr);
|
||||
void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
||||
void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
||||
|
||||
//server
|
||||
void SendPhase2 (NTCPWork * work=nullptr);
|
||||
void SendPhase4 (uint32_t tsA, uint32_t tsB);
|
||||
void HandlePhase1Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
|
||||
void HandlePhase3Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
|
||||
void HandlePhase3ExtraReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB, size_t paddingLen);
|
||||
void HandlePhase3 (uint32_t tsB, size_t paddingLen);
|
||||
void HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
|
||||
// common
|
||||
void Receive ();
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
bool DecryptNextBlock (const uint8_t * encrypted);
|
||||
|
||||
void Send (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
boost::asio::const_buffers_1 CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg);
|
||||
void Send (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
|
||||
private:
|
||||
|
||||
NTCPServer& m_Server;
|
||||
boost::asio::ip::tcp::socket m_Socket;
|
||||
bool m_IsEstablished, m_IsTerminated;
|
||||
|
||||
i2p::crypto::CBCDecryption m_Decryption;
|
||||
i2p::crypto::CBCEncryption m_Encryption;
|
||||
|
||||
struct Establisher
|
||||
{
|
||||
NTCPPhase1 phase1;
|
||||
NTCPPhase2 phase2;
|
||||
} * m_Establisher;
|
||||
|
||||
i2p::crypto::AESAlignedBuffer<NTCP_BUFFER_SIZE + 16> m_ReceiveBuffer;
|
||||
i2p::crypto::AESAlignedBuffer<16> m_TimeSyncBuffer;
|
||||
int m_ReceiveBufferOffset;
|
||||
|
||||
std::shared_ptr<I2NPMessage> m_NextMessage;
|
||||
size_t m_NextMessageOffset;
|
||||
i2p::I2NPMessagesHandler m_Handler;
|
||||
|
||||
bool m_IsSending;
|
||||
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||
};
|
||||
|
||||
// TODO: move to NTCP.h/.cpp
|
||||
class NTCPServer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef i2p::worker::ThreadPool<NTCPSession> Pool;
|
||||
|
||||
enum RemoteAddressType
|
||||
{
|
||||
eIP4Address,
|
||||
eIP6Address,
|
||||
eHostname
|
||||
};
|
||||
|
||||
enum ProxyType
|
||||
{
|
||||
eNoProxy,
|
||||
eSocksProxy,
|
||||
eHTTPProxy
|
||||
};
|
||||
|
||||
|
||||
NTCPServer (int workers=4);
|
||||
~NTCPServer ();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
bool AddNTCPSession (std::shared_ptr<NTCPSession> session);
|
||||
void RemoveNTCPSession (std::shared_ptr<NTCPSession> session);
|
||||
std::shared_ptr<NTCPSession> FindNTCPSession (const i2p::data::IdentHash& ident);
|
||||
void ConnectWithProxy (const std::string& addr, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCPSession> conn);
|
||||
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCPSession> conn);
|
||||
|
||||
bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; };
|
||||
bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; };
|
||||
bool NetworkIsReady() const { return IsBoundV4() || IsBoundV6() || UsingProxy(); };
|
||||
bool UsingProxy() const { return m_ProxyType != eNoProxy; };
|
||||
|
||||
void UseProxy(ProxyType proxy, const std::string & address, uint16_t port);
|
||||
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
|
||||
void SetSessionLimits(uint16_t softLimit, uint16_t hardLimit) { m_SoftLimit = softLimit; m_HardLimit = hardLimit; }
|
||||
bool ShouldLimit() const { return ShouldHardLimit() || ShouldSoftLimit(); }
|
||||
void Work(std::shared_ptr<NTCPSession> conn, Pool::WorkFunc work)
|
||||
{
|
||||
m_CryptoPool->Offer({conn, work});
|
||||
}
|
||||
private:
|
||||
|
||||
/** @brief return true for hard limit */
|
||||
bool ShouldHardLimit() const { return m_HardLimit && m_NTCPSessions.size() >= m_HardLimit; }
|
||||
|
||||
/** @brief return true for probabalistic soft backoff */
|
||||
bool ShouldSoftLimit() const
|
||||
{
|
||||
auto sessions = m_NTCPSessions.size();
|
||||
return sessions && m_SoftLimit && m_SoftLimit < sessions && ( rand() % sessions ) <= m_SoftLimit;
|
||||
}
|
||||
void Run ();
|
||||
void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
|
||||
void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
|
||||
|
||||
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
||||
|
||||
void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
|
||||
void AfterSocksHandshake(std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
|
||||
|
||||
// timer
|
||||
void ScheduleTermination ();
|
||||
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsRunning;
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service m_Service;
|
||||
boost::asio::io_service::work m_Work;
|
||||
boost::asio::deadline_timer m_TerminationTimer;
|
||||
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<NTCPSession> > m_NTCPSessions; // access from m_Thread only
|
||||
std::list<std::shared_ptr<NTCPSession> > m_PendingIncomingSessions;
|
||||
|
||||
ProxyType m_ProxyType;
|
||||
std::string m_ProxyAddress;
|
||||
uint16_t m_ProxyPort;
|
||||
boost::asio::ip::tcp::resolver m_Resolver;
|
||||
boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
|
||||
|
||||
std::shared_ptr<Pool> m_CryptoPool;
|
||||
|
||||
uint16_t m_SoftLimit, m_HardLimit;
|
||||
public:
|
||||
|
||||
// for HTTP/I2PControl
|
||||
const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -125,7 +125,8 @@ namespace data
|
||||
}
|
||||
}
|
||||
if (!m_IsRunning) break;
|
||||
|
||||
if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline
|
||||
|
||||
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
|
||||
{
|
||||
@ -560,6 +561,9 @@ namespace data
|
||||
updatedCount++;
|
||||
continue;
|
||||
}
|
||||
// make router reachable back if too few routers
|
||||
if (it.second->IsUnreachable () && total - deletedCount < NETDB_MIN_ROUTERS)
|
||||
it.second->SetUnreachable (false);
|
||||
// find & mark expired routers
|
||||
if (it.second->UsesIntroducer ())
|
||||
{
|
||||
@ -575,7 +579,7 @@ namespace data
|
||||
// delete RI file
|
||||
m_Storage.Remove(ident);
|
||||
deletedCount++;
|
||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||
}
|
||||
} // m_RouterInfos iteration
|
||||
|
||||
@ -610,7 +614,7 @@ namespace data
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete)
|
||||
void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct)
|
||||
{
|
||||
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
|
||||
if (!dest)
|
||||
@ -621,7 +625,23 @@ namespace data
|
||||
|
||||
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||
if (floodfill)
|
||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||
{
|
||||
if (direct)
|
||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||
else
|
||||
{
|
||||
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
|
||||
auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr;
|
||||
if (outbound && inbound)
|
||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
|
||||
m_Requests.RequestComplete (destination, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
|
||||
@ -775,37 +795,21 @@ namespace data
|
||||
// reply to our destination. Try other floodfills
|
||||
if (outbound && inbound)
|
||||
{
|
||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||
auto count = dest->GetExcludedPeers ().size ();
|
||||
if (count < 7)
|
||||
{
|
||||
auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
|
||||
if (nextFloodfill)
|
||||
{
|
||||
// tell floodfill about us
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
nextFloodfill->GetIdentHash (), 0,
|
||||
CreateDatabaseStoreMsg ()
|
||||
});
|
||||
|
||||
// request destination
|
||||
LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ());
|
||||
auto msg = dest->CreateRequestMessage (nextFloodfill, inbound);
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
nextFloodfill->GetIdentHash (), 0, msg
|
||||
});
|
||||
outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0,
|
||||
dest->CreateRequestMessage (nextFloodfill, inbound));
|
||||
deleteDest = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills");
|
||||
|
||||
if (msgs.size () > 0)
|
||||
outbound->SendTunnelDataMsg (msgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ namespace data
|
||||
std::shared_ptr<LeaseSet> FindLeaseSet (const IdentHash& destination) const;
|
||||
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
||||
|
||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true);
|
||||
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||
|
||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
@ -63,7 +63,6 @@ namespace i2p
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
@ -83,8 +82,6 @@ namespace i2p
|
||||
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
if (ipv6)
|
||||
{
|
||||
@ -99,8 +96,6 @@ namespace i2p
|
||||
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
|
||||
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
||||
@ -115,20 +110,17 @@ namespace i2p
|
||||
{
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
UpdateNTCP2Address (true);
|
||||
if (!ntcp) // NTCP2 should replace NTCP
|
||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||
if (published)
|
||||
PublishNTCP2Address (port, true);
|
||||
if (ipv6)
|
||||
{
|
||||
PublishNTCP2Address (port, true);
|
||||
if (ipv6)
|
||||
{
|
||||
// add NTCP2 ipv6 address
|
||||
std::string host = "::1";
|
||||
if (!i2p::config::IsDefault ("ntcp2.addressv6"))
|
||||
i2p::config::GetOption ("ntcp2.addressv6", host);
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (host), port);
|
||||
}
|
||||
// add NTCP2 ipv6 address
|
||||
std::string host = "::1";
|
||||
if (!i2p::config::IsDefault ("ntcp2.addressv6"))
|
||||
i2p::config::GetOption ("ntcp2.addressv6", host);
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (host), port);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,48 +373,19 @@ namespace i2p
|
||||
return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
|
||||
}
|
||||
|
||||
void RouterContext::PublishNTCPAddress (bool publish, bool v4only)
|
||||
void RouterContext::RemoveNTCPAddress (bool v4only)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
if (publish)
|
||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
||||
{
|
||||
for (const auto& addr : addresses) // v4
|
||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
||||
(!v4only || (*it)->host.is_v4 ()))
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
addr->host.is_v4 ())
|
||||
{
|
||||
// insert NTCP address with host/port from SSU
|
||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!v4only)
|
||||
{
|
||||
for (const auto& addr : addresses) // v6
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
addr->host.is_v6 ())
|
||||
{
|
||||
// insert NTCP address with host/port from SSU
|
||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
||||
{
|
||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
||||
(!v4only || (*it)->host.is_v4 ()))
|
||||
{
|
||||
it = addresses.erase (it);
|
||||
if (v4only) break; // otherwise might be more than one address
|
||||
}
|
||||
else
|
||||
++it;
|
||||
it = addresses.erase (it);
|
||||
if (v4only) break; // otherwise might be more than one address
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,16 +407,10 @@ namespace i2p
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
// remove NTCP or NTCP2 v4 address
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
PublishNTCPAddress (false);
|
||||
else
|
||||
{
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
PublishNTCP2Address (port, false, true);
|
||||
}
|
||||
// remove NTCP2 v4 address
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
PublishNTCP2Address (port, false, true);
|
||||
// update
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
@ -477,23 +434,16 @@ namespace i2p
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
// insert NTCP or NTCP2 back
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
PublishNTCPAddress (true);
|
||||
else
|
||||
// insert NTCP2 back
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
// ntcp2
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
||||
if (!ntcp2Port) ntcp2Port = port;
|
||||
PublishNTCP2Address (ntcp2Port, true, true);
|
||||
}
|
||||
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
||||
if (!ntcp2Port) ntcp2Port = port;
|
||||
PublishNTCP2Address (ntcp2Port, true, true);
|
||||
}
|
||||
}
|
||||
// update
|
||||
@ -506,7 +456,7 @@ namespace i2p
|
||||
{
|
||||
m_RouterInfo.EnableV6 ();
|
||||
// insert v6 addresses if necessary
|
||||
bool foundSSU = false, foundNTCP = false, foundNTCP2 = false;
|
||||
bool foundSSU = false, foundNTCP2 = false;
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
@ -515,12 +465,8 @@ namespace i2p
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
foundSSU = true;
|
||||
else if (addr->IsNTCP2 ())
|
||||
{
|
||||
if (addr->IsPublishedNTCP2 ()) foundNTCP2 = true;
|
||||
}
|
||||
else
|
||||
foundNTCP = true;
|
||||
else if (addr->IsPublishedNTCP2 ())
|
||||
foundNTCP2 = true;
|
||||
}
|
||||
port = addr->port;
|
||||
}
|
||||
@ -552,16 +498,6 @@ namespace i2p
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port);
|
||||
}
|
||||
}
|
||||
// NTCP
|
||||
if (!foundNTCP)
|
||||
{
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
{
|
||||
std::string host = "::1";
|
||||
m_RouterInfo.AddNTCPAddress (host.c_str (), port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_RouterInfo.DisableV6 ();
|
||||
|
@ -37,7 +37,8 @@ namespace i2p
|
||||
enum RouterError
|
||||
{
|
||||
eRouterErrorNone = 0,
|
||||
eRouterErrorClockSkew = 1
|
||||
eRouterErrorClockSkew = 1,
|
||||
eRouterErrorOffline = 2
|
||||
};
|
||||
|
||||
class RouterContext: public i2p::garlic::GarlicDestination
|
||||
@ -89,7 +90,7 @@ namespace i2p
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
||||
void UpdateNTCP2Address (bool enable);
|
||||
void PublishNTCPAddress (bool publish, bool v4only = true);
|
||||
void RemoveNTCPAddress (bool v4only = true); // delete NTCP address for older routers. TODO: remove later
|
||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
bool IsUnreachable () const;
|
||||
|
@ -316,7 +316,7 @@ namespace data
|
||||
}
|
||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||
if (supportedTransports)
|
||||
if (supportedTransports & ~(eNTCPV4 | eNTCPV6)) // exclude NTCP only
|
||||
{
|
||||
addresses->push_back(address);
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
@ -477,7 +477,12 @@ namespace data
|
||||
s.write ((const char *)&address.date, sizeof (address.date));
|
||||
std::stringstream properties;
|
||||
if (address.transportStyle == eTransportNTCP)
|
||||
WriteString (address.IsNTCP2 () ? "NTCP2" : "NTCP", s);
|
||||
{
|
||||
if (address.IsNTCP2 ())
|
||||
WriteString ("NTCP2", s);
|
||||
else
|
||||
continue; // don't write NTCP address
|
||||
}
|
||||
else if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
WriteString ("SSU", s);
|
||||
@ -704,20 +709,6 @@ namespace data
|
||||
s.write (str.c_str (), len);
|
||||
}
|
||||
|
||||
void RouterInfo::AddNTCPAddress (const char * host, int port)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 6;
|
||||
addr->date = 0;
|
||||
for (const auto& it: *m_Addresses) // don't insert same address twice
|
||||
if (*it == *addr) return;
|
||||
m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
||||
m_Addresses->push_front(std::move(addr)); // always make NTCP first
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
@ -817,14 +808,6 @@ namespace data
|
||||
return "";
|
||||
}
|
||||
|
||||
bool RouterInfo::IsNTCP (bool v4only) const
|
||||
{
|
||||
if (v4only)
|
||||
return m_SupportedTransports & eNTCPV4;
|
||||
else
|
||||
return m_SupportedTransports & (eNTCPV4 | eNTCPV6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsSSU (bool v4only) const
|
||||
{
|
||||
if (v4only)
|
||||
@ -907,15 +890,6 @@ namespace data
|
||||
return m_Caps & Caps::eUnreachable; // non-reachable
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCPAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (
|
||||
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportNTCP) && !address->IsNTCP2Only () && (!v4only || address->host.is_v4 ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (
|
||||
|
@ -153,12 +153,10 @@ namespace data
|
||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||
int GetVersion () const { return m_Version; };
|
||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
||||
std::shared_ptr<const Address> GetNTCPAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetNTCP2Address (bool publishedOnly, bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||
|
||||
void AddNTCPAddress (const char * host, int port);
|
||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
|
||||
bool AddIntroducer (const Introducer& introducer);
|
||||
@ -169,7 +167,6 @@ namespace data
|
||||
void ClearProperties () { m_Properties.clear (); };
|
||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||
bool IsNTCP (bool v4only = true) const;
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsSSUV6 () const;
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "RouterContext.h"
|
||||
@ -243,10 +242,16 @@ namespace transport
|
||||
|
||||
void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (to.protocol () == boost::asio::ip::udp::v4())
|
||||
m_Socket.send_to (boost::asio::buffer (buf, len), to);
|
||||
m_Socket.send_to (boost::asio::buffer (buf, len), to, 0, ec);
|
||||
else
|
||||
m_SocketV6.send_to (boost::asio::buffer (buf, len), to);
|
||||
m_SocketV6.send_to (boost::asio::buffer (buf, len), to, 0, ec);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
LogPrint (eLogError, "SSU: send exception: ", ec.message (), " while trying to send data to ", to.address (), ":", to.port (), " (length: ", len, ")");
|
||||
}
|
||||
}
|
||||
|
||||
void SSUServer::Receive ()
|
||||
@ -265,7 +270,13 @@ namespace transport
|
||||
|
||||
void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
|
||||
{
|
||||
if (!ecode)
|
||||
if (!ecode ||
|
||||
ecode == boost::asio::error::connection_refused ||
|
||||
ecode == boost::asio::error::connection_reset ||
|
||||
ecode == boost::asio::error::network_unreachable ||
|
||||
ecode == boost::asio::error::host_unreachable)
|
||||
// just try continue reading when received ICMP response otherwise socket can crash,
|
||||
// but better to find out which host were sent it and mark that router as unreachable
|
||||
{
|
||||
packet->len = bytes_transferred;
|
||||
std::vector<SSUPacket *> packets;
|
||||
@ -287,7 +298,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SSU: receive_from error: ", ec.message ());
|
||||
LogPrint (eLogError, "SSU: receive_from error: code ", ec.value(), ": ", ec.message ());
|
||||
delete packet;
|
||||
break;
|
||||
}
|
||||
@ -302,7 +313,7 @@ namespace transport
|
||||
delete packet;
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
{
|
||||
LogPrint (eLogError, "SSU: receive error: ", ecode.message ());
|
||||
LogPrint (eLogError, "SSU: receive error: code ", ecode.value(), ": ", ecode.message ());
|
||||
m_Socket.close ();
|
||||
OpenSocket ();
|
||||
Receive ();
|
||||
@ -312,7 +323,13 @@ namespace transport
|
||||
|
||||
void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
|
||||
{
|
||||
if (!ecode)
|
||||
if (!ecode ||
|
||||
ecode == boost::asio::error::connection_refused ||
|
||||
ecode == boost::asio::error::connection_reset ||
|
||||
ecode == boost::asio::error::network_unreachable ||
|
||||
ecode == boost::asio::error::host_unreachable)
|
||||
// just try continue reading when received ICMP response otherwise socket can crash,
|
||||
// but better to find out which host were sent it and mark that router as unreachable
|
||||
{
|
||||
packet->len = bytes_transferred;
|
||||
std::vector<SSUPacket *> packets;
|
||||
@ -334,7 +351,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SSU: v6 receive_from error: ", ec.message ());
|
||||
LogPrint (eLogError, "SSU: v6 receive_from error: code ", ec.value(), ": ", ec.message ());
|
||||
delete packet;
|
||||
break;
|
||||
}
|
||||
@ -349,7 +366,7 @@ namespace transport
|
||||
delete packet;
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
{
|
||||
LogPrint (eLogError, "SSU: v6 receive error: ", ecode.message ());
|
||||
LogPrint (eLogError, "SSU: v6 receive error: code ", ecode.value(), ": ", ecode.message ());
|
||||
m_SocketV6.close ();
|
||||
OpenSocketV6 ();
|
||||
ReceiveV6 ();
|
||||
@ -460,6 +477,7 @@ namespace transport
|
||||
// otherwise create new session
|
||||
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
|
||||
sessions[remoteEndpoint] = session;
|
||||
|
||||
// connect
|
||||
LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ",
|
||||
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "NetDb.hpp"
|
||||
@ -301,7 +300,7 @@ namespace transport
|
||||
void SSUData::Send (std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
uint32_t msgID = msg->ToSSU ();
|
||||
if (m_SentMessages.count (msgID) > 0)
|
||||
if (m_SentMessages.find (msgID) != m_SentMessages.end())
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU: message ", msgID, " already sent");
|
||||
return;
|
||||
@ -326,8 +325,7 @@ namespace transport
|
||||
{
|
||||
Fragment * fragment = new Fragment;
|
||||
fragment->fragmentNum = fragmentNum;
|
||||
uint8_t * buf = fragment->buf;
|
||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||
uint8_t * payload = fragment->buf + sizeof (SSUHeader);
|
||||
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
||||
payload++;
|
||||
*payload = 1; // always 1 message fragment per message
|
||||
@ -346,14 +344,20 @@ namespace transport
|
||||
payload += 3;
|
||||
memcpy (payload, msgBuf, size);
|
||||
|
||||
size += payload - buf;
|
||||
if (size & 0x0F) // make sure 16 bytes boundary
|
||||
size = ((size >> 4) + 1) << 4; // (/16 + 1)*16
|
||||
size += payload - fragment->buf;
|
||||
uint8_t rem = size & 0x0F;
|
||||
if (rem) // make sure 16 bytes boundary
|
||||
{
|
||||
auto padding = 16 - rem;
|
||||
memset (fragment->buf + size, 0, padding);
|
||||
size += padding;
|
||||
}
|
||||
fragment->len = size;
|
||||
fragments.push_back (std::unique_ptr<Fragment> (fragment));
|
||||
|
||||
// encrypt message with session key
|
||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size);
|
||||
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, fragment->buf, size, buf);
|
||||
try
|
||||
{
|
||||
m_Session.Send (buf, size);
|
||||
@ -432,6 +436,7 @@ namespace transport
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
{
|
||||
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
int numResent = 0;
|
||||
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
||||
@ -444,8 +449,9 @@ namespace transport
|
||||
if (f)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_Session.Send (f->buf, f->len); // resend
|
||||
{
|
||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, f->buf, f->len, buf);
|
||||
m_Session.Send (buf, f->len); // resend
|
||||
numResent++;
|
||||
}
|
||||
catch (boost::system::system_error& ec)
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
@ -124,8 +124,8 @@ namespace transport
|
||||
private:
|
||||
|
||||
SSUSession& m_Session;
|
||||
std::map<uint32_t, std::unique_ptr<IncompleteMessage> > m_IncompleteMessages;
|
||||
std::map<uint32_t, std::unique_ptr<SentMessage> > m_SentMessages;
|
||||
std::unordered_map<uint32_t, std::unique_ptr<IncompleteMessage> > m_IncompleteMessages;
|
||||
std::unordered_map<uint32_t, std::unique_ptr<SentMessage> > m_SentMessages;
|
||||
std::unordered_set<uint32_t> m_ReceivedMessages;
|
||||
boost::asio::deadline_timer m_ResendTimer, m_IncompleteMessagesCleanupTimer;
|
||||
int m_MaxPacketSize, m_PacketSize;
|
||||
|
@ -6,7 +6,6 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include "version.h"
|
||||
#include "Crypto.h"
|
||||
#include "Log.h"
|
||||
@ -225,7 +224,11 @@ namespace transport
|
||||
return;
|
||||
}
|
||||
if (!m_DHKeysPair)
|
||||
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||
{
|
||||
auto pair = std::make_shared<i2p::crypto::DHKeys> ();
|
||||
pair->GenerateKeys ();
|
||||
m_DHKeysPair = pair;
|
||||
}
|
||||
CreateAESandMacKey (buf + headerSize);
|
||||
SendSessionCreated (buf + headerSize, sendRelayTag);
|
||||
}
|
||||
@ -744,27 +747,33 @@ namespace transport
|
||||
}
|
||||
|
||||
void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len)
|
||||
{
|
||||
FillHeaderAndEncrypt (payloadType, buf, len, buf);
|
||||
}
|
||||
|
||||
void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out)
|
||||
{
|
||||
if (len < sizeof (SSUHeader))
|
||||
{
|
||||
LogPrint (eLogError, "SSU: Unexpected packet length ", len);
|
||||
return;
|
||||
}
|
||||
SSUHeader * header = (SSUHeader *)buf;
|
||||
SSUHeader * header = (SSUHeader *)out;
|
||||
RAND_bytes (header->iv, 16); // random iv
|
||||
m_SessionKeyEncryption.SetIV (header->iv);
|
||||
header->flag = payloadType << 4; // MSB is 0
|
||||
htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ());
|
||||
uint8_t * encrypted = &header->flag;
|
||||
uint16_t encryptedLen = len - (encrypted - buf);
|
||||
m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted);
|
||||
// assume actual buffer size is 18 (16 + 2) bytes more
|
||||
memcpy (buf + len, header->iv, 16);
|
||||
SSUHeader * inHeader = (SSUHeader *)in;
|
||||
inHeader->flag = payloadType << 4; // MSB is 0
|
||||
htobe32buf (inHeader->time, i2p::util::GetSecondsSinceEpoch ());
|
||||
uint8_t * encrypted = &header->flag, * clear = &inHeader->flag;
|
||||
uint16_t encryptedLen = len - (encrypted - out);
|
||||
m_SessionKeyEncryption.Encrypt (clear, encryptedLen, encrypted);
|
||||
// assume actual out buffer size is 18 (16 + 2) bytes more
|
||||
memcpy (out + len, header->iv, 16);
|
||||
uint16_t netid = i2p::context.GetNetID ();
|
||||
htobe16buf (buf + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8));
|
||||
htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8));
|
||||
i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac);
|
||||
}
|
||||
|
||||
|
||||
void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey)
|
||||
{
|
||||
if (len < sizeof (SSUHeader))
|
||||
@ -821,9 +830,9 @@ namespace transport
|
||||
{
|
||||
if (m_State == eSessionStateUnknown)
|
||||
{
|
||||
// set connect timer
|
||||
ScheduleConnectTimer ();
|
||||
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||
ScheduleConnectTimer (); // set connect timer
|
||||
m_DHKeysPair = std::make_shared<i2p::crypto::DHKeys> ();
|
||||
m_DHKeysPair->GenerateKeys ();
|
||||
SendSessionRequest ();
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ namespace transport
|
||||
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey,
|
||||
const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0);
|
||||
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key
|
||||
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out); // with session key
|
||||
void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey);
|
||||
void DecryptSessionKey (uint8_t * buf, size_t len);
|
||||
bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey);
|
||||
@ -165,6 +166,7 @@ namespace transport
|
||||
bool m_IsDataReceived;
|
||||
std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only
|
||||
std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie
|
||||
std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -351,6 +351,28 @@ namespace stream
|
||||
return true;
|
||||
}
|
||||
|
||||
void Stream::HandlePing (Packet * packet)
|
||||
{
|
||||
uint16_t flags = packet->GetFlags ();
|
||||
if (ProcessOptions (flags, packet) && m_RemoteIdentity)
|
||||
{
|
||||
// send pong
|
||||
Packet p;
|
||||
memset (p.buf, 0, 22); // minimal header all zeroes
|
||||
memcpy (p.buf + 4, packet->buf, 4); // but receiveStreamID is the sendStreamID from the ping
|
||||
htobe16buf (p.buf + 18, PACKET_FLAG_ECHO); // and echo flag
|
||||
ssize_t payloadLen = packet->len - (packet->GetPayload () - packet->buf);
|
||||
if (payloadLen > 0)
|
||||
memcpy (p.buf + 22, packet->GetPayload (), payloadLen);
|
||||
else
|
||||
payloadLen = 0;
|
||||
p.len = payloadLen + 22;
|
||||
SendPackets (std::vector<Packet *> { &p });
|
||||
LogPrint (eLogDebug, "Streaming: Pong of ", p.len, " bytes sent");
|
||||
}
|
||||
m_LocalDestination.DeletePacket (packet);
|
||||
}
|
||||
|
||||
void Stream::ProcessAck (Packet * packet)
|
||||
{
|
||||
bool acknowledged = false;
|
||||
@ -609,6 +631,7 @@ namespace stream
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
}
|
||||
packet[size] = 0;
|
||||
size++; // resend delay
|
||||
htobuf16 (packet + size, 0); // no flags set
|
||||
size += 2; // flags
|
||||
@ -666,6 +689,7 @@ namespace stream
|
||||
size += 4; // ack Through
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
packet[size] = 0;
|
||||
size++; // resend delay
|
||||
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
||||
size += 2; // flags
|
||||
@ -1016,6 +1040,13 @@ namespace stream
|
||||
auto it = m_Streams.find (sendStreamID);
|
||||
if (it != m_Streams.end ())
|
||||
it->second->HandleNextPacket (packet);
|
||||
else if (packet->IsEcho () && m_Owner->IsStreamingAnswerPings ())
|
||||
{
|
||||
// ping
|
||||
LogPrint (eLogInfo, "Streaming: Ping received sSID=", sendStreamID);
|
||||
auto s = std::make_shared<Stream> (m_Owner->GetService (), *this);
|
||||
s->HandlePing (packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogInfo, "Streaming: Unknown stream sSID=", sendStreamID);
|
||||
|
@ -87,6 +87,7 @@ namespace stream
|
||||
|
||||
bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; };
|
||||
bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; };
|
||||
bool IsEcho () const { return GetFlags () & PACKET_FLAG_ECHO; };
|
||||
};
|
||||
|
||||
struct PacketCmp
|
||||
@ -168,6 +169,7 @@ namespace stream
|
||||
StreamingDestination& GetLocalDestination () { return m_LocalDestination; };
|
||||
|
||||
void HandleNextPacket (Packet * packet);
|
||||
void HandlePing (Packet * packet);
|
||||
size_t Send (const uint8_t * buf, size_t len);
|
||||
void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler);
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace transport
|
||||
public:
|
||||
|
||||
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
|
||||
m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
|
||||
m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
|
||||
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ())
|
||||
{
|
||||
if (router)
|
||||
@ -103,7 +103,6 @@ namespace transport
|
||||
|
||||
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
||||
mutable std::mutex m_RemoteIdentityMutex;
|
||||
std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server
|
||||
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||
bool m_IsOutgoing;
|
||||
int m_TerminationTimeout;
|
||||
|
@ -27,20 +27,20 @@ namespace transport
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
EphemeralKeysSupplier<Keys>::~EphemeralKeysSupplier ()
|
||||
{
|
||||
Stop ();
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Start ()
|
||||
{
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier<Keys>::Run, this));
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Stop ()
|
||||
{
|
||||
{
|
||||
@ -56,7 +56,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Run ()
|
||||
{
|
||||
while (m_IsRunning)
|
||||
@ -81,7 +81,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::CreateEphemeralKeys (int num)
|
||||
{
|
||||
if (num > 0)
|
||||
@ -96,7 +96,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
std::shared_ptr<Keys> EphemeralKeysSupplier<Keys>::Acquire ()
|
||||
{
|
||||
{
|
||||
@ -115,7 +115,7 @@ namespace transport
|
||||
return pair;
|
||||
}
|
||||
|
||||
template<typename Keys>
|
||||
template<typename Keys>
|
||||
void EphemeralKeysSupplier<Keys>::Return (std::shared_ptr<Keys> pair)
|
||||
{
|
||||
if (pair)
|
||||
@ -131,10 +131,10 @@ namespace transport
|
||||
Transports transports;
|
||||
|
||||
Transports::Transports ():
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
|
||||
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||
m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr),
|
||||
m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||
m_X25519KeysPairSupplier (5), // 5 pre-generated keys
|
||||
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
|
||||
m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0),
|
||||
@ -154,7 +154,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
void Transports::Start (bool enableNTCP, bool enableSSU)
|
||||
void Transports::Start (bool enableNTCP2, bool enableSSU)
|
||||
{
|
||||
if (!m_Service)
|
||||
{
|
||||
@ -165,54 +165,13 @@ namespace transport
|
||||
}
|
||||
|
||||
i2p::config::GetOption("nat", m_IsNAT);
|
||||
m_DHKeysPairSupplier.Start ();
|
||||
m_X25519KeysPairSupplier.Start ();
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
|
||||
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||
i2p::http::URL proxyurl;
|
||||
uint16_t softLimit, hardLimit, threads;
|
||||
i2p::config::GetOption("limits.ntcpsoft", softLimit);
|
||||
i2p::config::GetOption("limits.ntcphard", hardLimit);
|
||||
i2p::config::GetOption("limits.ntcpthreads", threads);
|
||||
if(softLimit > 0 && hardLimit > 0 && softLimit >= hardLimit)
|
||||
{
|
||||
LogPrint(eLogError, "ntcp soft limit must be less than ntcp hard limit");
|
||||
return;
|
||||
}
|
||||
if(ntcpproxy.size() && enableNTCP)
|
||||
{
|
||||
if(proxyurl.parse(ntcpproxy))
|
||||
{
|
||||
if(proxyurl.schema == "socks" || proxyurl.schema == "http")
|
||||
{
|
||||
m_NTCPServer = new NTCPServer(threads);
|
||||
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
|
||||
NTCPServer::ProxyType proxytype = NTCPServer::eSocksProxy;
|
||||
|
||||
if (proxyurl.schema == "http")
|
||||
proxytype = NTCPServer::eHTTPProxy;
|
||||
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port);
|
||||
m_NTCPServer->Start();
|
||||
if(!m_NTCPServer->NetworkIsReady())
|
||||
{
|
||||
LogPrint(eLogError, "Transports: NTCP failed to start with proxy");
|
||||
m_NTCPServer->Stop();
|
||||
delete m_NTCPServer;
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "Transports: unsupported NTCP proxy URL ", ntcpproxy);
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy);
|
||||
return;
|
||||
}
|
||||
// create NTCP2. TODO: move to acceptor
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
if (enableNTCP2)
|
||||
{
|
||||
if(!ntcp2proxy.empty())
|
||||
{
|
||||
@ -248,20 +207,6 @@ namespace transport
|
||||
for (const auto& address : addresses)
|
||||
{
|
||||
if (!address) continue;
|
||||
if (m_NTCPServer == nullptr && enableNTCP)
|
||||
{
|
||||
m_NTCPServer = new NTCPServer (threads);
|
||||
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
|
||||
m_NTCPServer->Start ();
|
||||
if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) {
|
||||
/** failed to bind to NTCP */
|
||||
LogPrint(eLogError, "Transports: failed to bind to TCP");
|
||||
m_NTCPServer->Stop();
|
||||
delete m_NTCPServer;
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (address->transportStyle == RouterInfo::eTransportSSU)
|
||||
{
|
||||
if (m_SSUServer == nullptr && enableSSU)
|
||||
@ -306,12 +251,6 @@ namespace transport
|
||||
delete m_SSUServer;
|
||||
m_SSUServer = nullptr;
|
||||
}
|
||||
if (m_NTCPServer)
|
||||
{
|
||||
m_NTCPServer->Stop ();
|
||||
delete m_NTCPServer;
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_NTCP2Server)
|
||||
{
|
||||
@ -320,7 +259,6 @@ namespace transport
|
||||
m_NTCP2Server = nullptr;
|
||||
}
|
||||
|
||||
m_DHKeysPairSupplier.Stop ();
|
||||
m_X25519KeysPairSupplier.Stop ();
|
||||
m_IsRunning = false;
|
||||
if (m_Service) m_Service->stop ();
|
||||
@ -381,7 +319,8 @@ namespace transport
|
||||
|
||||
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
|
||||
if (m_IsOnline)
|
||||
SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
|
||||
}
|
||||
|
||||
void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
|
||||
@ -431,7 +370,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "Transports: delayed messages queue size to ",
|
||||
LogPrint (eLogWarning, "Transports: delayed messages queue size to ",
|
||||
ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
@ -452,7 +391,7 @@ namespace transport
|
||||
{
|
||||
// NTCP2 have priority over NTCP
|
||||
auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only
|
||||
if (address && !peer.router->IsUnreachable ())
|
||||
if (address && !peer.router->IsUnreachable () && (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host)))
|
||||
{
|
||||
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
|
||||
|
||||
@ -472,48 +411,17 @@ namespace transport
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer.numAttempts == 1) // NTCP1
|
||||
{
|
||||
peer.numAttempts++;
|
||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
||||
if (address && m_NTCPServer)
|
||||
{
|
||||
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
|
||||
{
|
||||
if(!m_NTCPServer->ShouldLimit())
|
||||
{
|
||||
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
||||
if(m_NTCPServer->UsingProxy())
|
||||
{
|
||||
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
|
||||
std::string addr = address->host.to_string();
|
||||
|
||||
if(address->host.is_v6())
|
||||
remote = NTCPServer::eIP6Address;
|
||||
|
||||
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
|
||||
}
|
||||
else
|
||||
m_NTCPServer->Connect (address->host, address->port, s);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU");
|
||||
}
|
||||
if (peer.numAttempts == 2)// SSU
|
||||
if (peer.numAttempts == 1)// SSU
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||
{
|
||||
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
|
||||
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
||||
return true;
|
||||
if (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host))
|
||||
{
|
||||
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
|
||||
@ -630,16 +538,6 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::crypto::DHKeys> Transports::GetNextDHKeysPair ()
|
||||
{
|
||||
return m_DHKeysPairSupplier.Acquire ();
|
||||
}
|
||||
|
||||
void Transports::ReuseDHKeysPair (std::shared_ptr<i2p::crypto::DHKeys> pair)
|
||||
{
|
||||
m_DHKeysPairSupplier.Return (pair);
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::crypto::X25519Keys> Transports::GetNextX25519KeysPair ()
|
||||
{
|
||||
return m_X25519KeysPairSupplier.Acquire ();
|
||||
@ -649,7 +547,7 @@ namespace transport
|
||||
{
|
||||
m_X25519KeysPairSupplier.Return (pair);
|
||||
}
|
||||
|
||||
|
||||
void Transports::PeerConnected (std::shared_ptr<TransportSession> session)
|
||||
{
|
||||
m_Service->post([session, this]()
|
||||
@ -850,5 +748,17 @@ namespace transport
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Transports::SetOnline (bool online)
|
||||
{
|
||||
if (m_IsOnline != online)
|
||||
{
|
||||
m_IsOnline = online;
|
||||
if (online)
|
||||
PeerTest ();
|
||||
else
|
||||
i2p::context.SetError (eRouterErrorOffline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <atomic>
|
||||
#include <boost/asio.hpp>
|
||||
#include "TransportSession.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "SSU.h"
|
||||
#include "NTCP2.h"
|
||||
#include "RouterInfo.h"
|
||||
@ -60,7 +59,6 @@ namespace transport
|
||||
std::condition_variable m_Acquired;
|
||||
std::mutex m_AcquiredMutex;
|
||||
};
|
||||
typedef EphemeralKeysSupplier<i2p::crypto::DHKeys> DHKeysPairSupplier;
|
||||
typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier;
|
||||
|
||||
struct Peer
|
||||
@ -88,19 +86,16 @@ namespace transport
|
||||
Transports ();
|
||||
~Transports ();
|
||||
|
||||
void Start (bool enableNTCP=true, bool enableSSU=true);
|
||||
void Start (bool enableNTCP2=true, bool enableSSU=true);
|
||||
void Stop ();
|
||||
|
||||
bool IsBoundNTCP() const { return m_NTCPServer != nullptr; }
|
||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
|
||||
|
||||
bool IsOnline() const { return m_IsOnline; };
|
||||
void SetOnline (bool online) { m_IsOnline = online; };
|
||||
void SetOnline (bool online);
|
||||
|
||||
boost::asio::io_service& GetService () { return *m_Service; };
|
||||
std::shared_ptr<i2p::crypto::DHKeys> GetNextDHKeysPair ();
|
||||
void ReuseDHKeysPair (std::shared_ptr<i2p::crypto::DHKeys> pair);
|
||||
std::shared_ptr<i2p::crypto::X25519Keys> GetNextX25519KeysPair ();
|
||||
void ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair);
|
||||
|
||||
@ -138,6 +133,9 @@ namespace transport
|
||||
|
||||
void PeerTest ();
|
||||
|
||||
void SetCheckReserved (bool check) { m_CheckReserved = check; };
|
||||
bool IsCheckReserved () { return m_CheckReserved; };
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
@ -153,19 +151,18 @@ namespace transport
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsOnline, m_IsRunning, m_IsNAT;
|
||||
volatile bool m_IsOnline;
|
||||
bool m_IsRunning, m_IsNAT, m_CheckReserved;
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service * m_Service;
|
||||
boost::asio::io_service::work * m_Work;
|
||||
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
|
||||
|
||||
NTCPServer * m_NTCPServer;
|
||||
SSUServer * m_SSUServer;
|
||||
NTCP2Server * m_NTCP2Server;
|
||||
mutable std::mutex m_PeersMutex;
|
||||
std::unordered_map<i2p::data::IdentHash, Peer> m_Peers;
|
||||
|
||||
DHKeysPairSupplier m_DHKeysPairSupplier;
|
||||
X25519KeysPairSupplier m_X25519KeysPairSupplier;
|
||||
|
||||
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
|
||||
@ -186,7 +183,6 @@ namespace transport
|
||||
public:
|
||||
|
||||
// for HTTP only
|
||||
const NTCPServer * GetNTCPServer () const { return m_NTCPServer; };
|
||||
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
||||
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
|
||||
|
@ -303,6 +303,7 @@ namespace tunnel
|
||||
{
|
||||
for (auto& msg : msgs)
|
||||
{
|
||||
if (!msg.data) continue;
|
||||
switch (msg.deliveryType)
|
||||
{
|
||||
case eDeliveryTypeLocal:
|
||||
@ -521,7 +522,7 @@ namespace tunnel
|
||||
}
|
||||
|
||||
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (ts - lastTs >= 15) // manage tunnels every 15 seconds
|
||||
if (ts - lastTs >= 15 && i2p::transport::transports.IsOnline()) // manage tunnels every 15 seconds
|
||||
{
|
||||
ManageTunnels ();
|
||||
lastTs = ts;
|
||||
|
@ -36,7 +36,7 @@ namespace tunnel
|
||||
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
|
||||
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
||||
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
|
||||
const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message
|
||||
const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message
|
||||
|
||||
enum TunnelState
|
||||
{
|
||||
|
@ -61,6 +61,9 @@ int inet_pton_xp(int af, const char *src, void *dst)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#define address_pair_v4(a,b) { boost::asio::ip::address_v4::from_string (a).to_ulong (), boost::asio::ip::address_v4::from_string (b).to_ulong () }
|
||||
#define address_pair_v6(a,b) { boost::asio::ip::address_v6::from_string (a).to_bytes (), boost::asio::ip::address_v6::from_string (b).to_bytes () }
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace util
|
||||
@ -391,6 +394,50 @@ namespace net
|
||||
return boost::asio::ip::address::from_string(fallback);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool IsInReservedRange(const boost::asio::ip::address& host) {
|
||||
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
||||
if(host.is_v4())
|
||||
{
|
||||
static const std::vector< std::pair<uint32_t, uint32_t> > reservedIPv4Ranges {
|
||||
address_pair_v4("0.0.0.0", "0.255.255.255"),
|
||||
address_pair_v4("10.0.0.0", "10.255.255.255"),
|
||||
address_pair_v4("100.64.0.0", "100.127.255.255"),
|
||||
address_pair_v4("127.0.0.0", "127.255.255.255"),
|
||||
address_pair_v4("169.254.0.0", "169.254.255.255"),
|
||||
address_pair_v4("172.16.0.0", "172.31.255.255"),
|
||||
address_pair_v4("192.0.0.0", "192.0.0.255"),
|
||||
address_pair_v4("192.0.2.0", "192.0.2.255"),
|
||||
address_pair_v4("192.88.99.0", "192.88.99.255"),
|
||||
address_pair_v4("192.168.0.0", "192.168.255.255"),
|
||||
address_pair_v4("198.18.0.0", "192.19.255.255"),
|
||||
address_pair_v4("198.51.100.0", "198.51.100.255"),
|
||||
address_pair_v4("203.0.113.0", "203.0.113.255"),
|
||||
address_pair_v4("224.0.0.0", "255.255.255.255")
|
||||
};
|
||||
|
||||
uint32_t ipv4_address = host.to_v4 ().to_ulong ();
|
||||
for(const auto& it : reservedIPv4Ranges) {
|
||||
if (ipv4_address >= it.first && ipv4_address <= it.second)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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("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")
|
||||
};
|
||||
|
||||
boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes ();
|
||||
for(const auto& it : reservedIPv6Ranges) {
|
||||
if (ipv6_address >= it.first && ipv6_address <= it.second)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // net
|
||||
} // util
|
||||
} // i2p
|
||||
|
@ -172,6 +172,7 @@ namespace util
|
||||
{
|
||||
int GetMTU (const boost::asio::ip::address& localAddress);
|
||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
|
||||
bool IsInReservedRange(const boost::asio::ip::address& host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 32
|
||||
#define I2PD_VERSION_MICRO 1
|
||||
#define I2PD_VERSION_MINOR 33
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||
#define VERSION I2PD_VERSION
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 46
|
||||
#define I2P_VERSION_MICRO 47
|
||||
#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)
|
||||
|
@ -198,13 +198,18 @@ namespace client
|
||||
|
||||
for (const auto& it: addresses)
|
||||
{
|
||||
f << it.first << ",";
|
||||
if (it.second->IsIdentHash ())
|
||||
f << it.second->identHash.ToBase32 ();
|
||||
if (it.second->IsValid ())
|
||||
{
|
||||
f << it.first << ",";
|
||||
if (it.second->IsIdentHash ())
|
||||
f << it.second->identHash.ToBase32 ();
|
||||
else
|
||||
f << it.second->blindedPublicKey->ToB33 ();
|
||||
f << std::endl;
|
||||
num++;
|
||||
}
|
||||
else
|
||||
f << it.second->blindedPublicKey->ToB33 ();
|
||||
f << std::endl;
|
||||
num++;
|
||||
LogPrint (eLogWarning, "Addressbook: invalid address ", it.first);
|
||||
}
|
||||
LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved");
|
||||
return num;
|
||||
@ -801,6 +806,7 @@ namespace client
|
||||
i2p::http::HTTPReq req;
|
||||
req.AddHeader("Host", dest_host);
|
||||
req.AddHeader("User-Agent", "Wget/1.11.4");
|
||||
req.AddHeader("Accept-Encoding", "gzip");
|
||||
req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0");
|
||||
req.AddHeader("Connection", "close");
|
||||
if (!m_Etag.empty())
|
||||
@ -811,6 +817,7 @@ namespace client
|
||||
url.schema = "";
|
||||
url.host = "";
|
||||
req.uri = url.to_string();
|
||||
req.version = "HTTP/1.1";
|
||||
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
||||
std::string request = req.to_string();
|
||||
stream->Send ((const uint8_t *) request.data(), request.length());
|
||||
@ -882,7 +889,7 @@ namespace client
|
||||
/* assert: res.code == 200 */
|
||||
auto it = res.headers.find("ETag");
|
||||
if (it != res.headers.end()) m_Etag = it->second;
|
||||
it = res.headers.find("If-Modified-Since");
|
||||
it = res.headers.find("Last-Modified");
|
||||
if (it != res.headers.end()) m_LastModified = it->second;
|
||||
if (res.is_chunked())
|
||||
{
|
||||
@ -890,7 +897,7 @@ namespace client
|
||||
i2p::http::MergeChunkedResponse (in, out);
|
||||
response = out.str();
|
||||
}
|
||||
else if (res.is_gzipped())
|
||||
if (res.is_gzipped())
|
||||
{
|
||||
std::stringstream out;
|
||||
i2p::data::GzipInflator inflator;
|
||||
|
@ -102,10 +102,11 @@ namespace client
|
||||
{
|
||||
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
||||
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
||||
bool singleThread; i2p::config::GetOption("i2cp.singlethread", singleThread);
|
||||
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
||||
try
|
||||
{
|
||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort, singleThread);
|
||||
m_I2CPServer->Start ();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
@ -253,7 +254,8 @@ namespace client
|
||||
bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
|
||||
i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType)
|
||||
{
|
||||
if (filename == "transient")
|
||||
static const std::string transient("transient");
|
||||
if (!filename.compare (0, transient.length (), transient)) // starts with transient
|
||||
{
|
||||
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType);
|
||||
LogPrint (eLogInfo, "Clients: New transient keys address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created");
|
||||
@ -400,7 +402,14 @@ namespace client
|
||||
|
||||
void ClientContext::CreateNewSharedLocalDestination ()
|
||||
{
|
||||
m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, EDDSA
|
||||
std::map<std::string, std::string> params
|
||||
{
|
||||
{ I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, "2" },
|
||||
{ I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, "2" },
|
||||
{ I2CP_PARAM_LEASESET_TYPE, "3" }
|
||||
};
|
||||
m_SharedLocalDestination = CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, ¶ms); // non-public, EDDSA
|
||||
m_SharedLocalDestination->Acquire ();
|
||||
}
|
||||
|
||||
@ -435,7 +444,7 @@ namespace client
|
||||
}
|
||||
|
||||
template<typename Section>
|
||||
void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
|
||||
void ClientContext::ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const
|
||||
{
|
||||
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
||||
@ -445,6 +454,7 @@ namespace client
|
||||
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
|
||||
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
|
||||
options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY);
|
||||
options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false);
|
||||
options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE);
|
||||
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "");
|
||||
if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType;
|
||||
@ -533,6 +543,7 @@ namespace client
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, std::shared_ptr<ClientDestination> > destinations; // keys -> destination
|
||||
for (auto& section: pt)
|
||||
{
|
||||
std::string name = section.first;
|
||||
@ -559,23 +570,30 @@ namespace client
|
||||
i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
|
||||
// I2CP
|
||||
std::map<std::string, std::string> options;
|
||||
ReadI2CPOptions (section, options);
|
||||
ReadI2CPOptions (section, false, options);
|
||||
|
||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||
if (keys.length () > 0)
|
||||
{
|
||||
i2p::data::PrivateKeys k;
|
||||
if(LoadPrivateKeys (k, keys, sigType, cryptoType))
|
||||
{
|
||||
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
|
||||
if (!localDestination)
|
||||
auto it = destinations.find (keys);
|
||||
if (it != destinations.end ())
|
||||
localDestination = it->second;
|
||||
else
|
||||
{
|
||||
i2p::data::PrivateKeys k;
|
||||
if(LoadPrivateKeys (k, keys, sigType, cryptoType))
|
||||
{
|
||||
if(matchTunnels)
|
||||
localDestination = CreateNewMatchedTunnelDestination(k, dest, &options);
|
||||
else
|
||||
localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options);
|
||||
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
|
||||
if (!localDestination)
|
||||
{
|
||||
if(matchTunnels)
|
||||
localDestination = CreateNewMatchedTunnelDestination(k, dest, &options);
|
||||
else
|
||||
localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options);
|
||||
destinations[keys] = localDestination;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
|
||||
@ -676,15 +694,24 @@ namespace client
|
||||
|
||||
// I2CP
|
||||
std::map<std::string, std::string> options;
|
||||
ReadI2CPOptions (section, options);
|
||||
ReadI2CPOptions (section, true, options);
|
||||
|
||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||
i2p::data::PrivateKeys k;
|
||||
if(!LoadPrivateKeys (k, keys, sigType, cryptoType))
|
||||
continue;
|
||||
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
|
||||
if (!localDestination)
|
||||
localDestination = CreateNewLocalDestination (k, true, &options);
|
||||
auto it = destinations.find (keys);
|
||||
if (it != destinations.end ())
|
||||
localDestination = it->second;
|
||||
else
|
||||
{
|
||||
i2p::data::PrivateKeys k;
|
||||
if(!LoadPrivateKeys (k, keys, sigType, cryptoType))
|
||||
continue;
|
||||
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
|
||||
if (!localDestination)
|
||||
{
|
||||
localDestination = CreateNewLocalDestination (k, true, &options);
|
||||
destinations[keys] = localDestination;
|
||||
}
|
||||
}
|
||||
if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
|
||||
{
|
||||
// udp server tunnel
|
||||
@ -819,6 +846,8 @@ namespace client
|
||||
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
|
||||
if (socksproxy)
|
||||
{
|
||||
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
||||
// we still need httpProxyKeys to compare with sockProxyKeys
|
||||
std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys);
|
||||
std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
|
||||
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
|
||||
@ -827,7 +856,12 @@ namespace client
|
||||
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
|
||||
LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort);
|
||||
if (socksProxyKeys.length () > 0)
|
||||
if (httpProxyKeys == socksProxyKeys && m_HttpProxy)
|
||||
{
|
||||
localDestination = m_HttpProxy->GetLocalDestination ();
|
||||
localDestination->Acquire ();
|
||||
}
|
||||
else if (socksProxyKeys.length () > 0)
|
||||
{
|
||||
i2p::data::PrivateKeys keys;
|
||||
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
|
||||
|
@ -115,7 +115,7 @@ namespace client
|
||||
template<typename Section>
|
||||
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
|
||||
template<typename Section>
|
||||
void ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const; // for tunnels
|
||||
void ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const; // for tunnels
|
||||
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const; // for HTTP and SOCKS proxy
|
||||
|
||||
void CleanupUDP(const boost::system::error_code & ecode);
|
||||
|
@ -23,36 +23,13 @@ namespace i2p
|
||||
namespace client
|
||||
{
|
||||
|
||||
I2CPDestination::I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||
RunnableService ("I2CP"), LeaseSetDestination (GetIOService (), isPublic, ¶ms),
|
||||
I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||
LeaseSetDestination (service, isPublic, ¶ms),
|
||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ())
|
||||
{
|
||||
}
|
||||
|
||||
I2CPDestination::~I2CPDestination ()
|
||||
{
|
||||
if (IsRunning ())
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void I2CPDestination::Start ()
|
||||
{
|
||||
if (!IsRunning ())
|
||||
{
|
||||
LeaseSetDestination::Start ();
|
||||
StartIOService ();
|
||||
}
|
||||
}
|
||||
|
||||
void I2CPDestination::Stop ()
|
||||
{
|
||||
if (IsRunning ())
|
||||
{
|
||||
LeaseSetDestination::Stop ();
|
||||
StopIOService ();
|
||||
}
|
||||
}
|
||||
|
||||
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
||||
{
|
||||
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key);
|
||||
@ -217,6 +194,37 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
RunnableI2CPDestination::RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner,
|
||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||
RunnableService ("I2CP"),
|
||||
I2CPDestination (GetIOService (), owner, identity, isPublic, params)
|
||||
{
|
||||
}
|
||||
|
||||
RunnableI2CPDestination::~RunnableI2CPDestination ()
|
||||
{
|
||||
if (IsRunning ())
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void RunnableI2CPDestination::Start ()
|
||||
{
|
||||
if (!IsRunning ())
|
||||
{
|
||||
I2CPDestination::Start ();
|
||||
StartIOService ();
|
||||
}
|
||||
}
|
||||
|
||||
void RunnableI2CPDestination::Stop ()
|
||||
{
|
||||
if (IsRunning ())
|
||||
{
|
||||
I2CPDestination::Stop ();
|
||||
StopIOService ();
|
||||
}
|
||||
}
|
||||
|
||||
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<proto::socket> socket):
|
||||
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
||||
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
||||
@ -451,7 +459,9 @@ namespace client
|
||||
if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false;
|
||||
if (!m_Destination)
|
||||
{
|
||||
m_Destination = std::make_shared<I2CPDestination>(shared_from_this (), identity, isPublic, params);
|
||||
m_Destination = m_Owner.IsSingleThread () ?
|
||||
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, isPublic, params):
|
||||
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, isPublic, params);
|
||||
SendSessionStatusMessage (1); // created
|
||||
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
@ -800,9 +810,9 @@ namespace client
|
||||
std::placeholders::_1, std::placeholders::_2, buf));
|
||||
}
|
||||
|
||||
I2CPServer::I2CPServer (const std::string& interface, int port):
|
||||
m_IsRunning (false), m_Thread (nullptr),
|
||||
m_Acceptor (m_Service,
|
||||
I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread):
|
||||
RunnableService ("I2CP"), m_IsSingleThread (isSingleThread),
|
||||
m_Acceptor (GetIOService (),
|
||||
#ifdef ANDROID
|
||||
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
|
||||
#else
|
||||
@ -825,20 +835,18 @@ namespace client
|
||||
|
||||
I2CPServer::~I2CPServer ()
|
||||
{
|
||||
if (m_IsRunning)
|
||||
if (IsRunning ())
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void I2CPServer::Start ()
|
||||
{
|
||||
Accept ();
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&I2CPServer::Run, this));
|
||||
StartIOService ();
|
||||
}
|
||||
|
||||
void I2CPServer::Stop ()
|
||||
{
|
||||
m_IsRunning = false;
|
||||
m_Acceptor.cancel ();
|
||||
{
|
||||
auto sessions = m_Sessions;
|
||||
@ -846,33 +854,12 @@ namespace client
|
||||
it.second->Stop ();
|
||||
}
|
||||
m_Sessions.clear ();
|
||||
m_Service.stop ();
|
||||
if (m_Thread)
|
||||
{
|
||||
m_Thread->join ();
|
||||
delete m_Thread;
|
||||
m_Thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void I2CPServer::Run ()
|
||||
{
|
||||
while (m_IsRunning)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_Service.run ();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ());
|
||||
}
|
||||
}
|
||||
StopIOService ();
|
||||
}
|
||||
|
||||
void I2CPServer::Accept ()
|
||||
{
|
||||
auto newSocket = std::make_shared<I2CPSession::proto::socket> (m_Service);
|
||||
auto newSocket = std::make_shared<I2CPSession::proto::socket> (GetIOService ());
|
||||
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
||||
std::placeholders::_1, newSocket));
|
||||
}
|
||||
|
@ -63,16 +63,14 @@ namespace client
|
||||
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
|
||||
|
||||
class I2CPSession;
|
||||
class I2CPDestination: private i2p::util::RunnableService, public LeaseSetDestination
|
||||
class I2CPDestination: public LeaseSetDestination
|
||||
{
|
||||
public:
|
||||
|
||||
I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
||||
~I2CPDestination ();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
||||
~I2CPDestination () {};
|
||||
|
||||
void SetEncryptionPrivateKey (const uint8_t * key);
|
||||
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
|
||||
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
|
||||
@ -109,6 +107,18 @@ namespace client
|
||||
uint64_t m_LeaseSetExpirationTime;
|
||||
};
|
||||
|
||||
class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination
|
||||
{
|
||||
public:
|
||||
|
||||
RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity,
|
||||
bool isPublic, const std::map<std::string, std::string>& params);
|
||||
~RunnableI2CPDestination ();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
};
|
||||
|
||||
class I2CPServer;
|
||||
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
|
||||
{
|
||||
@ -179,17 +189,18 @@ namespace client
|
||||
};
|
||||
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
|
||||
|
||||
class I2CPServer
|
||||
class I2CPServer: private i2p::util::RunnableService
|
||||
{
|
||||
public:
|
||||
|
||||
I2CPServer (const std::string& interface, int port);
|
||||
I2CPServer (const std::string& interface, int port, bool isSingleThread);
|
||||
~I2CPServer ();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
|
||||
boost::asio::io_service& GetService () { return GetIOService (); };
|
||||
bool IsSingleThread () const { return m_IsSingleThread; };
|
||||
|
||||
bool InsertSession (std::shared_ptr<I2CPSession> session);
|
||||
void RemoveSession (uint16_t sessionID);
|
||||
|
||||
@ -203,12 +214,10 @@ namespace client
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsSingleThread;
|
||||
I2CPMessageHandler m_MessagesHandlers[256];
|
||||
std::map<uint16_t, std::shared_ptr<I2CPSession> > m_Sessions;
|
||||
|
||||
bool m_IsRunning;
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service m_Service;
|
||||
I2CPSession::proto::acceptor m_Acceptor;
|
||||
|
||||
public:
|
||||
|
@ -139,22 +139,25 @@ namespace client
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Stream)
|
||||
{
|
||||
auto s = shared_from_this ();
|
||||
m_Stream->AsyncSend (m_Buffer, bytes_transferred,
|
||||
[s](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (!ecode)
|
||||
s->Receive ();
|
||||
else
|
||||
s->Terminate ();
|
||||
});
|
||||
}
|
||||
}
|
||||
WriteToStream (m_Buffer, bytes_transferred);
|
||||
}
|
||||
|
||||
void I2PTunnelConnection::WriteToStream (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_Stream)
|
||||
{
|
||||
auto s = shared_from_this ();
|
||||
m_Stream->AsyncSend (buf, len,
|
||||
[s](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (!ecode)
|
||||
s->Receive ();
|
||||
else
|
||||
s->Terminate ();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode)
|
||||
@ -302,7 +305,8 @@ namespace client
|
||||
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host):
|
||||
I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false), m_From (stream->GetRemoteIdentity ())
|
||||
I2PTunnelConnection (owner, stream, socket, target), m_Host (host),
|
||||
m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ())
|
||||
{
|
||||
}
|
||||
|
||||
@ -324,7 +328,7 @@ namespace client
|
||||
if (line == "\r") endOfHeader = true;
|
||||
else
|
||||
{
|
||||
if (m_Host.length () > 0 && line.find ("Host:") != std::string::npos)
|
||||
if (m_Host.length () > 0 && !line.compare(0, 5, "Host:"))
|
||||
m_OutHeader << "Host: " << m_Host << "\r\n"; // override host
|
||||
else
|
||||
m_OutHeader << line << "\n";
|
||||
@ -333,12 +337,63 @@ namespace client
|
||||
else
|
||||
break;
|
||||
}
|
||||
// add X-I2P fields
|
||||
if (m_From)
|
||||
|
||||
if (endOfHeader)
|
||||
{
|
||||
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
|
||||
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
|
||||
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
|
||||
// add X-I2P fields
|
||||
if (m_From)
|
||||
{
|
||||
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
|
||||
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
|
||||
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
|
||||
}
|
||||
|
||||
m_OutHeader << "\r\n"; // end of header
|
||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||
m_InHeader.str ("");
|
||||
m_From = nullptr;
|
||||
m_HeaderSent = true;
|
||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2PServerTunnelConnectionHTTP::WriteToStream (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_ResponseHeaderSent)
|
||||
I2PTunnelConnection::WriteToStream (buf, len);
|
||||
else
|
||||
{
|
||||
m_InHeader.clear ();
|
||||
if (m_InHeader.str ().empty ()) m_OutHeader.str (""); // start of response
|
||||
m_InHeader.write ((const char *)buf, len);
|
||||
std::string line;
|
||||
bool endOfHeader = false;
|
||||
while (!endOfHeader)
|
||||
{
|
||||
std::getline(m_InHeader, line);
|
||||
if (!m_InHeader.fail ())
|
||||
{
|
||||
if (line == "\r") endOfHeader = true;
|
||||
else
|
||||
{
|
||||
static const std::vector<std::string> excluded // list of excluded headers
|
||||
{
|
||||
"Server:", "Date:", "X-Runtime:", "X-Powered-By:", "Proxy"
|
||||
};
|
||||
bool matched = false;
|
||||
for (const auto& it: excluded)
|
||||
if (!line.compare(0, it.length (), it))
|
||||
{
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
if (!matched)
|
||||
m_OutHeader << line << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (endOfHeader)
|
||||
@ -346,12 +401,15 @@ namespace client
|
||||
m_OutHeader << "\r\n"; // end of header
|
||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||
m_InHeader.str ("");
|
||||
m_HeaderSent = true;
|
||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
}
|
||||
}
|
||||
m_ResponseHeaderSent = true;
|
||||
I2PTunnelConnection::WriteToStream ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
m_OutHeader.str ("");
|
||||
}
|
||||
else
|
||||
Receive ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
|
||||
@ -708,9 +766,12 @@ namespace client
|
||||
if(!ecode)
|
||||
{
|
||||
LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint);
|
||||
LastActivity = i2p::util::GetMillisecondsSinceEpoch();
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||
auto session = m_Destination->GetSession (Identity);
|
||||
m_Destination->SendDatagram(session, m_Buffer, len, LocalPort, RemotePort);
|
||||
if (ts > LastActivity + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL)
|
||||
m_Destination->SendDatagram(session, m_Buffer, len, LocalPort, RemotePort);
|
||||
else
|
||||
m_Destination->SendRawDatagram(session, m_Buffer, len, LocalPort, RemotePort);
|
||||
size_t numPackets = 0;
|
||||
while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE)
|
||||
{
|
||||
@ -724,6 +785,7 @@ namespace client
|
||||
if (numPackets > 0)
|
||||
LogPrint(eLogDebug, "UDPSession: forward more ", numPackets, "packets B from ", FromEndpoint);
|
||||
m_Destination->FlushSendQueue (session);
|
||||
LastActivity = ts;
|
||||
Receive();
|
||||
}
|
||||
else
|
||||
@ -841,9 +903,13 @@ namespace client
|
||||
m_LastPort = remotePort;
|
||||
}
|
||||
// send off to remote i2p destination
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||
LogPrint(eLogDebug, "UDP Client: send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort);
|
||||
auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent);
|
||||
m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
if (ts > m_LastSession->second + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL)
|
||||
m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
else
|
||||
m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
size_t numPackets = 0;
|
||||
while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE)
|
||||
{
|
||||
@ -862,7 +928,7 @@ namespace client
|
||||
|
||||
// mark convo as active
|
||||
if (m_LastSession)
|
||||
m_LastSession->second = i2p::util::GetMillisecondsSinceEpoch();
|
||||
m_LastSession->second = ts;
|
||||
RecvFromLocal();
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,8 @@ namespace client
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
|
||||
void HandleWrite (const boost::system::error_code& ecode);
|
||||
|
||||
virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded
|
||||
|
||||
void StreamReceive ();
|
||||
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleConnect (const boost::system::error_code& ecode);
|
||||
@ -103,12 +104,13 @@ namespace client
|
||||
protected:
|
||||
|
||||
void Write (const uint8_t * buf, size_t len);
|
||||
void WriteToStream (const uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Host;
|
||||
std::stringstream m_InHeader, m_OutHeader;
|
||||
bool m_HeaderSent;
|
||||
bool m_HeaderSent, m_ResponseHeaderSent;
|
||||
std::shared_ptr<const i2p::data::IdentityEx> m_From;
|
||||
};
|
||||
|
||||
@ -165,7 +167,8 @@ namespace client
|
||||
|
||||
/** 2 minute timeout for udp sessions */
|
||||
const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2;
|
||||
|
||||
const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds
|
||||
|
||||
/** max size for i2p udp */
|
||||
const size_t I2P_UDP_MAX_MTU = 64*1024;
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
<translation type="qt" />
|
||||
|
||||
<releases>
|
||||
<release version="2.33.0" date="2020-08-24" />
|
||||
<release version="2.32.1" date="2020-06-02" />
|
||||
<release version="2.32.0" date="2020-05-25" />
|
||||
<release version="2.31.0" date="2020-04-10" />
|
||||
|
@ -42,7 +42,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
||||
../../libi2pd/NetDb.cpp \
|
||||
../../libi2pd/NetDbRequests.cpp \
|
||||
../../libi2pd/NTCP2.cpp \
|
||||
../../libi2pd/NTCPSession.cpp \
|
||||
../../libi2pd/Poly1305.cpp \
|
||||
../../libi2pd/Profiling.cpp \
|
||||
../../libi2pd/Reseed.cpp \
|
||||
@ -123,7 +122,6 @@ HEADERS += DaemonQT.h mainwindow.h \
|
||||
../../libi2pd/NetDb.hpp \
|
||||
../../libi2pd/NetDbRequests.h \
|
||||
../../libi2pd/NTCP2.h \
|
||||
../../libi2pd/NTCPSession.h \
|
||||
../../libi2pd/Poly1305.h \
|
||||
../../libi2pd/Profiling.h \
|
||||
../../libi2pd/Queue.h \
|
||||
|
Loading…
Reference in New Issue
Block a user