[-]
[+]
|
Changed |
_service:tar_git:i2pd.spec
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -1,8 +1,11 @@
<services>
<service name="tar_git">
<param name="url">https://github.com/nephros/i2pd</param>
+ <param name="branch">next</param>
+ <!--
<param name="branch"></param>
<param name="revision">2.50.2+git3</param>
+ -->
<param name="token"/>
<param name="debian">N</param>
<param name="dumb">N</param>
|
[-]
[+]
|
Deleted |
_service:tar_git:i2pd-2.50.2+git3.tar.gz/upstream/.github/workflows/build-windows-msvc.yml
^
|
@@ -1,52 +0,0 @@
-name: Build on Windows with MSVC
-
-on: [push, pull_request]
-
-jobs:
- build:
- name: Build
- runs-on: windows-latest
-
- strategy:
- fail-fast: false
-
- steps:
- - name: Checkout
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
-
- - name: Build and install zlib
- run: |
- powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)"
- powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings
- set BUILD_TYPE=Debug
- ./install_zlib.bat
- set BUILD_TYPE=Release
- ./install_zlib.bat
- del install_zlib.bat
-
- - name: Install Boost
- uses: crazy-max/ghaction-chocolatey@v2
- with:
- args: install boost-msvc-14.3 --version=1.81.0
-
- - name: Install OpenSSL
- uses: crazy-max/ghaction-chocolatey@v2
- with:
- args: install openssl
-
- - name: Configure
- working-directory: build
- run: cmake -DWITH_STATIC=ON .
-
- - name: Build
- working-directory: build
- run: cmake --build . --config Debug -- -m
-
- - name: Upload artifacts
- uses: actions/upload-artifact@v3
- with:
- name: i2pd-msvc
- path: build/Debug/i2pd.*
-
|
[-]
[+]
|
Deleted |
_service:tar_git:i2pd-2.50.2+git3.tar.gz/upstream/contrib/certificates/reseed/null_at_i2pmail.org.crt
^
|
@@ -1,33 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw
-cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
-ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM
-EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2
-WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD
-VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE
-AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
-ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0
-XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE
-ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA
-1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp
-gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp
-486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR
-gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW
-DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn
-KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX
-kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV
-bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G
-A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
-VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG
-9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss
-q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj
-EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39
-gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV
-La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH
-xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6
-a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8
-NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK
-heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO
-j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU
-vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw=
------END CERTIFICATE-----
|
[-]
[+]
|
Deleted |
_service:tar_git:i2pd-2.50.2+git3.tar.gz/upstream/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt
^
|
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw
-fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
-ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM
-HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX
-DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD
-VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL
-EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC
-IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6
-MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI
-Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt
-4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5
-UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k
-P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t
-3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5
-zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r
-Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ
-lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1
-sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz
-euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW
-MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf
-BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC
-AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj
-tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6
-ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf
-xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD
-UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM
-XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE
-Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p
-Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq
-NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr
-QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9
-0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY=
------END CERTIFICATE-----
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build-deb.yml
^
|
@@ -1,6 +1,24 @@
name: Build Debian packages
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build-deb.yml
+ - contrib/**
+ - daemon/**
+ - debian/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Makefile
+ - Makefile.linux
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
jobs:
build:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build-freebsd.yml
^
|
@@ -1,6 +1,24 @@
name: Build on FreeBSD
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build-freebsd.yml
+ - build/CMakeLists.txt
+ - build/cmake_modules/**
+ - daemon/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Makefile
+ - Makefile.homebrew
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
jobs:
build:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build-osx.yml
^
|
@@ -1,6 +1,22 @@
name: Build on OSX
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build-osx.yml
+ - daemon/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Makefile
+ - Makefile.homebrew
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
jobs:
build:
|
[-]
[+]
|
Added |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build-windows-msvc.yml-disabled
^
|
@@ -0,0 +1,80 @@
+name: Build on Windows with MSVC
+
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build-windows-msvc.yml
+ - build/CMakeLists.txt
+ - build/cmake_modules/**
+ - daemon/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Win32/**
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
+
+jobs:
+ build:
+ name: Build
+ runs-on: windows-latest
+ env:
+ boost_path: ${{ github.workspace }}\boost_1_83_0
+ openssl_path: ${{ github.workspace }}\openssl_3_2_1
+
+ strategy:
+ fail-fast: false
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Build and install zlib
+ run: |
+ powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)"
+ powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings
+ set BUILD_TYPE=Debug
+ ./install_zlib.bat
+ set BUILD_TYPE=Release
+ ./install_zlib.bat
+ del install_zlib.bat
+
+ - name: Install Boost
+ run: |
+ powershell -Command "(Start-BitsTransfer -Source https://sourceforge.net/projects/boost/files/boost-binaries/1.83.0/boost_1_83_0-msvc-14.3-64.exe/download -Destination boost_1_83_0-msvc-14.3-64.exe)"
+ ./boost_1_83_0-msvc-14.3-64.exe /DIR="${{env.boost_path}}" /VERYSILENT /SUPPRESSMSGBOXES /SP-
+
+ - name: Install OpenSSL
+ run: |
+ powershell -Command "(Start-BitsTransfer -Source https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -Destination Win64OpenSSL-3_2_1.exe)"
+ ./Win64OpenSSL-3_2_1.exe /DIR="${{env.openssl_path}}" /TASKS="copytobin" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
+
+ - name: Make copy of the OpenSSL libraries for CMake
+ run: |
+ dir ${{ github.workspace }}
+ dir ${{env.openssl_path}}\lib\VC
+ dir ${{env.openssl_path}}\lib\VC\x64\
+ dir ${{env.openssl_path}}\lib\VC\x64\MTd\
+ xcopy /s /y "${{env.openssl_path}}\lib\VC\x64\MTd" "${{env.openssl_path}}\lib"
+
+ - name: Configure
+ working-directory: build
+ run: cmake -DBoost_ROOT="${{env.boost_path}}" -DOPENSSL_ROOT_DIR="${{env.openssl_path}}" -DWITH_STATIC=ON .
+
+ - name: Build
+ working-directory: build
+ run: cmake --build . --config Debug -- -m
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: i2pd-msvc
+ path: build/Debug/i2pd.*
+
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build-windows.yml
^
|
@@ -1,6 +1,25 @@
name: Build on Windows
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build-windows.yml
+ - build/CMakeLists.txt
+ - build/cmake_modules/**
+ - daemon/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Win32/**
+ - Makefile
+ - Makefile.mingw
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
defaults:
run:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/.github/workflows/build.yml
^
|
@@ -1,6 +1,24 @@
name: Build on Ubuntu
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '*'
+ paths:
+ - .github/workflows/build.yml
+ - build/CMakeLists.txt
+ - build/cmake_modules/**
+ - daemon/**
+ - i18n/**
+ - libi2pd/**
+ - libi2pd_client/**
+ - Makefile
+ - Makefile.linux
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - '*'
jobs:
build-make:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/ChangeLog
^
|
@@ -1,6 +1,67 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
+## [2.51.0] - 2024-04-06
+### Added
+- Non-blocking mode for UDP sockets
+- Set SSU2 socket buffer size based on bandwidth limit
+- Encrypted tunnel tests
+- Support for multiple UDP server tunnels on one destination
+- Publish medium congestion indication
+- Local domain sockets for SOCKS proxy upstream
+- Tunnel status "declined" in web console
+- SAM error reply "Incompatible crypto" if remote destination has incompatible crypto
+- Reduce amount of traffic by handling local message drops
+- Keep SSU2 socket open even if it fails to bind
+- Lower SSU2 resend traffic spikes
+- Expiration for messages in SSU2 send queue
+- Use EWMA for stream RTT estimation
+- Request choking delay if too many NACKs in stream
+- Allow 0ms latency for tunnel
+- Randomize tunnels selection for tests
+### Changed
+- Upstream SOCKS proxy from SOCKS4 to SOCKS5
+- Transit tunnels limit to 4 bytes. Default value to 10K
+- Reply CANT_REACH_PEER if connect to ourselves in SAM
+- Don't send already expired I2NP messages
+- Use monotonic timer to measure tunnel test latency
+- Standard NTCP2 frame doesn't exceed 16K
+- Always send request through tunnels in case of restricted routes
+- Don't delete connected routers from NetDb
+- Send lookup reply directly to reply tunnel gateway if possible
+- Reduce unreachable router ban interval to 8 minutes
+- Don't request banned routers / don't try to connect to unreachable router
+- Consider 'M' routers as low bandwidth
+- Limit minimal received SSU2 packet size to 40 bytes
+- Bob picks peer test session only if Charlie's address supports peer testing
+- Reject peer test msg 2 if peer testing is not supported
+- Don't request termination if SSU2 session was not established
+- Set maximum SSU2 queue size depending on RTT value
+- New streaming RTT calculation algorithm
+- Don't double initial RTO for streams when changing tunnels
+- Restore failed tunnel if test or data for inbound tunnel received
+- Don't fail last remaining tunnel in pool
+- Publish LeasetSet again if local destination was not ready or no tunnels
+- Make more attempts to pick high bandwidth hop for client tunnel
+- Reduced SSU2 session termination timeout to 165 seconds
+- Reseeds list
+### Fixed
+- ECIESx25519 symmetric key tagset early expiration
+- Encrypted LeaseSet lookup
+- Outbound tunnel build fails if it's endpoint is the same as reply tunnel gateway
+- I2PControl RouterManager returns invalid JSON when unknown params are passed
+- Mix of data between different UDP sessions on the same server
+- TARGET_OS_SIMULATOR check
+- Handling of "reservedrange" param
+- New NTCP2 session gets teminated upon termination of old one
+- New SSU2 session gets teminated upon termination of old one
+- Peer test to non-supporting router
+- Streaming ackThrough off 1 if number of NACKs exceeds 255
+- Race condition in ECIESx25519 tags table
+- Good tunnel becomes failed
+- Crash when packet comes to terminated stream
+- Stream hangs during LeaseSet update
+
## [2.50.2] - 2024-01-06
###Fixed
- Crash with OpenSSL 3.2.0
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/Makefile.bsd
^
|
@@ -6,7 +6,12 @@
## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
## -std=c++11. If you want to remove this variable please do so in a way that allows setting
## custom FLAGS to work at build-time.
-NEEDED_CXXFLAGS = -std=c++11
+CXXVER := $(shell $(CXX) -dumpversion)
+ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1
+ NEEDED_CXXFLAGS = -std=c++11
+else # newer versions support C++17
+ NEEDED_CXXFLAGS = -std=c++17
+endif
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/Win32/Win32App.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -145,7 +145,7 @@
s << bytes << " Bytes\n";
}
- static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing)
+ static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
{
switch (status)
{
@@ -158,18 +158,24 @@
};
if (testing)
s << " (Test)";
- if (i2p::context.GetError () != eRouterErrorNone)
+ if (error != eRouterErrorNone)
{
- switch (i2p::context.GetError ())
+ switch (error)
{
case eRouterErrorClockSkew:
- s << " - Clock skew";
+ s << " - " << tr("Clock skew");
break;
case eRouterErrorOffline:
- s << " - Offline";
+ s << " - " << tr("Offline");
break;
case eRouterErrorSymmetricNAT:
- s << " - Symmetric NAT";
+ s << " - " << tr("Symmetric NAT");
+ break;
+ case eRouterErrorFullConeNAT:
+ s << " - " << tr("Full cone NAT");
+ break;
+ case eRouterErrorNoDescriptors:
+ s << " - " << tr("No Descriptors");
break;
default: ;
}
@@ -180,11 +186,11 @@
{
s << "\n";
s << "Status: ";
- ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ());
+ ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
if (i2p::context.SupportsV6 ())
{
s << " / ";
- ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ());
+ ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
}
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
|
[-]
[+]
|
Added |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/contrib/certificates/reseed/admin_at_stormycloud.org.crt
^
|
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF1zCCA7+gAwIBAgIRAMDqFR09Xuj8ZUu+oetSvAEwDQYJKoZIhvcNAQELBQAw
+dTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
+ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxHjAcBgNVBAMM
+FWFkbWluQHN0b3JteWNsb3VkLm9yZzAeFw0yNDAxMjUxNDE1MzBaFw0zNDAxMjUx
+NDE1MzBaMHUxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx
+HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR4w
+HAYDVQQDDBVhZG1pbkBzdG9ybXljbG91ZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDbGX+GikPzQXr9zvkrhfO9g0l49KHLNQhUKYqd6T+PfnGo
+Fm0d3ZZVVQZ045vWgroOXDGGZZWxUIlb2inRaR2DF1TxN3pPYt59RgY9ZQ9+TL7o
+isY91krCRygY8EcAmHIjlfZQ9dBVcL7CfyT0MYZA5Efee9+NDHSewTfQP9T2faIE
+83Fcyd93a2mIHYjKUbJnojng/wgsy8srbsEuuTok4MIQmDj+B5nz+za2FgI0/ydh
+srlMt4aGJF4/DIem9z9d0zBCOkwrmtFIzjNF1mOSA8ES4m5YnKA/y9rZlRidLPGu
+prbXhPVnqHeOnHMz2QCw1wbVo504kl0bMqyEz2tVWsO9ep7iZoQs2xkFAEaegYNT
+QLUpwVGlyuq3wXXwopFRffOSimGSazICwWI6j+K0pOtgefNJaWrqKYvtkj1SbK2L
+LBNUIENz6VnB7KPRckuX6zxC8PpOiBK9BcftfO+xAz/wC6qq3riBPw30KKSym0nC
+Zp5KciDn4Phtw9PGq8Bkl8SyWl0jtFnfTB1tzJkisf2qKcNHaFTEe2JW763YLbh/
+AU+8X8evFu40qLgvOgKoyy5DLy6i8zetX+3t9K0Fxt9+Vzzq6lm5V/RS8iIPPn+M
+q1/3Z5kD0KQBG9h/Gl8BH+lB71ZxPAOZ3SMu8DJZcxBLVmDWqQPCr5CKnoz0swID
+AQABo2IwYDAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG
+AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHgYDVR0OBBcEFWFkbWluQHN0b3JteWNs
+b3VkLm9yZzANBgkqhkiG9w0BAQsFAAOCAgEARWOJ69vTHMneSXYscha+4Ytjg0RM
+faewJNEGj8qy/Qvh9si2bWYNPRK6BlbHFS7pRYBLAnhaeLBGVv1CCR6GUMMe74zQ
+UuMeAoWU6qMDmB3GfYoZJh8sIxpwHqyJeTdeccRbZ4sX4F6u3IHPXYiU/AgbYqH7
+pYXQg2lCjXZYaDFAlEf5SlYUDOhhXe5kR8Edhlrsu32/JzA1DQK0JjxKCBp+DQmA
+ltdOpQtAg03fHP4ssdj7VvjIDl28iIlATwBvHrdNm7T0tYWn6TWhvxbRqvfTxfaH
+MvxnPdIJwNP4/9TyQkwjwHb1h+ucho3CnxI/AxspdOvT1ElMhP6Ce6rcS9pk11Rl
+x0ChsqpWwDg7KYpg0qZFSKCTBp4zBq9xoMJ6BQcgMfyl736WbsCzFTEyfifp8beg
+NxUa/Qk7w7cuSPGyMIKNOmOR7FLlFbtocy8sXVsUQdqnp/edelufdNe39U9uNtY6
+yoXI9//Tc6NgOwy2Oyia0slZ5qHRkB7e4USXMRzJ3p4q9eCVKjAJs81Utp7O2U+9
+vhbhwWP8CAnNTT1E5WS6EKtfrdqF7wjkV+noPGLDGmrXi01J1fSMAjMfVO+7/LOL
+UN+G4ybKWnEhhOO27yidN8Xx6UrCS23DBlPPQAeA74dTsTExiOxf1o1EXzcQiMyO
+LAj3/Ojbi1xkWhI=
+-----END CERTIFICATE-----
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/contrib/rpm/i2pd-git.spec
^
|
@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
-Version: 2.50.2
+Version: 2.51.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@@ -144,6 +144,9 @@
%changelog
+* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
+- update to 2.51.0
+
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/contrib/rpm/i2pd.spec
^
|
@@ -1,5 +1,5 @@
Name: i2pd
-Version: 2.50.2
+Version: 2.51.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -142,6 +142,9 @@
%changelog
+* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
+- update to 2.51.0
+
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/daemon/Daemon.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -160,6 +160,10 @@
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);
+
+ bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved);
+ i2p::transport::transports.SetCheckReserved(checkReserved);
+
i2p::context.Init ();
i2p::transport::InitTransports ();
@@ -175,7 +179,7 @@
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
- uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
+ uint32_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels"))
transitTunnels *= 2; // double default number of transit tunnels for floodfill
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels);
@@ -298,12 +302,10 @@
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
- bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: Starting Transports");
if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
- i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu2);
if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started");
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/daemon/HTTPServer.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -133,23 +133,19 @@
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
{
std::string state, stateText;
- switch (eState) {
+ switch (eState)
+ {
case i2p::tunnel::eTunnelStateBuildReplyReceived :
case i2p::tunnel::eTunnelStatePending : state = "building"; break;
- case i2p::tunnel::eTunnelStateBuildFailed :
- case i2p::tunnel::eTunnelStateTestFailed :
+ case i2p::tunnel::eTunnelStateBuildFailed : state = "failed"; stateText = "declined"; break;
+ case i2p::tunnel::eTunnelStateTestFailed : state = "failed"; stateText = "test failed"; break;
case i2p::tunnel::eTunnelStateFailed : state = "failed"; break;
case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break;
case i2p::tunnel::eTunnelStateEstablished : state = "established"; break;
default: state = "unknown"; break;
}
-
- if (state == "building") stateText = tr("building");
- else if (state == "failed") stateText = tr("failed");
- else if (state == "expiring") stateText = tr("expiring");
- else if (state == "established") stateText = tr("established");
- else stateText = tr("unknown");
-
+ if (stateText.empty ()) stateText = tr(state);
+
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, ";
ShowTraffic(s, bytes);
s << "\r\n";
@@ -776,7 +772,7 @@
s << " <a class=\"button" << (loglevel == eLogInfo ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogDebug ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
- uint16_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels ();
+ uint32_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels ();
s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n";
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/daemon/HTTPServer.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -25,7 +25,7 @@
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds
- const int TRANSIT_TUNNELS_LIMIT = 65535;
+ const int TRANSIT_TUNNELS_LIMIT = 1000000;
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
{
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/daemon/I2PControl.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -338,10 +338,11 @@
{
for (auto it = params.begin (); it != params.end (); it++)
{
- if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first);
auto it1 = m_RouterManagerHandlers.find (it->first);
- if (it1 != m_RouterManagerHandlers.end ()) {
+ if (it1 != m_RouterManagerHandlers.end ())
+ {
+ if (it != params.begin ()) results << ",";
(this->*(it1->second))(results);
} else
LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/debian/changelog
^
|
@@ -1,8 +1,14 @@
-i2pd (2.50.2) unstable; urgency=medium
+i2pd (2.51.0-1) unstable; urgency=medium
+
+ * updated to version 2.51.0/0.9.62
+
+ -- orignal <orignal@i2pmail.org> Sat, 06 Apr 2024 16:00:00 +0000
+
+i2pd (2.50.2-1) unstable; urgency=medium
* updated to version 2.50.2/0.9.61
--- orignal <orignal@i2pmail.org> Sat, 06 Jan 2024 16:00:00 +0000
+ -- orignal <orignal@i2pmail.org> Sat, 06 Jan 2024 16:00:00 +0000
i2pd (2.50.1-1) unstable; urgency=medium
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Config.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -77,7 +77,7 @@
limits.add_options()
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
- ("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)")
+ ("limits.transittunnels", value<uint32_t>()->default_value(10000), "Maximum active transit tunnels (default:10000)")
("limits.zombies", value<double>()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
@@ -222,8 +222,7 @@
"https://www2.mk16.de/,"
"https://i2p.ghativega.in/,"
"https://i2p.novg.net/,"
- "https://reseed.is.prestium.org/,"
- "https://reseed.us.prestium.org/"
+ "https://reseed.stormycloud.org/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/,"
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Datagram.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,7 +19,7 @@
namespace datagram
{
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
- m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
+ m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip)
{
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
@@ -119,19 +119,79 @@
void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
- if (m_RawReceiver)
- m_RawReceiver (fromPort, toPort, buf, len);
+ auto r = FindRawReceiver(toPort);
+
+ if (r)
+ r (fromPort, toPort, buf, len);
else
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
}
+ void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port)
+ {
+ std::lock_guard<std::mutex> lock(m_ReceiversMutex);
+ m_ReceiversByPorts[port] = receiver;
+ if (!m_DefaultReceiver) {
+ m_DefaultReceiver = receiver;
+ m_DefaultReceiverPort = port;
+ }
+ }
+
+ void DatagramDestination::ResetReceiver (uint16_t port)
+ {
+ std::lock_guard<std::mutex> lock(m_ReceiversMutex);
+ m_ReceiversByPorts.erase (port);
+ if (m_DefaultReceiverPort == port) {
+ m_DefaultReceiver = nullptr;
+ m_DefaultReceiverPort = 0;
+ }
+ }
+
+
+ void DatagramDestination::SetRawReceiver (const RawReceiver& receiver, uint16_t port)
+ {
+ std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
+ m_RawReceiversByPorts[port] = receiver;
+ if (!m_DefaultRawReceiver) {
+ m_DefaultRawReceiver = receiver;
+ m_DefaultRawReceiverPort = port;
+ }
+ }
+
+ void DatagramDestination::ResetRawReceiver (uint16_t port)
+ {
+ std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
+ m_RawReceiversByPorts.erase (port);
+ if (m_DefaultRawReceiverPort == port) {
+ m_DefaultRawReceiver = nullptr;
+ m_DefaultRawReceiverPort = 0;
+ }
+ }
+
+
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
- Receiver r = m_Receiver;
+ Receiver r = nullptr;
auto itr = m_ReceiversByPorts.find(port);
if (itr != m_ReceiversByPorts.end())
r = itr->second;
+ else {
+ r = m_DefaultReceiver;
+ }
+ return r;
+ }
+
+ DatagramDestination::RawReceiver DatagramDestination::FindRawReceiver(uint16_t port)
+ {
+ std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
+ RawReceiver r = nullptr;
+ auto itr = m_RawReceiversByPorts.find(port);
+ if (itr != m_RawReceiversByPorts.end())
+ r = itr->second;
+ else {
+ r = m_DefaultRawReceiver;
+ }
return r;
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Datagram.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -126,14 +126,12 @@
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
- void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
- void ResetReceiver () { m_Receiver = nullptr; };
- void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; };
- void ResetReceiver (uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); };
+ void SetReceiver (const Receiver& receiver, uint16_t port);
+ void ResetReceiver (uint16_t port);
- void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
- void ResetRawReceiver () { m_RawReceiver = nullptr; };
+ void SetRawReceiver (const RawReceiver& receiver, uint16_t port);
+ void ResetRawReceiver (uint16_t port);
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
@@ -150,20 +148,26 @@
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
- /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
Receiver FindReceiver(uint16_t port);
+ RawReceiver FindRawReceiver(uint16_t port);
private:
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
- Receiver m_Receiver; // default
- RawReceiver m_RawReceiver; // default
- bool m_Gzip; // gzip compression of data messages
+
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
+
+ Receiver m_DefaultReceiver;
+ RawReceiver m_DefaultRawReceiver;
+ uint16_t m_DefaultReceiverPort;
+ uint16_t m_DefaultRawReceiverPort;
std::mutex m_ReceiversMutex;
- std::map<uint16_t, Receiver> m_ReceiversByPorts;
+ std::mutex m_RawReceiversMutex;
+ std::unordered_map<uint16_t, Receiver> m_ReceiversByPorts;
+ std::unordered_map<uint16_t, RawReceiver> m_RawReceiversByPorts;
+ bool m_Gzip; // gzip compression of data messages
i2p::data::GzipInflator m_Inflator;
std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
std::vector<uint8_t> m_From, m_Signature;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Destination.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -367,9 +367,12 @@
HandleDataMessage (payload, len);
break;
case eI2NPDeliveryStatus:
- // we assume tunnel tests non-encrypted
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
break;
+ case eI2NPTunnelTest:
+ if (m_Pool)
+ m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET));
+ break;
case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (payload, len);
break;
@@ -407,6 +410,7 @@
}
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
+ std::shared_ptr<LeaseSetRequest> request;
switch (buf[DATABASE_STORE_TYPE_OFFSET])
{
case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
@@ -462,34 +466,59 @@
case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
{
auto it2 = m_LeaseSetRequests.find (key);
- if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
- {
- auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
- it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
- if (ls2->IsValid () && !ls2->IsExpired ())
- {
- leaseSet = ls2;
- std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
- m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
- m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
+ if (it2 != m_LeaseSetRequests.end ())
+ {
+ request = it2->second;
+ m_LeaseSetRequests.erase (it2);
+ if (request->requestedBlindedKey)
+ {
+ auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
+ request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
+ if (ls2->IsValid () && !ls2->IsExpired ())
+ {
+ leaseSet = ls2;
+ std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
+ m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
+ m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
+ }
+ else
+ LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
}
else
- LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
+ {
+ // publishing verification doesn't have requestedBlindedKey
+ auto localLeaseSet = GetLeaseSetMt ();
+ if (localLeaseSet->GetStoreHash () == key)
+ {
+ auto ls = std::make_shared<i2p::data::LeaseSet2> (i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2,
+ localLeaseSet->GetBuffer (), localLeaseSet->GetBufferLen (), false);
+ leaseSet = ls;
+ }
+ else
+ LogPrint (eLogWarning, "Destination: Encrypted LeaseSet2 received for request without blinded key");
+ }
}
else
- LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
+ LogPrint (eLogWarning, "Destination: Couldn't find request for encrypted LeaseSet2");
break;
}
default:
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
}
- auto it1 = m_LeaseSetRequests.find (key);
- if (it1 != m_LeaseSetRequests.end ())
+ if (!request)
+ {
+ auto it1 = m_LeaseSetRequests.find (key);
+ if (it1 != m_LeaseSetRequests.end ())
+ {
+ request = it1->second;
+ m_LeaseSetRequests.erase (it1);
+ }
+ }
+ if (request)
{
- it1->second->requestTimeoutTimer.cancel ();
- if (it1->second) it1->second->Complete (leaseSet);
- m_LeaseSetRequests.erase (it1);
+ request->requestTimeoutTimer.cancel ();
+ request->Complete (leaseSet);
}
}
@@ -502,38 +531,43 @@
if (it != m_LeaseSetRequests.end ())
{
auto request = it->second;
- bool found = false;
- if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
+ for (int i = 0; i < num; i++)
{
- 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))
{
- 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
- }
+ 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)
- {
- LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
- if (SendLeaseSetRequest (key, floodfill, request))
- found = true;
- }
- }
- if (!found)
- {
- LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
- request->Complete (nullptr);
- m_LeaseSetRequests.erase (key);
}
+ SendNextLeaseSetRequest (key, request);
}
else
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
}
+ void LeaseSetDestination::SendNextLeaseSetRequest (const i2p::data::IdentHash& key,
+ std::shared_ptr<LeaseSetRequest> request)
+ {
+ bool found = false;
+ if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
+ {
+ auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
+ if (floodfill)
+ {
+ LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
+ if (SendLeaseSetRequest (key, floodfill, request))
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
+ request->Complete (nullptr);
+ m_LeaseSetRequests.erase (key);
+ }
+ }
+
void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID)
{
if (msgID == m_PublishReplyToken)
@@ -578,12 +612,7 @@
shared_from_this (), std::placeholders::_1));
return;
}
- if (!m_Pool->GetInboundTunnels ().size () || !m_Pool->GetOutboundTunnels ().size ())
- {
- LogPrint (eLogError, "Destination: Can't publish LeaseSet. Destination is not ready");
- return;
- }
- auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
+ auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetStoreHash (), m_ExcludedFloodfills);
if (!floodfill)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
@@ -594,26 +623,39 @@
auto inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!outbound || !inbound)
{
- LogPrint (eLogInfo, "Destination: No compatible tunnels with ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another floodfill");
- m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
- floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
- if (floodfill)
- {
- outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
- if (outbound)
+ if (!m_Pool->GetInboundTunnels ().empty () && !m_Pool->GetOutboundTunnels ().empty ())
+ {
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Destination.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -176,6 +176,7 @@
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
+ void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets ();
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/ECIESX25519AEADRatchetSession.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -117,6 +117,12 @@
return session->HandleNextMessage (buf, len, shared_from_this (), index);
}
+ bool ReceiveRatchetTagSet::IsSessionTerminated () const
+ {
+ return !m_Session || m_Session->IsTerminated ();
+ }
+
+
SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
@@ -857,7 +863,7 @@
payloadLen += msg->GetPayloadLength () + 13;
if (m_Destination) payloadLen += 32;
}
- if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
+ if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASESET_CONFIRMATION_TIMEOUT)
{
// resubmit non-confirmed LeaseSet
SetLeaseSetUpdateStatus (eLeaseSetUpdated);
@@ -1148,7 +1154,7 @@
return len;
}
- std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
+ std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<I2NPMessage> msg, const uint8_t * key, uint64_t tag)
{
auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128);
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
@@ -1168,10 +1174,16 @@
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
+ if (msg->onDrop)
+ {
+ // move onDrop to the wrapping I2NP messages
+ m->onDrop = msg->onDrop;
+ msg->onDrop = nullptr;
+ }
return m;
}
- std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey)
+ std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<I2NPMessage> msg, const uint8_t * routerPublicKey)
{
// Noise_N, we are Alice, routerPublicKey is Bob's
i2p::crypto::NoiseSymmetricState noiseState;
@@ -1205,6 +1217,12 @@
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
+ if (msg->onDrop)
+ {
+ // move onDrop to the wrapping I2NP messages
+ m->onDrop = msg->onDrop;
+ msg->onDrop = nullptr;
+ }
return m;
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/ECIESX25519AEADRatchetSession.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2021, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -86,7 +86,8 @@
virtual bool IsIndexExpired (int index) const;
virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
-
+ virtual bool IsSessionTerminated () const;
+
private:
int m_TrimBehindIndex = 0;
@@ -101,9 +102,10 @@
SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key);
- bool IsIndexExpired (int index) const { return false; };
- bool HandleNextMessage (uint8_t * buf, size_t len, int index);
-
+ bool IsIndexExpired (int index) const override { return false; };
+ bool HandleNextMessage (uint8_t * buf, size_t len, int index) override;
+ bool IsSessionTerminated () const override { return false; }
+
private:
GarlicDestination * m_Destination;
@@ -245,8 +247,8 @@
i2p::crypto::NoiseSymmetricState m_CurrentNoiseState;
};
- std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
- std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey);
+ std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<I2NPMessage> msg, const uint8_t * key, uint64_t tag);
+ std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<I2NPMessage> msg, const uint8_t * routerPublicKey);
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/FS.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -9,6 +9,11 @@
#include <algorithm>
#include <boost/filesystem.hpp>
+#if defined(MAC_OSX)
+#include <boost/system/system_error.hpp>
+#include <TargetConditionals.h>
+#endif
+
#ifdef _WIN32
#include <shlobj.h>
#include <windows.h>
@@ -251,8 +256,22 @@
auto p = root + i2p::fs::dirSep + prefix1 + chars[i];
if (boost::filesystem::exists(p))
continue;
- if (boost::filesystem::create_directory(p))
+#if TARGET_OS_SIMULATOR
+ // ios simulator fs says it is case sensitive, but it is not
+ boost::system::error_code ec;
+ if (boost::filesystem::create_directory(p, ec))
+ continue;
+ switch (ec.value()) {
+ case boost::system::errc::file_exists:
+ case boost::system::errc::success:
+ continue;
+ default:
+ throw boost::system::system_error( ec, __func__ );
+ }
+#else
+ if (boost::filesystem::create_directory(p))
continue; /* ^ throws exception on failure */
+#endif
return false;
}
return true;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Garlic.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -80,7 +80,7 @@
void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts)
{
- if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT)
+ if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASESET_CONFIRMATION_TIMEOUT)
{
if (GetOwner ())
GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID);
@@ -232,7 +232,7 @@
if (GetOwner ())
{
// resubmit non-confirmed LeaseSet
- if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
+ if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASESET_CONFIRMATION_TIMEOUT)
{
SetLeaseSetUpdateStatus (eLeaseSetUpdated);
SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed
@@ -887,8 +887,7 @@
}
else
{
- auto session = it->second.tagset->GetSession ();
- if (!session || session->IsTerminated())
+ if (it->second.tagset->IsSessionTerminated ())
{
it = m_ECIESx25519Tags.erase (it);
numExpiredTags++;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Garlic.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -50,7 +50,7 @@
const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes
const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes
const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds
- const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
+ const int LEASESET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds
const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used
@@ -221,7 +221,7 @@
struct ECIESX25519AEADRatchetIndexTagset
{
int index;
- ReceiveRatchetTagSetPtr tagset;
+ ReceiveRatchetTagSetPtr tagset; // null if used
};
class GarlicDestination: public i2p::data::LocalDestination
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/I2NPProtocol.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -72,11 +72,15 @@
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
}
- bool I2NPMessage::IsExpired () const
+ bool I2NPMessage::IsExpired (uint64_t ts) const
{
- auto ts = i2p::util::GetMillisecondsSinceEpoch ();
auto exp = GetExpiration ();
return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future
+ }
+
+ bool I2NPMessage::IsExpired () const
+ {
+ return IsExpired (i2p::util::GetMillisecondsSinceEpoch ());
}
std::shared_ptr<I2NPMessage> CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID)
@@ -111,6 +115,17 @@
return newMsg;
}
+ std::shared_ptr<I2NPMessage> CreateTunnelTestMsg (uint32_t msgID)
+ {
+ auto m = NewI2NPShortMessage ();
+ uint8_t * buf = m->GetPayload ();
+ htobe32buf (buf + TUNNEL_TEST_MSGID_OFFSET, msgID);
+ htobe64buf (buf + TUNNEL_TEST_TIMESTAMP_OFFSET, i2p::util::GetMonotonicMicroseconds ());
+ m->len += TUNNEL_TEST_SIZE;
+ m->FillI2NPMessageHeader (eI2NPTunnelTest);
+ return m;
+ }
+
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
{
auto m = NewI2NPShortMessage ();
@@ -369,10 +384,20 @@
if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
{
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
- if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
+ if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
+ {
+ LogPrint (eLogWarning, "I2NP: Failed to decrypt tunnel build record");
+ return false;
+ }
+ if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32) && // if next ident is now ours
+ !(clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG)) // and not endpoint
+ {
+ LogPrint (eLogWarning, "I2NP: Next ident is ours in tunnel build record");
+ return false;
+ }
uint8_t retCode = 0;
// replace record to reply
- if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ())
+ if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < CONGESTION_LEVEL_FULL)
{
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
@@ -577,16 +602,24 @@
memcpy (ivKey, noiseState.m_CK + 32, 32);
}
else
+ {
+ if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours
+ {
+ LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record");
+ return;
+ }
memcpy (ivKey, noiseState.m_CK , 32);
+ }
// check if we accept this tunnel
+ std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
uint8_t retCode = 0;
- if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ())
+ if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL)
retCode = 30;
if (!retCode)
{
// create new transit tunnel
- auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
+ transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
@@ -620,11 +653,22 @@
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
}
// send reply
+ auto onDrop = [transitTunnel]()
+ {
+ if (transitTunnel)
+ {
+ auto t = transitTunnel->GetCreationTime ();
+ if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT)
+ // make transit tunnel expired
+ transitTunnel->SetCreationTime (t - i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT);
+ }
+ };
if (isEndpoint)
{
auto replyMsg = NewI2NPShortMessage ();
replyMsg->Concat (buf, len);
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
+ if (transitTunnel) replyMsg->onDrop = onDrop;
if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
{
@@ -642,15 +686,21 @@
uint32_t tunnelID = bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET);
auto tunnel = i2p::tunnel::tunnels.GetTunnel (tunnelID);
if (tunnel)
+ {
tunnel->SendTunnelDataMsg (replyMsg);
+ tunnel->FlushTunnelDataMsgs ();
+ }
else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
}
}
else
- transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
- CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
- bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
+ {
+ auto msg = CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
+ bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
+ if (transitTunnel) msg->onDrop = onDrop;
+ transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, msg);
+ }
return;
}
record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
@@ -710,7 +760,11 @@
return msg;
}
else
- return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
+ {
+ auto newMsg = CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
+ if (msg->onDrop) newMsg->onDrop = msg->onDrop;
+ return newMsg;
+ }
}
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType,
@@ -827,6 +881,10 @@
i2p::context.ProcessDeliveryStatusMessage (msg);
break;
}
+ case eI2NPTunnelTest:
+ if (msg->from && msg->from->GetTunnelPool ())
+ msg->from->GetTunnelPool ()->ProcessTunnelTest (msg);
+ break;
case eI2NPVariableTunnelBuild:
case eI2NPTunnelBuild:
case eI2NPShortTunnelBuild:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/I2NPProtocol.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -13,6 +13,7 @@
#include <string.h>
#include <set>
#include <memory>
+#include <functional>
#include "Crypto.h"
#include "I2PEndian.h"
#include "Identity.h"
@@ -47,6 +48,11 @@
const size_t DELIVERY_STATUS_TIMESTAMP_OFFSET = DELIVERY_STATUS_MSGID_OFFSET + 4;
const size_t DELIVERY_STATUS_SIZE = DELIVERY_STATUS_TIMESTAMP_OFFSET + 8;
+ // TunnelTest
+ const size_t TUNNEL_TEST_MSGID_OFFSET = 0;
+ const size_t TUNNEL_TEST_TIMESTAMP_OFFSET = TUNNEL_TEST_MSGID_OFFSET + 4;
+ const size_t TUNNEL_TEST_SIZE = TUNNEL_TEST_TIMESTAMP_OFFSET + 8;
+
// DatabaseStore
const size_t DATABASE_STORE_KEY_OFFSET = 0;
const size_t DATABASE_STORE_TYPE_OFFSET = DATABASE_STORE_KEY_OFFSET + 32;
@@ -115,7 +121,8 @@
eI2NPVariableTunnelBuild = 23,
eI2NPVariableTunnelBuildReply = 24,
eI2NPShortTunnelBuild = 25,
- eI2NPShortTunnelBuildReply = 26
+ eI2NPShortTunnelBuildReply = 26,
+ eI2NPTunnelTest = 231
};
const uint8_t TUNNEL_BUILD_RECORD_GATEWAY_FLAG = 0x80;
@@ -138,9 +145,16 @@
class TunnelPool;
}
+ const int CONGESTION_LEVEL_MEDIUM = 70;
+ const int CONGESTION_LEVEL_HIGH = 90;
+ const int CONGESTION_LEVEL_FULL = 100;
+
const size_t I2NP_MAX_MESSAGE_SIZE = 62708;
const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096;
const size_t I2NP_MAX_MEDIUM_MESSAGE_SIZE = 16384;
+ const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_FACTOR = 3; // multiples of RTT
+ const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MIN = 200000; // in microseconds
+ const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX = 2000000; // in microseconds
const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT)
const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds
@@ -149,9 +163,11 @@
uint8_t * buf;
size_t len, offset, maxLen;
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
+ std::function<void ()> onDrop;
+ uint64_t enqueueTime; // monotonic microseconds
- I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
- offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
+ I2NPMessage (): buf (nullptr), len (I2NP_HEADER_SIZE + 2),
+ offset(2), maxLen (0), from (nullptr), enqueueTime (0) {}; // reserve 2 bytes for NTCP header
// header accessors
uint8_t * GetHeader () { return GetBuffer (); };
@@ -161,7 +177,9 @@
void SetMsgID (uint32_t msgID) { htobe32buf (GetHeader () + I2NP_HEADER_MSGID_OFFSET, msgID); };
uint32_t GetMsgID () const { return bufbe32toh (GetHeader () + I2NP_HEADER_MSGID_OFFSET); };
void SetExpiration (uint64_t expiration) { htobe64buf (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET, expiration); };
+ void SetEnqueueTime (uint64_t mts) { enqueueTime = mts; };
uint64_t GetExpiration () const { return bufbe64toh (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET); };
+ uint64_t GetEnqueueTime () const { return enqueueTime; };
void SetSize (uint16_t size) { htobe16buf (GetHeader () + I2NP_HEADER_SIZE_OFFSET, size); };
uint16_t GetSize () const { return bufbe16toh (GetHeader () + I2NP_HEADER_SIZE_OFFSET); };
void UpdateSize () { SetSize (GetPayloadLength ()); };
@@ -241,7 +259,6 @@
SetSize (len - offset - I2NP_HEADER_SIZE);
SetChks (0);
}
-
void ToNTCP2 ()
{
uint8_t * ntcp2 = GetNTCP2Header ();
@@ -252,6 +269,9 @@
void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0, bool checksum = true);
void RenewI2NPMessageHeader ();
bool IsExpired () const;
+ bool IsExpired (uint64_t ts) const; // in milliseconds
+
+ void Drop () { if (onDrop) { onDrop (); onDrop = nullptr; }; }
};
template<int sz>
@@ -271,6 +291,7 @@
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg);
+ std::shared_ptr<I2NPMessage> CreateTunnelTestMsg (uint32_t msgID);
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID);
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);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Log.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -87,8 +87,8 @@
Log ();
~Log ();
- LogType GetLogType () { return m_Destination; };
- LogLevel GetLogLevel () { return m_MinLevel; };
+ LogType GetLogType () const { return m_Destination; };
+ LogLevel GetLogLevel () const { return m_MinLevel; };
void Start ();
void Stop ();
@@ -160,6 +160,11 @@
} // log
} // i2p
+inline bool CheckLogLevel (LogLevel level) noexcept
+{
+ return level <= i2p::log::Logger().GetLogLevel ();
+}
+
/** internal usage only -- folding args array to single string */
template<typename TValue>
void LogPrint (std::stringstream& s, TValue&& arg) noexcept
@@ -185,9 +190,7 @@
template<typename... TArgs>
void LogPrint (LogLevel level, TArgs&&... args) noexcept
{
- i2p::log::Log &log = i2p::log::Logger();
- if (level > log.GetLogLevel ())
- return;
+ if (!CheckLogLevel (level)) return;
// fold message to single string
std::stringstream ss;
@@ -200,7 +203,7 @@
auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), std::move(ss).str());
msg->tid = std::this_thread::get_id();
- log.Append(msg);
+ i2p::log::Logger().Append(msg);
}
/**
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/NTCP2.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,9 +19,10 @@
#include "RouterContext.h"
#include "Transports.h"
#include "NetDb.hpp"
-#include "NTCP2.h"
#include "HTTP.h"
#include "util.h"
+#include "Socks5.h"
+#include "NTCP2.h"
#if defined(__linux__) && !defined(_NETINET_IN_H)
#include <linux/in6.h>
@@ -373,13 +374,15 @@
m_Socket.close ();
transports.PeerDisconnected (shared_from_this ());
m_Server.RemoveNTCP2Session (shared_from_this ());
+ for (auto& it: m_SendQueue)
+ it->Drop ();
m_SendQueue.clear ();
SetSendQueueSize (0);
auto remoteIdentity = GetRemoteIdentity ();
if (remoteIdentity)
{
LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (),
- " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
+ " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated");
}
else
{
@@ -833,14 +836,19 @@
CreateNextReceivedBuffer (m_NextReceivedLen);
boost::system::error_code ec;
size_t moreBytes = m_Socket.available(ec);
- if (!ec && moreBytes >= m_NextReceivedLen)
- {
- // read and process message immediately if available
- moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec);
- HandleReceived (ec, moreBytes);
- }
+ if (!ec)
+ {
+ if (moreBytes >= m_NextReceivedLen)
+ {
+ // read and process message immediately if available
+ moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec);
+ HandleReceived (ec, moreBytes);
+ }
+ else
+ Receive ();
+ }
else
- Receive ();
+ LogPrint (eLogWarning, "NTCP2: Socket error: ", ec.message ());
}
else
{
@@ -866,8 +874,8 @@
{
if (ecode)
{
- if (ecode != boost::asio::error::operation_aborted)
- LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ());
+ if (ecode != boost::asio::error::operation_aborted)
+ LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ());
Terminate ();
}
else
@@ -1046,6 +1054,11 @@
macBuf = m_NextSendBuffer + paddingLen;
totalLen += paddingLen;
}
+ if (totalLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE)
+ {
+ LogPrint (eLogError, "NTCP2: Frame to send is too long ", totalLen);
+ return;
+ }
uint8_t nonce[12];
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers
@@ -1070,6 +1083,12 @@
delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr;
return;
}
+ if (payloadLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE)
+ {
+ LogPrint (eLogError, "NTCP2: Buffer to send is too long ", payloadLen);
+ delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr;
+ return;
+ }
// encrypt
uint8_t nonce[12];
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
@@ -1116,20 +1135,31 @@
if (!m_SendQueue.empty ())
{
std::vector<std::shared_ptr<I2NPMessage> > msgs;
+ auto ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t s = 0;
while (!m_SendQueue.empty ())
{
auto msg = m_SendQueue.front ();
+ if (!msg || msg->IsExpired (ts))
+ {
+ // drop null or expired message
+ if (msg) msg->Drop ();
+ m_SendQueue.pop_front ();
+ continue;
+ }
size_t len = msg->GetNTCP2Length ();
if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header
{
msgs.push_back (msg);
s += (len + 3);
m_SendQueue.pop_front ();
+ if (s >= NTCP2_SEND_AFTER_FRAME_SIZE)
+ break; // send frame right a way
}
else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE)
{
LogPrint (eLogError, "NTCP2: I2NP message of size ", len, " can't be sent. Dropped");
+ msg->Drop ();
m_SendQueue.pop_front ();
}
else
@@ -1145,7 +1175,12 @@
len -= 3;
if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero
size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100;
- if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3;
+ if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE)
+ {
+ int l = (int)NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3;
+ if (l <= 0) return 0;
+ paddingSize = l;
+ }
if (paddingSize > len) paddingSize = len;
if (paddingSize)
{
@@ -1154,7 +1189,7 @@
RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes));
m_NextPaddingSize = 0;
}
- paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize;
+ paddingSize = m_PaddingSizes[m_NextPaddingSize++] % (paddingSize + 1);
}
buf[0] = eNTCP2BlkPadding; // blk
htobe16buf (buf + 1, paddingSize); // size
@@ -1219,8 +1254,13 @@
void NTCP2Session::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
{
if (m_IsTerminated) return;
+ bool isSemiFull = m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE/2;
for (auto it: msgs)
- m_SendQueue.push_back (std::move (it));
+ if (isSemiFull && it->onDrop)
+ it->Drop (); // drop earlier because we can handle it
+ else
+ m_SendQueue.push_back (std::move (it));
+
if (!m_IsSending)
SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
@@ -1234,7 +1274,7 @@
void NTCP2Session::SendLocalRouterInfo (bool update)
{
- if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session
+ if (update || !IsOutgoing ()) // we send it in SessionConfirmed for outgoing session
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
}
@@ -1400,7 +1440,11 @@
void NTCP2Server::RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session)
{
if (session && session->GetRemoteIdentity ())
- m_NTCP2Sessions.erase (session->GetRemoteIdentity ()->GetIdentHash ());
+ {
+ auto it = m_NTCP2Sessions.find (session->GetRemoteIdentity ()->GetIdentHash ());
+ if (it != m_NTCP2Sessions.end () && it->second == session)
+ m_NTCP2Sessions.erase (it);
+ }
}
std::shared_ptr<NTCP2Session> NTCP2Server::FindNTCP2Session (const i2p::data::IdentHash& ident)
@@ -1490,7 +1534,7 @@
if (!ec)
{
LogPrint (eLogDebug, "NTCP2: Connected from ", ep);
- if (!i2p::util::net::IsInReservedRange(ep.address ()))
+ if (!i2p::transport::transports.IsInReservedRange(ep.address ()))
{
if (m_PendingIncomingSessions.emplace (ep.address (), conn).second)
{
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/NTCP2.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -28,6 +28,7 @@
{
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
+ const size_t NTCP2_SEND_AFTER_FRAME_SIZE = 16386; // send frame when exceeds this size
const size_t NTCP2_SESSION_REQUEST_MAX_SIZE = 287;
const size_t NTCP2_SESSION_CREATED_MAX_SIZE = 287;
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
@@ -266,8 +267,7 @@
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
- void AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
-
+
// timer
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/NetDb.cpp
^
|
@@ -106,7 +106,7 @@
{
i2p::util::SetThreadName("NetDB");
- uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
+ uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0;
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
int16_t profilesCleanupVariance = 0;
@@ -149,7 +149,7 @@
if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
- if (ts - lastManageRequest >= 15 || ts + 15 < lastManageRequest) // manage requests every 15 seconds
+ if (ts - lastManageRequest >= MANAGE_REQUESTS_INTERVAL || ts + MANAGE_REQUESTS_INTERVAL < lastManageRequest) // manage requests every 15 seconds
{
m_Requests.ManageRequests ();
lastManageRequest = ts;
@@ -165,13 +165,6 @@
lastManage = ts;
}
- if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT ||
- ts + i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT < lastDestinationCleanup)
- {
- i2p::context.CleanupDestination ();
- lastDestinationCleanup = ts;
- }
-
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) ||
ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup)
{
@@ -226,7 +219,8 @@
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
{
bool updated;
- AddRouterInfo (ident, buf, len, updated);
+ if (!AddRouterInfo (ident, buf, len, updated))
+ updated = false;
return updated;
}
@@ -240,7 +234,7 @@
{
bool wasFloodfill = r->IsFloodfill ();
{
- std::unique_lock<std::mutex> l(m_RouterInfosMutex);
+ std::lock_guard<std::mutex> l(m_RouterInfosMutex);
if (!r->Update (buf, len))
{
updated = false;
@@ -254,18 +248,20 @@
m_RouterInfos.erase (ident);
if (wasFloodfill)
{
- std::unique_lock<std::mutex> l(m_FloodfillsMutex);
+ std::lock_guard<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.Remove (r->GetIdentHash ());
}
m_Requests.RequestComplete (ident, nullptr);
return nullptr;
}
}
- LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
+ if (CheckLogLevel (eLogInfo))
+ LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
{
- LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
- std::unique_lock<std::mutex> l(m_FloodfillsMutex);
+ if (CheckLogLevel (eLogDebug))
+ LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
+ std::lock_guard<std::mutex> l(m_FloodfillsMutex);
if (wasFloodfill)
m_Floodfills.Remove (r->GetIdentHash ());
else if (r->IsEligibleFloodfill ())
@@ -279,7 +275,8 @@
}
else
{
- LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
+ if (CheckLogLevel (eLogDebug))
+ LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
updated = false;
}
}
@@ -291,18 +288,19 @@
{
bool inserted = false;
{
- std::unique_lock<std::mutex> l(m_RouterInfosMutex);
+ std::lock_guard<std::mutex> l(m_RouterInfosMutex);
inserted = m_RouterInfos.insert ({r->GetIdentHash (), r}).second;
}
if (inserted)
{
- LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
+ if (CheckLogLevel (eLogInfo))
+ LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
{
if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD ||
r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough
{
- std::unique_lock<std::mutex> l(m_FloodfillsMutex);
+ std::lock_guard<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.Insert (r);
}
else
@@ -325,7 +323,7 @@
bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len)
{
- std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
+ std::lock_guard<std::mutex> lock(m_LeaseSetsMutex);
bool updated = false;
auto it = m_LeaseSets.find(ident);
if (it != m_LeaseSets.end () && it->second->GetStoreType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
@@ -337,10 +335,11 @@
if(it->second->GetExpirationTime() < expires)
{
it->second->Update (buf, len, false); // signature is verified already
- LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32());
+ if (CheckLogLevel (eLogInfo))
+ LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32());
updated = true;
}
- else
+ else if (CheckLogLevel (eLogDebug))
LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32());
}
else
@@ -351,7 +350,8 @@
auto leaseSet = std::make_shared<LeaseSet> (buf, len, false); // we don't need leases in netdb
if (leaseSet->IsValid ())
{
- LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32());
+ if (CheckLogLevel (eLogInfo))
+ LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32());
m_LeaseSets[ident] = leaseSet;
updated = true;
}
@@ -366,7 +366,7 @@
auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb
if (leaseSet->IsValid ())
{
- std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
+ std::lock_guard<std::mutex> lock(m_LeaseSetsMutex);
auto it = m_LeaseSets.find(ident);
if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType ||
leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ())
@@ -375,7 +375,8 @@
i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ())
{
// TODO: implement actual update
- LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32());
+ if (CheckLogLevel (eLogInfo))
+ LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32());
m_LeaseSets[ident] = leaseSet;
return true;
}
@@ -393,7 +394,7 @@
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
{
- std::unique_lock<std::mutex> l(m_RouterInfosMutex);
+ std::lock_guard<std::mutex> l(m_RouterInfosMutex);
auto it = m_RouterInfos.find (ident);
if (it != m_RouterInfos.end ())
return it->second;
@@ -403,7 +404,7 @@
std::shared_ptr<LeaseSet> NetDb::FindLeaseSet (const IdentHash& destination) const
{
- std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
+ std::lock_guard<std::mutex> lock(m_LeaseSetsMutex);
auto it = m_LeaseSets.find (destination);
if (it != m_LeaseSets.end ())
return it->second;
@@ -437,7 +438,7 @@
auto r = FindRouter (ident);
if (r)
{
- std::unique_lock<std::mutex> l(m_RouterInfosMutex);
+ std::lock_guard<std::mutex> l(m_RouterInfosMutex);
r->ExcludeReachableTransports (transports);
}
}
@@ -527,7 +528,7 @@
void NetDb::VisitLeaseSets(LeaseSetVisitor v)
{
- std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
+ std::lock_guard<std::mutex> lock(m_LeaseSetsMutex);
for ( auto & entry : m_LeaseSets)
v(entry.first, entry.second);
}
@@ -543,7 +544,7 @@
void NetDb::VisitRouterInfos(RouterInfoVisitor v)
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/NetDbRequests.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -11,11 +11,23 @@
#include "Transports.h"
#include "NetDb.hpp"
#include "NetDbRequests.h"
+#include "ECIESX25519AEADRatchetSession.h"
namespace i2p
{
namespace data
{
+ RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
+ m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct),
+ m_CreationTime (i2p::util::GetSecondsSinceEpoch ()), m_LastRequestTime (0)
+ {
+ }
+
+ RequestedDestination::~RequestedDestination ()
+ {
+ if (m_RequestComplete) m_RequestComplete (nullptr);
+ }
+
std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
{
@@ -28,7 +40,7 @@
msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
if(router)
m_ExcludedPeers.insert (router->GetIdentHash ());
- m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
+ m_LastRequestTime = i2p::util::GetSecondsSinceEpoch ();
return msg;
}
@@ -37,7 +49,7 @@
auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers);
m_ExcludedPeers.insert (floodfill);
- m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
+ m_LastRequestTime = i2p::util::GetSecondsSinceEpoch ();
return msg;
}
@@ -74,15 +86,36 @@
}
- std::shared_ptr<RequestedDestination> NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete)
+ std::shared_ptr<RequestedDestination> NetDbRequests::CreateRequest (const IdentHash& destination,
+ bool isExploratory, bool direct, RequestedDestination::RequestComplete requestComplete)
{
// request RouterInfo directly
- auto dest = std::make_shared<RequestedDestination> (destination, isExploratory);
+ auto dest = std::make_shared<RequestedDestination> (destination, isExploratory, direct);
dest->SetRequestComplete (requestComplete);
{
- std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
- if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted
+ std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
+ auto ret = m_RequestedDestinations.emplace (destination, dest);
+ if (!ret.second) // not inserted
+ {
+ dest->SetRequestComplete (nullptr); // don't call requestComplete in destructor
+ if (requestComplete)
+ {
+ auto prev = ret.first->second->GetRequestComplete ();
+ if (prev) // if already set
+ ret.first->second->SetRequestComplete (
+ [requestComplete, prev](std::shared_ptr<RouterInfo> r)
+ {
+ prev (r); // call previous
+ requestComplete (r); // then new
+ });
+ else
+ ret.first->second->SetRequestComplete (requestComplete);
+ }
+ if (i2p::util::GetSecondsSinceEpoch () > ret.first->second->GetLastRequestTime () + MIN_REQUEST_TIME)
+ if (!SendNextRequest (ret.first->second)) // try next floodfill
+ m_RequestedDestinations.erase (ret.first); // delete request if failed
return nullptr;
+ }
}
return dest;
}
@@ -125,35 +158,10 @@
{
auto& dest = it->second;
bool done = false;
- if (ts < dest->GetCreationTime () + 60) // request is worthless after 1 minute
+ if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) // request becomes worthless
{
- if (ts > dest->GetCreationTime () + 5) // no response for 5 seconds
- {
- auto count = dest->GetExcludedPeers ().size ();
- if (!dest->IsExploratory () && count < 7)
- {
- auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
- auto outbound = pool->GetNextOutboundTunnel ();
- auto inbound = pool->GetNextInboundTunnel ();
- auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
- if (nextFloodfill && outbound && inbound)
- outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0,
- dest->CreateRequestMessage (nextFloodfill, inbound));
- else
- {
- done = true;
- if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels");
- if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels");
- if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills");
- }
- }
- else
- {
- if (!dest->IsExploratory ())
- LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts");
- done = true;
- }
- }
+ if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval
+ done = !SendNextRequest (dest);
}
else // delete obsolete request
done = true;
@@ -164,5 +172,62 @@
++it;
}
}
+
+ bool NetDbRequests::SendNextRequest (std::shared_ptr<RequestedDestination> dest)
+ {
+ if (!dest) return false;
+ bool ret = true;
+ auto count = dest->GetExcludedPeers ().size ();
+ if (!dest->IsExploratory () && count < MAX_NUM_REQUEST_ATTEMPTS)
+ {
+ auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
+ if (nextFloodfill)
+ {
+ bool direct = dest->IsDirect ();
+ if (direct && !nextFloodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
+ !i2p::transport::transports.IsConnected (nextFloodfill->GetIdentHash ()))
+ direct = false; // floodfill can't be reached directly
+ if (direct)
+ {
+ LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " directly");
+ auto msg = dest->CreateRequestMessage (nextFloodfill->GetIdentHash ());
+ msg->onDrop = [this, dest]() { this->SendNextRequest (dest); };
+ i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), msg);
+ }
+ else
+ {
+ auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
+ auto outbound = pool->GetNextOutboundTunnel ();
+ auto inbound = pool->GetNextInboundTunnel ();
+ if (nextFloodfill && outbound && inbound)
+ {
+ LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " through tunnels");
+ auto msg = dest->CreateRequestMessage (nextFloodfill, inbound);
+ msg->onDrop = [this, dest]() { this->SendNextRequest (dest); };
+ outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0,
+ i2p::garlic::WrapECIESX25519MessageForRouter (msg, nextFloodfill->GetIdentity ()->GetEncryptionPublicKey ()));
+ }
+ else
+ {
+ ret = false;
+ if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels");
+ if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels");
+ }
+ }
+ }
+ else
+ {
+ ret = false;
+ if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills");
+ }
+ }
+ else
+ {
+ if (!dest->IsExploratory ())
+ LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts");
+ ret = false;
+ }
+ return ret;
+ }
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/NetDbRequests.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -9,9 +9,10 @@
#ifndef NETDB_REQUESTS_H__
#define NETDB_REQUESTS_H__
+#include <inttypes.h>
#include <memory>
#include <set>
-#include <map>
+#include <unordered_map>
#include "Identity.h"
#include "RouterInfo.h"
@@ -19,27 +20,34 @@
{
namespace data
{
+ const size_t MAX_NUM_REQUEST_ATTEMPTS = 7;
+ const uint64_t MANAGE_REQUESTS_INTERVAL = 15; // in seconds
+ const uint64_t MIN_REQUEST_TIME = 5; // in seconds
+ const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS*MANAGE_REQUESTS_INTERVAL;
+
class RequestedDestination
{
public:
typedef std::function<void (std::shared_ptr<RouterInfo>)> RequestComplete;
- RequestedDestination (const IdentHash& destination, bool isExploratory = false):
- m_Destination (destination), m_IsExploratory (isExploratory), m_CreationTime (0) {};
- ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); };
+ RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true);
+ ~RequestedDestination ();
const IdentHash& GetDestination () const { return m_Destination; };
int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); };
const std::set<IdentHash>& GetExcludedPeers () { return m_ExcludedPeers; };
void ClearExcludedPeers ();
bool IsExploratory () const { return m_IsExploratory; };
+ bool IsDirect () const { return m_IsDirect; };
bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); };
uint64_t GetCreationTime () const { return m_CreationTime; };
+ uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
std::shared_ptr<I2NPMessage> CreateRequestMessage (std::shared_ptr<const RouterInfo>, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel);
std::shared_ptr<I2NPMessage> CreateRequestMessage (const IdentHash& floodfill);
void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; };
+ RequestComplete GetRequestComplete () const { return m_RequestComplete; };
bool IsRequestComplete () const { return m_RequestComplete != nullptr; };
void Success (std::shared_ptr<RouterInfo> r);
void Fail ();
@@ -47,9 +55,9 @@
private:
IdentHash m_Destination;
- bool m_IsExploratory;
+ bool m_IsExploratory, m_IsDirect;
std::set<IdentHash> m_ExcludedPeers;
- uint64_t m_CreationTime;
+ uint64_t m_CreationTime, m_LastRequestTime; // in seconds
RequestComplete m_RequestComplete;
};
@@ -60,15 +68,17 @@
void Start ();
void Stop ();
- std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
+ std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory,
+ bool direct = false, RequestedDestination::RequestComplete requestComplete = nullptr);
void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
void ManageRequests ();
-
+ bool SendNextRequest (std::shared_ptr<RequestedDestination> dest);
+
private:
mutable std::mutex m_RequestedDestinationsMutex;
- std::map<IdentHash, std::shared_ptr<RequestedDestination> > m_RequestedDestinations;
+ std::unordered_map<IdentHash, std::shared_ptr<RequestedDestination> > m_RequestedDestinations;
};
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Profiling.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -245,6 +245,15 @@
return profile;
}
+ bool IsRouterBanned (const IdentHash& identHash)
+ {
+ std::unique_lock<std::mutex> l(g_ProfilesMutex);
+ auto it = g_Profiles.find (identHash);
+ if (it != g_Profiles.end ())
+ return it->second->IsUnreachable ();
+ return false;
+ }
+
void InitProfilesStorage ()
{
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Profiling.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -35,7 +35,7 @@
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour)
const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes)
const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes)
- const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours)
+ const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes)
const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
class RouterProfile
@@ -87,6 +87,7 @@
};
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
+ bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles
void InitProfilesStorage ();
void DeleteObsoleteProfiles ();
void SaveProfiles ();
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Reseed.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -26,6 +26,7 @@
#include "HTTP.h"
#include "util.h"
#include "Config.h"
+#include "Socks5.h"
namespace i2p
{
@@ -615,62 +616,21 @@
{
// assume socks if not http, is checked before this for other types
// TODO: support username/password auth etc
- uint8_t hs_writebuf[3] = {0x05, 0x01, 0x00};
- uint8_t hs_readbuf[2];
- boost::asio::write(sock, boost::asio::buffer(hs_writebuf, 3), boost::asio::transfer_all(), ecode);
- if(ecode)
+ bool success = false;
+ i2p::transport::Socks5Handshake (sock, std::make_pair(url.host, url.port),
+ [&success](const boost::system::error_code& ec)
+ {
+ if (!ec)
+ success = true;
+ else
+ LogPrint (eLogError, "Reseed: SOCKS handshake failed: ", ec.message());
+ });
+ service.run (); // execute all async operations
+ if (!success)
{
sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake write failed: ", ecode.message());
return "";
- }
- boost::asio::read(sock, boost::asio::buffer(hs_readbuf, 2), ecode);
- if(ecode)
- {
- sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake read failed: ", ecode.message());
- return "";
- }
- size_t sz = 0;
- uint8_t buf[256];
-
- buf[0] = 0x05;
- buf[1] = 0x01;
- buf[2] = 0x00;
- buf[3] = 0x03;
- sz += 4;
- size_t hostsz = url.host.size();
- if(1 + 2 + hostsz + sz > sizeof(buf))
- {
- sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake failed, hostname too big: ", url.host);
- return "";
- }
- buf[4] = (uint8_t) hostsz;
- memcpy(buf+5, url.host.c_str(), hostsz);
- sz += hostsz + 1;
- htobe16buf(buf+sz, url.port);
- sz += 2;
- boost::asio::write(sock, boost::asio::buffer(buf, sz), boost::asio::transfer_all(), ecode);
- if(ecode)
- {
- sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake failed writing: ", ecode.message());
- return "";
- }
- boost::asio::read(sock, boost::asio::buffer(buf, 10), ecode);
- if(ecode)
- {
- sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake failed reading: ", ecode.message());
- return "";
- }
- if(buf[1] != 0x00)
- {
- sock.close();
- LogPrint(eLogError, "Reseed: SOCKS handshake bad reply code: ", std::to_string(buf[1]));
- return "";
- }
+ }
}
}
}
@@ -687,18 +647,16 @@
while (it != end)
{
boost::asio::ip::tcp::endpoint ep = *it;
- if (
- (
- !i2p::util::net::IsInReservedRange(ep.address ()) && (
- (ep.address ().is_v4 () && i2p::context.SupportsV4 ()) ||
- (ep.address ().is_v6 () && i2p::context.SupportsV6 ())
- )
- ) ||
- (
- i2p::util::net::IsYggdrasilAddress (ep.address ()) &&
- i2p::context.SupportsMesh ()
- )
- )
+ bool supported = false;
+ if (!ep.address ().is_unspecified ())
+ {
+ if (ep.address ().is_v4 ())
+ supported = i2p::context.SupportsV4 ();
+ else if (ep.address ().is_v6 ())
+ supported = i2p::util::net::IsYggdrasilAddress (ep.address ()) ?
+ i2p::context.SupportsMesh () : i2p::context.SupportsV6 ();
+ }
+ if (supported)
{
s.lowest_layer().connect (ep, ecode);
if (!ecode)
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/RouterContext.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -40,7 +40,7 @@
void RouterContext::Init ()
{
srand (i2p::util::GetMillisecondsSinceEpoch () % 1000);
- m_StartupTime = std::chrono::steady_clock::now();
+ m_StartupTime = i2p::util::GetMonotonicSeconds ();
if (!Load ())
CreateNewRouter ();
@@ -61,9 +61,11 @@
{
m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
ScheduleInitialPublish ();
- m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
- ScheduleCongestionUpdate ();
}
+ m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
+ ScheduleCongestionUpdate ();
+ m_CleanupTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ()));
+ ScheduleCleanupTimer ();
}
}
@@ -303,6 +305,8 @@
SetTesting (false);
if (status != m_Status)
{
+ LogPrint(eLogInfo, "Router: network status v4 changed ",
+ ROUTER_STATUS_NAMES[m_Status], " -> ", ROUTER_STATUS_NAMES[status]);
m_Status = status;
switch (m_Status)
{
@@ -323,6 +327,8 @@
SetTestingV6 (false);
if (status != m_StatusV6)
{
+ LogPrint(eLogInfo, "Router: network status v6 changed ",
+ ROUTER_STATUS_NAMES[m_StatusV6], " -> ", ROUTER_STATUS_NAMES[status]);
m_StatusV6 = status;
switch (m_StatusV6)
{
@@ -596,9 +602,9 @@
{
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48
- case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break;
- case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
- case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256
+ case i2p::data::CAPS_FLAG_LOW_BANDWIDTH3 : limit = 64; type = low; break;
+ case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 128; type = high; break;
+ case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
default:
@@ -1131,13 +1137,14 @@
return i2p::tunnel::tunnels.GetExploratoryPool ();
}
- bool RouterContext::IsHighCongestion () const
+ int RouterContext::GetCongestionLevel (bool longTerm) const
{
- return i2p::tunnel::tunnels.IsTooManyTransitTunnels () ||
- i2p::transport::transports.IsBandwidthExceeded () ||
- i2p::transport::transports.IsTransitBandwidthExceeded ();
- }
-
+ return std::max (
+ i2p::tunnel::tunnels.GetCongestionLevel (),
+ i2p::transport::transports.GetCongestionLevel (longTerm)
+ );
+ }
+
void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len)
{
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
@@ -1145,6 +1152,13 @@
bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID)
{
+ if (typeID == eI2NPTunnelTest)
+ {
+ // try tunnel test
+ auto pool = GetTunnelPool ();
+ if (pool && pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET)))
+ return true;
+ }
auto msg = CreateI2NPMessage (typeID, payload, len, msgID);
if (!msg) return false;
i2p::HandleI2NPMessage (msg);
@@ -1199,21 +1213,30 @@
else
i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
}
-
- void RouterContext::CleanupDestination ()
+
+ void RouterContext::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
{
if (m_Service)
- m_Service->GetService ().post ([this]()
- {
- this->i2p::garlic::GarlicDestination::CleanupExpiredTags ();
- });
+ {
+ struct
+ {
+ uint8_t k[32];
+ uint64_t t;
+ } data;
+ memcpy (data.k, key, 32);
+ data.t = tag;
+ m_Service->GetService ().post ([this,data](void)
+ {
+ AddECIESx25519Key (data.k, data.t);
+ });
+ }
else
LogPrint (eLogError, "Router: service is NULL");
- }
+ }
uint32_t RouterContext::GetUptime () const
{
- return std::chrono::duration_cast<std::chrono::seconds> (std::chrono::steady_clock::now() - m_StartupTime).count ();
+ return i2p::util::GetMonotonicSeconds () - m_StartupTime;
}
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
@@ -1354,10 +1377,19 @@
uint32_t replyToken;
RAND_bytes ((uint8_t *)&replyToken, 4);
LogPrint (eLogInfo, "Router: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken);
+ auto onDrop = [this]()
+ {
+ if (m_Service)
+ m_Service->GetService ().post ([this]() { HandlePublishResendTimer (boost::system::error_code ()); });
+ };
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
+ {
// send directly
- i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
+ auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken);
+ msg->onDrop = onDrop;
+ i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), msg);
+ }
else
{
// otherwise through exploratory
@@ -1368,6 +1400,7 @@
{
// encrypt for floodfill
auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound);
+ msg->onDrop = onDrop;
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
}
@@ -1422,13 +1455,41 @@
if (ecode != boost::asio::error::operation_aborted)
{
auto c = i2p::data::RouterInfo::eLowCongestion;
- if (!AcceptsTunnels ())
+ if (!AcceptsTunnels () || !m_ShareRatio)
c = i2p::data::RouterInfo::eRejectAll;
- else if (IsHighCongestion ())
- c = i2p::data::RouterInfo::eHighCongestion;
+ else
+ {
+ int congestionLevel = GetCongestionLevel (true);
+ if (congestionLevel > CONGESTION_LEVEL_HIGH)
+ c = i2p::data::RouterInfo::eHighCongestion;
+ else if (congestionLevel > CONGESTION_LEVEL_MEDIUM)
+ c = i2p::data::RouterInfo::eMediumCongestion;
+ }
if (m_RouterInfo.UpdateCongestion (c))
UpdateRouterInfo ();
ScheduleCongestionUpdate ();
}
}
+
+ void RouterContext::ScheduleCleanupTimer ()
+ {
+ if (m_CleanupTimer)
+ {
+ m_CleanupTimer->cancel ();
+ m_CleanupTimer->expires_from_now (boost::posix_time::minutes(ROUTER_INFO_CLEANUP_INTERVAL));
+ m_CleanupTimer->async_wait (std::bind (&RouterContext::HandleCleanupTimer,
+ this, std::placeholders::_1));
+ }
+ else
+ LogPrint (eLogError, "Router: Cleanup timer is NULL");
+ }
+
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/RouterContext.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -12,7 +12,6 @@
#include <inttypes.h>
#include <string>
#include <memory>
-#include <chrono>
#include <set>
#include <boost/asio.hpp>
#include "Identity.h"
@@ -38,6 +37,7 @@
const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds
const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds
+ const int ROUTER_INFO_CLEANUP_INTERVAL = 5; // in minutes
enum RouterStatus
{
@@ -48,6 +48,15 @@
eRouterStatusMesh = 4
};
+ const char* const ROUTER_STATUS_NAMES[] =
+ {
+ "OK", // 0
+ "Firewalled", // 1
+ "Unknown", // 2
+ "Proxy", // 3
+ "Mesh" // 4
+ };
+
enum RouterError
{
eRouterErrorNone = 0,
@@ -136,6 +145,7 @@
void SetNetID (int netID) { m_NetID = netID; };
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data);
bool DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data);
+ void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag);
void UpdatePort (int port); // called from Daemon
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU2 or Daemon
@@ -156,7 +166,7 @@
void SetShareRatio (int percents); // 0 - 100
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
- bool IsHighCongestion () const;
+ int GetCongestionLevel (bool longTerm) const;
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
bool SupportsV4 () const { return m_RouterInfo.IsV4 (); };
bool SupportsMesh () const { return m_RouterInfo.IsMesh (); };
@@ -171,7 +181,6 @@
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove
void UpdateStats ();
void UpdateTimestamp (uint64_t ts); // in seconds, called from NetDb before publishing
- void CleanupDestination (); // garlic destination
// implements LocalDestination
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
@@ -220,6 +229,8 @@
void HandlePublishResendTimer (const boost::system::error_code& ecode);
void ScheduleCongestionUpdate ();
void HandleCongestionUpdateTimer (const boost::system::error_code& ecode);
+ void ScheduleCleanupTimer ();
+ void HandleCleanupTimer (const boost::system::error_code& ecode);
private:
@@ -229,7 +240,7 @@
std::shared_ptr<i2p::garlic::RouterIncomingRatchetSession> m_ECIESSession;
uint64_t m_LastUpdateTime; // in seconds
bool m_AcceptsTunnels, m_IsFloodfill;
- std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
+ uint64_t m_StartupTime; // monotonic seconds
uint64_t m_BandwidthLimit; // allowed bandwidth
int m_ShareRatio;
RouterStatus m_Status, m_StatusV6;
@@ -243,7 +254,7 @@
i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState;
// publish
std::unique_ptr<RouterService> m_Service;
- std::unique_ptr<boost::asio::deadline_timer> m_PublishTimer, m_CongestionUpdateTimer;
+ std::unique_ptr<boost::asio::deadline_timer> m_PublishTimer, m_CongestionUpdateTimer, m_CleanupTimer;
std::set<i2p::data::IdentHash> m_PublishExcluded;
uint32_t m_PublishReplyToken;
bool m_IsHiddenMode; // not publish
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/RouterInfo.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -21,6 +21,7 @@
#include "Base.h"
#include "Timestamp.h"
#include "Log.h"
+#include "Transports.h"
#include "NetDb.hpp"
#include "RouterContext.h"
#include "RouterInfo.h"
@@ -130,7 +131,7 @@
m_BufferLen = s.tellg ();
if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE)
{
- LogPrint(eLogError, "RouterInfo: File", fullPath, " is malformed");
+ LogPrint(eLogError, "RouterInfo: File ", fullPath, " is malformed");
return false;
}
s.seekg(0, std::ios::beg);
@@ -253,7 +254,7 @@
address->host = boost::asio::ip::address::from_string (value, ecode);
if (!ecode && !address->host.is_unspecified ())
{
- if (!i2p::util::net::IsInReservedRange (address->host) ||
+ if (!i2p::transport::transports.IsInReservedRange (address->host) ||
i2p::util::net::IsYggdrasilAddress (address->host))
isHost = true;
else
@@ -515,7 +516,6 @@
break;
case CAPS_FLAG_HIGH_BANDWIDTH1:
case CAPS_FLAG_HIGH_BANDWIDTH2:
- case CAPS_FLAG_HIGH_BANDWIDTH3:
m_Caps |= Caps::eHighBandwidth;
break;
case CAPS_FLAG_EXTRA_BANDWIDTH1:
@@ -995,7 +995,7 @@
bool RouterInfo::IsPublished (bool v4) const
{
- if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published
+ if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addresses are not published
auto addr = GetAddresses ();
if (v4)
return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) ||
@@ -1177,7 +1177,7 @@
CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X'
CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
else
- caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
+ caps += CAPS_FLAG_HIGH_BANDWIDTH2; // 'O'
caps += CAPS_FLAG_FLOODFILL; // floodfill
}
else
@@ -1185,7 +1185,7 @@
if (c & eExtraBandwidth)
caps += (c & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */
else
- caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
+ caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH2 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
}
if (c & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden
if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/RouterInfo.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -39,9 +39,9 @@
/* bandwidth flags */
const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */
const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */
- const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */
- const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */
- const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */
+ const char CAPS_FLAG_LOW_BANDWIDTH3 = 'M'; /* 48-64 KBps */
+ const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'N'; /* 64-128 KBps */
+ const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'O'; /* 128-256 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */
// bandwidth limits in kBps
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/SSU2.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022-2023, The PurpleI2P Project
+* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -210,27 +210,40 @@
return ep.port ();
}
- void SSU2Server::AdjustTimeOffset (int64_t offset)
+ void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from)
{
if (offset)
{
if (m_PendingTimeOffset) // one more
{
- if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW)
+ if (m_PendingTimeOffsetFrom && from &&
+ m_PendingTimeOffsetFrom->GetIdentHash ().GetLL()[0] != from->GetIdentHash ().GetLL()[0]) // from different routers
{
- offset = (m_PendingTimeOffset + offset)/2; // average
- LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds");
- i2p::util::AdjustTimeOffset (offset);
- }
+ if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW)
+ {
+ offset = (m_PendingTimeOffset + offset)/2; // average
+ LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds");
+ i2p::util::AdjustTimeOffset (offset);
+ }
+ else
+ LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted");
+ m_PendingTimeOffset = 0;
+ m_PendingTimeOffsetFrom = nullptr;
+ }
else
- LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted");
- m_PendingTimeOffset = 0;
+ LogPrint (eLogWarning, "SSU2: Time offsets from same router. Clock not adjusted");
}
else
+ {
m_PendingTimeOffset = offset; // first
+ m_PendingTimeOffsetFrom = from;
+ }
}
else
+ {
m_PendingTimeOffset = 0; // reset
+ m_PendingTimeOffsetFrom = nullptr;
+ }
}
boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint)
@@ -243,15 +256,49 @@
socket.open (localEndpoint.protocol ());
if (localEndpoint.address ().is_v6 ())
socket.set_option (boost::asio::ip::v6_only (true));
- socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU2_SOCKET_RECEIVE_BUFFER_SIZE));
- socket.set_option (boost::asio::socket_base::send_buffer_size (SSU2_SOCKET_SEND_BUFFER_SIZE));
+
+ uint64_t bufferSize = i2p::context.GetBandwidthLimit() * 1024 / 5; // max lag = 200ms
+ bufferSize = std::max(SSU2_SOCKET_MIN_BUFFER_SIZE, std::min(bufferSize, SSU2_SOCKET_MAX_BUFFER_SIZE));
+
+ boost::asio::socket_base::receive_buffer_size receiveBufferSizeSet (bufferSize);
+ boost::asio::socket_base::send_buffer_size sendBufferSizeSet (bufferSize);
+ socket.set_option (receiveBufferSizeSet);
+ socket.set_option (sendBufferSizeSet);
+ boost::asio::socket_base::receive_buffer_size receiveBufferSizeGet;
+ boost::asio::socket_base::send_buffer_size sendBufferSizeGet;
+ socket.get_option (receiveBufferSizeGet);
+ socket.get_option (sendBufferSizeGet);
+ if (receiveBufferSizeGet.value () != receiveBufferSizeSet.value () ||
+ sendBufferSizeGet.value () != sendBufferSizeSet.value ())
+ {
+ LogPrint (eLogWarning, "SSU2: Socket receive buffer size: requested = ",
+ receiveBufferSizeSet.value (), ", got = ", receiveBufferSizeGet.value ());
+ LogPrint (eLogWarning, "SSU2: Socket send buffer size: requested = ",
+ sendBufferSizeSet.value (), ", got = ", sendBufferSizeGet.value ());
+ }
+ else
+ {
+ LogPrint (eLogInfo, "SSU2: Socket receive buffer size: ", receiveBufferSizeGet.value ());
+ LogPrint (eLogInfo, "SSU2: Socket send buffer size: ", sendBufferSizeGet.value ());
+ }
+
+ socket.non_blocking (true);
+ }
+ catch (std::exception& ex )
+ {
+ LogPrint (eLogCritical, "SSU2: Failed to open socket on ", localEndpoint.address (), ": ", ex.what());
+ ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint.address (), ": ", ex.what ());
+ return socket;
+ }
+ try
+ {
socket.bind (localEndpoint);
LogPrint (eLogInfo, "SSU2: Start listening on ", localEndpoint);
}
catch (std::exception& ex )
{
- LogPrint (eLogCritical, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what());
- ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint, ": ", ex.what ());
+ LogPrint (eLogWarning, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what(), ". Actual endpoint is ", socket.local_endpoint ());
+ // we can continue without binding being firewalled
}
return socket;
}
@@ -283,8 +330,15 @@
// but better to find out which host were sent it and mark that router as unreachable
{
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred);
+ if (bytes_transferred < SSU2_MIN_RECEIVED_PACKET_SIZE)
+ {
+ // drop too short packets
+ m_PacketsPool.ReleaseMt (packet);
+ Receive (socket);
+ return;
+ }
packet->len = bytes_transferred;
-
+
boost::system::error_code ec;
size_t moreBytes = socket.available (ec);
if (!ec && moreBytes)
@@ -382,7 +436,11 @@
{
auto ident = it->second->GetRemoteIdentity ();
if (ident)
- m_SessionsByRouterHash.erase (ident->GetIdentHash ());
+ {
+ auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ());
+ if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second)
+ m_SessionsByRouterHash.erase (it1);
+ }
if (m_LastSession == it->second)
m_LastSession = nullptr;
m_Sessions.erase (it);
@@ -440,7 +498,7 @@
m_PendingOutgoingSessions.erase (ep);
}
- std::shared_ptr<SSU2Session> SSU2Server::GetRandomSession (
+ std::shared_ptr<SSU2Session> SSU2Server::GetRandomPeerTestSession (
i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded) const
{
if (m_Sessions.empty ()) return nullptr;
@@ -451,7 +509,7 @@
std::advance (it, ind);
while (it != m_Sessions.end ())
{
- if ((it->second->GetRemoteTransports () & remoteTransports) &&
+ if ((it->second->GetRemotePeerTestTransports () & remoteTransports) &&
it->second->GetRemoteIdentity ()->GetIdentHash () != excluded)
return it->second;
it++;
@@ -460,7 +518,7 @@
it = m_Sessions.begin ();
while (it != m_Sessions.end () && ind)
{
- if ((it->second->GetRemoteTransports () & remoteTransports) &&
+ if ((it->second->GetRemotePeerTestTransports () & remoteTransports) &&
it->second->GetRemoteIdentity ()->GetIdentHash () != excluded)
return it->second;
it++; ind--;
@@ -566,7 +624,7 @@
else
it1->second->ProcessRetry (buf, len);
}
- else if (!i2p::util::net::IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ())
+ else if (!i2p::transport::transports.IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ())
{
// assume new incoming session
auto session = std::make_shared<SSU2Session> (*this);
@@ -608,7 +666,10 @@
if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen);
else
- LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to);
+ {
+ LogPrint (ec == boost::asio::error::would_block ? eLogInfo : eLogError,
+ "SSU2: Send exception: ", ec.message (), " to ", to);
+ }
}
void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
@@ -642,7 +703,10 @@
if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen);
else
- LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to);
+ {
+ LogPrint (ec == boost::asio::error::would_block ? eLogInfo : eLogError,
+ "SSU2: Send exception: ", ec.message (), " to ", to);
+ }
}
bool SSU2Server::CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/SSU2.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022-2023, The PurpleI2P Project
+* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -13,6 +13,7 @@
#include <mutex>
#include "util.h"
#include "SSU2Session.h"
+#include "Socks5.h"
namespace i2p
{
@@ -20,13 +21,14 @@
{
const int SSU2_TERMINATION_CHECK_TIMEOUT = 25; // in seconds
const int SSU2_CLEANUP_INTERVAL = 72; // in seconds
- const int SSU2_RESEND_CHECK_TIMEOUT = 400; // in milliseconds
- const int SSU2_RESEND_CHECK_TIMEOUT_VARIANCE = 100; // in milliseconds
+ const int SSU2_RESEND_CHECK_TIMEOUT = 40; // in milliseconds
+ const int SSU2_RESEND_CHECK_TIMEOUT_VARIANCE = 10; // in milliseconds
const int SSU2_RESEND_CHECK_MORE_TIMEOUT = 10; // in milliseconds
const size_t SSU2_MAX_RESEND_PACKETS = 128; // packets to resend at the time
- const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
- const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
+ const uint64_t SSU2_SOCKET_MIN_BUFFER_SIZE = 128 * 1024;
+ const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 4 * 1024 * 1024;
const size_t SSU2_MAX_NUM_INTRODUCERS = 3;
+ const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC
const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds
@@ -66,7 +68,7 @@
bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const;
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
- void AdjustTimeOffset (int64_t offset);
+ void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from);
void AddSession (std::shared_ptr<SSU2Session> session);
void RemoveSession (uint64_t connID);
@@ -75,7 +77,7 @@
void RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep);
std::shared_ptr<SSU2Session> FindSession (const i2p::data::IdentHash& ident) const;
std::shared_ptr<SSU2Session> FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const;
- std::shared_ptr<SSU2Session> GetRandomSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports,
+ std::shared_ptr<SSU2Session> GetRandomPeerTestSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports,
const i2p::data::IdentHash& excluded) const;
void AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay);
@@ -163,6 +165,7 @@
bool m_IsPublished; // if we maintain introducers
bool m_IsSyncClockFromPeers;
int64_t m_PendingTimeOffset; // during peer test
+ std::shared_ptr<const i2p::data::IdentityEx> m_PendingTimeOffsetFrom;
// proxy
bool m_IsThroughProxy;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/SSU2Session.cpp
^
|
@@ -81,12 +81,15 @@
SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT),
- m_Server (server), m_Address (addr), m_RemoteTransports (0),
+ m_Server (server), m_Address (addr), m_RemoteTransports (0), m_RemotePeerTestTransports (0),
m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown),
m_SendPacketNum (0), m_ReceivePacketNum (0), m_LastDatetimeSentPacketNum (0),
- m_IsDataReceived (false), m_WindowSize (SSU2_MIN_WINDOW_SIZE),
- m_RTT (SSU2_RESEND_INTERVAL), m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0),
- m_ConnectTimer (server.GetService ()), m_TerminationReason (eSSU2TerminationReasonNormalClose),
+ m_IsDataReceived (false), m_RTT (SSU2_UNKNOWN_RTT),
+ m_MsgLocalExpirationTimeout (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX),
+ m_MsgLocalSemiExpirationTimeout (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX / 2),
+ m_WindowSize (SSU2_MIN_WINDOW_SIZE),
+ m_RTO (SSU2_INITIAL_RTO), m_RelayTag (0),m_ConnectTimer (server.GetService ()),
+ m_TerminationReason (eSSU2TerminationReasonNormalClose),
m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32) // min size
{
m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState);
@@ -96,6 +99,8 @@
InitNoiseXKState1 (*m_NoiseState, m_Address->s);
m_RemoteEndpoint = boost::asio::ip::udp::endpoint (m_Address->host, m_Address->port);
m_RemoteTransports = in_RemoteRouter->GetCompatibleTransports (false);
+ if (in_RemoteRouter->IsSSU2PeerTesting (true)) m_RemotePeerTestTransports |= i2p::data::RouterInfo::eSSU2V4;
+ if (in_RemoteRouter->IsSSU2PeerTesting (false)) m_RemotePeerTestTransports |= i2p::data::RouterInfo::eSSU2V6;
RAND_bytes ((uint8_t *)&m_DestConnID, 8);
RAND_bytes ((uint8_t *)&m_SourceConnID, 8);
}
@@ -262,6 +267,8 @@
m_SentHandshakePacket.reset (nullptr);
m_SessionConfirmedFragment.reset (nullptr);
m_PathChallenge.reset (nullptr);
+ for (auto& it: m_SendQueue)
+ it->Drop ();
m_SendQueue.clear ();
SetSendQueueSize (0);
m_SentPackets.clear ();
@@ -275,7 +282,7 @@
if (remoteIdentity)
{
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
- " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
+ " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated");
}
else
{
@@ -290,8 +297,10 @@
{
m_TerminationReason = reason;
SendTermination ();
+ m_State = eSSU2SessionStateClosing;
}
- m_State = eSSU2SessionStateClosing;
+ else
+ Done ();
}
void SSU2Session::Established ()
@@ -349,21 +358,33 @@
void SSU2Session::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs)
{
if (m_State == eSSU2SessionStateTerminated) return;
+ uint64_t mts = i2p::util::GetMonotonicMicroseconds ();
+ bool isSemiFull = false;
+ if (m_SendQueue.size ())
+ {
+ int64_t queueLag = (int64_t)mts - (int64_t)m_SendQueue.front ()->GetEnqueueTime ();
+ isSemiFull = queueLag > m_MsgLocalSemiExpirationTimeout;
+ if (isSemiFull)
+ {
+ LogPrint (eLogWarning, "SSU2: Outgoing messages queue to ",
+ i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()),
+ " is semi-full (size = ", m_SendQueue.size (), ", lag = ", queueLag / 1000, ", rtt = ", (int)m_RTT, ")");
+ }
+ }
for (auto it: msgs)
- m_SendQueue.push_back (std::move (it));
- SendQueue ();
-
- if (m_SendQueue.size () > 0) // windows is full
{
- if (m_SendQueue.size () <= SSU2_MAX_OUTGOING_QUEUE_SIZE)
- Resend (i2p::util::GetMillisecondsSinceEpoch ());
+ if (isSemiFull && it->onDrop)
+ it->Drop (); // drop earlier because we can handle it
else
{
- LogPrint (eLogWarning, "SSU2: Outgoing messages queue size to ",
- GetIdentHashBase64(), " exceeds ", SSU2_MAX_OUTGOING_QUEUE_SIZE);
- RequestTermination (eSSU2TerminationReasonTimeout);
+ it->SetEnqueueTime (mts);
+ m_SendQueue.push_back (std::move (it));
}
}
+ SendQueue ();
+
+ if (m_SendQueue.size () > 0) // windows is full
+ Resend (i2p::util::GetMillisecondsSinceEpoch ());
SetSendQueueSize (m_SendQueue.size ());
}
@@ -372,6 +393,7 @@
if (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize)
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
+ uint64_t mts = i2p::util::GetMonotonicMicroseconds ();
auto packet = m_Server.GetSentPacketsPool ().AcquireShared ();
size_t ackBlockSize = CreateAckBlock (packet->payload, m_MaxPayloadSize);
bool ackBlockSent = false;
@@ -379,8 +401,10 @@
while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize)
{
auto msg = m_SendQueue.front ();
- if (!msg)
+ if (!msg || msg->IsExpired (ts) || msg->GetEnqueueTime() + m_MsgLocalExpirationTimeout < mts)
{
+ // drop null or expired message
+ if (msg) msg->Drop ();
m_SendQueue.pop_front ();
continue;
}
@@ -517,7 +541,7 @@
if (m_SentPackets.empty ()) return 0;
std::map<uint32_t, std::shared_ptr<SSU2SentPacket> > resentPackets;
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end (); )
- if (ts >= it->second->sendTime + it->second->numResends*m_RTO)
+ if (ts >= it->second->sendTime + (it->second->numResends + 1) * m_RTO)
{
if (it->second->numResends > SSU2_MAX_NUM_RESENDS)
{
@@ -1102,6 +1126,10 @@
AdjustMaxPayloadSize ();
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now
m_RemoteTransports = ri->GetCompatibleTransports (false);
+ m_RemotePeerTestTransports = 0;
+ if (ri->IsSSU2PeerTesting (true)) m_RemotePeerTestTransports |= i2p::data::RouterInfo::eSSU2V4;
+ if (ri->IsSSU2PeerTesting (false)) m_RemotePeerTestTransports |= i2p::data::RouterInfo::eSSU2V6;
+
// handle other blocks
HandlePayload (decryptedPayload.data () + riSize + 3, decryptedPayload.size () - riSize - 3);
Established ();
@@ -1471,7 +1499,7 @@
ResendHandshakePacket (); // assume we receive
return;
}
- if (from != m_RemoteEndpoint && !i2p::util::net::IsInReservedRange (from.address ()))
+ if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ()))
{
LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from);
m_RemoteEndpoint = from;
@@ -1670,10 +1698,10 @@
if (std::abs (offset) > SSU2_CLOCK_THRESHOLD)
{
LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint);
- m_Server.AdjustTimeOffset (-offset);
+ m_Server.AdjustTimeOffset (-offset, GetRemoteIdentity ());
}
else
- m_Server.AdjustTimeOffset (0);
+ m_Server.AdjustTimeOffset (0, nullptr);
}
else if (std::abs (offset) > SSU2_CLOCK_SKEW)
{
@@ -1729,8 +1757,15 @@
if (ts > it1->second->sendTime)
{
auto rtt = ts - it1->second->sendTime;
- m_RTT = std::round ((m_RTT*m_SendPacketNum + rtt)/(m_SendPacketNum + 1.0));
+ if (m_RTT != SSU2_UNKNOWN_RTT)
+ m_RTT = SSU2_RTT_EWMA_ALPHA * rtt + (1.0 - SSU2_RTT_EWMA_ALPHA) * m_RTT;
+ else
+ m_RTT = rtt;
m_RTO = m_RTT*SSU2_kAPPA;
+ m_MsgLocalExpirationTimeout = std::max (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MIN,
+ std::min (I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX,
+ (unsigned int)(m_RTT * 1000 * I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_FACTOR)));
+ m_MsgLocalSemiExpirationTimeout = m_MsgLocalExpirationTimeout / 2;
if (m_RTO < SSU2_MIN_RTO) m_RTO = SSU2_MIN_RTO;
if (m_RTO > SSU2_MAX_RTO) m_RTO = SSU2_MAX_RTO;
}
@@ -1753,7 +1788,7 @@
if (ExtractEndpoint (buf, len, ep))
{
LogPrint (eLogInfo, "SSU2: Our external address is ", ep);
- if (!i2p::util::net::IsInReservedRange (ep.address ()))
+ if (!i2p::transport::transports.IsInReservedRange (ep.address ()))
{
i2p::context.UpdateAddress (ep.address ());
// check our port
@@ -2101,7 +2136,7 @@
{
case 1: // Bob from Alice
{
- auto session = m_Server.GetRandomSession ((buf[12] == 6) ? i2p::data::RouterInfo::eSSU2V4 : i2p::data::RouterInfo::eSSU2V6,
+ auto session = m_Server.GetRandomPeerTestSession ((buf[12] == 6) ? i2p::data::RouterInfo::eSSU2V4 : i2p::data::RouterInfo::eSSU2V6,
GetRemoteIdentity ()->GetIdentHash ());
if (session) // session with Charlie
{
@@ -2172,7 +2207,8 @@
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/SSU2Session.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022-2023, The PurpleI2P Project
+* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -25,7 +25,7 @@
namespace transport
{
const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds
- const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes
+ const int SSU2_TERMINATION_TIMEOUT = 165; // in seconds
const int SSU2_CLOCK_SKEW = 60; // in seconds
const int SSU2_CLOCK_THRESHOLD = 15; // in seconds, if more we should adjust
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // for Retry message, in seconds
@@ -36,7 +36,6 @@
const size_t SSU2_MAX_PACKET_SIZE = 1500;
const size_t SSU2_MIN_PACKET_SIZE = 1280;
const int SSU2_HANDSHAKE_RESEND_INTERVAL = 1000; // in milliseconds
- const int SSU2_RESEND_INTERVAL = 300; // in milliseconds
const int SSU2_MAX_NUM_RESENDS = 5;
const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
const int SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS = 5000; // how many msgID we store for duplicates check
@@ -45,9 +44,11 @@
const size_t SSU2_MIN_WINDOW_SIZE = 16; // in packets
const size_t SSU2_MAX_WINDOW_SIZE = 256; // in packets
const size_t SSU2_MIN_RTO = 100; // in milliseconds
+ const size_t SSU2_INITIAL_RTO = 540; // in milliseconds
const size_t SSU2_MAX_RTO = 2500; // in milliseconds
+ const double SSU2_UNKNOWN_RTT = -1;
+ const double SSU2_RTT_EWMA_ALPHA = 0.125;
const float SSU2_kAPPA = 1.8;
- const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500; // in messages
const int SSU2_MAX_NUM_ACNT = 255; // acnt, acks or nacks
const int SSU2_MAX_NUM_ACK_PACKETS = 511; // ackthrough + acnt + 1 range
const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send
@@ -238,6 +239,7 @@
void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; };
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; };
i2p::data::RouterInfo::CompatibleTransports GetRemoteTransports () const { return m_RemoteTransports; };
+ i2p::data::RouterInfo::CompatibleTransports GetRemotePeerTestTransports () const { return m_RemotePeerTestTransports; };
std::shared_ptr<const i2p::data::RouterInfo::Address> GetAddress () const { return m_Address; };
void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; };
OnEstablished GetOnEstablished () const { return m_OnEstablished; };
@@ -343,7 +345,7 @@
std::unique_ptr<HandshakePacket> m_SentHandshakePacket; // SessionRequest, SessionCreated or SessionConfirmed
std::shared_ptr<const i2p::data::RouterInfo::Address> m_Address;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
- i2p::data::RouterInfo::CompatibleTransports m_RemoteTransports; // for peer tests
+ i2p::data::RouterInfo::CompatibleTransports m_RemoteTransports, m_RemotePeerTestTransports;
uint64_t m_DestConnID, m_SourceConnID;
SSU2SessionState m_State;
uint8_t m_KeyDataSend[64], m_KeyDataReceive[64];
@@ -356,7 +358,10 @@
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
i2p::I2NPMessagesHandler m_Handler;
bool m_IsDataReceived;
- size_t m_WindowSize, m_RTT, m_RTO;
+ double m_RTT;
+ int m_MsgLocalExpirationTimeout;
+ int m_MsgLocalSemiExpirationTimeout;
+ size_t m_WindowSize, m_RTO;
uint32_t m_RelayTag; // between Bob and Charlie
OnEstablished m_OnEstablished; // callback from Established
boost::asio::deadline_timer m_ConnectTimer;
|
[-]
[+]
|
Added |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Socks5.h
^
|
@@ -0,0 +1,210 @@
+/*
+* Copyright (c) 2024, 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 SOCKS5_H__
+#define SOCKS5_H__
+
+#include <string>
+#include <memory>
+#include <boost/asio.hpp>
+#include "I2PEndian.h"
+
+namespace i2p
+{
+namespace transport
+{
+ // SOCKS5 constants
+ const uint8_t SOCKS5_VER = 0x05;
+ const uint8_t SOCKS5_CMD_CONNECT = 0x01;
+ const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
+ const uint8_t SOCKS5_ATYP_IPV4 = 0x01;
+ const uint8_t SOCKS5_ATYP_IPV6 = 0x04;
+ const uint8_t SOCKS5_ATYP_NAME = 0x03;
+ const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10;
+ const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22;
+
+ const uint8_t SOCKS5_REPLY_SUCCESS = 0x00;
+ const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01;
+ const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02;
+ const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03;
+ const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04;
+ const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05;
+ const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06;
+ const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07;
+ const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08;
+
+ // SOCKS5 handshake
+ template<typename Socket, typename Handler>
+ void Socks5ReadReply (Socket& s, Handler handler)
+ {
+ auto readbuff = std::make_shared<std::vector<int8_t> >(258); // max possible
+ boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address
+ [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred)
+ {
+ if (!ec)
+ {
+ if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS)
+ {
+ size_t len = 0;
+ switch ((*readbuff)[3]) // ATYP
+ {
+ case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes
+ case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes
+ case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length
+ default: ;
+ }
+ if (len)
+ {
+ len += 2; // port
+ boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(),
+ [readbuff, handler](const boost::system::error_code& ec, std::size_t transferred)
+ {
+ if (!ec)
+ handler (boost::system::error_code ()); // success
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted));
+ });
+ }
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type
+ }
+ else
+ switch ((*readbuff)[1]) // REP
+ {
+ case SOCKS5_REPLY_SERVER_FAILURE:
+ handler (boost::asio::error::make_error_code (boost::asio::error::access_denied ));
+ break;
+ case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED:
+ handler (boost::asio::error::make_error_code (boost::asio::error::no_permission));
+ break;
+ case SOCKS5_REPLY_HOST_UNREACHABLE:
+ handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable));
+ break;
+ case SOCKS5_REPLY_NETWORK_UNREACHABLE:
+ handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable));
+ break;
+ case SOCKS5_REPLY_CONNECTION_REFUSED:
+ handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused));
+ break;
+ case SOCKS5_REPLY_TTL_EXPIRED:
+ handler (boost::asio::error::make_error_code (boost::asio::error::timed_out));
+ break;
+ case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED:
+ handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported));
+ break;
+ case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED:
+ handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option));
+ break;
+ default:
+ handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted));
+ }
+ }
+ else
+ handler (ec);
+ });
+ }
+
+ template<typename Socket, typename Handler>
+ void Socks5Connect (Socket& s, Handler handler, std::shared_ptr<std::vector<uint8_t> > buff, uint16_t port)
+ {
+ if (buff && buff->size () >= 6)
+ {
+ (*buff)[0] = SOCKS5_VER;
+ (*buff)[1] = SOCKS5_CMD_CONNECT;
+ (*buff)[2] = 0x00;
+ htobe16buf(buff->data () + buff->size () - 2, port);
+ boost::asio::async_write(s, boost::asio::buffer(*buff), boost::asio::transfer_all(),
+ [buff, &s, handler](const boost::system::error_code& ec, std::size_t transferred)
+ {
+ (void) transferred;
+ if (!ec)
+ Socks5ReadReply (s, handler);
+ else
+ handler (ec);
+ });
+ }
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::no_buffer_space));
+ }
+
+ template<typename Socket, typename Handler>
+ void Socks5Connect (Socket& s, const boost::asio::ip::tcp::endpoint& ep, Handler handler)
+ {
+ std::shared_ptr<std::vector<uint8_t> > buff;
+ if(ep.address ().is_v4 ())
+ {
+ buff = std::make_shared<std::vector<uint8_t> >(10);
+ (*buff)[3] = SOCKS5_ATYP_IPV4;
+ auto addrbytes = ep.address ().to_v4().to_bytes();
+ memcpy(buff->data () + 4, addrbytes.data(), 4);
+ }
+ else if (ep.address ().is_v6 ())
+ {
+ buff = std::make_shared<std::vector<uint8_t> >(22);
+ (*buff)[3] = SOCKS5_ATYP_IPV6;
+ auto addrbytes = ep.address ().to_v6().to_bytes();
+ memcpy(buff->data () + 4, addrbytes.data(), 16);
+ }
+ if (buff)
+ Socks5Connect (s, handler, buff, ep.port ());
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::fault));
+ }
+
+ template<typename Socket, typename Handler>
+ void Socks5Connect (Socket& s, const std::pair<std::string, uint16_t>& ep, Handler handler)
+ {
+ auto& addr = ep.first;
+ if (addr.length () <= 255)
+ {
+ auto buff = std::make_shared<std::vector<uint8_t> >(addr.length () + 7);
+ (*buff)[3] = SOCKS5_ATYP_NAME;
+ (*buff)[4] = addr.length ();
+ memcpy (buff->data () + 5, addr.c_str (), addr.length ());
+ Socks5Connect (s, handler, buff, ep.second);
+ }
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::name_too_long));
+ }
+
+
+ template<typename Socket, typename Endpoint, typename Handler>
+ void Socks5Handshake (Socket& s, Endpoint ep, Handler handler)
+ {
+ static const uint8_t methodSelection[3] = { SOCKS5_VER, 0x01, 0x00 }; // 1 method, no auth
+ boost::asio::async_write(s, boost::asio::buffer(methodSelection, 3), boost::asio::transfer_all(),
+ [&s, ep, handler] (const boost::system::error_code& ec, std::size_t transferred)
+ {
+ (void) transferred;
+ if (!ec)
+ {
+ auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
+ boost::asio::async_read(s, boost::asio::buffer(*readbuff), boost::asio::transfer_all(),
+ [&s, ep, handler, readbuff] (const boost::system::error_code& ec, std::size_t transferred)
+ {
+ if (!ec)
+ {
+ if (transferred == 2 && (*readbuff)[1] == 0x00) // no auth
+ Socks5Connect (s, ep, handler);
+ else
+ handler (boost::asio::error::make_error_code (boost::asio::error::invalid_argument));
+ }
+ else
+ handler (ec);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Streaming.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -68,11 +68,12 @@
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local,
std::shared_ptr<const i2p::data::LeaseSet> remote, int port): m_Service (service),
- m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
+ m_SendStreamID (0), m_SequenceNumber (0),
+ m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1),
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service),
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
- m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO),
+ m_RTT (INITIAL_RTT), m_WindowSize (MIN_WINDOW_SIZE), m_RTO (INITIAL_RTO),
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
{
@@ -81,11 +82,12 @@
}
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local):
- m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
+ m_Service (service), m_SendStreamID (0), m_SequenceNumber (0),
+ m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1),
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
- m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE),
- m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
+ m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT),
+ m_WindowSize (MIN_WINDOW_SIZE), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
{
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
@@ -129,6 +131,11 @@
void Stream::HandleNextPacket (Packet * packet)
{
+ if (m_Status == eStreamStatusTerminated)
+ {
+ m_LocalDestination.DeletePacket (packet);
+ return;
+ }
m_NumReceivedBytes += packet->GetLength ();
if (!m_SendStreamID)
{
@@ -159,7 +166,8 @@
{
// we have received next in sequence message
ProcessPacket (packet);
-
+ if (m_Status == eStreamStatusTerminated) return;
+
// we should also try stored messages if any
for (auto it = m_SavedPackets.begin (); it != m_SavedPackets.end ();)
{
@@ -169,6 +177,7 @@
m_SavedPackets.erase (it++);
ProcessPacket (savedPacket);
+ if (m_Status == eStreamStatusTerminated) return;
}
else
break;
@@ -179,13 +188,9 @@
{
if (!m_IsAckSendScheduled)
{
- m_IsAckSendScheduled = true;
auto ackTimeout = m_RTT/10;
if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay;
- else if (ackTimeout < MIN_SEND_ACK_TIMEOUT) ackTimeout = MIN_SEND_ACK_TIMEOUT;
- m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout));
- m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
- shared_from_this (), std::placeholders::_1));
+ ScheduleAck (ackTimeout);
}
}
else if (packet->IsSYN ())
@@ -208,22 +213,17 @@
SavePacket (packet);
if (m_LastReceivedSequenceNumber >= 0)
{
- // send NACKs for missing messages ASAP
- if (m_IsAckSendScheduled)
- {
- m_IsAckSendScheduled = false;
- m_AckSendTimer.cancel ();
- }
- SendQuickAck ();
- }
+ if (!m_IsAckSendScheduled)
+ {
+ // send NACKs for missing messages
+ int ackTimeout = MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size ();
+ if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay;
+ ScheduleAck (ackTimeout);
+ }
+ }
else
- {
// wait for SYN
- m_IsAckSendScheduled = true;
- m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT));
- m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
- shared_from_this (), std::placeholders::_1));
- }
+ ScheduleAck (SYN_TIMEOUT);
}
}
}
@@ -289,6 +289,8 @@
m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
shared_from_this (), std::placeholders::_1));
}
+ if (delayRequested >= DELAY_CHOKING)
+ m_WindowSize = 1;
}
optionData += 2;
}
@@ -406,6 +408,8 @@
LogPrint (eLogError, "Streaming: Unexpected ackThrough=", ackThrough, " > seqn=", m_SequenceNumber);
return;
}
+ int rttSample = INT_MAX;
+ bool firstRttSample = false;
int nackCount = packet->GetNACKCount ();
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();)
{
@@ -429,38 +433,51 @@
}
}
auto sentPacket = *it;
- uint64_t rtt = ts - sentPacket->sendTime;
- if(ts < sentPacket->sendTime)
+ int64_t rtt = (int64_t)ts - (int64_t)sentPacket->sendTime;
+ if (rtt < 0)
+ LogPrint (eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime);
+ if (!seqn)
{
- LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime);
- rtt = 1;
+ firstRttSample = true;
+ rttSample = rtt < 0 ? 1 : rtt;
}
- m_RTT = std::round ((m_RTT*seqn + rtt)/(seqn + 1.0));
- m_RTO = m_RTT*1.5; // TODO: implement it better
+ else if (!sentPacket->resent && seqn > m_TunnelsChangeSequenceNumber && rtt >= 0)
+ rttSample = std::min (rttSample, (int)rtt);
LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime);
m_SentPackets.erase (it++);
m_LocalDestination.DeletePacket (sentPacket);
acknowledged = true;
if (m_WindowSize < WINDOW_SIZE)
m_WindowSize++; // slow start
- else
- {
- // linear growth
- if (ts > m_LastWindowSizeIncreaseTime + m_RTT)
- {
- m_WindowSize++;
- if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
- m_LastWindowSizeIncreaseTime = ts;
- }
- }
- if (!seqn && m_RoutingSession) // first message confirmed
- m_RoutingSession->SetSharedRoutingPath (
- std::make_shared<i2p::garlic::GarlicRoutingPath> (
- i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, m_RTT, 0, 0}));
}
else
break;
}
+ if (rttSample != INT_MAX)
+ {
+ if (firstRttSample)
+ m_RTT = rttSample;
+ else
+ m_RTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_RTT;
+ bool wasInitial = m_RTO == INITIAL_RTO;
+ m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.5)); // TODO: implement it better
+ if (wasInitial)
+ ScheduleResend ();
+ }
+ if (acknowledged && m_WindowSize >= WINDOW_SIZE)
+ {
+ // linear growth
+ if (ts > m_LastWindowSizeIncreaseTime + m_RTT)
+ {
+ m_WindowSize++;
+ if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
+ m_LastWindowSizeIncreaseTime = ts;
+ }
+ }
+ if (firstRttSample && m_RoutingSession)
+ m_RoutingSession->SetSharedRoutingPath (
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Streaming.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -56,6 +56,9 @@
const int WINDOW_SIZE = 6; // in messages
const int MIN_WINDOW_SIZE = 1;
const int MAX_WINDOW_SIZE = 128;
+ const int WINDOW_SIZE_DROP_FRACTION = 10; // 1/10
+ const double RTT_EWMA_ALPHA = 0.125;
+ const int MIN_RTO = 20; // in milliseconds
const int INITIAL_RTT = 8000; // in milliseconds
const int INITIAL_RTO = 9000; // in milliseconds
const int MIN_SEND_ACK_TIMEOUT = 2; // in milliseconds
@@ -63,14 +66,16 @@
const size_t MAX_PENDING_INCOMING_BACKLOG = 128;
const int PENDING_INCOMING_TIMEOUT = 10; // in seconds
const int MAX_RECEIVE_TIMEOUT = 20; // in seconds
+ const uint16_t DELAY_CHOKING = 60000; // in milliseconds
struct Packet
{
size_t len, offset;
uint8_t buf[MAX_PACKET_SIZE];
uint64_t sendTime;
+ bool resent;
- Packet (): len (0), offset (0), sendTime (0) {};
+ Packet (): len (0), offset (0), sendTime (0), resent (false) {};
uint8_t * GetBuffer () { return buf + offset; };
size_t GetLength () const { return len - offset; };
@@ -227,12 +232,14 @@
void ScheduleResend ();
void HandleResendTimer (const boost::system::error_code& ecode);
+ void ScheduleAck (int timeout);
void HandleAckSendTimer (const boost::system::error_code& ecode);
private:
boost::asio::io_service& m_Service;
uint32_t m_SendStreamID, m_RecvStreamID, m_SequenceNumber;
+ uint32_t m_TunnelsChangeSequenceNumber;
int32_t m_LastReceivedSequenceNumber;
StreamStatus m_Status;
bool m_IsAckSendScheduled;
@@ -251,7 +258,8 @@
uint16_t m_Port;
SendBufferQueue m_SendBuffer;
- int m_WindowSize, m_RTT, m_RTO, m_AckDelay;
+ double m_RTT;
+ int m_WindowSize, m_RTO, m_AckDelay;
uint64_t m_LastWindowSizeIncreaseTime;
int m_NumResendAttempts;
size_t m_MTU;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Timestamp.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -232,6 +232,24 @@
return GetLocalHoursSinceEpoch () + g_TimeOffset/3600;
}
+ uint64_t GetMonotonicMicroseconds()
+ {
+ return std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count();
+ }
+
+ uint64_t GetMonotonicMilliseconds()
+ {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count();
+ }
+
+ uint64_t GetMonotonicSeconds ()
+ {
+ return std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count();
+ }
+
void GetCurrentDate (char * date)
{
GetDateString (GetSecondsSinceEpoch (), date);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Timestamp.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -24,6 +24,10 @@
uint32_t GetMinutesSinceEpoch ();
uint32_t GetHoursSinceEpoch ();
+ uint64_t GetMonotonicMicroseconds ();
+ uint64_t GetMonotonicMilliseconds ();
+ uint64_t GetMonotonicSeconds ();
+
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
void GetDateString (uint64_t timestamp, char * date); // timestamp is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
void AdjustTimeOffset (int64_t offset); // in seconds from current
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/TransportSession.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -187,15 +187,6 @@
uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp;
uint32_t m_InBandwidth, m_OutBandwidth;
};
-
- // SOCKS5 proxy
- const uint8_t SOCKS5_VER = 0x05;
- const uint8_t SOCKS5_CMD_CONNECT = 0x01;
- const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
- const uint8_t SOCKS5_ATYP_IPV4 = 0x01;
- const uint8_t SOCKS5_ATYP_IPV6 = 0x04;
- const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10;
- const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22;
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Transports.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -140,10 +140,8 @@
m_X25519KeysPairSupplier (15), // 15 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), m_LastTransitBandwidthUpdateBytes (0),
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
- m_LastInBandwidth15sUpdateBytes (0), m_LastOutBandwidth15sUpdateBytes (0), m_LastTransitBandwidth15sUpdateBytes (0),
- m_LastBandwidth15sUpdateTime (0)
+ m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0)
{
}
@@ -306,6 +304,16 @@
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT));
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
+ uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
+ for (int i = 0; i < TRAFFIC_SAMPLE_COUNT; i++)
+ {
+ m_TrafficSamples[i].Timestamp = ts - (TRAFFIC_SAMPLE_COUNT - i - 1) * 1000;
+ m_TrafficSamples[i].TotalReceivedBytes = 0;
+ m_TrafficSamples[i].TotalSentBytes = 0;
+ m_TrafficSamples[i].TotalTransitTransmittedBytes = 0;
+ }
+ m_TrafficSamplePtr = TRAFFIC_SAMPLE_COUNT - 1;
+
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
@@ -364,51 +372,67 @@
}
}
+ void Transports::UpdateBandwidthValues(int interval, uint32_t& in, uint32_t& out, uint32_t& transit)
+ {
+ TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr];
+ TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT];
+ auto delta = (int64_t)sample1.Timestamp - (int64_t)sample2.Timestamp;
+ if (delta <= 0)
+ {
+ LogPrint (eLogError, "Transports: Backward clock jump detected, got ", delta, " instead of ", interval * 1000);
+ return;
+ }
+ in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta;
+ out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta;
+ transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta;
+ }
+
void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
{
- uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
-
- // updated every second
- m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes;
- m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes;
- m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes;
-
- m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes;
- m_LastOutBandwidthUpdateBytes = m_TotalSentBytes;
- m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes;
-
- // updated every 15 seconds
- auto delta = ts - m_LastBandwidth15sUpdateTime;
- if (delta > 15 * 1000)
- {
- m_InBandwidth15s = (m_TotalReceivedBytes - m_LastInBandwidth15sUpdateBytes) * 1000 / delta;
- m_OutBandwidth15s = (m_TotalSentBytes - m_LastOutBandwidth15sUpdateBytes) * 1000 / delta;
- m_TransitBandwidth15s = (m_TotalTransitTransmittedBytes - m_LastTransitBandwidth15sUpdateBytes) * 1000 / delta;
-
- m_LastBandwidth15sUpdateTime = ts;
- m_LastInBandwidth15sUpdateBytes = m_TotalReceivedBytes;
- m_LastOutBandwidth15sUpdateBytes = m_TotalSentBytes;
- m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes;
- }
+ m_TrafficSamplePtr++;
+ if (m_TrafficSamplePtr == TRAFFIC_SAMPLE_COUNT)
+ m_TrafficSamplePtr = 0;
+
+ TrafficSample& sample = m_TrafficSamples[m_TrafficSamplePtr];
+ sample.Timestamp = i2p::util::GetMillisecondsSinceEpoch();
+ sample.TotalReceivedBytes = m_TotalReceivedBytes;
+ sample.TotalSentBytes = m_TotalSentBytes;
+ sample.TotalTransitTransmittedBytes = m_TotalTransitTransmittedBytes;
+
+ UpdateBandwidthValues (1, m_InBandwidth, m_OutBandwidth, m_TransitBandwidth);
+ UpdateBandwidthValues (15, m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s);
+ UpdateBandwidthValues (300, m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m);
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
}
}
- bool Transports::IsBandwidthExceeded () const
+ int Transports::GetCongestionLevel (bool longTerm) const
{
- auto limit = i2p::context.GetBandwidthLimit() * 1024; // convert to bytes
- auto bw = std::max (m_InBandwidth15s, m_OutBandwidth15s);
- return bw > limit;
- }
+ auto bwLimit = i2p::context.GetBandwidthLimit () * 1024; // convert to bytes
+ auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes
- bool Transports::IsTransitBandwidthExceeded () const
- {
- auto limit = i2p::context.GetTransitBandwidthLimit() * 1024; // convert to bytes
- return m_TransitBandwidth > limit;
+ if (tbwLimit == 0 || bwLimit == 0)
+ return CONGESTION_LEVEL_FULL;
+
+ uint32_t bw;
+ uint32_t tbw;
+ if (longTerm)
+ {
+ bw = std::max (m_InBandwidth5m, m_OutBandwidth5m);
+ tbw = m_TransitBandwidth5m;
+ }
+ else
+ {
+ bw = std::max (m_InBandwidth15s, m_OutBandwidth15s);
+ tbw = m_TransitBandwidth;
+ }
+ auto bwCongestionLevel = CONGESTION_LEVEL_FULL * bw / bwLimit;
+ auto tbwCongestionLevel = CONGESTION_LEVEL_FULL * tbw / tbwLimit;
+ return std::max (bwCongestionLevel, tbwCongestionLevel);
}
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
@@ -436,6 +460,9 @@
auto it = m_Peers.find (ident);
if (it == m_Peers.end ())
{
+ // check if not banned
+ if (i2p::data::IsRouterBanned (ident)) return; // don't create peer to unreachable router
+ // try to connect
bool connected = false;
try
{
@@ -454,7 +481,7 @@
}
if (!connected) return;
}
- if (!it->second.sessions.empty ())
+ if (it->second.IsConnected ())
it->second.sessions.front ()->SendI2NPMessages (msgs);
else
{
@@ -463,17 +490,19 @@
{
if (sz < CHECK_PROFILE_NUM_DELAYED_MESSAGES && sz + msgs.size () >= CHECK_PROFILE_NUM_DELAYED_MESSAGES)
{
- auto profile = i2p::data::GetRouterProfile (ident);
- if (profile && profile->IsUnreachable ())
+ if (i2p::data::IsRouterBanned (ident))
{
- LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), " reports unreachable. Dropped");
+ LogPrint (eLogWarning, "Transports: Router ", ident.ToBase64 (), " is banned. Peer dropped");
std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.erase (it);
return;
}
}
for (auto& it1: msgs)
- it->second.delayedMessages.push_back (it1);
+ if (sz > MAX_NUM_DELAYED_MESSAGES/2 && it1->onDrop)
+ it1->Drop (); // drop earlier because we can handle it
+ else
+ it->second.delayedMessages.push_back (it1);
}
else
{
@@ -505,7 +534,7 @@
if (!m_NTCP2Server) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eNTCP2V6) ?
peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address ();
- if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ if (address && IsInReservedRange(address->host))
address = nullptr;
if (address)
{
@@ -524,7 +553,7 @@
if (!m_SSU2Server) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eSSU2V6) ?
peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address ();
- if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ if (address && IsInReservedRange(address->host))
address = nullptr;
if (address && address->IsReachableSSU ())
{
@@ -558,6 +587,14 @@
m_Peers.erase (ident);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Transports.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -85,11 +85,14 @@
isReachable = (bool)router->GetCompatibleTransports (true);
}
}
-
+
void Done ()
{
for (auto& it: sessions)
it->Done ();
+ // drop not sent delayed messages
+ for (auto& it: delayedMessages)
+ it->Drop ();
}
void SetRouter (std::shared_ptr<const i2p::data::RouterInfo> r)
@@ -101,6 +104,8 @@
isReachable = (bool)router->GetCompatibleTransports (true);
}
}
+
+ bool IsConnected () const { return !sessions.empty (); }
};
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
@@ -109,6 +114,17 @@
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
const int MAX_NUM_DELAYED_MESSAGES = 150;
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
+
+ const int TRAFFIC_SAMPLE_COUNT = 301; // seconds
+
+ struct TrafficSample
+ {
+ uint64_t Timestamp;
+ uint64_t TotalReceivedBytes;
+ uint64_t TotalSentBytes;
+ uint64_t TotalTransitTransmittedBytes;
+ };
+
class Transports
{
public:
@@ -148,8 +164,7 @@
uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; };
uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; };
uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; };
- bool IsBandwidthExceeded () const;
- bool IsTransitBandwidthExceeded () const;
+ int GetCongestionLevel (bool longTerm) const;
size_t GetNumPeers () const { return m_Peers.size (); };
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
@@ -160,14 +175,15 @@
/** restrict routes to use only these router families for first hops */
void RestrictRoutesToFamilies(const std::set<std::string>& families);
/** restrict routes to use only these routers for first hops */
- void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
+ void RestrictRoutesToRouters(const std::set<i2p::data::IdentHash>& routers);
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
void PeerTest (bool ipv4 = true, bool ipv6 = true);
void SetCheckReserved (bool check) { m_CheckReserved = check; };
- bool IsCheckReserved () { return m_CheckReserved; };
+ bool IsCheckReserved () const { return m_CheckReserved; };
+ bool IsInReservedRange (const boost::asio::ip::address& host) const;
private:
@@ -180,6 +196,7 @@
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
void HandlePeerTestTimer (const boost::system::error_code& ecode);
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
+ void UpdateBandwidthValues (int interval, uint32_t& in, uint32_t& out, uint32_t& transit);
void DetectExternalIP ();
@@ -204,14 +221,15 @@
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
+ TrafficSample m_TrafficSamples[TRAFFIC_SAMPLE_COUNT];
+ int m_TrafficSamplePtr;
+
// Bandwidth per second
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth;
- uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes, m_LastTransitBandwidthUpdateBytes;
-
- // Bandwidth every 15 seconds
+ // Bandwidth during last 15 seconds
uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s;
- uint64_t m_LastInBandwidth15sUpdateBytes, m_LastOutBandwidth15sUpdateBytes, m_LastTransitBandwidth15sUpdateBytes;
- uint64_t m_LastBandwidth15sUpdateTime;
+ // Bandwidth during last 5 minutes
+ uint32_t m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m;
/** which router families to trust for first hops */
std::vector<i2p::data::FamilyID> m_TrustedFamilies;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Tunnel.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -33,7 +33,7 @@
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
- m_IsRecreated (false), m_Latency (0)
+ m_IsRecreated (false), m_Latency (UNKNOWN_LATENCY)
{
}
@@ -52,7 +52,7 @@
// shuffle records
std::vector<int> recordIndicies;
for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
- std::shuffle (recordIndicies.begin(), recordIndicies.end(), std::mt19937(std::random_device()()));
+ std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()()));
// create real records
uint8_t * records = msg->GetPayload () + 1;
@@ -90,7 +90,13 @@
hop = hop->prev;
}
msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
-
+ auto s = shared_from_this ();
+ msg->onDrop = [s]()
+ {
+ LogPrint (eLogInfo, "I2NP: Tunnel ", s->GetTunnelID (), " request was not sent");
+ s->SetState (i2p::tunnel::eTunnelStateBuildFailed);
+ };
+
// send message
if (outboundTunnel)
{
@@ -116,7 +122,7 @@
if (m_Pool && m_Pool->GetLocalDestination ())
m_Pool->GetLocalDestination ()->SubmitECIESx25519Key (key, tag);
else
- i2p::context.AddECIESx25519Key (key, tag);
+ i2p::context.SubmitECIESx25519Key (key, tag);
}
i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
}
@@ -192,10 +198,10 @@
return established;
}
- bool Tunnel::LatencyFitsRange(uint64_t lower, uint64_t upper) const
+ bool Tunnel::LatencyFitsRange(int lowerbound, int upperbound) const
{
auto latency = GetMeanLatency();
- return latency >= lower && latency <= upper;
+ return latency >= lowerbound && latency <= upperbound;
}
void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
@@ -244,9 +250,9 @@
void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg)
{
- if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
+ if (GetState () != eTunnelStateExpiring) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
EncryptTunnelMsg (msg, msg);
- msg->from = shared_from_this ();
+ msg->from = GetSharedFromThis ();
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
}
@@ -261,7 +267,7 @@
if (msg)
{
m_NumReceivedBytes += msg->GetLength ();
- msg->from = shared_from_this ();
+ msg->from = GetSharedFromThis ();
HandleI2NPMessage (msg);
}
}
@@ -673,9 +679,10 @@
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
{
auto tunnel = *it;
- if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
+ if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT ||
+ ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ())
{
- LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
+ LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed");
auto pool = tunnel->GetTunnelPool ();
if (pool)
pool->TunnelExpired (tunnel);
@@ -724,10 +731,10 @@
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
{
auto tunnel = *it;
- if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT ||
+ if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT ||
ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ())
{
- LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
+ LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed");
auto pool = tunnel->GetTunnelPool ();
if (pool)
pool->TunnelExpired (tunnel);
@@ -979,7 +986,7 @@
return m_OutboundTunnels.size();
}
- void Tunnels::SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels)
+ void Tunnels::SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels)
{
if (maxNumTransitTunnels > 0 && m_MaxNumTransitTunnels != maxNumTransitTunnels)
{
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/Tunnel.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -39,7 +39,8 @@
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message
const int MAX_NUM_RECORDS = 8;
- const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds
+ const int UNKNOWN_LATENCY = -1;
+ const int HIGH_LATENCY_PER_HOP = 250000; // in microseconds
const int MAX_TUNNEL_MSGS_BATCH_SIZE = 100; // handle messages without interrupt
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000;
const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds
@@ -65,7 +66,8 @@
class OutboundTunnel;
class InboundTunnel;
- class Tunnel: public TunnelBase
+ class Tunnel: public TunnelBase,
+ public std::enable_shared_from_this<Tunnel>
{
struct TunnelHop
{
@@ -90,7 +92,7 @@
i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; };
TunnelState GetState () const { return m_State; };
void SetState (TunnelState state);
- bool IsEstablished () const { return m_State == eTunnelStateEstablished; };
+ bool IsEstablished () const { return m_State == eTunnelStateEstablished || m_State == eTunnelStateTestFailed; };
bool IsFailed () const { return m_State == eTunnelStateFailed; };
bool IsRecreated () const { return m_IsRecreated; };
void SetRecreated (bool recreated) { m_IsRecreated = recreated; };
@@ -107,14 +109,14 @@
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) override;
/** @brief add latency sample */
- void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; }
+ void AddLatencySample(const int us) { m_Latency = LatencyIsKnown() ? (m_Latency + us) >> 1 : us; }
/** @brief get this tunnel's estimated latency */
- uint64_t GetMeanLatency() const { return m_Latency; }
+ int GetMeanLatency() const { return (m_Latency + 500) / 1000; }
/** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */
- bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const;
+ bool LatencyFitsRange(int lowerbound, int upperbound) const;
- bool LatencyIsKnown() const { return m_Latency > 0; }
- bool IsSlow () const { return LatencyIsKnown() && (int)m_Latency > HIGH_LATENCY_PER_HOP*GetNumHops (); }
+ bool LatencyIsKnown() const { return m_Latency != UNKNOWN_LATENCY; }
+ bool IsSlow () const { return LatencyIsKnown() && m_Latency > HIGH_LATENCY_PER_HOP*GetNumHops (); }
/** visit all hops we currently store */
void VisitTunnelHops(TunnelHopVisitor v);
@@ -128,7 +130,7 @@
TunnelState m_State;
i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports;
bool m_IsRecreated; // if tunnel is replaced by new, or new tunnel requested to replace
- uint64_t m_Latency; // in milliseconds
+ int m_Latency; // in microseconds
};
class OutboundTunnel: public Tunnel
@@ -155,7 +157,7 @@
i2p::data::IdentHash m_EndpointIdentHash;
};
- class InboundTunnel: public Tunnel, public std::enable_shared_from_this<InboundTunnel>
+ class InboundTunnel: public Tunnel
{
public:
@@ -167,6 +169,13 @@
// override TunnelBase
void Cleanup () override { m_Endpoint.Cleanup (); };
+ protected:
+
+ std::shared_ptr<InboundTunnel> GetSharedFromThis ()
+ {
+ return std::static_pointer_cast<InboundTunnel>(shared_from_this ());
+ }
+
private:
TunnelEndpoint m_Endpoint;
@@ -230,9 +239,9 @@
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint);
- void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
- uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
- bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
+ void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels);
+ uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
+ int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; }
private:
@@ -292,7 +301,7 @@
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE> > m_I2NPTunnelEndpointMessagesMemoryPool;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_MESSAGE_SIZE> > m_I2NPTunnelMessagesMemoryPool;
- uint16_t m_MaxNumTransitTunnels;
+ uint32_t m_MaxNumTransitTunnels;
// count of tunnels for total TCSR algorithm
int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations;
double m_TunnelCreationSuccessRate;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/TunnelGateway.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2021, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -35,6 +35,13 @@
if (!m_CurrentTunnelDataMsg)
{
CreateCurrentTunnelDataMessage ();
+ if (block.data && block.data->onDrop)
+ {
+ // onDrop is called for the first fragment in tunnel message
+ // that's usually true for short TBMs or lookups
+ m_CurrentTunnelDataMsg->onDrop = block.data->onDrop;
+ block.data->onDrop = nullptr;
+ }
messageCreated = true;
}
@@ -155,7 +162,6 @@
void TunnelGatewayBuffer::CreateCurrentTunnelDataMessage ()
{
- m_CurrentTunnelDataMsg = nullptr;
m_CurrentTunnelDataMsg = NewI2NPTunnelMessage (true); // tunnel endpoint is at least of two tunnel messages size
// we reserve space for padding
m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE;
@@ -223,6 +229,7 @@
m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg);
htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ());
newMsg->FillI2NPMessageHeader (eI2NPTunnelData);
+ if (tunnelMsg->onDrop) newMsg->onDrop = tunnelMsg->onDrop;
newTunnelMsgs.push_back (newMsg);
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/TunnelPool.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -7,13 +7,13 @@
*/
#include <algorithm>
-#include <random>
#include "I2PEndian.h"
#include "Crypto.h"
#include "Tunnel.h"
#include "NetDb.hpp"
#include "Timestamp.h"
#include "Garlic.h"
+#include "ECIESX25519AEADRatchetSession.h"
#include "Transports.h"
#include "Log.h"
#include "Tunnel.h"
@@ -45,7 +45,7 @@
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance),
- m_IsActive (true), m_CustomPeerSelector(nullptr)
+ m_IsActive (true), m_CustomPeerSelector(nullptr), m_Rng(m_Rd())
{
if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY)
m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY;
@@ -102,7 +102,10 @@
it->SetTunnelPool (nullptr);
m_OutboundTunnels.clear ();
}
- m_Tests.clear ();
+ {
+ std::unique_lock<std::mutex> l(m_TestsMutex);
+ m_Tests.clear ();
+ }
}
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)
@@ -145,8 +148,11 @@
if (expiredTunnel)
{
expiredTunnel->SetTunnelPool (nullptr);
- for (auto& it: m_Tests)
- if (it.second.second == expiredTunnel) it.second.second = nullptr;
+ {
+ std::unique_lock<std::mutex> l(m_TestsMutex);
+ for (auto& it: m_Tests)
+ if (it.second.second == expiredTunnel) it.second.second = nullptr;
+ }
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
m_InboundTunnels.erase (expiredTunnel);
@@ -167,8 +173,11 @@
if (expiredTunnel)
{
expiredTunnel->SetTunnelPool (nullptr);
- for (auto& it: m_Tests)
- if (it.second.first == expiredTunnel) it.second.first = nullptr;
+ {
+ std::unique_lock<std::mutex> l(m_TestsMutex);
+ for (auto& it: m_Tests)
+ if (it.second.first == expiredTunnel) it.second.first = nullptr;
+ }
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
m_OutboundTunnels.erase (expiredTunnel);
@@ -301,7 +310,7 @@
{
for (auto it: m_OutboundTunnels)
{
- // try to create inbound tunnel through the same path as succesive outbound
+ // try to create inbound tunnel through the same path as successive outbound
CreatePairedInboundTunnel (it);
num++;
if (num >= m_NumInboundTunnels) break;
@@ -337,9 +346,12 @@
{
it.second.first->SetState (eTunnelStateFailed);
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
- m_OutboundTunnels.erase (it.second.first);
+ if (m_OutboundTunnels.size () > 1 || m_NumOutboundTunnels <= 1) // don't fail last tunnel
+ m_OutboundTunnels.erase (it.second.first);
+ else
+ it.second.first->SetState (eTunnelStateTestFailed);
}
- else
+ else if (it.second.first->GetState () != eTunnelStateExpiring)
it.second.first->SetState (eTunnelStateTestFailed);
}
if (it.second.second)
@@ -349,47 +361,88 @@
it.second.second->SetState (eTunnelStateFailed);
{
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
- m_InboundTunnels.erase (it.second.second);
+ if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel
+ m_InboundTunnels.erase (it.second.second);
+ else
+ it.second.second->SetState (eTunnelStateTestFailed);
}
if (m_LocalDestination)
m_LocalDestination->SetLeaseSetUpdated ();
}
- else
+ else if (it.second.second->GetState () != eTunnelStateExpiring)
it.second.second->SetState (eTunnelStateTestFailed);
}
}
// new tests
- std::unique_lock<std::mutex> l1(m_OutboundTunnelsMutex);
- auto it1 = m_OutboundTunnels.begin ();
- std::unique_lock<std::mutex> l2(m_InboundTunnelsMutex);
- auto it2 = m_InboundTunnels.begin ();
- while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ())
+ if (!m_LocalDestination) return;
+ std::vector<std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > newTests;
+ std::vector<std::shared_ptr<OutboundTunnel> > outboundTunnels;
{
- bool failed = false;
- if ((*it1)->IsFailed ())
- {
- failed = true;
- ++it1;
- }
- if ((*it2)->IsFailed ())
- {
- failed = true;
- ++it2;
- }
- if (!failed)
- {
- uint32_t msgID;
- RAND_bytes ((uint8_t *)&msgID, 4);
+ std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
+ for (auto& it: m_OutboundTunnels)
+ if (it->IsEstablished ())
+ outboundTunnels.push_back (it);
+ }
+ std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), m_Rng);
+ std::vector<std::shared_ptr<InboundTunnel> > inboundTunnels;
+ {
+ std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
+ for (auto& it: m_InboundTunnels)
+ if (it->IsEstablished ())
+ inboundTunnels.push_back (it);
+ }
+ std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), m_Rng);
+ auto it1 = outboundTunnels.begin ();
+ auto it2 = inboundTunnels.begin ();
+ while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ())
+ {
+ newTests.push_back(std::make_pair (*it1, *it2));
+ ++it1; ++it2;
+ }
+ bool isECIES = m_LocalDestination->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
+ for (auto& it: newTests)
+ {
+ uint32_t msgID;
+ RAND_bytes ((uint8_t *)&msgID, 4);
+ {
+ std::unique_lock<std::mutex> l(m_TestsMutex);
+ m_Tests[msgID] = it;
+ }
+ auto msg = CreateTunnelTestMsg (msgID);
+ auto outbound = it.first;
+ auto s = shared_from_this ();
+ msg->onDrop = [msgID, outbound, s]()
{
- std::unique_lock<std::mutex> l(m_TestsMutex);
- m_Tests[msgID] = std::make_pair (*it1, *it2);
- }
- (*it1)->SendTunnelDataMsgTo ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
- CreateDeliveryStatusMsg (msgID));
- ++it1; ++it2;
+ // if test msg dropped locally it's outbound tunnel to blame
+ outbound->SetState (eTunnelStateFailed);
+ {
+ std::unique_lock<std::mutex> l(s->m_TestsMutex);
+ s->m_Tests.erase (msgID);
+ }
+ {
+ std::unique_lock<std::mutex> l(s->m_OutboundTunnelsMutex);
+ s->m_OutboundTunnels.erase (outbound);
+ }
+ };
+ // encrypt
+ if (isECIES)
+ {
+ uint8_t key[32]; RAND_bytes (key, 32);
+ uint64_t tag; RAND_bytes ((uint8_t *)&tag, 8);
+ m_LocalDestination->SubmitECIESx25519Key (key, tag);
+ msg = i2p::garlic::WrapECIESX25519Message (msg, key, tag);
}
- }
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/TunnelPool.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -15,6 +15,7 @@
#include <utility>
#include <mutex>
#include <memory>
+#include <random>
#include "Identity.h"
#include "LeaseSet.h"
#include "RouterInfo.h"
@@ -30,7 +31,8 @@
const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds
const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16;
const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16;
- const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 2;
+ const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 3;
+ const int TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS = 3;
class Tunnel;
class InboundTunnel;
@@ -83,6 +85,8 @@
void ManageTunnels (uint64_t ts);
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
void ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg);
+ void ProcessTunnelTest (std::shared_ptr<I2NPMessage> msg);
+ bool ProcessTunnelTest (uint32_t msgID, uint64_t timestamp);
bool IsExploratory () const;
bool IsActive () const { return m_IsActive; };
@@ -102,7 +106,7 @@
bool HasCustomPeerSelector();
/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
- void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
+ void RequireLatency(int min, int max) { m_MinLatency = min; m_MaxLatency = max; }
/** @brief return true if this tunnel pool has a latency requirement */
bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
@@ -115,6 +119,8 @@
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse, bool endpoint) const;
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop);
+ std::mt19937& GetRng () { return m_Rng; }
+
private:
void TestTunnels ();
@@ -145,9 +151,12 @@
std::mutex m_CustomPeerSelectorMutex;
ITunnelPeerSelector * m_CustomPeerSelector;
- uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
- uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
+ int m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
+ int m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
+ std::random_device m_Rd;
+ std::mt19937 m_Rng;
+
public:
// for HTTP only
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/api.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -44,6 +44,9 @@
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);
+ bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved);
+ i2p::transport::transports.SetCheckReserved(checkReserved);
+
i2p::context.Init ();
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd/version.h
^
|
@@ -18,8 +18,8 @@
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
#define I2PD_VERSION_MAJOR 2
-#define I2PD_VERSION_MINOR 50
-#define I2PD_VERSION_MICRO 2
+#define I2PD_VERSION_MINOR 51
+#define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0
#ifdef GITVER
#define I2PD_VERSION XSTRINGIZE(GITVER)
@@ -33,7 +33,7 @@
#define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9
-#define I2P_VERSION_MICRO 61
+#define I2P_VERSION_MICRO 62
#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)
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/ClientContext.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -16,6 +16,7 @@
#include "Identity.h"
#include "util.h"
#include "ClientContext.h"
+#include "HTTPProxy.h"
#include "SOCKS.h"
#include "MatchedDestination.h"
@@ -775,7 +776,7 @@
address = "127.0.0.1";
}
auto localAddress = boost::asio::ip::address::from_string(address);
- auto serverTunnel = std::make_shared<I2PUDPServerTunnel>(name, localDestination, localAddress, endpoint, port, gzip);
+ auto serverTunnel = std::make_shared<I2PUDPServerTunnel>(name, localDestination, localAddress, endpoint, inPort, gzip);
if(!isUniqueLocal)
{
LogPrint(eLogInfo, "Clients: Disabling loopback address mapping");
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/ClientContext.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -15,8 +15,6 @@
#include <boost/asio.hpp>
#include "Destination.h"
#include "I2PService.h"
-#include "HTTPProxy.h"
-#include "SOCKS.h"
#include "I2PTunnel.h"
#include "UDPTunnel.h"
#include "SAM.h"
@@ -141,8 +139,7 @@
AddressBook m_AddressBook;
- i2p::proxy::HTTPProxy * m_HttpProxy;
- i2p::proxy::SOCKSProxy * m_SocksProxy;
+ I2PService * m_HttpProxy, * m_SocksProxy;
std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint -> tunnel
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port> -> tunnel
@@ -167,8 +164,8 @@
const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; };
const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; }
const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; }
- const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; }
- const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; }
+ const I2PService * GetHttpProxy () const { return m_HttpProxy; }
+ const I2PService * GetSocksProxy () const { return m_SocksProxy; }
};
extern ClientContext context;
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/HTTPProxy.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -29,6 +29,7 @@
#include "Config.h"
#include "HTTP.h"
#include "I18N.h"
+#include "Socks5.h"
namespace i2p {
namespace proxy {
@@ -93,9 +94,6 @@
void HTTPConnect(const std::string & host, uint16_t port);
void HandleHTTPConnectStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream);
- void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered);
- void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered);
-
typedef std::function<void(boost::asio::ip::tcp::endpoint)> ProxyResolvedHandler;
void HandleUpstreamProxyResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr, ProxyResolvedHandler handler);
@@ -113,7 +111,6 @@
bool m_Addresshelper;
i2p::http::URL m_ProxyURL;
i2p::http::URL m_RequestURL;
- uint8_t m_socks_buf[255+8]; // for socks request/response
int m_req_len;
i2p::http::URL m_ClientRequestURL;
i2p::http::HTTPReq m_ClientRequest;
@@ -612,49 +609,36 @@
void HTTPReqHandler::HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec)
{
- if(!ec) {
- if(m_RequestURL.host.size() > 255) {
+ if(!ec)
+ {
+ if(m_RequestURL.host.size() > 255)
+ {
GenericProxyError(tr("Hostname is too long"), m_RequestURL.host);
return;
}
uint16_t port = m_RequestURL.port;
if(!port) port = 80;
LogPrint(eLogDebug, "HTTPProxy: Connected to SOCKS upstream");
-
std::string host = m_RequestURL.host;
- std::size_t reqsize = 0;
- m_socks_buf[0] = '\x04';
- m_socks_buf[1] = 1;
- htobe16buf(m_socks_buf+2, port);
- m_socks_buf[4] = 0;
- m_socks_buf[5] = 0;
- m_socks_buf[6] = 0;
- m_socks_buf[7] = 1;
- // user id
- m_socks_buf[8] = 'i';
- m_socks_buf[9] = '2';
- m_socks_buf[10] = 'p';
- m_socks_buf[11] = 'd';
- m_socks_buf[12] = 0;
- reqsize += 13;
- memcpy(m_socks_buf+ reqsize, host.c_str(), host.size());
- reqsize += host.size();
- m_socks_buf[++reqsize] = 0;
- boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2));
- } else GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message());
- }
-
- void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred)
- {
- LogPrint(eLogDebug, "HTTPProxy: Upstream SOCKS handshake sent");
- if(ec) GenericProxyError(tr("Cannot negotiate with SOCKS proxy"), ec.message());
- else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2));
+ auto s = shared_from_this ();
+ i2p::transport::Socks5Handshake (*m_proxysock, std::make_pair(host, port),
+ [s](const boost::system::error_code& ec)
+ {
+ if (!ec)
+ s->SocksProxySuccess();
+ else
+ s->GenericProxyError(tr("SOCKS proxy error"), ec.message ());
+ });
+
+ }
+ else
+ GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message());
}
void HTTPReqHandler::HandoverToUpstreamProxy()
{
LogPrint(eLogDebug, "HTTPProxy: Handover to SOCKS proxy");
- auto connection = std::make_shared<i2p::client::TCPIPPipe>(GetOwner(), m_proxysock, m_sock);
+ auto connection = CreateSocketsPipe (GetOwner(), m_proxysock, m_sock);
m_sock = nullptr;
m_proxysock = nullptr;
GetOwner()->AddHandler(connection);
@@ -714,24 +698,6 @@
}
}
- void HTTPReqHandler::HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transferred)
- {
- if(!ec)
- {
- if(m_socks_buf[1] == 90) {
- // success
- SocksProxySuccess();
- } else {
- std::stringstream ss;
- ss << "error code: ";
- ss << (int) m_socks_buf[1];
- std::string msg = ss.str();
- GenericProxyError(tr("SOCKS proxy error"), msg);
- }
- }
- else GenericProxyError(tr("No reply from SOCKS proxy"), ec.message());
- }
-
void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec)
{
if(!ec) {
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/I2PService.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -147,196 +147,5 @@
m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port);
}
}
-
- TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
- {
- boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
- upstream->set_option(option);
- downstream->set_option(option);
- }
-
- TCPIPPipe::~TCPIPPipe()
- {
- Terminate();
- }
-
- void TCPIPPipe::Start()
- {
- AsyncReceiveUpstream();
- AsyncReceiveDownstream();
- }
-
- void TCPIPPipe::Terminate()
- {
- if(Kill()) return;
- if (m_up)
- {
- if (m_up->is_open())
- m_up->close();
- m_up = nullptr;
- }
- if (m_down)
- {
- if (m_down->is_open())
- m_down->close();
- m_down = nullptr;
- }
- Done(shared_from_this());
- }
-
- void TCPIPPipe::AsyncReceiveUpstream()
- {
- if (m_up)
- {
- m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
- std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
- std::placeholders::_1, std::placeholders::_2));
- }
- else
- LogPrint(eLogError, "TCPIPPipe: Upstream receive: No socket");
- }
-
- void TCPIPPipe::AsyncReceiveDownstream()
- {
- if (m_down) {
- m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
- std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
- std::placeholders::_1, std::placeholders::_2));
- }
- else
- LogPrint(eLogError, "TCPIPPipe: Downstream receive: No socket");
- }
-
- void TCPIPPipe::UpstreamWrite(size_t len)
- {
- if (m_up)
- {
- LogPrint(eLogDebug, "TCPIPPipe: Upstream: ", (int) len, " bytes written");
- boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
- boost::asio::transfer_all(),
- std::bind(&TCPIPPipe::HandleUpstreamWrite,
- shared_from_this(),
- std::placeholders::_1));
- }
- else
- LogPrint(eLogError, "TCPIPPipe: Upstream write: no socket");
- }
-
- void TCPIPPipe::DownstreamWrite(size_t len)
- {
- if (m_down)
- {
- LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written");
- boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
- boost::asio::transfer_all(),
- std::bind(&TCPIPPipe::HandleDownstreamWrite,
- shared_from_this(),
- std::placeholders::_1));
- }
- else
- LogPrint(eLogError, "TCPIPPipe: Downstream write: No socket");
- }
-
-
- void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
- {
- LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received");
- if (ecode)
- {
- LogPrint(eLogError, "TCPIPPipe: Downstream read error:" , ecode.message());
- if (ecode != boost::asio::error::operation_aborted)
- Terminate();
- } else {
- if (bytes_transfered > 0 )
- memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
- UpstreamWrite(bytes_transfered);
- }
- }
-
- void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
- if (ecode)
- {
- LogPrint(eLogError, "TCPIPPipe: Downstream write error:" , ecode.message());
- if (ecode != boost::asio::error::operation_aborted)
- Terminate();
- }
- else
- AsyncReceiveUpstream();
- }
-
- void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
- if (ecode)
- {
- LogPrint(eLogError, "TCPIPPipe: Upstream write error:" , ecode.message());
- if (ecode != boost::asio::error::operation_aborted)
- Terminate();
- }
- else
- AsyncReceiveDownstream();
- }
-
- void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
- {
- LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received");
- if (ecode)
- {
- LogPrint(eLogError, "TCPIPPipe: Upstream read error:" , ecode.message());
- if (ecode != boost::asio::error::operation_aborted)
- Terminate();
- } else {
- if (bytes_transfered > 0 )
- memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
- DownstreamWrite(bytes_transfered);
- }
- }
-
- void TCPIPAcceptor::Start ()
- {
- m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
- // update the local end point in case port has been set zero and got updated now
- m_LocalEndpoint = m_Acceptor->local_endpoint();
- m_Acceptor->listen ();
- Accept ();
- }
-
- void TCPIPAcceptor::Stop ()
- {
- if (m_Acceptor)
- {
- m_Acceptor->close();
- m_Acceptor.reset (nullptr);
- }
- m_Timer.cancel ();
- ClearHandlers();
- }
-
- void TCPIPAcceptor::Accept ()
- {
- auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ());
- m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
- std::placeholders::_1, newSocket));
- }
-
- void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
- {
- if (!ecode)
- {
- LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
- auto handler = CreateHandler(socket);
- if (handler)
- {
- AddHandler(handler);
- handler->Handle();
- }
- else
- socket->close();
- Accept();
- }
- else
- {
- if (ecode != boost::asio::error::operation_aborted)
- LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/I2PService.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -99,6 +99,7 @@
virtual ~I2PServiceHandler() { }
//If you override this make sure you call it from the children
virtual void Handle() {}; //Start handling the socket
+ virtual void Start () {};
void Terminate () { Kill (); };
@@ -119,72 +120,171 @@
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
};
- const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8;
+ const size_t SOCKETS_PIPE_BUFFER_SIZE = 8192 * 8;
- // bidirectional pipe for 2 tcp/ip sockets
- class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
+ // bidirectional pipe for 2 stream sockets
+ template<typename SocketUpstream, typename SocketDownstream>
+ class SocketsPipe: public I2PServiceHandler,
+ public std::enable_shared_from_this<SocketsPipe<SocketUpstream, SocketDownstream> >
{
public:
- TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
- ~TCPIPPipe();
- void Start();
-
- protected:
+ SocketsPipe(I2PService * owner, std::shared_ptr<SocketUpstream> upstream, std::shared_ptr<SocketDownstream> downstream):
+ I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
+ {
+ boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE);
+ upstream->set_option(option);
+ downstream->set_option(option);
+ }
+ ~SocketsPipe() { Terminate(); }
+
+ void Start() override
+ {
+ Transfer (m_up, m_down, m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream
+ Transfer (m_down, m_up, m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream
+ }
- void Terminate();
- void AsyncReceiveUpstream();
- void AsyncReceiveDownstream();
- void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
- void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
- void HandleUpstreamWrite(const boost::system::error_code & ecode);
- void HandleDownstreamWrite(const boost::system::error_code & ecode);
- void UpstreamWrite(size_t len);
- void DownstreamWrite(size_t len);
+ private:
+ void Terminate()
+ {
+ if(Kill()) return;
+ if (m_up)
+ {
+ if (m_up->is_open())
+ m_up->close();
+ m_up = nullptr;
+ }
+ if (m_down)
+ {
+ if (m_down->is_open())
+ m_down->close();
+ m_down = nullptr;
+ }
+ Done(SocketsPipe<SocketUpstream, SocketDownstream>::shared_from_this());
+ }
+
+ template<typename From, typename To>
+ void Transfer (std::shared_ptr<From> from, std::shared_ptr<To> to, uint8_t * buf, size_t len)
+ {
+ if (!from || !to || !buf) return;
+ auto s = SocketsPipe<SocketUpstream, SocketDownstream>::shared_from_this ();
+ from->async_read_some(boost::asio::buffer(buf, len),
+ [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred)
+ {
+ if (ecode == boost::asio::error::operation_aborted) return;
+ if (!ecode)
+ {
+ boost::asio::async_write(*to, boost::asio::buffer(buf, transferred), boost::asio::transfer_all(),
+ [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred)
+ {
+ (void) transferred;
+ if (ecode == boost::asio::error::operation_aborted) return;
+ if (!ecode)
+ s->Transfer (from, to, buf, len);
+ else
+ {
+ LogPrint(eLogWarning, "SocketsPipe: Write error:" , ecode.message());
+ s->Terminate();
+ }
+ });
+ }
+ else
+ {
+ LogPrint(eLogWarning, "SocketsPipe: Read error:" , ecode.message());
+ s->Terminate();
+ }
+ });
+ }
+
private:
- uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
- uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
- std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
+ uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE];
+ std::shared_ptr<SocketUpstream> m_up;
+ std::shared_ptr<SocketDownstream> m_down;
};
- /* TODO: support IPv6 too */
- //This is a service that listens for connections on the IP network and interacts with I2P
- class TCPIPAcceptor: public I2PService
+ template<typename SocketUpstream, typename SocketDownstream>
+ std::shared_ptr<I2PServiceHandler> CreateSocketsPipe (I2PService * owner, std::shared_ptr<SocketUpstream> upstream, std::shared_ptr<SocketDownstream> downstream)
+ {
+ return std::make_shared<SocketsPipe<SocketUpstream, SocketDownstream> >(owner, upstream, downstream);
+ }
+
+ //This is a service that listens for connections on the IP network or local socket and interacts with I2P
+ template<typename Protocol>
+ class ServiceAcceptor: public I2PService
{
public:
- TCPIPAcceptor (const std::string& address, uint16_t port, std::shared_ptr<ClientDestination> localDestination = nullptr) :
- I2PService(localDestination),
- m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
- m_Timer (GetService ()) {}
- TCPIPAcceptor (const std::string& address, uint16_t port, i2p::data::SigningKeyType kt) :
- I2PService(kt),
- m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
- m_Timer (GetService ()) {}
- virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); }
- //If you override this make sure you call it from the children
- void Start ();
- //If you override this make sure you call it from the children
- void Stop ();
-
- const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
+ ServiceAcceptor (const typename Protocol::endpoint& localEndpoint, std::shared_ptr<ClientDestination> localDestination = nullptr) :
+ I2PService(localDestination), m_LocalEndpoint (localEndpoint) {}
+
+ virtual ~ServiceAcceptor () { Stop(); }
+ void Start () override
+ {
+ m_Acceptor.reset (new typename Protocol::acceptor (GetService (), m_LocalEndpoint));
+ // update the local end point in case port has been set zero and got updated now
+ m_LocalEndpoint = m_Acceptor->local_endpoint();
+ m_Acceptor->listen ();
+ Accept ();
+ }
+ void Stop () override
+ {
+ if (m_Acceptor)
+ {
+ m_Acceptor->close();
+ m_Acceptor.reset (nullptr);
+ }
+ ClearHandlers();
+ }
+ const typename Protocol::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
- virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
+ const char* GetName() override { return "Generic TCP/IP accepting daemon"; }
protected:
- virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
+ virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<typename Protocol::socket> socket) = 0;
private:
- void Accept();
- void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
- boost::asio::ip::tcp::endpoint m_LocalEndpoint;
- std::unique_ptr<boost::asio::ip::tcp::acceptor> m_Acceptor;
- boost::asio::deadline_timer m_Timer;
+ void Accept()
+ {
+ auto newSocket = std::make_shared<typename Protocol::socket> (GetService ());
+ m_Acceptor->async_accept (*newSocket,
+ [newSocket, this](const boost::system::error_code& ecode)
+ {
+ if (ecode == boost::asio::error::operation_aborted) return;
+ if (!ecode)
+ {
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/SAM.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -415,12 +415,17 @@
{
session->UDPEndpoint = forward;
auto dest = session->GetLocalDestination ()->CreateDatagramDestination ();
+ auto port = std::stoi(params[SAM_PARAM_PORT]);
if (type == eSAMSessionTypeDatagram)
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
- std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5),
+ port
+ );
else // raw
dest->SetRawReceiver (std::bind (&SAMSocket::HandleI2PRawDatagramReceive, shared_from_this (),
- std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
+ port
+ );
}
if (session->GetLocalDestination ()->IsReady ())
@@ -523,15 +528,20 @@
{
if (addr->IsIdentHash ())
{
- auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash);
- if (leaseSet)
- Connect(leaseSet, session);
- else
+ if (session->GetLocalDestination ()->GetIdentHash () != addr->identHash)
{
- session->GetLocalDestination ()->RequestDestination(addr->identHash,
- std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete,
- shared_from_this(), std::placeholders::_1));
+ auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash);
+ if (leaseSet)
+ Connect(leaseSet, session);
+ else
+ {
+ session->GetLocalDestination ()->RequestDestination(addr->identHash,
+ std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete,
+ shared_from_this(), std::placeholders::_1));
+ }
}
+ else
+ SendStreamCantReachPeer ("Can't connect to myself");
}
else // B33
session->GetLocalDestination ()->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey,
@@ -550,17 +560,22 @@
if (!session) session = m_Owner.FindSession(m_ID);
if (session)
{
- m_SocketType = eSAMSocketTypeStream;
- m_Stream = session->GetLocalDestination ()->CreateStream (remote);
- if (m_Stream)
+ if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ()))
{
- m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send
- m_BufferOffset = 0;
- I2PReceive ();
- SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
+ m_SocketType = eSAMSocketTypeStream;
+ m_Stream = session->GetLocalDestination ()->CreateStream (remote);
+ if (m_Stream)
+ {
+ m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send
+ m_BufferOffset = 0;
+ I2PReceive ();
+ SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
+ }
+ else
+ SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
}
else
- SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
+ SendStreamCantReachPeer ("Incompatible crypto");
}
else
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
@@ -573,7 +588,7 @@
else
{
LogPrint (eLogError, "SAM: Destination to connect not found");
- SendMessageReply (SAM_STREAM_STATUS_CANT_REACH_PEER, strlen(SAM_STREAM_STATUS_CANT_REACH_PEER), true);
+ SendStreamCantReachPeer ("LeaseSet not found");
}
}
@@ -602,27 +617,27 @@
session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1));
}
else
- {
+ {
auto ts = i2p::util::GetSecondsSinceEpoch ();
while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts)
- {
+ {
auto socket = session->acceptQueue.front ().first;
session->acceptQueue.pop_front ();
if (socket)
m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket));
- }
+ }
if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE)
{
// already accepting, queue up
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts));
- }
- else
- {
+ }
+ else
+ {
LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ());
SendStreamI2PError ("Already accepting");
- }
- }
+ }
+ }
}
else
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
@@ -857,28 +872,33 @@
SendSessionI2PError ("Wrong session type");
}
- void SAMSocket::SendSessionI2PError(const std::string & msg)
+ void SAMSocket::SendReplyWithMessage (const char * reply, const std::string & msg)
{
- LogPrint (eLogError, "SAM: Session I2P error: ", msg);
#ifdef _MSC_VER
- size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
+ size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str());
#else
- size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
+ size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str());
#endif
SendMessageReply (m_Buffer, len, true);
}
+ void SAMSocket::SendSessionI2PError(const std::string & msg)
+ {
+ LogPrint (eLogError, "SAM: Session I2P error: ", msg);
+ SendReplyWithMessage (SAM_SESSION_STATUS_I2P_ERROR, msg);
+ }
+
void SAMSocket::SendStreamI2PError(const std::string & msg)
{
LogPrint (eLogError, "SAM: Stream I2P error: ", msg);
-#ifdef _MSC_VER
- size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str());
-#else
- size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str());
-#endif
- SendMessageReply (m_Buffer, len, true);
+ SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg);
}
-
+
+ void SAMSocket::SendStreamCantReachPeer(const std::string & msg)
+ {
+ SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg);
+ }
+
void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, std::string name)
{
if (leaseSet)
@@ -1078,14 +1098,14 @@
// pending acceptors
auto ts = i2p::util::GetSecondsSinceEpoch ();
while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts)
- {
+ {
auto socket = session->acceptQueue.front ().first;
session->acceptQueue.pop_front ();
if (socket)
m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket));
- }
+ }
if (!session->acceptQueue.empty ())
- {
+ {
auto socket = session->acceptQueue.front ().first;
session->acceptQueue.pop_front ();
if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor)
@@ -1093,7 +1113,7 @@
socket->m_IsAccepting = true;
session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1));
}
- }
+ }
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/SAM.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -51,7 +51,7 @@
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n";
- const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n";
+ const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"%s\"\n";
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n";
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
const char SAM_STREAM_FORWARD[] = "STREAM FORWARD";
@@ -144,8 +144,10 @@
void ProcessNamingLookup (char * buf, size_t len);
void ProcessSessionAdd (char * buf, size_t len);
void ProcessSessionRemove (char * buf, size_t len);
+ void SendReplyWithMessage (const char * reply, const std::string & msg);
void SendSessionI2PError(const std::string & msg);
void SendStreamI2PError(const std::string & msg);
+ void SendStreamCantReachPeer(const std::string & msg);
size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0
void ExtractParams (char * buf, std::map<std::string, std::string>& params);
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/SOCKS.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2023, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,6 +19,7 @@
#include "I2PTunnel.h"
#include "I2PService.h"
#include "util.h"
+#include "Socks5.h"
namespace i2p
{
@@ -27,10 +28,6 @@
static const size_t socks_buffer_size = 8192;
static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse
- //static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192;
-
- static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8;
-
struct SOCKSDnsAddress
{
uint8_t size;
@@ -132,7 +129,6 @@
boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method);
boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port);
boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port);
- boost::asio::const_buffers_1 GenerateUpstreamRequest();
bool Socks5ChooseAuth();
void Socks5UserPasswdResponse ();
void SocksRequestFailed(errTypes error);
@@ -143,12 +139,11 @@
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
void ForwardSOCKS();
- void SocksUpstreamSuccess();
+ template<typename Socket>
+ void SocksUpstreamSuccess(std::shared_ptr<Socket>& upstreamSock);
void AsyncUpstreamSockRead();
- void SendUpstreamRequest();
- void HandleUpstreamData(uint8_t * buff, std::size_t len);
- void HandleUpstreamSockSend(const boost::system::error_code & ecode, std::size_t bytes_transfered);
- void HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
+ template<typename Socket>
+ void SendUpstreamRequest(std::shared_ptr<Socket>& upstreamSock);
void HandleUpstreamConnected(const boost::system::error_code & ecode,
boost::asio::ip::tcp::resolver::iterator itr);
void HandleUpstreamResolved(const boost::system::error_code & ecode,
@@ -157,13 +152,13 @@
boost::asio::ip::tcp::resolver m_proxy_resolver;
uint8_t m_sock_buff[socks_buffer_size];
std::shared_ptr<boost::asio::ip::tcp::socket> m_sock, m_upstreamSock;
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ std::shared_ptr<boost::asio::local::stream_protocol::socket> m_upstreamLocalSock;
+#endif
std::shared_ptr<i2p::stream::Stream> m_stream;
uint8_t *m_remaining_data; //Data left to be sent
uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded
uint8_t m_response[7+max_socks_hostname_size];
- uint8_t m_upstream_response[SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE];
- uint8_t m_upstream_request[14+max_socks_hostname_size];
- std::size_t m_upstream_response_len;
address m_address; //Address
std::size_t m_remaining_data_len; //Size of the data left to be sent
uint32_t m_4aip; //Used in 4a requests
@@ -222,6 +217,14 @@
m_upstreamSock->close();
m_upstreamSock = nullptr;
}
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ if (m_upstreamLocalSock)
+ {
+ LogPrint(eLogDebug, "SOCKS: Closing upstream local socket");
+ m_upstreamLocalSock->close();
+ m_upstreamLocalSock = nullptr;
+ }
+#endif
if (m_stream)
{
LogPrint(eLogDebug, "SOCKS: Closing stream");
@@ -280,37 +283,6 @@
return boost::asio::const_buffers_1(m_response, size);
}
- boost::asio::const_buffers_1 SOCKSHandler::GenerateUpstreamRequest()
- {
- size_t upstreamRequestSize = 0;
- // TODO: negotiate with upstream
- // SOCKS 4a
- m_upstream_request[0] = '\x04'; //version
- m_upstream_request[1] = m_cmd;
- htobe16buf(m_upstream_request + 2, m_port);
- m_upstream_request[4] = 0;
- m_upstream_request[5] = 0;
- m_upstream_request[6] = 0;
- m_upstream_request[7] = 1;
- // user id
- m_upstream_request[8] = 'i';
- m_upstream_request[9] = '2';
- m_upstream_request[10] = 'p';
- m_upstream_request[11] = 'd';
- m_upstream_request[12] = 0;
- upstreamRequestSize += 13;
- if (m_address.dns.size <= max_socks_hostname_size - ( upstreamRequestSize + 1) ) {
- // bounds check okay
- memcpy(m_upstream_request + upstreamRequestSize, m_address.dns.value, m_address.dns.size);
- upstreamRequestSize += m_address.dns.size;
- // null terminate
- m_upstream_request[++upstreamRequestSize] = 0;
- } else {
- LogPrint(eLogError, "SOCKS: BUG!!! m_addr.dns.sizs > max_socks_hostname - ( upstreamRequestSize + 1 ) )");
- }
- return boost::asio::const_buffers_1(m_upstream_request, upstreamRequestSize);
- }
-
bool SOCKSHandler::Socks5ChooseAuth()
{
m_response[0] = '\x05'; // Version
@@ -718,39 +690,45 @@
void SOCKSHandler::ForwardSOCKS()
{
LogPrint(eLogInfo, "SOCKS: Forwarding to upstream");
- EnterState(UPSTREAM_RESOLVE);
- boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort));
- m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(),
- std::placeholders::_1, std::placeholders::_2));
- }
-
- void SOCKSHandler::AsyncUpstreamSockRead()
- {
- LogPrint(eLogDebug, "SOCKS: Async upstream sock read");
- if (m_upstreamSock) {
- m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE),
- std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
- } else {
- LogPrint(eLogError, "SOCKS: No upstream socket for read");
- SocksRequestFailed(SOCKS5_GEN_FAIL);
- }
- }
-
- void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered)
- {
- if (ecode) {
- if (m_state == UPSTREAM_HANDSHAKE ) {
- // we are trying to handshake but it failed
- SocksRequestFailed(SOCKS5_NET_UNREACH);
- } else {
- LogPrint(eLogError, "SOCKS: Bad state when reading from upstream: ", (int) m_state);
- }
- return;
+ if (m_UpstreamProxyPort) // TCP
+ {
+ EnterState(UPSTREAM_RESOLVE);
+ boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort));
+ m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(),
+ std::placeholders::_1, std::placeholders::_2));
+ }
+ else if (!m_UpstreamProxyAddress.empty ())// local
+ {
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ EnterState(UPSTREAM_CONNECT);
+ m_upstreamLocalSock = std::make_shared<boost::asio::local::stream_protocol::socket>(GetOwner()->GetService());
+ auto s = shared_from_this ();
+ m_upstreamLocalSock->async_connect(m_UpstreamProxyAddress,
+ [s](const boost::system::error_code& ecode)
+ {
+ if (ecode)
+ {
+ LogPrint(eLogWarning, "SOCKS: Could not connect to local upstream proxy: ", ecode.message());
+ s->SocksRequestFailed(SOCKS5_NET_UNREACH);
+ return;
+ }
+ LogPrint(eLogInfo, "SOCKS: Connected to local upstream proxy");
+ s->SendUpstreamRequest(s->m_upstreamLocalSock);
+ });
+#else
+ LogPrint(eLogError, "SOCKS: Local sockets for upstream proxy not supported");
+ SocksRequestFailed(SOCKS5_ADDR_UNSUP);
+#endif
}
- HandleUpstreamData(m_upstream_response, bytes_transfered);
+ else
+ {
+ LogPrint(eLogError, "SOCKS: Incorrect upstream proxy address");
+ SocksRequestFailed(SOCKS5_ADDR_UNSUP);
+ }
}
- void SOCKSHandler::SocksUpstreamSuccess()
+ template<typename Socket>
+ void SOCKSHandler::SocksUpstreamSuccess(std::shared_ptr<Socket>& upstreamSock)
{
LogPrint(eLogInfo, "SOCKS: Upstream success");
boost::asio::const_buffers_1 response(nullptr, 0);
@@ -767,55 +745,36 @@
break;
}
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/UDPTunnel.cpp
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,16 +19,22 @@
void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0] || fromPort != m_LastSession->RemotePort)
- {
- std::lock_guard<std::mutex> lock(m_SessionsMutex);
m_LastSession = ObtainUDPSession(from, toPort, fromPort);
- }
m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch();
}
- void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t, uint16_t, const uint8_t * buf, size_t len)
+ void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
+ if (m_LastSession && (fromPort != m_LastSession->RemotePort || toPort != m_LastSession->LocalPort))
+ {
+ std::lock_guard<std::mutex> lock(m_SessionsMutex);
+ auto it = m_Sessions.find (GetSessionIndex (fromPort, toPort));
+ if (it != m_Sessions.end ())
+ m_LastSession = it->second;
+ else
+ m_LastSession = nullptr;
+ }
if (m_LastSession)
{
m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
@@ -41,11 +47,12 @@
std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
auto itr = m_Sessions.begin();
- while(itr != m_Sessions.end()) {
- if(now - (*itr)->LastActivity >= delta )
+ while(itr != m_Sessions.end())
+ {
+ if(now - itr->second->LastActivity >= delta )
itr = m_Sessions.erase(itr);
else
- ++itr;
+ itr++;
}
}
@@ -66,15 +73,25 @@
UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort)
{
auto ih = from.GetIdentHash();
- for (auto & s : m_Sessions )
+ auto idx = GetSessionIndex (remotePort, localPort);
{
- if (s->Identity.GetLL()[0] == ih.GetLL()[0] && remotePort == s->RemotePort)
+ std::lock_guard<std::mutex> lock(m_SessionsMutex);
+ auto it = m_Sessions.find (idx);
+ if (it != m_Sessions.end ())
{
- /** found existing session */
- LogPrint(eLogDebug, "UDPServer: Found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32());
- return s;
+ if (it->second->Identity.GetLL()[0] == ih.GetLL()[0])
+ {
+ LogPrint(eLogDebug, "UDPServer: Found session ", it->second->IPSocket.local_endpoint(), " ", ih.ToBase32());
+ return it->second;
+ }
+ else
+ {
+ LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed");
+ m_Sessions.erase (it);
+ }
}
}
+
boost::asio::ip::address addr;
/** create new udp session */
if(m_IsUniqueLocal && m_LocalAddress.is_loopback())
@@ -84,10 +101,12 @@
}
else
addr = m_LocalAddress;
- boost::asio::ip::udp::endpoint ep(addr, 0);
- m_Sessions.push_back(std::make_shared<UDPSession>(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort));
- auto & back = m_Sessions.back();
- return back;
+
+ auto s = std::make_shared<UDPSession>(boost::asio::ip::udp::endpoint(addr, 0),
+ m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort);
+ std::lock_guard<std::mutex> lock(m_SessionsMutex);
+ m_Sessions.emplace (idx, s);
+ return s;
}
UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
@@ -144,9 +163,9 @@
}
I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
- const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t port, bool gzip) :
+ const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t inPort, bool gzip) :
m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress),
- m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_Gzip (gzip)
+ m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_inPort(inPort), m_Gzip (gzip)
{
}
@@ -160,14 +179,23 @@
m_LocalDest->Start ();
auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip);
- dgram->SetReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
- dgram->SetRawReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+ dgram->SetReceiver (
+ std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5),
+ m_inPort
+ );
+ dgram->SetRawReceiver (
+ std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
+ m_inPort
+ );
}
void I2PUDPServerTunnel::Stop ()
{
auto dgram = m_LocalDest->GetDatagramDestination ();
- if (dgram) dgram->ResetReceiver ();
+ if (dgram) {
+ dgram->ResetReceiver (m_inPort);
+ dgram->ResetRawReceiver (m_inPort);
+ }
}
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPServerTunnel::GetSessions ()
@@ -175,8 +203,9 @@
std::vector<std::shared_ptr<DatagramSessionInfo> > sessions;
std::lock_guard<std::mutex> lock (m_SessionsMutex);
- for (UDPSessionPtr s: m_Sessions)
+ for (auto it: m_Sessions)
{
+ auto s = it.second;
if (!s->m_Destination) continue;
auto info = s->m_Destination->GetInfoForRemote (s->Identity);
if (!info) continue;
@@ -220,9 +249,13 @@
dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
- std::placeholders::_5));
+ std::placeholders::_5),
+ RemotePort
+ );
dgram->SetRawReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this,
- std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
+ RemotePort
+ );
m_LocalDest->Start ();
if (m_ResolveThread == nullptr)
@@ -233,7 +266,10 @@
void I2PUDPClientTunnel::Stop ()
{
auto dgram = m_LocalDest->GetDatagramDestination ();
- if (dgram) dgram->ResetReceiver ();
+ if (dgram) {
+ dgram->ResetReceiver (RemotePort);
+ dgram->ResetRawReceiver (RemotePort);
+ }
m_cancel_resolve = true;
m_Sessions.clear();
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd-2.51.0+git1.tar.gz/upstream/libi2pd_client/UDPTunnel.h
^
|
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013-2022, The PurpleI2P Project
+* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -72,7 +72,7 @@
boost::asio::ip::udp::endpoint LocalEndpoint;
/** client's udp endpoint */
boost::asio::ip::udp::endpoint RemoteEndpoint;
- /** how long has this converstation been idle in ms */
+ /** how long has this conversation been idle in ms */
uint64_t idle;
};
@@ -104,6 +104,7 @@
void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
+ uint32_t GetSessionIndex (uint16_t fromPort, uint16_t toPort) const { return ((uint32_t)fromPort << 16) + toPort; }
private:
@@ -112,9 +113,10 @@
boost::asio::ip::address m_LocalAddress;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
std::mutex m_SessionsMutex;
- std::vector<UDPSessionPtr> m_Sessions;
+ std::unordered_map<uint32_t, UDPSessionPtr> m_Sessions; // (from port, to port)->session
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
UDPSessionPtr m_LastSession;
+ uint16_t m_inPort;
bool m_Gzip;
public:
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd.service
^
|
@@ -1,7 +1,7 @@
[Unit]
Description=I2P Router
Documentation=https://i2pd.readthedocs.io/en/latest/
-Documentation=https://github.com/nephros/i2pd/blob/master/README.md
+Documentation=https://github.com/nephros/i2pd/blob/main/README.md
After=network.target
After=local-fs.target
After=home.mount
|
[-]
[+]
|
Changed |
_service:tar_git:i2pd.yaml
^
|
@@ -1,6 +1,6 @@
Name: i2pd
Summary: End-to-End encrypted and anonymous Internet daemon
-Version: 2.50.2
+Version: 2.51.0
Release: 1
Group: Applications/Internet
License: BSD-3-Clause
|