Compare commits

..

2 Commits

Author SHA1 Message Date
R4SAS
58e351f5d9 use 15s average bw for transit limits check
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-12-12 18:22:16 +03:00
R4SAS
2a01ad953c calculate bandwidth every 1 and 15 seconds
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-12-12 08:12:23 +03:00
72 changed files with 627 additions and 1266 deletions

View File

@@ -1,27 +0,0 @@
# editorconfig.org
root = true
[*]
# Unix style files
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile,Makefile.*]
indent_style = tab
indent_size = 4
[*.{h,cpp}]
indent_style = tab
indent_size = 4
[*.rc]
indent_style = space
indent_size = 4
[*.{md,markdown}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false

View File

@@ -14,7 +14,6 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: install packages - name: install packages
run: | run: |
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew update brew update
brew install boost miniupnpc openssl@1.1 brew install boost miniupnpc openssl@1.1
- name: build application - name: build application

View File

@@ -1,39 +1,6 @@
# for this file format description, # for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog # see https://github.com/olivierlacan/keep-a-changelog
## [2.45.0] - 2023-01-03
### Added
- Test for Symmetric NAT with peer test msgs 6 and 7
- Webconsole "No Descriptors" router error state
- 1 and 15 seconds bandwidth calculation for i2pcontrol
- Show non-zero send queue size for transports in web console
- Compressible padding for I2P addresses
- Localization to Czech
- Don't accept incoming session from invalid/reserved addresses for NTCP2 and SSU2
- Limit simultaneous tunnel build requests by 4 per pool
### Changed
- Removed SSU support
- Reduced bandwidth calculation interval from 60 to 15 seconds
- Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill
- Transit tunnels limit is doubled if floodfill mode is enabled
- NTCP2 and SSU2 timestamps are rounded to seconds
- Drop RouterInfos and LeaseSets with timestamp from future
- Don't delete unreachable routers if tunnel creation success rate is too low
- Refuse duplicated incoming pending NTCP2 session from same IP
- Don't send SSU2 termination again if termination received block received
- Handle standard network error for SSU2 without throwing an exception
- Don't select overloaded peer for next tunnel
- Remove "X-Requested-With" in HTTP Proxy for non-AJAX requests
### Fixed
- File descriptors leak
- Random crash on AddressBook update
- Crash if incorrect LeaseSet size
- Spamming to log if no descriptors
- ::1 address in RouterInfo
- SSU2 network error handling (especially for Windows)
- Race condition with pending outgoing SSU2 sessions
- RTT self-reduction for long-live streams
## [2.44.0] - 2022-11-20 ## [2.44.0] - 2022-11-20
### Added ### Added
- SSL connection for server I2P tunnels - SSL connection for server I2P tunnels
@@ -44,7 +11,7 @@
- SSU2 send and verify path challenge - SSU2 send and verify path challenge
- Configurable ssu2.mtu4 and ssu2.mtu6 - Configurable ssu2.mtu4 and ssu2.mtu6
### Changed ### Changed
- SSU2 is enabled and SSU is disabled by default - SSU2 is enbaled and SSU is disabled by default
- Separate network status and error - Separate network status and error
- Random selection between NTCP2 and SSU2 priority - Random selection between NTCP2 and SSU2 priority
- Added notbob.i2p to jump services - Added notbob.i2p to jump services

View File

@@ -20,17 +20,12 @@ option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_GIT_VERSION "Use git commit info as version" OFF) option(WITH_GIT_VERSION "Use git commit info as version" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
option(BUILD_TESTING "Build tests" OFF)
IF(BUILD_TESTING)
enable_testing()
ENDIF()
# paths # paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
# Handle paths nicely #Handle paths nicely
include(GNUInstallDirs) include(GNUInstallDirs)
# architecture # architecture
@@ -176,12 +171,14 @@ if(WITH_THREADSANITIZER)
endif() endif()
endif() endif()
# Use std::atomic instead of GCC builtins on macOS PowerPC:
# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111 # Enable usage of STD's Atomic instead of Boost's on PowerPC
if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc") # For more information refer to https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
if(ARCHITECTURE MATCHES "ppc")
add_definitions(-DBOOST_SP_USE_STD_ATOMIC) add_definitions(-DBOOST_SP_USE_STD_ATOMIC)
endif() endif()
# libraries # libraries
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@@ -278,13 +275,9 @@ if(WITH_BINARY)
set(DL_LIB ${CMAKE_DL_LIBS}) set(DL_LIB ${CMAKE_DL_LIBS})
endif() endif()
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin") set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin")
endif() endif()
if(BUILD_TESTING)
add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests)
endif()

View File

@@ -1,23 +1,18 @@
# atomic builtins are required for threading support. # atomic builtins are required for threading support.
INCLUDE(CheckCXXSourceCompiles) INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
# Sometimes linking against libatomic is required for atomic ops, if # Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics. # the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname) function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") set(CMAKE_REQUIRED_FLAGS "-std=c++11")
CHECK_CXX_SOURCE_COMPILES(" CHECK_CXX_SOURCE_COMPILES("
#include <atomic> #include <atomic>
std::atomic<int> x; std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() { int main() {
++z; return x;
++y;
return ++x;
} }
" ${varname}) " ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
@@ -32,7 +27,6 @@ function(check_working_cxx_atomics64 varname)
std::atomic<uint64_t> x (0); std::atomic<uint64_t> x (0);
int main() { int main() {
uint64_t i = x.load(std::memory_order_relaxed); uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0; return 0;
} }
" ${varname}) " ${varname})
@@ -40,16 +34,15 @@ int main() {
endfunction(check_working_cxx_atomics64) endfunction(check_working_cxx_atomics64)
# Check for (non-64-bit) atomic operations. # This isn't necessary on MSVC, so avoid command-line switch annoyance
if(MSVC) # by only running on GCC-like hosts.
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
else()
# First check if atomics work without the library. # First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it. # If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if(HAVE_LIBATOMIC) if( HAVE_LIBATOMIC )
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB) if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
@@ -65,20 +58,20 @@ endif()
if(MSVC) if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
else() else()
# First check if atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it. endif()
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) # If not, check if the library exists, and atomics work with it.
if(HAVE_CXX_LIBATOMICS64) if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) if(HAVE_CXX_LIBATOMICS64)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
endif() if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
else() message(FATAL_ERROR "Host compiler must support std::atomic!")
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
endif() endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif() endif()
endif() endif()
@@ -87,6 +80,7 @@ endif()
## assumes C++11 <atomic> works. ## assumes C++11 <atomic> works.
CHECK_CXX_SOURCE_COMPILES(" CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER #ifdef _MSC_VER
#include <Intrin.h> /* Workaround for PR19898. */
#include <windows.h> #include <windows.h>
#endif #endif
int main() { int main() {

View File

@@ -1,55 +0,0 @@
# - Try to find the CHECK libraries
# Once done this will define
#
# CHECK_FOUND - system has check
# CHECK_INCLUDE_DIRS - the check include directory
# CHECK_LIBRARIES - check library
#
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007-2009 Bjoern Ricks <bjoern.ricks@gmail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
INCLUDE( FindPkgConfig )
IF ( Check_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "REQUIRED" )
ELSE( Check_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "" )
ENDIF ( Check_FIND_REQUIRED )
IF ( CHECK_MIN_VERSION )
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} )
ELSE ( CHECK_MIN_VERSION )
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check )
ENDIF ( CHECK_MIN_VERSION )
# Look for CHECK include dir and libraries
IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
FIND_PATH( CHECK_INCLUDE_DIRS check.h )
FIND_LIBRARY( CHECK_LIBRARIES NAMES check )
IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
SET( CHECK_FOUND 1 )
IF ( NOT Check_FIND_QUIETLY )
MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" )
ENDIF ( NOT Check_FIND_QUIETLY )
ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
IF ( Check_FIND_REQUIRED )
MESSAGE( FATAL_ERROR "Could NOT find CHECK" )
ELSE ( Check_FIND_REQUIRED )
IF ( NOT Check_FIND_QUIETLY )
MESSAGE( STATUS "Could NOT find CHECK" )
ENDIF ( NOT Check_FIND_QUIETLY )
ENDIF ( Check_FIND_REQUIRED )
ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
# Hide advanced variables from CMake GUIs
MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES )

View File

@@ -126,7 +126,7 @@ port = 7070
# user = i2pd # user = i2pd
# pass = changeme # pass = changeme
## Select webconsole language ## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, czech, french, ## Currently supported english (default), afrikaans, armenian, chinese, french,
## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages ## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
# lang = english # lang = english
@@ -237,9 +237,8 @@ verify = true
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt # subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
[limits] [limits]
## Maximum active transit sessions (default: 5000) ## Maximum active transit sessions (default:2500)
## This value is doubled if floodfill mode is enabled! # transittunnels = 2500
# transittunnels = 5000
## Limit number of open file descriptors (0 - use system limit) ## Limit number of open file descriptors (0 - use system limit)
# openfiles = 0 # openfiles = 0
## Maximum size of corefile in Kb (0 - use system limit) ## Maximum size of corefile in Kb (0 - use system limit)

View File

@@ -29,7 +29,7 @@ SendSIGKILL=yes
#TimeoutStopSec=10m #TimeoutStopSec=10m
# If you have problems with hanging i2pd, you can try increase this # If you have problems with hanging i2pd, you can try increase this
LimitNOFILE=8192 LimitNOFILE=4096
# To enable write of coredump uncomment this # To enable write of coredump uncomment this
#LimitCORE=infinity #LimitCORE=infinity

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7) %define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git Name: i2pd-git
Version: 2.45.0 Version: 2.44.0
Release: git%{git_hash}%{?dist} Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd Conflicts: i2pd
@@ -158,9 +158,6 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Mon Tue 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0 * Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0 - update to 2.44.0

View File

@@ -1,5 +1,5 @@
Name: i2pd Name: i2pd
Version: 2.45.0 Version: 2.44.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd-git Conflicts: i2pd-git
@@ -155,9 +155,6 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0 * Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0 - update to 2.44.0

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -165,21 +165,20 @@ namespace util
i2p::transport::InitTransports (); i2p::transport::InitTransports ();
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
SetMaxNumTransitTunnels (transitTunnels);
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) if (isFloodfill) {
{
LogPrint(eLogInfo, "Daemon: Router configured as floodfill"); LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
i2p::context.SetFloodfill (true); i2p::context.SetFloodfill (true);
} }
else else
{
i2p::context.SetFloodfill (false); i2p::context.SetFloodfill (false);
}
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels"))
transitTunnels *= 2; // double default number of transit tunnels for floodfill
SetMaxNumTransitTunnels (transitTunnels);
/* this section also honors 'floodfill' flag, if set above */ /* this section also honors 'floodfill' flag, if set above */
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -87,6 +87,8 @@ namespace http {
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string"; const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css"; const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
static std::string ConvertTime (uint64_t time) static std::string ConvertTime (uint64_t time)
{ {
@@ -234,6 +236,7 @@ namespace http {
} }
if (error != eRouterErrorNone) if (error != eRouterErrorNone)
{ {
s << "<br>";
switch (error) switch (error)
{ {
case eRouterErrorClockSkew: case eRouterErrorClockSkew:
@@ -299,7 +302,7 @@ namespace http {
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n"; s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
} }
if (includeHiddenContent) if (includeHiddenContent)
{ {
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n"; s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
if (!i2p::context.GetRouterInfo().GetProperty("family").empty()) if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
@@ -309,10 +312,9 @@ namespace http {
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n"; s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
auto addresses = i2p::context.GetRouterInfo().GetAddresses (); auto addresses = i2p::context.GetRouterInfo().GetAddresses ();
if (addresses) if (addresses)
{ {
for (const auto& address : *addresses) for (const auto& address : *addresses)
{ {
if (!address) continue;
s << "<tr>\r\n<td>"; s << "<tr>\r\n<td>";
switch (address->transportStyle) switch (address->transportStyle)
{ {
@@ -342,7 +344,7 @@ namespace http {
} }
s << "</tr>\r\n"; s << "</tr>\r\n";
} }
} }
s << "</tbody></table>\r\n"; s << "</tbody></table>\r\n";
} }
s << "</div>\r\n</div>\r\n"; s << "</div>\r\n</div>\r\n";
@@ -805,8 +807,6 @@ namespace http {
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ()) if (it.second->GetRelayTag ())
tmp_s << " [itag:" << it.second->GetRelayTag () << "]"; tmp_s << " [itag:" << it.second->GetRelayTag () << "]";
if (it.second->GetSendQueueSize () > 0)
tmp_s << " [queue:" << it.second->GetSendQueueSize () << "]";
tmp_s << "</div>\r\n" << std::endl; tmp_s << "</div>\r\n" << std::endl;
cnt++; cnt++;
} }
@@ -820,8 +820,6 @@ namespace http {
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ()) if (it.second->GetRelayTag ())
tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]"; tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]";
if (it.second->GetSendQueueSize () > 0)
tmp_s6 << " [queue:" << it.second->GetSendQueueSize () << "]";
tmp_s6 << "</div>\r\n" << std::endl; tmp_s6 << "</div>\r\n" << std::endl;
cnt6++; cnt6++;
} }

11
debian/changelog vendored
View File

@@ -1,14 +1,3 @@
i2pd (2.45.0-1) unstable; urgency=high
* updated to version 2.45.0/0.9.57
* compat level 12
* standards version 4.3.0
* increased nofile limit in service and init.d to 8192
* added conffiles
* removed #1210 patch
-- r4sas <r4sas@i2pmail.org> Tue, 3 Jan 2023 18:00:00 +0000
i2pd (2.44.0-1) unstable; urgency=medium i2pd (2.44.0-1) unstable; urgency=medium
* updated to version 2.44.0/0.9.56 * updated to version 2.44.0/0.9.56

2
debian/compat vendored
View File

@@ -1 +1 @@
12 9

2
debian/conffiles vendored
View File

@@ -1,2 +0,0 @@
/etc/i2pd/i2pd.conf
/etc/i2pd/tunnels.conf

4
debian/control vendored
View File

@@ -2,8 +2,8 @@ Source: i2pd
Section: net Section: net
Priority: optional Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org> Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 12~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.17.2~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 4.3.0 Standards-Version: 3.9.8
Homepage: http://i2pd.website/ Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd Vcs-Browser: https://github.com/PurpleI2P/i2pd

6
debian/copyright vendored
View File

@@ -3,18 +3,18 @@ Upstream-Name: i2pd
Source: https://github.com/PurpleI2P Source: https://github.com/PurpleI2P
Files: * Files: *
Copyright: 2013-2023 PurpleI2P Copyright: 2013-2020 PurpleI2P
License: BSD-3-clause License: BSD-3-clause
Files: debian/* Files: debian/*
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org> Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
2014-2016 hagen <hagen@i2pmail.org> 2014-2016 hagen <hagen@i2pmail.org>
2016-2023 R4SAS <r4sas@i2pmail.org> 2016-2020 R4SAS <r4sas@i2pmail.org>
2017-2020 Yangfl <mmyangfl@gmail.com> 2017-2020 Yangfl <mmyangfl@gmail.com>
License: GPL-2+ License: GPL-2+
License: BSD-3-clause License: BSD-3-clause
Copyright (c) 2013-2023, The PurpleI2P Project Copyright (c) 2013-2017, The PurpleI2P Project
. .
All rights reserved. All rights reserved.
. .

2
debian/i2pd.default vendored
View File

@@ -8,4 +8,4 @@ I2PD_ENABLED="yes"
DAEMON_OPTS="" DAEMON_OPTS=""
# If you have problems with hunging i2pd, you can try enable this # If you have problems with hunging i2pd, you can try enable this
ulimit -n 8192 ulimit -n 4096

1
debian/i2pd.install vendored
View File

@@ -1,6 +1,7 @@
i2pd usr/sbin/ i2pd usr/sbin/
contrib/i2pd.conf etc/i2pd/ contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/
contrib/subscriptions.txt etc/i2pd/
contrib/certificates/ usr/share/i2pd/ contrib/certificates/ usr/share/i2pd/
contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/ contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d contrib/apparmor/usr.sbin.i2pd etc/apparmor.d

3
debian/i2pd.links vendored
View File

@@ -1,4 +1,5 @@
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d
usr/share/i2pd/certificates var/lib/i2pd/certificates usr/share/i2pd/certificates var/lib/i2pd/certificates

27
debian/patches/01-fix-1210.patch vendored Normal file
View File

@@ -0,0 +1,27 @@
Description: fix #1210
Disables two options, which not presented in old systemd versions
Author: r4sas <r4sas@i2pmail.org>
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2020-05-25
Index: i2pd/contrib/i2pd.service
===================================================================
--- i2pd.orig/contrib/i2pd.service
+++ i2pd/contrib/i2pd.service
@@ -6,10 +6,10 @@ After=network.target
[Service]
User=i2pd
Group=i2pd
-RuntimeDirectory=i2pd
-RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#RuntimeDirectory=i2pd
+#RuntimeDirectoryMode=0700
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/sh -c "kill -HUP $MAINPID"

View File

@@ -1 +1,2 @@
01-upnp.patch 01-fix-1210.patch
02-upnp.patch

3
debian/watch vendored
View File

@@ -1,4 +1,3 @@
version=4 version=4 opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
https://github.com/PurpleI2P/i2pd/tags \ https://github.com/PurpleI2P/i2pd/tags \
(?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate (?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate

View File

@@ -1,216 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Czech localization file
namespace i2p
{
namespace i18n
{
namespace czech // language namespace
{
// language name in lowercase
static std::string language = "czech";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2;
}
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "vytváří se"},
{"failed", "selhalo"},
{"expiring", "končící"},
{"established", "vytvořeno"},
{"unknown", "neznámý"},
{"exploratory", "průzkumné"},
{"Purple I2P Webconsole", "Purple I2P Webkonsole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsole"},
{"Main page", "Hlavní stránka"},
{"Router commands", "Router příkazy"},
{"Local Destinations", "Lokální destinace"},
{"LeaseSets", "LeaseSety"},
{"Tunnels", "Tunely"},
{"Transit Tunnels", "Transitní tunely"},
{"Transports", "Transporty"},
{"I2P tunnels", "I2P tunely"},
{"SAM sessions", "SAM relace"},
{"ERROR", "CHYBA"},
{"OK", "OK"},
{"Testing", "Testuji"},
{"Firewalled", "Za Firewallem"},
{"Unknown", "Neznámý"},
{"Proxy", "Proxy"},
{"Mesh", "Síť"},
{"Error", "Chyba"},
{"Clock skew", "Časová nesrovnalost"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetrický NAT"},
{"Uptime", "Doba provozu"},
{"Network status", "Status sítě"},
{"Network status v6", "Status sítě v6"},
{"Stopping in", "Zastavuji za"},
{"Family", "Rodina"},
{"Tunnel creation success rate", "Úspěšnost vytváření tunelů"},
{"Received", "Přijato"},
{"KiB/s", "KiB/s"},
{"Sent", "Odesláno"},
{"Transit", "Tranzit"},
{"Data path", "Cesta k data souborům"},
{"Hidden content. Press on text to see.", "Skrytý kontent. Pro zobrazení, klikni na text."},
{"Router Ident", "Routerová Identita"},
{"Router Family", "Rodina routerů"},
{"Router Caps", "Omezení Routerů"},
{"Version", "Verze"},
{"Our external address", "Naše externí adresa"},
{"supported", "podporováno"},
{"Routers", "Routery"},
{"Floodfills", "Floodfilly"},
{"Client Tunnels", "Klientské tunely"},
{"Services", "Služby"},
{"Enabled", "Zapnuto"},
{"Disabled", "Vypnuto"},
{"Encrypted B33 address", "Šifrovaná adresa B33"},
{"Address registration line", "Registrační řádek adresy"},
{"Domain", "Doména"},
{"Generate", "Vygenerovat"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Poznámka:</b> výsledný řetězec může být použit pouze pro registraci 2LD domén (example.i2p). Pro registraci subdomén použijte prosím i2pd-tools."},
{"Address", "Adresa"},
{"Type", "Typ"},
{"EncType", "EncType"},
{"Inbound tunnels", "Příchozí tunely"},
{"ms", "ms"},
{"Outbound tunnels", "Odchozí tunely"},
{"Tags", "Štítky"},
{"Incoming", "Příchozí"},
{"Outgoing", "Odchozí"},
{"Destination", "Destinace"},
{"Amount", "Množství"},
{"Incoming Tags", "Příchozí štítky"},
{"Tags sessions", "Relace štítků"},
{"Status", "Status"},
{"Local Destination", "Lokální Destinace"},
{"Streams", "Toky"},
{"Close stream", "Uzavřít tok"},
{"I2CP session not found", "I2CP relace nenalezena"},
{"I2CP is not enabled", "I2CP není zapnuto"},
{"Invalid", "Neplatný"},
{"Store type", "Druh uložení"},
{"Expires", "Vyprší"},
{"Non Expired Leases", "Nevypršené Leasy"},
{"Gateway", "Brána"},
{"TunnelID", "ID tunelu"},
{"EndDate", "Datum ukončení"},
{"not floodfill", "není floodfill"},
{"Queue size", "Velikost fronty"},
{"Run peer test", "Spustit peer test"},
{"Decline transit tunnels", "Odmítnout tranzitní tunely"},
{"Accept transit tunnels", "Přijmout tranzitní tunely"},
{"Cancel graceful shutdown", "Zrušit hladké vypnutí"},
{"Start graceful shutdown", "Zahájit hladké vypnutí"},
{"Force shutdown", "Vynutit vypnutí"},
{"Reload external CSS styles", "Znovu načíst externí CSS"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Poznámka:</b> žádná vykonaná akce zde není trvalá a nemění konfigurační soubory."},
{"Logging level", "Úroveň logování"},
{"Transit tunnels limit", "Limit tranzitních tunelů"},
{"Change", "Změnit"},
{"Change language", "Změnit jazyk"},
{"no transit tunnels currently built", "Žádný tranzitní tunel není momentálně vytvořen"},
{"SAM disabled", "SAM vypnutý"},
{"no sessions currently running", "Momentálně nejsou spuštěné žádné relace"},
{"SAM session not found", "SAM relace nenalezena"},
{"SAM Session", "SAM Relace"},
{"Server Tunnels", "Server Tunely"},
{"Client Forwards", "Přesměrování Klienta"},
{"Server Forwards", "Přesměrování Serveru"},
{"Unknown page", "Neznámá stránka"},
{"Invalid token", "Neplatný token"},
{"SUCCESS", "ÚSPĚCH"},
{"Stream closed", "Tok uzavřen"},
{"Stream not found or already was closed", "Tok nenalezen nebo byl již uzavřen"},
{"Destination not found", "Destinace nenalezena"},
{"StreamID can't be null", "StreamID nemůže být null"},
{"Return to destination page", "Zpět na stránku destinací"},
{"You will be redirected in 5 seconds", "Budete přesměrováni za 5 vteřin"},
{"Transit tunnels count must not exceed 65535", "Počet tranzitních tunelů nesmí přesáhnout 65535"},
{"Back to commands list", "Zpět na list příkazů"},
{"Register at reg.i2p", "Zaregistrovat na reg.i2p"},
{"Description", "Popis"},
{"A bit information about service on domain", "Trochu informací o službě na doméně"},
{"Submit", "Odeslat"},
{"Domain can't end with .b32.i2p", "Doména nesmí končit na .b32.i2p"},
{"Domain must end with .i2p", "Doména musí končit s .i2p"},
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
{"Unknown command", "Neznámý příkaz"},
{"Command accepted", "Příkaz přijat"},
{"Proxy error", "Chyba proxy serveru"},
{"Proxy info", "Proxy informace"},
{"Proxy error: Host not found", "Chyba proxy serveru: Hostitel nenalezen"},
{"Remote host not found in router's addressbook", "Vzdálený hostitel nebyl nalezen v adresáři routeru"},
{"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"},
{"Invalid request", "Neplatný požadavek"},
{"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"},
{"addresshelper is not supported", "Adresshelper není podporován"},
{"Host", "Hostitel"},
{"added to router's addressbook from helper", "přidáno do adresáře routeru od pomocníka"},
{"Click here to proceed:", "Pro pokračování, klikněte zde:"},
{"Continue", "Pokračovat"},
{"Addresshelper found", "Adresář nalezen"},
{"already in router's addressbook", "je již v adresáři routeru"},
{"Click here to update record:", "Pro aktualizaci záznamu, klikněte zde:"},
{"invalid request uri", "neplatný URI požadavek"},
{"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"},
{"Outproxy failure", "Outproxy selhání"},
{"bad outproxy settings", "špatné outproxy nastavení"},
{"not inside I2P network, but outproxy is not enabled", "není uvnitř I2P sítě a outproxy není nastavena"},
{"unknown outproxy url", "neznámá outproxy URL"},
{"cannot resolve upstream proxy", "nelze rozluštit upstream proxy server"},
{"hostname too long", "Název hostitele je příliš dlouhý"},
{"cannot connect to upstream socks proxy", "nelze se připojit k upstream socks proxy serveru"},
{"Cannot negotiate with socks proxy", "Nelze vyjednávat se socks proxy serverem"},
{"CONNECT error", "Chyba PŘIPOJENÍ"},
{"Failed to Connect", "Připojení se nezdařilo"},
{"socks proxy error", "chyba socks proxy serveru"},
{"failed to send request to upstream", "odeslání žádosti upstream serveru se nezdařilo"},
{"No Reply From socks proxy", "Žádná odpověď od socks proxy serveru"},
{"cannot connect", "nelze se připojit"},
{"http out proxy not implemented", "http out proxy není implementován"},
{"cannot connect to upstream http proxy", "nelze se připojit k upstream socks proxy serveru"},
{"Host is down", "Hostitel je nedostupný"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"den", "dny", "dní", "dní"}},
{"hours", {"hodina", "hodiny", "hodin", "hodin"}},
{"minutes", {"minuta", "minuty", "minut", "minut"}},
{"seconds", {"vteřina", "vteřiny", "vteřin", "vteřin"}},
{"", {"", "", "", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -26,7 +26,6 @@ namespace i18n
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace czech { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
@@ -45,7 +44,6 @@ namespace i18n
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} }, { "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
{ "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} }, { "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} }, { "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} },
{ "czech", {"čeština", "cs", i2p::i18n::czech::GetLocale} },
{ "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "english", {"English", "en", i2p::i18n::english::GetLocale} },
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },

View File

@@ -135,7 +135,7 @@ namespace data
//---------------------------------------------------------- //----------------------------------------------------------
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01; const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
// const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04; const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth): BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):

View File

@@ -77,7 +77,7 @@ namespace config {
limits.add_options() limits.add_options()
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("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.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<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored") ("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored") ("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored") ("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")

View File

@@ -159,10 +159,8 @@ namespace crypto
// DH/ElGamal // DH/ElGamal
#if !defined(__x86_64__)
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
#endif
const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048; const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8; const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;

View File

@@ -1096,13 +1096,13 @@ namespace client
} }
auto leaseSet = FindLeaseSet (dest); auto leaseSet = FindLeaseSet (dest);
if (leaseSet) if (leaseSet)
{ {
auto stream = CreateStream (leaseSet, port); auto stream = CreateStream (leaseSet, port);
GetService ().post ([streamRequestComplete, stream]() GetService ().post ([streamRequestComplete, stream]()
{ {
streamRequestComplete(stream); streamRequestComplete(stream);
}); });
} }
else else
{ {
auto s = GetSharedFromThis (); auto s = GetSharedFromThis ();
@@ -1135,8 +1135,8 @@ namespace client
}); });
} }
template<typename Dest> template<typename Dest>
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port) std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
{ {
std::shared_ptr<i2p::stream::Stream> stream; std::shared_ptr<i2p::stream::Stream> stream;
std::condition_variable streamRequestComplete; std::condition_variable streamRequestComplete;
@@ -1152,18 +1152,18 @@ namespace client
dest, port); dest, port);
streamRequestComplete.wait (l); streamRequestComplete.wait (l);
return stream; return stream;
} }
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
{ {
return CreateStreamSync (dest, port); return CreateStreamSync (dest, port);
} }
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port) std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
{ {
return CreateStreamSync (dest, port); return CreateStreamSync (dest, port);
} }
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port) std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
{ {
if (m_StreamingDestination) if (m_StreamingDestination)

View File

@@ -284,9 +284,9 @@ namespace client
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey); void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params); void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
template<typename Dest> template<typename Dest>
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port); std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port);
private: private:
i2p::data::PrivateKeys m_Keys; i2p::data::PrivateKeys m_Keys;

View File

@@ -558,8 +558,7 @@ namespace i2p
return; return;
} }
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
uint8_t replyKey[32]; // AEAD/Chacha20/Poly1305 uint8_t replyKey[32], layerKey[32], ivKey[32];
i2p::crypto::AESKey layerKey, ivKey; // AES
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
memcpy (replyKey, noiseState.m_CK + 32, 32); memcpy (replyKey, noiseState.m_CK + 32, 32);
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);

View File

@@ -309,7 +309,7 @@ namespace tunnel
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs; std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs;
}; };
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000; const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500;
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
uint16_t GetMaxNumTransitTunnels (); uint16_t GetMaxNumTransitTunnels ();
} }

View File

@@ -49,22 +49,30 @@ namespace data
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType) IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
{ {
uint8_t randomPaddingBlock[32]; /*uint8_t randomPaddingBlock[32];
RAND_bytes (randomPaddingBlock, 32); RAND_bytes (randomPaddingBlock, 32);*/
if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{ {
memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32); /*memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32);
for (int i = 0; i < 7; i++) // 224 bytes for (int i = 0; i < 7; i++) // 224 bytes
memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32); memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32);*/
if (publicKey)
{
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
}
else
RAND_bytes (m_StandardIdentity.publicKey, 256);
} }
else else
{ {
if (publicKey) if (publicKey)
memcpy (m_StandardIdentity.publicKey, publicKey, 256); memcpy (m_StandardIdentity.publicKey, publicKey, 256);
else else
for (int i = 0; i < 8; i++) // 256 bytes RAND_bytes (m_StandardIdentity.publicKey, 256);
memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32); /*for (int i = 0; i < 8; i++) // 256 bytes
} memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32);*/
}
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{ {
size_t excessLen = 0; size_t excessLen = 0;
@@ -102,8 +110,9 @@ namespace data
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
{ {
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32 size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
for (int i = 0; i < 3; i++) // 96 bytes /*for (int i = 0; i < 3; i++) // 96 bytes
memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32); memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32);*/
RAND_bytes (m_StandardIdentity.signingKey, 96);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
break; break;
} }
@@ -717,7 +726,7 @@ namespace data
uint8_t publicKey[256]; uint8_t publicKey[256];
if (isDestination) if (isDestination)
RAND_bytes (keys.m_PrivateKey, 256); RAND_bytes (keys.m_PrivateKey, 256);
else else
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey); GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
// identity // identity
keys.m_Public = std::make_shared<IdentityEx> (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType); keys.m_Public = std::make_shared<IdentityEx> (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType);

View File

@@ -261,12 +261,12 @@ namespace data
{ {
LogPrint (eLogError, "LeaseSet: Buffer is too long ", len); LogPrint (eLogError, "LeaseSet: Buffer is too long ", len);
len = MAX_LS_BUFFER_SIZE; len = MAX_LS_BUFFER_SIZE;
} }
if (m_Buffer && len > m_BufferLen) if (m_Buffer && len > m_BufferLen)
{ {
delete[] m_Buffer; delete[] m_Buffer;
m_Buffer = nullptr; m_Buffer = nullptr;
} }
if (!m_Buffer) if (!m_Buffer)
m_Buffer = new uint8_t[len]; m_Buffer = new uint8_t[len];
m_BufferLen = len; m_BufferLen = len;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2020, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -18,11 +18,11 @@ namespace log {
/** /**
* @brief Maps our loglevel to their symbolic name * @brief Maps our loglevel to their symbolic name
*/ */
static const char *g_LogLevelStr[eNumLogLevels] = static const char * g_LogLevelStr[eNumLogLevels] =
{ {
"none", // eLogNone "none", // eLogNone
"error", // eLogError "error", // eLogError
"warn", // eLogWarning "warn", // eLogWarn
"info", // eLogInfo "info", // eLogInfo
"debug" // eLogDebug "debug" // eLogDebug
}; };
@@ -35,12 +35,12 @@ namespace log {
static const char *LogMsgColors[] = { "", "", "", "", "", "" }; static const char *LogMsgColors[] = { "", "", "", "", "", "" };
#else /* UNIX */ #else /* UNIX */
static const char *LogMsgColors[] = { static const char *LogMsgColors[] = {
"\033[1;32m", /* none: green */ [eLogNone] = "\033[0m", /* reset */
"\033[1;31m", /* error: red */ [eLogError] = "\033[1;31m", /* red */
"\033[1;33m", /* warning: yellow */ [eLogWarning] = "\033[1;33m", /* yellow */
"\033[1;36m", /* info: cyan */ [eLogInfo] = "\033[1;36m", /* cyan */
"\033[1;34m", /* debug: blue */ [eLogDebug] = "\033[1;34m", /* blue */
"\033[0m" /* reset */ [eNumLogLevels] = "\033[0m", /* reset */
}; };
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -139,7 +139,7 @@ namespace transport
m3p2[3] = 0; // flag m3p2[3] = 0; // flag
memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex
// 2 bytes reserved // 2 bytes reserved
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA
// 4 bytes reserved // 4 bytes reserved
// sign and encrypt options, use m_H as AD // sign and encrypt options, use m_H as AD
uint8_t nonce[12]; uint8_t nonce[12];
@@ -162,7 +162,7 @@ namespace transport
uint8_t options[16]; uint8_t options[16];
memset (options, 0, 16); memset (options, 0, 16);
htobe16buf (options + 2, paddingLen); // padLen htobe16buf (options + 2, paddingLen); // padLen
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsB
// sign and encrypt options, use m_H as AD // sign and encrypt options, use m_H as AD
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); // set nonce to zero memset (nonce, 0, 12); // set nonce to zero
@@ -374,16 +374,10 @@ namespace transport
transports.PeerDisconnected (shared_from_this ()); transports.PeerDisconnected (shared_from_this ());
m_Server.RemoveNTCP2Session (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ());
m_SendQueue.clear (); m_SendQueue.clear ();
m_SendQueueSize = 0;
LogPrint (eLogDebug, "NTCP2: Session terminated"); LogPrint (eLogDebug, "NTCP2: Session terminated");
} }
} }
void NTCP2Session::Close ()
{
m_Socket.close ();
}
void NTCP2Session::TerminateByTimeout () void NTCP2Session::TerminateByTimeout ()
{ {
SendTerminationAndTerminate (eNTCP2IdleTimeout); SendTerminationAndTerminate (eNTCP2IdleTimeout);
@@ -752,8 +746,6 @@ namespace transport
void NTCP2Session::ServerLogin () void NTCP2Session::ServerLogin ()
{ {
SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT);
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_Establisher->CreateEphemeralKey (); m_Establisher->CreateEphemeralKey ();
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
@@ -1058,10 +1050,7 @@ namespace transport
SendRouterInfo (); SendRouterInfo ();
} }
else else
{
SendQueue (); SendQueue ();
m_SendQueueSize = m_SendQueue.size ();
}
} }
} }
@@ -1169,7 +1158,7 @@ namespace transport
{ {
if (m_IsTerminated) return; if (m_IsTerminated) return;
for (auto it: msgs) for (auto it: msgs)
m_SendQueue.push_back (std::move (it)); m_SendQueue.push_back (it);
if (!m_IsSending) if (!m_IsSending)
SendQueue (); SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
@@ -1178,7 +1167,6 @@ namespace transport
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate (); Terminate ();
} }
m_SendQueueSize = m_SendQueue.size ();
} }
void NTCP2Session::SendLocalRouterInfo (bool update) void NTCP2Session::SendLocalRouterInfo (bool update)
@@ -1301,7 +1289,7 @@ namespace transport
for (auto& it: ntcpSessions) for (auto& it: ntcpSessions)
it.second->Terminate (); it.second->Terminate ();
for (auto& it: m_PendingIncomingSessions) for (auto& it: m_PendingIncomingSessions)
it.second->Terminate (); it->Terminate ();
} }
m_NTCP2Sessions.clear (); m_NTCP2Sessions.clear ();
@@ -1317,32 +1305,20 @@ namespace transport
{ {
if (!session) return false; if (!session) return false;
if (incoming) if (incoming)
m_PendingIncomingSessions.erase (session->GetRemoteEndpoint ().address ()); m_PendingIncomingSessions.remove (session);
if (!session->GetRemoteIdentity ()) if (!session->GetRemoteIdentity ()) return false;
{
LogPrint (eLogWarning, "NTCP2: Unknown identity for ", session->GetRemoteEndpoint ());
session->Terminate ();
return false;
}
auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto& ident = session->GetRemoteIdentity ()->GetIdentHash ();
auto it = m_NTCP2Sessions.find (ident); auto it = m_NTCP2Sessions.find (ident);
if (it != m_NTCP2Sessions.end ()) if (it != m_NTCP2Sessions.end ())
{ {
LogPrint (eLogWarning, "NTCP2: Session with ", ident.ToBase64 (), " already exists. ", incoming ? "Replaced" : "Dropped"); LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists");
if (incoming) if (incoming)
{
// replace by new session // replace by new session
auto s = it->second; it->second->Terminate ();
m_NTCP2Sessions.erase (it);
s->Terminate ();
}
else else
{
session->Terminate ();
return false; return false;
}
} }
m_NTCP2Sessions.emplace (ident, session); m_NTCP2Sessions.insert (std::make_pair (ident, session));
return true; return true;
} }
@@ -1437,38 +1413,29 @@ namespace transport
if (!ec) if (!ec)
{ {
LogPrint (eLogDebug, "NTCP2: Connected from ", ep); LogPrint (eLogDebug, "NTCP2: Connected from ", ep);
if (!i2p::util::net::IsInReservedRange(ep.address ())) if (conn)
{ {
if (conn) conn->SetRemoteEndpoint (ep);
{ conn->ServerLogin ();
if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) m_PendingIncomingSessions.push_back (conn);
{ conn = nullptr;
conn->SetRemoteEndpoint (ep);
conn->ServerLogin ();
conn = nullptr;
}
else
LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending");
}
} }
else
LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ());
} }
else else
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
} }
else else
{ {
LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); LogPrint (eLogError, "NTCP2: Accept error ", error.message ());
if (error == boost::asio::error::no_descriptors) if (error == boost::asio::error::no_descriptors)
{ {
i2p::context.SetError (eRouterErrorNoDescriptors); i2p::context.SetError (eRouterErrorNoDescriptors);
return; return;
} }
} }
if (error != boost::asio::error::operation_aborted) if (error != boost::asio::error::operation_aborted)
{ {
if (!conn) // connection is used, create new one if (!conn) // connection is used, create new one
conn = std::make_shared<NTCP2Session> (*this); conn = std::make_shared<NTCP2Session> (*this);
else // reuse failed else // reuse failed
@@ -1487,43 +1454,29 @@ namespace transport
if (!ec) if (!ec)
{ {
LogPrint (eLogDebug, "NTCP2: Connected from ", ep); LogPrint (eLogDebug, "NTCP2: Connected from ", ep);
if (!i2p::util::net::IsInReservedRange(ep.address ()) || if (conn)
i2p::util::net::IsYggdrasilAddress (ep.address ()))
{ {
if (conn) conn->SetRemoteEndpoint (ep);
{ conn->ServerLogin ();
if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) m_PendingIncomingSessions.push_back (conn);
{
conn->SetRemoteEndpoint (ep);
conn->ServerLogin ();
conn = nullptr;
}
else
LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending");
}
} }
else
LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ());
} }
else else
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
} }
else else
{ {
LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ()); LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ());
if (error == boost::asio::error::no_descriptors) if (error == boost::asio::error::no_descriptors)
{ {
i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); i2p::context.SetErrorV6 (eRouterErrorNoDescriptors);
return; return;
} }
} }
if (error != boost::asio::error::operation_aborted) if (error != boost::asio::error::operation_aborted)
{ {
if (!conn) // connection is used, create new one conn = std::make_shared<NTCP2Session> (*this);
conn = std::make_shared<NTCP2Session> (*this);
else // reuse failed
conn->Close ();
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this,
conn, std::placeholders::_1)); conn, std::placeholders::_1));
} }
@@ -1554,34 +1507,34 @@ namespace transport
// pending // pending
for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();) for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();)
{ {
if (it->second->IsEstablished () || it->second->IsTerminationTimeoutExpired (ts)) if ((*it)->IsEstablished () || (*it)->IsTerminationTimeoutExpired (ts))
{ {
it->second->Terminate (); (*it)->Terminate ();
it = m_PendingIncomingSessions.erase (it); // established of expired it = m_PendingIncomingSessions.erase (it); // established of expired
} }
else if (it->second->IsTerminated ()) else if ((*it)->IsTerminated ())
it = m_PendingIncomingSessions.erase (it); // already terminated it = m_PendingIncomingSessions.erase (it); // already terminated
else else
it++; it++;
} }
ScheduleTermination (); ScheduleTermination ();
// try to restart acceptors if no description // try to restart acceptors if no description
// we do it after timer to let timer take descriptor first // we do it after timer to let timer take descriptor first
if (i2p::context.GetError () == eRouterErrorNoDescriptors) if (i2p::context.GetError () == eRouterErrorNoDescriptors)
{ {
i2p::context.SetError (eRouterErrorNone); i2p::context.SetError (eRouterErrorNone);
auto conn = std::make_shared<NTCP2Session> (*this); auto conn = std::make_shared<NTCP2Session> (*this);
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this,
conn, std::placeholders::_1)); conn, std::placeholders::_1));
} }
if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors) if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors)
{ {
i2p::context.SetErrorV6 (eRouterErrorNone); i2p::context.SetErrorV6 (eRouterErrorNone);
auto conn = std::make_shared<NTCP2Session> (*this); auto conn = std::make_shared<NTCP2Session> (*this);
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this,
conn, std::placeholders::_1)); conn, std::placeholders::_1));
} }
} }
} }
@@ -1789,15 +1742,15 @@ namespace transport
}); });
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size
boost::asio::transfer_all(), boost::asio::transfer_all(),
[timer, conn, readbuff](const boost::system::error_code & e, std::size_t transferred) [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred)
{ {
if (e) if (e)
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message()); LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
else if (!(*readbuff)[1]) // succeeded else if (!(*readbuff)[1]) // succeeded
{ {
boost::system::error_code ec; boost::system::error_code ec;
size_t moreBytes = conn->GetSocket ().available(ec); size_t moreBytes = conn->GetSocket ().available(ec);
if (moreBytes) // read remaining portion of reply if ipv6 received if (moreBytes) // read remaining portion of reply if ipv6 received
boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec);
timer->cancel(); timer->cancel();

View File

@@ -134,22 +134,22 @@ namespace transport
~NTCP2Session (); ~NTCP2Session ();
void Terminate (); void Terminate ();
void TerminateByTimeout (); void TerminateByTimeout ();
void Done () override; void Done ();
void Close (); // for accept void Close () { m_Socket.close (); }; // for accept
void DeleteNextReceiveBuffer (uint64_t ts); void DeleteNextReceiveBuffer (uint64_t ts);
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; }; void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; };
bool IsEstablished () const override { return m_IsEstablished; }; bool IsEstablished () const { return m_IsEstablished; };
bool IsTerminated () const { return m_IsTerminated; }; bool IsTerminated () const { return m_IsTerminated; };
void ClientLogin (); // Alice void ClientLogin (); // Alice
void ServerLogin (); // Bob void ServerLogin (); // Bob
void SendLocalRouterInfo (bool update) override; // after handshake or by update void SendLocalRouterInfo (bool update); // after handshake or by update
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override; void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
private: private:
@@ -277,7 +277,7 @@ namespace transport
boost::asio::deadline_timer m_TerminationTimer; boost::asio::deadline_timer m_TerminationTimer;
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor; std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor;
std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions; std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions;
std::map<boost::asio::ip::address, std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions; std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
ProxyType m_ProxyType; ProxyType m_ProxyType;
std::string m_ProxyAddress, m_ProxyAuthorization; std::string m_ProxyAddress, m_ProxyAuthorization;

View File

@@ -295,8 +295,7 @@ namespace data
else else
{ {
r = std::make_shared<RouterInfo> (buf, len); r = std::make_shared<RouterInfo> (buf, len);
if (!r->IsUnreachable () && r->HasValidAddresses () && if (!r->IsUnreachable () && r->HasValidAddresses ())
i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ())
{ {
bool inserted = false; bool inserted = false;
{ {
@@ -366,16 +365,15 @@ namespace data
bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType) bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType)
{ {
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb
if (leaseSet->IsValid ()) if (leaseSet->IsValid ())
{ {
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
auto it = m_LeaseSets.find(ident); auto it = m_LeaseSets.find(ident);
if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType || if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType ||
leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ()) leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ())
{ {
if (leaseSet->IsPublic () && !leaseSet->IsExpired () && if (leaseSet->IsPublic () && !leaseSet->IsExpired ())
i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ())
{ {
// TODO: implement actual update // TODO: implement actual update
LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32());
@@ -384,7 +382,7 @@ namespace data
} }
else else
{ {
LogPrint (eLogWarning, "NetDb: Unpublished or expired or future LeaseSet2 received: ", ident.ToBase32()); LogPrint (eLogWarning, "NetDb: Unpublished or expired LeaseSet2 received: ", ident.ToBase32());
m_LeaseSets.erase (ident); m_LeaseSets.erase (ident);
} }
} }
@@ -496,7 +494,7 @@ namespace data
{ {
auto r = std::make_shared<RouterInfo>(path); auto r = std::make_shared<RouterInfo>(path);
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () && if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL) // too old ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
{ {
r->DeleteBuffer (); r->DeleteBuffer ();
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
@@ -639,12 +637,7 @@ namespace data
it.second->SetUnreachable (true); it.second->SetUnreachable (true);
} }
else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout)
it.second->SetUnreachable (true); it.second->SetUnreachable (true);
else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ())
{
LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds");
it.second->SetUnreachable (true);
}
if (it.second->IsUnreachable ()) if (it.second->IsUnreachable ())
{ {
@@ -658,8 +651,8 @@ namespace data
m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoBuffersPool.CleanUpMt ();
m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt ();
m_RouterInfoAddressVectorsPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt ();
if (updatedCount > 0) if (updatedCount > 0)
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
if (deletedCount > 0) if (deletedCount > 0)
@@ -763,7 +756,7 @@ namespace data
{ {
LogPrint (eLogError, "NetDb: Database store msg is too short ", len, ". Dropped"); LogPrint (eLogError, "NetDb: Database store msg is too short ", len, ". Dropped");
return; return;
} }
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET); IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
if (ident.IsZero ()) if (ident.IsZero ())
{ {
@@ -778,7 +771,7 @@ namespace data
{ {
LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped"); LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped");
return; return;
} }
auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); auto deliveryStatus = CreateDeliveryStatusMsg (replyToken);
uint32_t tunnelID = bufbe32toh (buf + offset); uint32_t tunnelID = bufbe32toh (buf + offset);
offset += 4; offset += 4;

View File

@@ -44,7 +44,6 @@ namespace data
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days
const int NETDB_EXPIRATION_TIMEOUT_THRESHOLD = 2*60; // 2 minutes
const int NETDB_PUBLISH_INTERVAL = 60 * 40; const int NETDB_PUBLISH_INTERVAL = 60 * 40;
const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
@@ -126,11 +125,11 @@ namespace data
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r); void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
std::shared_ptr<RouterInfo::Address> NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; std::shared_ptr<RouterInfo::Address> NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); };
boost::shared_ptr<RouterInfo::Addresses> NewRouterInfoAddresses () boost::shared_ptr<RouterInfo::Addresses> NewRouterInfoAddresses ()
{ {
return boost::shared_ptr<RouterInfo::Addresses>(m_RouterInfoAddressVectorsPool.AcquireMt (), return boost::shared_ptr<RouterInfo::Addresses>(m_RouterInfoAddressVectorsPool.AcquireMt (),
std::bind <void (i2p::util::MemoryPoolMt<RouterInfo::Addresses>::*)(RouterInfo::Addresses *)> std::bind <void (i2p::util::MemoryPoolMt<RouterInfo::Addresses>::*)(RouterInfo::Addresses *)>
(&i2p::util::MemoryPoolMt<RouterInfo::Addresses>::ReleaseMt, (&i2p::util::MemoryPoolMt<RouterInfo::Addresses>::ReleaseMt,
&m_RouterInfoAddressVectorsPool, std::placeholders::_1)); &m_RouterInfoAddressVectorsPool, std::placeholders::_1));
}; };
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };

View File

@@ -125,7 +125,7 @@ namespace i2p
} }
if (ipv6) if (ipv6)
{ {
std::string host; std::string host = "::1";
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
i2p::config::GetOption("host", host); i2p::config::GetOption("host", host);
else else
@@ -136,7 +136,6 @@ namespace i2p
if (ntcp2) if (ntcp2)
{ {
bool added = false;
if (ntcp2Published) if (ntcp2Published)
{ {
std::string ntcp2Host; std::string ntcp2Host;
@@ -144,13 +143,9 @@ namespace i2p
i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host);
else else
ntcp2Host = host; ntcp2Host = host;
if (!ntcp2Host.empty () && port) routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
{
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
added = true;
}
} }
if (!added) else
{ {
if (!ipv4) // no other ntcp2 addresses yet if (!ipv4) // no other ntcp2 addresses yet
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
@@ -159,18 +154,13 @@ namespace i2p
} }
if (ssu2) if (ssu2)
{ {
bool added = false;
if (ssu2Published) if (ssu2Published)
{ {
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = port; if (!ssu2Port) ssu2Port = port;
if (!host.empty () && ssu2Port) routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port);
{
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port);
added = true;
}
} }
if (!added) else
{ {
if (!ipv4) // no other ssu2 addresses yet if (!ipv4) // no other ssu2 addresses yet
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro); routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
@@ -254,7 +244,7 @@ namespace i2p
} }
} }
} }
void RouterContext::SetStatusV6 (RouterStatus status) void RouterContext::SetStatusV6 (RouterStatus status)
{ {
if (status != m_StatusV6) if (status != m_StatusV6)
@@ -274,7 +264,7 @@ namespace i2p
} }
} }
} }
void RouterContext::UpdatePort (int port) void RouterContext::UpdatePort (int port)
{ {
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
@@ -282,7 +272,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) for (auto& address : *addresses)
{ {
if (address && address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
{ {
address->port = port; address->port = port;
updated = true; updated = true;
@@ -300,7 +290,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) for (auto& address : *addresses)
{ {
if (address && address->IsNTCP2 () && (address->port != port || address->published != publish)) if (address->IsNTCP2 () && (address->port != port || address->published != publish))
{ {
bool isAddr = v4 && address->IsV4 (); bool isAddr = v4 && address->IsV4 ();
if (!isAddr && (v6 || ygg)) if (!isAddr && (v6 || ygg))
@@ -329,20 +319,23 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return; if (!addresses) return;
bool found = false, updated = false; bool found = false, updated = false;
for (auto& it: *addresses) for (auto it = addresses->begin (); it != addresses->end ();)
{ {
if (it && it->IsNTCP2 ()) if ((*it)->IsNTCP2 ())
{ {
found = true; found = true;
if (enable) if (enable)
{ {
it->s = m_NTCP2Keys->staticPublicKey; (*it)->s = m_NTCP2Keys->staticPublicKey;
memcpy (it->i, m_NTCP2Keys->iv, 16); memcpy ((*it)->i, m_NTCP2Keys->iv, 16);
it++;
} }
else else
it.reset (); it = addresses->erase (it);
updated = true; updated = true;
} }
else
it++;
} }
if (enable && !found) if (enable && !found)
{ {
@@ -362,7 +355,7 @@ namespace i2p
if (!port) if (!port)
{ {
for (const auto& address : *addresses) for (const auto& address : *addresses)
if (address && address->port) if (address->port)
{ {
newPort = address->port; newPort = address->port;
break; break;
@@ -372,7 +365,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) for (auto& address : *addresses)
{ {
if (address && address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) && if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ()))) ((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
{ {
if (port) address->port = port; if (port) address->port = port;
@@ -394,20 +387,23 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return; if (!addresses) return;
bool found = false, updated = false; bool found = false, updated = false;
for (auto& it : *addresses) for (auto it = addresses->begin (); it != addresses->end ();)
{ {
if (it && it->IsSSU2 ()) if ((*it)->IsSSU2 ())
{ {
found = true; found = true;
if (enable) if (enable)
{ {
it->s = m_SSU2Keys->staticPublicKey; (*it)->s = m_SSU2Keys->staticPublicKey;
it->i = m_SSU2Keys->intro; (*it)->i = m_SSU2Keys->intro;
it++;
} }
else else
it.reset (); it = addresses->erase (it);
updated = true; updated = true;
} }
else
it++;
} }
if (enable && !found) if (enable && !found)
{ {
@@ -437,53 +433,34 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return; if (!addresses) return;
bool updated = false; bool updated = false;
if (host.is_v4 ()) for (auto& address : *addresses)
{ {
auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx]; if (address->host != host && address->IsCompatible (host) &&
if (addr && addr->host != host) !i2p::util::net::IsYggdrasilAddress (address->host))
{ {
addr->host = host; // update host
address->host = host;
updated = true; updated = true;
} }
addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]; if (host.is_v6 () && address->IsV6 () && address->ssu &&
if (addr && addr->host != host) (!address->ssu->mtu || updated) && m_StatusV6 != eRouterStatusProxy)
{ {
addr->host = host; // update MTU
updated = true; auto mtu = i2p::util::net::GetMTU (host);
} if (mtu)
}
else if (host.is_v6 ())
{
auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx];
if (addr && addr->host != host)
{
addr->host = host;
updated = true;
}
addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx];
if (addr && (addr->host != host || !addr->ssu->mtu))
{
addr->host = host;
if (m_StatusV6 != eRouterStatusProxy)
{ {
// update MTU LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
auto mtu = i2p::util::net::GetMTU (host); int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ());
if (mtu) if (mtu > maxMTU)
{ {
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu); mtu = maxMTU;
int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ()); LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
if (mtu > maxMTU)
{
mtu = maxMTU;
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
}
addr->ssu->mtu = mtu;
} }
address->ssu->mtu = mtu;
updated = true;
} }
updated = true;
} }
} }
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL) if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
UpdateRouterInfo (); UpdateRouterInfo ();
@@ -505,12 +482,18 @@ namespace i2p
void RouterContext::ClearSSU2Introducers (bool v4) void RouterContext::ClearSSU2Introducers (bool v4)
{ {
auto addr = m_RouterInfo.GetSSU2Address (v4); auto addresses = m_RouterInfo.GetAddresses ();
if (addr && !addr->ssu->introducers.empty ()) if (!addresses) return;
{ bool updated = false;
addr->ssu->introducers.clear (); for (auto& addr : *addresses)
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
addr->ssu && !addr->ssu->introducers.empty ())
{
addr->ssu->introducers.clear ();
updated = true;
}
if (updated)
UpdateRouterInfo (); UpdateRouterInfo ();
}
} }
void RouterContext::SetFloodfill (bool floodfill) void RouterContext::SetFloodfill (bool floodfill)
@@ -626,17 +609,17 @@ namespace i2p
uint16_t port = 0; uint16_t port = 0;
// delete previous introducers // delete previous introducers
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (addresses) if (addresses)
{ {
for (auto& addr : *addresses) for (auto& addr : *addresses)
if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{ {
addr->published = false; addr->published = false;
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
addr->ssu->introducers.clear (); addr->ssu->introducers.clear ();
port = addr->port; port = addr->port;
} }
} }
// unpublish NTCP2 addreeses // unpublish NTCP2 addreeses
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2) if (ntcp2)
@@ -662,17 +645,17 @@ namespace i2p
// delete previous introducers // delete previous introducers
bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published); bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published);
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (addresses) if (addresses)
{ {
for (auto& addr : *addresses) for (auto& addr : *addresses)
if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{ {
addr->published = true; addr->published = true;
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer; addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
addr->ssu->introducers.clear (); addr->ssu->introducers.clear ();
if (addr->port) port = addr->port; if (addr->port) port = addr->port;
} }
} }
// publish NTCP2 // publish NTCP2
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2) if (ntcp2)
@@ -698,11 +681,11 @@ namespace i2p
bool foundNTCP2 = false, foundSSU2 = false; bool foundNTCP2 = false, foundSSU2 = false;
uint16_t port = 0; uint16_t port = 0;
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (addresses) if (addresses)
{ {
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr && addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host)) if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
{ {
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
@@ -715,7 +698,7 @@ namespace i2p
default: ; default: ;
} }
} }
if (addr) port = addr->port; port = addr->port;
} }
} }
if (!port) if (!port)
@@ -781,11 +764,11 @@ namespace i2p
std::string host = "127.0.0.1"; std::string host = "127.0.0.1";
uint16_t port = 0; uint16_t port = 0;
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (addresses) if (addresses)
{ {
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr && addr->IsV4 ()) if (addr->IsV4 ())
{ {
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
@@ -798,9 +781,9 @@ namespace i2p
default: ; default: ;
} }
} }
if (addr && addr->port) port = addr->port; if (addr->port) port = addr->port;
} }
} }
if (!port) if (!port)
{ {
i2p::config::GetOption("port", port); i2p::config::GetOption("port", port);
@@ -851,26 +834,26 @@ namespace i2p
{ {
if (supportsmesh) if (supportsmesh)
{ {
auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return;
m_RouterInfo.EnableMesh (); m_RouterInfo.EnableMesh ();
if ((*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]) return; // we have mesh address already
uint16_t port = 0; uint16_t port = 0;
i2p::config::GetOption ("ntcp2.port", port); i2p::config::GetOption ("ntcp2.port", port);
if (!port) i2p::config::GetOption("port", port); if (!port) i2p::config::GetOption("port", port);
if (!port) bool foundMesh = false;
auto addresses = m_RouterInfo.GetAddresses ();
if (addresses)
{ {
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr && addr->port) if (!port) port = addr->port;
if (i2p::util::net::IsYggdrasilAddress (addr->host))
{ {
port = addr->port; foundMesh = true;
break; break;
} }
} }
} }
if (!port) port = SelectRandomPort (); if (!foundMesh)
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
} }
else else
m_RouterInfo.DisableMesh (); m_RouterInfo.DisableMesh ();
@@ -884,8 +867,8 @@ namespace i2p
if (!addresses) return; if (!addresses) return;
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{ {
addr->ssu->mtu = mtu; addr->ssu->mtu = mtu;
LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu); LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu);
} }
@@ -900,7 +883,7 @@ namespace i2p
if (!addresses) return; if (!addresses) return;
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr && addr->IsPublishedNTCP2 ()) if (addr->IsPublishedNTCP2 ())
{ {
bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host); bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host);
if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1))) if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1)))

View File

@@ -209,6 +209,7 @@ namespace data
auto addresses = netdb.NewRouterInfoAddresses (); auto addresses = netdb.NewRouterInfoAddresses ();
uint8_t numAddresses; uint8_t numAddresses;
s.read ((char *)&numAddresses, sizeof (numAddresses)); s.read ((char *)&numAddresses, sizeof (numAddresses));
addresses->reserve (numAddresses);
for (int i = 0; i < numAddresses; i++) for (int i = 0; i < numAddresses; i++)
{ {
uint8_t supportedTransports = 0; uint8_t supportedTransports = 0;
@@ -329,9 +330,9 @@ namespace data
} }
Introducer& introducer = address->ssu->introducers.at (index); Introducer& introducer = address->ssu->introducers.at (index);
if (!strcmp (key, "ihost")) if (!strcmp (key, "ihost"))
introducer.isH = false; // SSU1 introducer.isH = false; // SSU1
else if (!strcmp (key, "iport")) else if (!strcmp (key, "iport"))
introducer.isH = false; // SSU1 introducer.isH = false; // SSU1
else if (!strcmp (key, "itag")) else if (!strcmp (key, "itag"))
{ {
try try
@@ -344,10 +345,10 @@ namespace data
} }
} }
else if (!strcmp (key, "ih")) else if (!strcmp (key, "ih"))
{ {
Base64ToByteStream (value, strlen (value), introducer.iH, 32); Base64ToByteStream (value, strlen (value), introducer.iH, 32);
introducer.isH = true; introducer.isH = true;
} }
else if (!strcmp (key, "iexp")) else if (!strcmp (key, "iexp"))
{ {
try try
@@ -417,11 +418,7 @@ namespace data
if (supportedTransports) if (supportedTransports)
{ {
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
{ addresses->push_back(address);
for (uint8_t i = 0; i < eNumTransports; i++)
if ((1 << i) & supportedTransports)
(*addresses)[i] = address;
}
m_SupportedTransports |= supportedTransports; m_SupportedTransports |= supportedTransports;
} }
} }
@@ -636,23 +633,13 @@ namespace data
{ {
m_SupportedTransports |= eNTCP2V4; m_SupportedTransports |= eNTCP2V4;
if (addr->published) m_ReachableTransports |= eNTCP2V4; if (addr->published) m_ReachableTransports |= eNTCP2V4;
(*m_Addresses)[eNTCP2V4Idx] = addr;
} }
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
if (i2p::util::net::IsYggdrasilAddress (addr->host)) m_SupportedTransports |= eNTCP2V6;
{ if (addr->published) m_ReachableTransports |= eNTCP2V6;
m_SupportedTransports |= eNTCP2V6Mesh;
m_ReachableTransports |= eNTCP2V6Mesh;
(*m_Addresses)[eNTCP2V6MeshIdx] = addr;
}
else
{
m_SupportedTransports |= eNTCP2V6;
if (addr->published) m_ReachableTransports |= eNTCP2V6;
(*m_Addresses)[eNTCP2V6Idx] = addr;
}
} }
m_Addresses->push_back(std::move(addr));
} }
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps) void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps)
@@ -666,16 +653,9 @@ namespace data
addr->ssu->mtu = 0; addr->ssu->mtu = 0;
memcpy (addr->s, staticKey, 32); memcpy (addr->s, staticKey, 32);
memcpy (addr->i, introKey, 32); memcpy (addr->i, introKey, 32);
if (addr->IsV4 ()) if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4;
{ if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6;
m_SupportedTransports |= eSSU2V4; m_Addresses->push_back(std::move(addr));
(*m_Addresses)[eSSU2V4Idx] = addr;
}
if (addr->IsV6 ())
{
m_SupportedTransports |= eSSU2V6;
(*m_Addresses)[eSSU2V6Idx] = addr;
}
} }
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
@@ -696,14 +676,13 @@ namespace data
{ {
m_SupportedTransports |= eSSU2V4; m_SupportedTransports |= eSSU2V4;
m_ReachableTransports |= eSSU2V4; m_ReachableTransports |= eSSU2V4;
(*m_Addresses)[eSSU2V4Idx] = addr;
} }
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
m_SupportedTransports |= eSSU2V6; m_SupportedTransports |= eSSU2V6;
m_ReachableTransports |= eSSU2V6; m_ReachableTransports |= eSSU2V6;
(*m_Addresses)[eSSU2V6Idx] = addr;
} }
m_Addresses->push_back(std::move(addr));
} }
bool RouterInfo::IsNTCP2 (bool v4only) const bool RouterInfo::IsNTCP2 (bool v4only) const
@@ -742,17 +721,21 @@ namespace data
{ {
if (IsV6 ()) if (IsV6 ())
{ {
if ((*m_Addresses)[eNTCP2V6Idx]) for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
{ {
if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 ()) auto addr = *it;
(*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV6; if (addr->IsV6 ())
(*m_Addresses)[eNTCP2V6Idx].reset (); {
} if (addr->IsV4 ())
if ((*m_Addresses)[eSSU2V6Idx]) {
{ addr->caps &= ~AddressCaps::eV6;
if ((*m_Addresses)[eSSU2V6Idx]->IsV4 ()) ++it;
(*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV6; }
(*m_Addresses)[eSSU2V6Idx].reset (); else
it = m_Addresses->erase (it);
}
else
++it;
} }
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
@@ -762,17 +745,21 @@ namespace data
{ {
if (IsV4 ()) if (IsV4 ())
{ {
if ((*m_Addresses)[eNTCP2V4Idx]) for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
{ {
if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 ()) auto addr = *it;
(*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV4; if (addr->IsV4 ())
(*m_Addresses)[eNTCP2V4Idx].reset (); {
} if (addr->IsV6 ())
if ((*m_Addresses)[eSSU2V4Idx]) {
{ addr->caps &= ~AddressCaps::eV4;
if ((*m_Addresses)[eSSU2V4Idx]->IsV6 ()) ++it;
(*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV4; }
(*m_Addresses)[eSSU2V4Idx].reset (); else
it = m_Addresses->erase (it);
}
else
++it;
} }
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
@@ -793,18 +780,33 @@ namespace data
{ {
m_SupportedTransports &= ~eNTCP2V6Mesh; m_SupportedTransports &= ~eNTCP2V6Mesh;
m_ReachableTransports &= ~eNTCP2V6Mesh; m_ReachableTransports &= ~eNTCP2V6Mesh;
(*m_Addresses)[eNTCP2V6MeshIdx].reset (); for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
{
auto addr = *it;
if (i2p::util::net::IsYggdrasilAddress (addr->host))
it = m_Addresses->erase (it);
else
++it;
}
} }
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const
{ {
return (*GetAddresses ())[eSSU2V4Idx]; return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV4();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
{ {
return (*GetAddresses ())[eSSU2V6Idx]; return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV6();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const
@@ -829,8 +831,8 @@ namespace data
#else #else
return m_Addresses; return m_Addresses;
#endif #endif
} }
template<typename Filter> template<typename Filter>
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
{ {
@@ -841,7 +843,7 @@ namespace data
auto addresses = m_Addresses; auto addresses = m_Addresses;
#endif #endif
for (const auto& address : *addresses) for (const auto& address : *addresses)
if (address && filter (address)) return address; if (filter (address)) return address;
return nullptr; return nullptr;
} }
@@ -859,29 +861,40 @@ namespace data
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const
{ {
if (!key) return nullptr; if (!key) return nullptr;
auto addr = (*GetAddresses ())[isV6 ? eSSU2V6Idx : eSSU2V4Idx]; return GetAddress (
if (addr && !memcmp (addr->s, key, 32)) [key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool
return addr; {
return nullptr; return address->IsSSU2 () && !memcmp (address->s, key, 32) &&
((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ()));
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
{ {
auto addr = (*GetAddresses ())[eNTCP2V4Idx]; return GetAddress (
if (addr && addr->IsPublishedNTCP2 ()) return addr; [](std::shared_ptr<const RouterInfo::Address> address)->bool
return nullptr; {
return address->IsPublishedNTCP2 () && address->host.is_v4 ();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const
{ {
auto addr = (*GetAddresses ())[eNTCP2V6Idx]; return GetAddress (
if (addr && addr->IsPublishedNTCP2 ()) return addr; [](std::shared_ptr<const RouterInfo::Address> address)->bool
return nullptr; {
return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
!i2p::util::net::IsYggdrasilAddress (address->host);
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const
{ {
return (*GetAddresses ())[eNTCP2V6MeshIdx]; return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
});
} }
std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const
@@ -908,22 +921,30 @@ namespace data
bool RouterInfo::IsSSU2PeerTesting (bool v4) const bool RouterInfo::IsSSU2PeerTesting (bool v4) const
{ {
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; return (bool)GetAddress (
return addr && addr->IsPeerTesting () && addr->IsReachableSSU (); [v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->IsSSU2 ()) && address->IsPeerTesting () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
});
} }
bool RouterInfo::IsSSU2Introducer (bool v4) const bool RouterInfo::IsSSU2Introducer (bool v4) const
{ {
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; return (bool)GetAddress (
return addr && addr->IsIntroducer () && !addr->host.is_unspecified () && addr->port; [v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->IsSSU2 ()) && address->IsIntroducer () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified ();
});
} }
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
{ {
for (auto& addr: *m_Addresses) for (auto& addr: *m_Addresses)
{ {
if (addr && !addr->published) if (!addr->published && (addr->transportStyle == eTransportNTCP2 || addr->transportStyle == eTransportSSU2))
{ {
addr->caps &= ~(eV4 | eV6); addr->caps &= ~(eV4 | eV6);
addr->caps |= transports; addr->caps |= transports;
@@ -937,7 +958,6 @@ namespace data
m_ReachableTransports = 0; m_ReachableTransports = 0;
for (const auto& addr: *m_Addresses) for (const auto& addr: *m_Addresses)
{ {
if (!addr) continue;
uint8_t transports = 0; uint8_t transports = 0;
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
@@ -1037,26 +1057,14 @@ namespace data
{ {
auto addresses = GetAddresses (); auto addresses = GetAddresses ();
if (!addresses) return; if (!addresses) return;
uint64_t ts = htobe64 (GetTimestamp ()); uint64_t ts = htobe64 (GetTimestamp ());
s.write ((const char *)&ts, sizeof (ts)); s.write ((const char *)&ts, sizeof (ts));
// addresses // addresses
uint8_t numAddresses = 0; uint8_t numAddresses = addresses->size ();
for (size_t idx = 0; idx < addresses->size(); idx++)
{
auto addr_ptr = (*addresses)[idx];
if (!addr_ptr) continue;
if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
numAddresses++;
}
s.write ((char *)&numAddresses, sizeof (numAddresses)); s.write ((char *)&numAddresses, sizeof (numAddresses));
for (size_t idx = 0; idx < addresses->size(); idx++) for (const auto& addr_ptr : *addresses)
{ {
auto addr_ptr = (*addresses)[idx];
if (!addr_ptr) continue;
if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
const Address& address = *addr_ptr; const Address& address = *addr_ptr;
// calculate cost // calculate cost
uint8_t cost = 0x7f; uint8_t cost = 0x7f;
@@ -1154,7 +1162,7 @@ namespace data
i = 0; i = 0;
for (const auto& introducer: address.ssu->introducers) for (const auto& introducer: address.ssu->introducers)
{ {
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties); WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
properties << '='; properties << '=';
char value[64]; char value[64];
size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64); size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64);
@@ -1174,7 +1182,7 @@ namespace data
} }
} }
} }
if (address.transportStyle == eTransportSSU2) if (address.transportStyle == eTransportSSU2)
{ {
// write mtu // write mtu
@@ -1259,14 +1267,16 @@ namespace data
{ {
auto addresses = GetAddresses (); auto addresses = GetAddresses ();
if (!addresses) return false; if (!addresses) return false;
auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; for (auto& addr : *addresses)
if (addr)
{ {
for (auto& intro: addr->ssu->introducers) if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
if (intro.iTag == introducer.iTag) return false; // already presented {
addr->ssu->introducers.push_back (introducer); for (auto& intro: addr->ssu->introducers)
SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6))); if (intro.iTag == introducer.iTag) return false; // already presented
return true; addr->ssu->introducers.push_back (introducer);
SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6)));
return true;
}
} }
return false; return false;
} }
@@ -1275,17 +1285,19 @@ namespace data
{ {
auto addresses = GetAddresses (); auto addresses = GetAddresses ();
if (!addresses) return false; if (!addresses) return false;
auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; for (auto& addr: *addresses)
if (addr)
{ {
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
if (h == it->iH) {
{ for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
addr->ssu->introducers.erase (it); if (h == it->iH)
if (addr->ssu->introducers.empty ()) {
SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6)); addr->ssu->introducers.erase (it);
return true; if (addr->ssu->introducers.empty ())
} SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6));
return true;
}
}
} }
return false; return false;
} }

View File

@@ -60,25 +60,13 @@ namespace data
{ {
public: public:
enum SupportedTransportsIdx
{
eNTCP2V4Idx = 0,
eNTCP2V6Idx,
eSSU2V4Idx,
eSSU2V6Idx,
eNTCP2V6MeshIdx,
eNumTransports
};
#define TransportBit(tr) e##tr = (1 << e##tr##Idx)
enum SupportedTransports enum SupportedTransports
{ {
TransportBit(NTCP2V4), // 0x01 eNTCP2V4 = 0x01,
TransportBit(NTCP2V6), // 0x02 eNTCP2V6 = 0x02,
TransportBit(SSU2V4), // 0x04 eSSU2V4 = 0x04,
TransportBit(SSU2V6), // 0x08 eSSU2V6 = 0x08,
TransportBit(NTCP2V6Mesh), // 0x10 eNTCP2V6Mesh = 0x10,
eAllTransports = 0xFF eAllTransports = 0xFF
}; };
typedef uint8_t CompatibleTransports; typedef uint8_t CompatibleTransports;
@@ -172,7 +160,7 @@ namespace data
Buffer (const uint8_t * buf, size_t len); Buffer (const uint8_t * buf, size_t len);
}; };
typedef std::array<std::shared_ptr<Address>, eNumTransports> Addresses; typedef std::vector<std::shared_ptr<Address> > Addresses;
RouterInfo (const std::string& fullPath); RouterInfo (const std::string& fullPath);
RouterInfo (const RouterInfo& ) = default; RouterInfo (const RouterInfo& ) = default;

View File

@@ -47,21 +47,21 @@ namespace transport
{ {
found = true; found = true;
if (address->IsV6 ()) if (address->IsV6 ())
{ {
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu); uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu);
if (!mtu || mtu > SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE) if (!mtu || mtu > SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE)
mtu = SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE; mtu = SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE;
i2p::context.SetMTU (mtu, false); i2p::context.SetMTU (mtu, false);
} }
else else
{ {
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu); uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu);
if (!mtu || mtu > SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE) if (!mtu || mtu > SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE)
mtu = SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE; mtu = SSU2_MAX_PACKET_SIZE - SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE;
i2p::context.SetMTU (mtu, true); i2p::context.SetMTU (mtu, true);
} }
continue; // we don't need port for proxy continue; // we don't need port for proxy
} }
auto port = address->port; auto port = address->port;
if (!port) if (!port)
{ {
@@ -103,11 +103,11 @@ namespace transport
} }
} }
if (found) if (found)
{ {
if (m_IsThroughProxy) if (m_IsThroughProxy)
ConnectToProxy (); ConnectToProxy ();
m_ReceiveService.Start (); m_ReceiveService.Start ();
} }
ScheduleTermination (); ScheduleTermination ();
ScheduleResend (false); ScheduleResend (false);
} }
@@ -136,11 +136,11 @@ namespace transport
m_SocketV6.close (); m_SocketV6.close ();
if (m_UDPAssociateSocket) if (m_UDPAssociateSocket)
{ {
m_UDPAssociateSocket->close (); m_UDPAssociateSocket->close ();
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
} }
StopIOService (); StopIOService ();
m_Sessions.clear (); m_Sessions.clear ();
@@ -168,12 +168,12 @@ namespace transport
m_AddressV6 = localAddress; m_AddressV6 = localAddress;
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu); uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu);
if (!mtu) if (!mtu)
{ {
int maxMTU = i2p::util::net::GetMaxMTU (localAddress.to_v6 ()); int maxMTU = i2p::util::net::GetMaxMTU (localAddress.to_v6 ());
mtu = i2p::util::net::GetMTU (localAddress); mtu = i2p::util::net::GetMTU (localAddress);
if (mtu > maxMTU) mtu = maxMTU; if (mtu > maxMTU) mtu = maxMTU;
} }
else else
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
i2p::context.SetMTU (mtu, false); i2p::context.SetMTU (mtu, false);
@@ -236,19 +236,7 @@ namespace transport
void SSU2Server::HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred, void SSU2Server::HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred,
Packet * packet, boost::asio::ip::udp::socket& socket) Packet * packet, boost::asio::ip::udp::socket& socket)
{ {
if (!ecode if (!ecode)
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
#endif
)
// just try continue reading when received ICMP response otherwise socket can crash,
// but better to find out which host were sent it and mark that router as unreachable
{ {
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); i2p::transport::transports.UpdateReceivedBytes (bytes_transferred);
packet->len = bytes_transferred; packet->len = bytes_transferred;
@@ -297,12 +285,12 @@ namespace transport
ConnectToProxy (); ConnectToProxy ();
} }
else else
{ {
auto ep = socket.local_endpoint (); auto ep = socket.local_endpoint ();
socket.close (); socket.close ();
OpenSocket (ep); OpenSocket (ep);
Receive (socket); Receive (socket);
} }
} }
} }
} }
@@ -313,7 +301,7 @@ namespace transport
{ {
if (m_IsThroughProxy) if (m_IsThroughProxy)
ProcessNextPacketFromProxy (packet->buf, packet->len); ProcessNextPacketFromProxy (packet->buf, packet->len);
else else
ProcessNextPacket (packet->buf, packet->len, packet->from); ProcessNextPacket (packet->buf, packet->len, packet->from);
m_PacketsPool.ReleaseMt (packet); m_PacketsPool.ReleaseMt (packet);
if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated)
@@ -326,7 +314,7 @@ namespace transport
if (m_IsThroughProxy) if (m_IsThroughProxy)
for (auto& packet: packets) for (auto& packet: packets)
ProcessNextPacketFromProxy (packet->buf, packet->len); ProcessNextPacketFromProxy (packet->buf, packet->len);
else else
for (auto& packet: packets) for (auto& packet: packets)
ProcessNextPacket (packet->buf, packet->len, packet->from); ProcessNextPacket (packet->buf, packet->len, packet->from);
m_PacketsPool.ReleaseMt (packets); m_PacketsPool.ReleaseMt (packets);
@@ -458,7 +446,7 @@ namespace transport
} }
return nullptr; return nullptr;
} }
void SSU2Server::ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) void SSU2Server::ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint)
{ {
if (len < 24) return; if (len < 24) return;
@@ -511,7 +499,7 @@ namespace transport
if (m_LastSession && m_LastSession->GetState () == eSSU2SessionStateClosing) if (m_LastSession && m_LastSession->GetState () == eSSU2SessionStateClosing)
m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again
break; break;
case eSSU2SessionStateClosingConfirmed: case eSSU2SessionStateClosingConfirmed:
case eSSU2SessionStateTerminated: case eSSU2SessionStateTerminated:
m_LastSession = nullptr; m_LastSession = nullptr;
break; break;
@@ -530,22 +518,20 @@ namespace transport
{ {
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex); std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
} }
else else
it1->second->ProcessRetry (buf, len); it1->second->ProcessRetry (buf, len);
} }
else if (!i2p::util::net::IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ()) else
{ {
// assume new incoming session // assume new incoming session
auto session = std::make_shared<SSU2Session> (*this); auto session = std::make_shared<SSU2Session> (*this);
session->SetRemoteEndpoint (senderEndpoint); session->SetRemoteEndpoint (senderEndpoint);
session->ProcessFirstIncomingMessage (connID, buf, len); session->ProcessFirstIncomingMessage (connID, buf, len);
} }
else
LogPrint (eLogError, "SSU2: Incoming packet received from invalid endpoint ", senderEndpoint);
} }
} }
void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen, void SSU2Server::Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen,
const boost::asio::ip::udp::endpoint& to) const boost::asio::ip::udp::endpoint& to)
{ {
@@ -553,7 +539,7 @@ namespace transport
{ {
SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to); SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to);
return; return;
} }
std::vector<boost::asio::const_buffer> bufs std::vector<boost::asio::const_buffer> bufs
{ {
boost::asio::buffer (header, headerLen), boost::asio::buffer (header, headerLen),
@@ -873,11 +859,11 @@ namespace transport
if (it != m_OutgoingTokens.end ()) if (it != m_OutgoingTokens.end ())
{ {
if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second) if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second)
{ {
// token expired // token expired
m_OutgoingTokens.erase (it); m_OutgoingTokens.erase (it);
return 0; return 0;
} }
return it->second.first; return it->second.first;
} }
return 0; return 0;
@@ -893,7 +879,7 @@ namespace transport
return it->second.first; return it->second.first;
else // token expired else // token expired
m_IncomingTokens.erase (it); m_IncomingTokens.erase (it);
} }
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
m_IncomingTokens.emplace (ep, std::make_pair (token, ts + SSU2_TOKEN_EXPIRATION_TIMEOUT)); m_IncomingTokens.emplace (ep, std::make_pair (token, ts + SSU2_TOKEN_EXPIRATION_TIMEOUT));
@@ -1139,23 +1125,23 @@ namespace transport
size_t requestHeaderSize = 0; size_t requestHeaderSize = 0;
memset (m_UDPRequestHeader, 0, 3); memset (m_UDPRequestHeader, 0, 3);
if (to.address ().is_v6 ()) if (to.address ().is_v6 ())
{ {
m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV6; m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV6;
memcpy (m_UDPRequestHeader + 4, to.address ().to_v6().to_bytes().data(), 16); memcpy (m_UDPRequestHeader + 4, to.address ().to_v6().to_bytes().data(), 16);
requestHeaderSize = SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE; requestHeaderSize = SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE;
} }
else else
{ {
m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV4; m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV4;
memcpy (m_UDPRequestHeader + 4, to.address ().to_v4().to_bytes().data(), 4); memcpy (m_UDPRequestHeader + 4, to.address ().to_v4().to_bytes().data(), 4);
requestHeaderSize = SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE; requestHeaderSize = SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE;
} }
htobe16buf (m_UDPRequestHeader + requestHeaderSize - 2, to.port ()); htobe16buf (m_UDPRequestHeader + requestHeaderSize - 2, to.port ());
std::vector<boost::asio::const_buffer> bufs; std::vector<boost::asio::const_buffer> bufs;
bufs.push_back (boost::asio::buffer (m_UDPRequestHeader, requestHeaderSize)); bufs.push_back (boost::asio::buffer (m_UDPRequestHeader, requestHeaderSize));
bufs.push_back (boost::asio::buffer (header, headerLen)); bufs.push_back (boost::asio::buffer (header, headerLen));
if (headerX) bufs.push_back (boost::asio::buffer (headerX, headerXLen)); if (headerX) bufs.push_back (boost::asio::buffer (headerX, headerXLen));
bufs.push_back (boost::asio::buffer (payload, payloadLen)); bufs.push_back (boost::asio::buffer (payload, payloadLen));
boost::system::error_code ec; boost::system::error_code ec;
@@ -1164,7 +1150,7 @@ namespace transport
i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen);
else else
LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to); LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to);
} }
void SSU2Server::ProcessNextPacketFromProxy (uint8_t * buf, size_t len) void SSU2Server::ProcessNextPacketFromProxy (uint8_t * buf, size_t len)
{ {
@@ -1172,11 +1158,11 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: Proxy packet fragmentation is not supported"); LogPrint (eLogWarning, "SSU2: Proxy packet fragmentation is not supported");
return; return;
} }
size_t offset = 0; size_t offset = 0;
boost::asio::ip::udp::endpoint ep; boost::asio::ip::udp::endpoint ep;
switch (buf[3]) // ATYP switch (buf[3]) // ATYP
{ {
case SOCKS5_ATYP_IPV4: case SOCKS5_ATYP_IPV4:
{ {
offset = SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE; offset = SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE;
@@ -1186,7 +1172,7 @@ namespace transport
uint16_t port = bufbe16toh (buf + 8); uint16_t port = bufbe16toh (buf + 8);
ep = boost::asio::ip::udp::endpoint (boost::asio::ip::address_v4 (bytes), port); ep = boost::asio::ip::udp::endpoint (boost::asio::ip::address_v4 (bytes), port);
break; break;
} }
case SOCKS5_ATYP_IPV6: case SOCKS5_ATYP_IPV6:
{ {
offset = SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE; offset = SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE;
@@ -1196,23 +1182,23 @@ namespace transport
uint16_t port = bufbe16toh (buf + 20); uint16_t port = bufbe16toh (buf + 20);
ep = boost::asio::ip::udp::endpoint (boost::asio::ip::address_v6 (bytes), port); ep = boost::asio::ip::udp::endpoint (boost::asio::ip::address_v6 (bytes), port);
break; break;
} }
default: default:
{ {
LogPrint (eLogWarning, "SSU2: Unknown ATYP ", (int)buf[3], " from proxy relay"); LogPrint (eLogWarning, "SSU2: Unknown ATYP ", (int)buf[3], " from proxy relay");
return; return;
} }
} }
ProcessNextPacket (buf + offset, len - offset, ep); ProcessNextPacket (buf + offset, len - offset, ep);
} }
void SSU2Server::ConnectToProxy () void SSU2Server::ConnectToProxy ()
{ {
if (!m_ProxyEndpoint) return; if (!m_ProxyEndpoint) return;
m_UDPAssociateSocket.reset (new boost::asio::ip::tcp::socket (m_ReceiveService.GetService ())); m_UDPAssociateSocket.reset (new boost::asio::ip::tcp::socket (m_ReceiveService.GetService ()));
m_UDPAssociateSocket->async_connect (*m_ProxyEndpoint, m_UDPAssociateSocket->async_connect (*m_ProxyEndpoint,
[this] (const boost::system::error_code& ecode) [this] (const boost::system::error_code& ecode)
{ {
if (ecode) if (ecode)
{ {
LogPrint (eLogError, "SSU2: Can't connect to proxy ", *m_ProxyEndpoint, " ", ecode.message ()); LogPrint (eLogError, "SSU2: Can't connect to proxy ", *m_ProxyEndpoint, " ", ecode.message ());
@@ -1222,12 +1208,12 @@ namespace transport
else else
HandshakeWithProxy (); HandshakeWithProxy ();
}); });
} }
void SSU2Server::HandshakeWithProxy () void SSU2Server::HandshakeWithProxy ()
{ {
if (!m_UDPAssociateSocket) return; if (!m_UDPAssociateSocket) return;
m_UDPRequestHeader[0] = SOCKS5_VER; m_UDPRequestHeader[0] = SOCKS5_VER;
m_UDPRequestHeader[1] = 1; // 1 method m_UDPRequestHeader[1] = 1; // 1 method
m_UDPRequestHeader[2] = 0; // no authentication m_UDPRequestHeader[2] = 0; // no authentication
boost::asio::async_write (*m_UDPAssociateSocket, boost::asio::buffer (m_UDPRequestHeader, 3), boost::asio::transfer_all(), boost::asio::async_write (*m_UDPAssociateSocket, boost::asio::buffer (m_UDPRequestHeader, 3), boost::asio::transfer_all(),
@@ -1237,13 +1223,13 @@ namespace transport
if (ecode) if (ecode)
{ {
LogPrint(eLogError, "SSU2: Proxy write error ", ecode.message()); LogPrint(eLogError, "SSU2: Proxy write error ", ecode.message());
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
ReconnectToProxy (); ReconnectToProxy ();
} }
else else
ReadHandshakeWithProxyReply (); ReadHandshakeWithProxyReply ();
}); });
} }
void SSU2Server::ReadHandshakeWithProxyReply () void SSU2Server::ReadHandshakeWithProxyReply ()
{ {
@@ -1257,7 +1243,7 @@ namespace transport
LogPrint(eLogError, "SSU2: Proxy read error ", ecode.message()); LogPrint(eLogError, "SSU2: Proxy read error ", ecode.message());
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
ReconnectToProxy (); ReconnectToProxy ();
} }
else else
{ {
if (m_UDPRequestHeader[0] == SOCKS5_VER && !m_UDPRequestHeader[1]) if (m_UDPRequestHeader[0] == SOCKS5_VER && !m_UDPRequestHeader[1])
@@ -1266,16 +1252,16 @@ namespace transport
{ {
LogPrint(eLogError, "SSU2: Invalid proxy reply"); LogPrint(eLogError, "SSU2: Invalid proxy reply");
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
} }
} }
}); });
} }
void SSU2Server::SendUDPAssociateRequest () void SSU2Server::SendUDPAssociateRequest ()
{ {
if (!m_UDPAssociateSocket) return; if (!m_UDPAssociateSocket) return;
m_UDPRequestHeader[0] = SOCKS5_VER; m_UDPRequestHeader[0] = SOCKS5_VER;
m_UDPRequestHeader[1] = SOCKS5_CMD_UDP_ASSOCIATE; m_UDPRequestHeader[1] = SOCKS5_CMD_UDP_ASSOCIATE;
m_UDPRequestHeader[2] = 0; // RSV m_UDPRequestHeader[2] = 0; // RSV
m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV4; // TODO: implement ipv6 proxy m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV4; // TODO: implement ipv6 proxy
memset (m_UDPRequestHeader + 4, 0, 6); // address and port all zeros memset (m_UDPRequestHeader + 4, 0, 6); // address and port all zeros
@@ -1286,13 +1272,13 @@ namespace transport
if (ecode) if (ecode)
{ {
LogPrint(eLogError, "SSU2: Proxy write error ", ecode.message()); LogPrint(eLogError, "SSU2: Proxy write error ", ecode.message());
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
ReconnectToProxy (); ReconnectToProxy ();
} }
else else
ReadUDPAssociateReply (); ReadUDPAssociateReply ();
}); });
} }
void SSU2Server::ReadUDPAssociateReply () void SSU2Server::ReadUDPAssociateReply ()
{ {
@@ -1306,11 +1292,11 @@ namespace transport
LogPrint(eLogError, "SSU2: Proxy read error ", ecode.message()); LogPrint(eLogError, "SSU2: Proxy read error ", ecode.message());
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
ReconnectToProxy (); ReconnectToProxy ();
} }
else else
{ {
if (m_UDPRequestHeader[0] == SOCKS5_VER && !m_UDPRequestHeader[1]) if (m_UDPRequestHeader[0] == SOCKS5_VER && !m_UDPRequestHeader[1])
{ {
if (m_UDPRequestHeader[3] == SOCKS5_ATYP_IPV4) if (m_UDPRequestHeader[3] == SOCKS5_ATYP_IPV4)
{ {
boost::asio::ip::address_v4::bytes_type bytes; boost::asio::ip::address_v4::bytes_type bytes;
@@ -1320,21 +1306,21 @@ namespace transport
m_SocketV4.open (boost::asio::ip::udp::v4 ()); m_SocketV4.open (boost::asio::ip::udp::v4 ());
Receive (m_SocketV4); Receive (m_SocketV4);
ReadUDPAssociateSocket (); ReadUDPAssociateSocket ();
} }
else else
{ {
LogPrint(eLogError, "SSU2: Proxy UDP associate unsupported ATYP ", (int)m_UDPRequestHeader[3]); LogPrint(eLogError, "SSU2: Proxy UDP associate unsupported ATYP ", (int)m_UDPRequestHeader[3]);
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
} }
} }
else else
{ {
LogPrint(eLogError, "SSU2: Proxy UDP associate error ", (int)m_UDPRequestHeader[1]); LogPrint(eLogError, "SSU2: Proxy UDP associate error ", (int)m_UDPRequestHeader[1]);
m_UDPAssociateSocket.reset (nullptr); m_UDPAssociateSocket.reset (nullptr);
} }
} }
}); });
} }
void SSU2Server::ReadUDPAssociateSocket () void SSU2Server::ReadUDPAssociateSocket ()
{ {
@@ -1350,18 +1336,18 @@ namespace transport
m_ProxyRelayEndpoint.reset (nullptr); m_ProxyRelayEndpoint.reset (nullptr);
m_SocketV4.close (); m_SocketV4.close ();
ConnectToProxy (); // try to reconnect immediately ConnectToProxy (); // try to reconnect immediately
} }
else else
ReadUDPAssociateSocket (); ReadUDPAssociateSocket ();
}); });
} }
void SSU2Server::ReconnectToProxy () void SSU2Server::ReconnectToProxy ()
{ {
LogPrint(eLogInfo, "SSU2: Reconnect to proxy after ", SSU2_PROXY_CONNECT_RETRY_TIMEOUT, " seconds"); LogPrint(eLogInfo, "SSU2: Reconnect to proxy after ", SSU2_PROXY_CONNECT_RETRY_TIMEOUT, " seconds");
if (m_ProxyConnectRetryTimer) if (m_ProxyConnectRetryTimer)
m_ProxyConnectRetryTimer->cancel (); m_ProxyConnectRetryTimer->cancel ();
else else
m_ProxyConnectRetryTimer.reset (new boost::asio::deadline_timer (m_ReceiveService.GetService ())); m_ProxyConnectRetryTimer.reset (new boost::asio::deadline_timer (m_ReceiveService.GetService ()));
m_ProxyConnectRetryTimer->expires_from_now (boost::posix_time::seconds (SSU2_PROXY_CONNECT_RETRY_TIMEOUT)); m_ProxyConnectRetryTimer->expires_from_now (boost::posix_time::seconds (SSU2_PROXY_CONNECT_RETRY_TIMEOUT));
m_ProxyConnectRetryTimer->async_wait ( m_ProxyConnectRetryTimer->async_wait (
@@ -1374,9 +1360,9 @@ namespace transport
LogPrint(eLogInfo, "SSU2: Reconnecting to proxy"); LogPrint(eLogInfo, "SSU2: Reconnecting to proxy");
ConnectToProxy (); ConnectToProxy ();
} }
}); });
} }
bool SSU2Server::SetProxy (const std::string& address, uint16_t port) bool SSU2Server::SetProxy (const std::string& address, uint16_t port)
{ {
boost::system::error_code ecode; boost::system::error_code ecode;
@@ -1385,14 +1371,14 @@ namespace transport
{ {
m_IsThroughProxy = true; m_IsThroughProxy = true;
m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint (addr, port)); m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint (addr, port));
} }
else else
{ {
if (ecode) if (ecode)
LogPrint (eLogError, "SSU2: Invalid proxy address ", address, " ", ecode.message()); LogPrint (eLogError, "SSU2: Invalid proxy address ", address, " ", ecode.message());
return false; return false;
} }
return true; return true;
} }
} }
} }

View File

@@ -30,7 +30,7 @@ namespace transport
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
class SSU2Server: private i2p::util::RunnableServiceWithWork class SSU2Server: private i2p::util::RunnableServiceWithWork
{ {
struct Packet struct Packet
@@ -132,7 +132,7 @@ namespace transport
void SendUDPAssociateRequest (); void SendUDPAssociateRequest ();
void ReadUDPAssociateReply (); void ReadUDPAssociateReply ();
void ReadUDPAssociateSocket (); // handle if closed by peer void ReadUDPAssociateSocket (); // handle if closed by peer
private: private:
ReceiveService m_ReceiveService; ReceiveService m_ReceiveService;
@@ -160,7 +160,7 @@ namespace transport
std::unique_ptr<boost::asio::ip::tcp::socket> m_UDPAssociateSocket; std::unique_ptr<boost::asio::ip::tcp::socket> m_UDPAssociateSocket;
std::unique_ptr<boost::asio::ip::udp::endpoint> m_ProxyRelayEndpoint; std::unique_ptr<boost::asio::ip::udp::endpoint> m_ProxyRelayEndpoint;
std::unique_ptr<boost::asio::deadline_timer> m_ProxyConnectRetryTimer; std::unique_ptr<boost::asio::deadline_timer> m_ProxyConnectRetryTimer;
public: public:
// for HTTP/I2PControl // for HTTP/I2PControl

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -96,7 +96,7 @@ namespace transport
// timeout expired // timeout expired
if (m_State == eSSU2SessionStateIntroduced) // WaitForIntroducer if (m_State == eSSU2SessionStateIntroduced) // WaitForIntroducer
LogPrint (eLogWarning, "SSU2: Session was not introduced after ", SSU2_CONNECT_TIMEOUT, " seconds"); LogPrint (eLogWarning, "SSU2: Session was not introduced after ", SSU2_CONNECT_TIMEOUT, " seconds");
else else
LogPrint (eLogWarning, "SSU2: Session with ", m_RemoteEndpoint, " was not established after ", SSU2_CONNECT_TIMEOUT, " seconds"); LogPrint (eLogWarning, "SSU2: Session with ", m_RemoteEndpoint, " was not established after ", SSU2_CONNECT_TIMEOUT, " seconds");
Terminate (); Terminate ();
} }
@@ -216,7 +216,6 @@ namespace transport
m_SessionConfirmedFragment.reset (nullptr); m_SessionConfirmedFragment.reset (nullptr);
m_PathChallenge.reset (nullptr); m_PathChallenge.reset (nullptr);
m_SendQueue.clear (); m_SendQueue.clear ();
m_SendQueueSize = 0;
m_SentPackets.clear (); m_SentPackets.clear ();
m_IncompleteMessages.clear (); m_IncompleteMessages.clear ();
m_RelaySessions.clear (); m_RelaySessions.clear ();
@@ -291,7 +290,7 @@ namespace transport
{ {
if (m_State == eSSU2SessionStateTerminated) return; if (m_State == eSSU2SessionStateTerminated) return;
for (auto it: msgs) for (auto it: msgs)
m_SendQueue.push_back (std::move (it)); m_SendQueue.push_back (it);
SendQueue (); SendQueue ();
if (m_SendQueue.size () > 0) // windows is full if (m_SendQueue.size () > 0) // windows is full
@@ -305,7 +304,6 @@ namespace transport
RequestTermination (eSSU2TerminationReasonTimeout); RequestTermination (eSSU2TerminationReasonTimeout);
} }
} }
m_SendQueueSize = m_SendQueue.size ();
} }
bool SSU2Session::SendQueue () bool SSU2Session::SendQueue ()
@@ -465,7 +463,6 @@ namespace transport
LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session"); LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session");
m_SentPackets.clear (); m_SentPackets.clear ();
m_SendQueue.clear (); m_SendQueue.clear ();
m_SendQueueSize = 0;
RequestTermination (eSSU2TerminationReasonTimeout); RequestTermination (eSSU2TerminationReasonTimeout);
return resentPackets.size (); return resentPackets.size ();
} }
@@ -530,7 +527,7 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len); LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len);
break; break;
} }
const uint8_t nonce[12] = {0}; const uint8_t nonce[12] = {0};
uint64_t headerX[2]; uint64_t headerX[2];
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
@@ -573,7 +570,7 @@ namespace transport
// payload // payload
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (ts + 500)/1000); htobe32buf (payload + 3, ts/1000);
size_t payloadSize = 7; size_t payloadSize = 7;
if (GetRouterStatus () == eRouterStatusFirewalled && m_Address->IsIntroducer ()) if (GetRouterStatus () == eRouterStatusFirewalled && m_Address->IsIntroducer ())
{ {
@@ -614,11 +611,11 @@ namespace transport
void SSU2Session::ProcessSessionRequest (Header& header, uint8_t * buf, size_t len) void SSU2Session::ProcessSessionRequest (Header& header, uint8_t * buf, size_t len)
{ {
// we are Bob // we are Bob
if (len < 88) if (len < 80)
{ {
LogPrint (eLogWarning, "SSU2: SessionRequest message too short ", len); LogPrint (eLogWarning, "SSU2: SessionRequest message too short ", len);
return; return;
} }
const uint8_t nonce[12] = {0}; const uint8_t nonce[12] = {0};
uint8_t headerX[48]; uint8_t headerX[48];
i2p::crypto::ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX); i2p::crypto::ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX);
@@ -687,7 +684,7 @@ namespace transport
size_t maxPayloadSize = m_MaxPayloadSize - 48; size_t maxPayloadSize = m_MaxPayloadSize - 48;
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (ts + 500)/1000); htobe32buf (payload + 3, ts/1000);
size_t payloadSize = 7; size_t payloadSize = 7;
payloadSize += CreateAddressBlock (payload + payloadSize, maxPayloadSize - payloadSize, m_RemoteEndpoint); payloadSize += CreateAddressBlock (payload + payloadSize, maxPayloadSize - payloadSize, m_RemoteEndpoint);
if (m_RelayTag) if (m_RelayTag)
@@ -889,7 +886,7 @@ namespace transport
LogPrint (eLogWarning, "SSU2: SessionConfirmed fragment too short ", len); LogPrint (eLogWarning, "SSU2: SessionConfirmed fragment too short ", len);
if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr);
return false; return false;
} }
if (!(header.h.flags[0] & 0xF0)) if (!(header.h.flags[0] & 0xF0))
{ {
// first fragment // first fragment
@@ -942,7 +939,7 @@ namespace transport
LogPrint (eLogWarning, "SSU2: SessionConfirmed message too short ", len); LogPrint (eLogWarning, "SSU2: SessionConfirmed message too short ", len);
if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr);
return false; return false;
} }
// KDF for Session Confirmed part 1 // KDF for Session Confirmed part 1
m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header) m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header)
// decrypt part1 // decrypt part1
@@ -1049,7 +1046,7 @@ namespace transport
// payload // payload
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; size_t payloadSize = 7;
payloadSize += CreatePaddingBlock (payload + payloadSize, 25 - payloadSize, 1); payloadSize += CreatePaddingBlock (payload + payloadSize, 25 - payloadSize, 1);
// encrypt // encrypt
@@ -1120,7 +1117,7 @@ namespace transport
// payload // payload
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; size_t payloadSize = 7;
payloadSize += CreateAddressBlock (payload + payloadSize, 56 - payloadSize, m_RemoteEndpoint); payloadSize += CreateAddressBlock (payload + payloadSize, 56 - payloadSize, m_RemoteEndpoint);
if (m_TerminationReason != eSSU2TerminationReasonNormalClose) if (m_TerminationReason != eSSU2TerminationReasonNormalClose)
@@ -1155,7 +1152,7 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: Retry message too short ", len); LogPrint (eLogWarning, "SSU2: Retry message too short ", len);
return false; return false;
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX); i2p::crypto::ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX);
@@ -1208,7 +1205,7 @@ namespace transport
// payload // payload
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; size_t payloadSize = 7;
payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, ep); payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, ep);
payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize,
@@ -1244,7 +1241,7 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: HolePunch message too short ", len); LogPrint (eLogWarning, "SSU2: HolePunch message too short ", len);
return false; return false;
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
@@ -1284,7 +1281,7 @@ namespace transport
// payload // payload
payload[0] = eSSU2BlkDateTime; payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; size_t payloadSize = 7;
if (msg == 6 || msg == 7) if (msg == 6 || msg == 7)
payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint); payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint);
@@ -1320,7 +1317,7 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len); LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len);
return false; return false;
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
@@ -1392,7 +1389,7 @@ namespace transport
{ {
LogPrint (eLogWarning, "SSU2: Data message too short ", len); LogPrint (eLogWarning, "SSU2: Data message too short ", len);
return; return;
} }
uint8_t payload[SSU2_MAX_PACKET_SIZE]; uint8_t payload[SSU2_MAX_PACKET_SIZE];
size_t payloadSize = len - 32; size_t payloadSize = len - 32;
uint32_t packetNum = be32toh (header.h.packetNum); uint32_t packetNum = be32toh (header.h.packetNum);
@@ -1465,19 +1462,19 @@ namespace transport
m_IsDataReceived = true; m_IsDataReceived = true;
break; break;
case eSSU2BlkTermination: case eSSU2BlkTermination:
{ {
uint8_t rsn = buf[11]; // reason uint8_t rsn = buf[11]; // reason
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
RequestTermination (eSSU2TerminationReasonTerminationReceived); RequestTermination (eSSU2TerminationReasonTerminationReceived);
else if (m_State != eSSU2SessionStateTerminated) else if (m_State != eSSU2SessionStateTerminated)
{ {
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
m_State = eSSU2SessionStateClosingConfirmed; m_State = eSSU2SessionStateClosingConfirmed;
Done (); Done ();
} }
break; break;
} }
case eSSU2BlkRelayRequest: case eSSU2BlkRelayRequest:
LogPrint (eLogDebug, "SSU2: RelayRequest"); LogPrint (eLogDebug, "SSU2: RelayRequest");
HandleRelayRequest (buf + offset, size); HandleRelayRequest (buf + offset, size);
@@ -1664,26 +1661,25 @@ namespace transport
bool isV4 = ep.address ().is_v4 (); bool isV4 = ep.address ().is_v4 ();
if (ep.port () != m_Server.GetPort (isV4)) if (ep.port () != m_Server.GetPort (isV4))
{ {
LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4));
if (isV4) if (isV4)
{ {
if (i2p::context.GetStatus () == eRouterStatusTesting || if (i2p::context.GetStatus () == eRouterStatusTesting ||
m_State == eSSU2SessionStatePeerTest) m_State == eSSU2SessionStatePeerTest)
{ {
i2p::context.SetStatus (eRouterStatusFirewalled);
i2p::context.SetError (eRouterErrorSymmetricNAT); i2p::context.SetError (eRouterErrorSymmetricNAT);
i2p::context.SetStatus (eRouterStatusFirewalled);
m_Server.RescheduleIntroducersUpdateTimer (); m_Server.RescheduleIntroducersUpdateTimer ();
} }
} }
else else
{ {
if (i2p::context.GetStatusV6 () == eRouterStatusTesting || if (i2p::context.GetStatusV6 () == eRouterStatusTesting ||
m_State == eSSU2SessionStatePeerTest) m_State == eSSU2SessionStatePeerTest)
{ {
i2p::context.SetStatusV6 (eRouterStatusFirewalled);
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
i2p::context.SetStatusV6 (eRouterStatusFirewalled);
m_Server.RescheduleIntroducersUpdateTimerV6 (); m_Server.RescheduleIntroducersUpdateTimerV6 ();
} }
} }
} }
else else
@@ -1691,20 +1687,12 @@ namespace transport
if (isV4) if (isV4)
{ {
if (i2p::context.GetError () == eRouterErrorSymmetricNAT) if (i2p::context.GetError () == eRouterErrorSymmetricNAT)
{
if (m_State == eSSU2SessionStatePeerTest)
i2p::context.SetStatus (eRouterStatusOK);
i2p::context.SetError (eRouterErrorNone); i2p::context.SetError (eRouterErrorNone);
}
} }
else else
{ {
if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT)
{
if (m_State == eSSU2SessionStatePeerTest)
i2p::context.SetStatusV6 (eRouterStatusOK);
i2p::context.SetErrorV6 (eRouterErrorNone); i2p::context.SetErrorV6 (eRouterErrorNone);
}
} }
} }
} }
@@ -1848,7 +1836,7 @@ namespace transport
session->SendData (payload, payloadSize); session->SendData (payload, payloadSize);
} }
void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len, int attempts) void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len)
{ {
// we are Charlie // we are Charlie
SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept; SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept;
@@ -1903,22 +1891,9 @@ namespace transport
code = eSSU2RelayResponseCodeCharlieSignatureFailure; code = eSSU2RelayResponseCodeCharlieSignatureFailure;
} }
} }
else if (!attempts)
{
// RouterInfo might come in the next packet, try again
auto vec = std::make_shared<std::vector<uint8_t> >(len);
memcpy (vec->data (), buf, len);
auto s = shared_from_this ();
m_Server.GetService ().post ([s, vec, attempts]()
{
LogPrint (eLogDebug, "SSU2: RelayIntro attempt ", attempts + 1);
s->HandleRelayIntro (vec->data (), vec->size (), attempts + 1);
});
return;
}
else else
{ {
LogPrint (eLogWarning, "SSU2: RelayIntro unknown router to introduce"); LogPrint (eLogError, "SSU2: RelayIntro unknown router to introduce");
code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; code = eSSU2RelayResponseCodeCharlieAliceIsUnknown;
} }
// send relay response to Bob // send relay response to Bob
@@ -2430,7 +2405,7 @@ namespace transport
d.quot = maxNumRanges; d.quot = maxNumRanges;
d.rem = 0; d.rem = 0;
} }
// Acks only ranges for acnt // Acks only ragnes for acnt
for (int i = 0; i < d.quot; i++) for (int i = 0; i < d.quot; i++)
{ {
buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = 255; // NACKs 0, Acks 255 buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = 255; // NACKs 0, Acks 255
@@ -2479,7 +2454,7 @@ namespace transport
} }
if (numRanges < maxNumRanges && it == m_OutOfSequencePackets.rend ()) if (numRanges < maxNumRanges && it == m_OutOfSequencePackets.rend ())
{ {
// add range between out-of-sequence and received // add range between out-of-seqence and received
int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1; int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1;
if (nacks > 0) if (nacks > 0)
{ {
@@ -2502,9 +2477,14 @@ namespace transport
size_t paddingSize = rand () & 0x0F; // 0 - 15 size_t paddingSize = rand () & 0x0F; // 0 - 15
if (paddingSize + 3 > len) paddingSize = len - 3; if (paddingSize + 3 > len) paddingSize = len - 3;
else if (paddingSize + 3 < minSize) paddingSize = minSize - 3; else if (paddingSize + 3 < minSize) paddingSize = minSize - 3;
buf[0] = eSSU2BlkPadding; if (paddingSize)
htobe16buf (buf + 1, paddingSize); {
memset (buf + 3, 0, paddingSize); buf[0] = eSSU2BlkPadding;
htobe16buf (buf + 1, paddingSize);
memset (buf + 3, 0, paddingSize);
}
else
return 0;
return paddingSize + 3; return paddingSize + 3;
} }
@@ -2841,8 +2821,6 @@ namespace transport
void SSU2Session::FlushData () void SSU2Session::FlushData ()
{ {
bool sent = SendQueue (); // if we have something to send bool sent = SendQueue (); // if we have something to send
if (sent)
m_SendQueueSize = m_SendQueue.size ();
if (m_IsDataReceived) if (m_IsDataReceived)
{ {
if (!sent) SendQuickAck (); if (!sent) SendQuickAck ();

View File

@@ -245,7 +245,7 @@ namespace transport
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override; void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
uint32_t GetRelayTag () const override { return m_RelayTag; }; uint32_t GetRelayTag () const override { return m_RelayTag; };
size_t Resend (uint64_t ts); // return number or resent packets size_t Resend (uint64_t ts); // return number or resent packets
bool IsEstablished () const override { return m_State == eSSU2SessionStateEstablished; }; bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; };
uint64_t GetConnID () const { return m_SourceConnID; }; uint64_t GetConnID () const { return m_SourceConnID; };
SSU2SessionState GetState () const { return m_State; }; SSU2SessionState GetState () const { return m_State; };
void SetState (SSU2SessionState state) { m_State = state; }; void SetState (SSU2SessionState state) { m_State = state; };
@@ -305,7 +305,7 @@ namespace transport
void HandleFollowOnFragment (const uint8_t * buf, size_t len); void HandleFollowOnFragment (const uint8_t * buf, size_t len);
bool ConcatOutOfSequenceFragments (std::shared_ptr<SSU2IncompleteMessage> m); // true if message complete bool ConcatOutOfSequenceFragments (std::shared_ptr<SSU2IncompleteMessage> m); // true if message complete
void HandleRelayRequest (const uint8_t * buf, size_t len); void HandleRelayRequest (const uint8_t * buf, size_t len);
void HandleRelayIntro (const uint8_t * buf, size_t len, int attempts = 0); void HandleRelayIntro (const uint8_t * buf, size_t len);
void HandleRelayResponse (const uint8_t * buf, size_t len); void HandleRelayResponse (const uint8_t * buf, size_t len);
void HandlePeerTest (const uint8_t * buf, size_t len); void HandlePeerTest (const uint8_t * buf, size_t len);

View File

@@ -478,11 +478,11 @@ namespace stream
{ {
if (!len) return 0; if (!len) return 0;
size_t ret = 0; size_t ret = 0;
volatile bool done = false;
std::condition_variable newDataReceived; std::condition_variable newDataReceived;
std::mutex newDataReceivedMutex; std::mutex newDataReceivedMutex;
std::unique_lock<std::mutex> l(newDataReceivedMutex);
AsyncReceive (boost::asio::buffer (buf, len), AsyncReceive (boost::asio::buffer (buf, len),
[&ret, &done, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred) [&ret, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred)
{ {
if (ecode == boost::asio::error::timed_out) if (ecode == boost::asio::error::timed_out)
ret = 0; ret = 0;
@@ -490,32 +490,13 @@ namespace stream
ret = bytes_transferred; ret = bytes_transferred;
std::unique_lock<std::mutex> l(newDataReceivedMutex); std::unique_lock<std::mutex> l(newDataReceivedMutex);
newDataReceived.notify_all (); newDataReceived.notify_all ();
done = true;
}, },
timeout); timeout);
if (!done) if (newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout)
{ std::unique_lock<std::mutex> l(newDataReceivedMutex); ret = 0;
if (!done && newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout)
ret = 0;
}
if (!done)
{
// make sure that AsycReceive complete
auto s = shared_from_this();
m_Service.post ([s]()
{
s->m_ReceiveTimer.cancel ();
});
int i = 0;
while (!done && i < 100) // 1 sec
{
std::this_thread::sleep_for (std::chrono::milliseconds(10));
i++;
}
}
return ret; return ret;
} }
size_t Stream::Send (const uint8_t * buf, size_t len) size_t Stream::Send (const uint8_t * buf, size_t len)
{ {
AsyncSend (buf, len, nullptr); AsyncSend (buf, len, nullptr);
@@ -1396,11 +1377,11 @@ namespace stream
}); });
if (timeout) if (timeout)
streamAccept.wait_for (l, std::chrono::seconds (timeout)); streamAccept.wait_for (l, std::chrono::seconds (timeout));
else else
streamAccept.wait (l); streamAccept.wait (l);
return stream; return stream;
} }
void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode) void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)

View File

@@ -186,7 +186,7 @@ namespace stream
void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0); void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0);
size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); }; size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); };
size_t Receive (uint8_t * buf, size_t len, int timeout); size_t Receive (uint8_t * buf, size_t len, int timeout);
void AsyncClose() { m_Service.post(std::bind(&Stream::Close, shared_from_this())); }; void AsyncClose() { m_Service.post(std::bind(&Stream::Close, shared_from_this())); };
/** only call close from destination thread, use Stream::AsyncClose for other threads */ /** only call close from destination thread, use Stream::AsyncClose for other threads */
@@ -280,7 +280,7 @@ namespace stream
void AcceptOnce (const Acceptor& acceptor); void AcceptOnce (const Acceptor& acceptor);
void AcceptOnceAcceptor (std::shared_ptr<Stream> stream, Acceptor acceptor, Acceptor prev); void AcceptOnceAcceptor (std::shared_ptr<Stream> stream, Acceptor acceptor, Acceptor prev);
std::shared_ptr<Stream> AcceptStream (int timeout = 0); // sync std::shared_ptr<Stream> AcceptStream (int timeout = 0); // sync
std::shared_ptr<i2p::client::ClientDestination> GetOwner () const { return m_Owner; }; std::shared_ptr<i2p::client::ClientDestination> GetOwner () const { return m_Owner; };
void SetOwner (std::shared_ptr<i2p::client::ClientDestination> owner) { m_Owner = owner; }; void SetOwner (std::shared_ptr<i2p::client::ClientDestination> owner) { m_Owner = owner; };
uint16_t GetLocalPort () const { return m_LocalPort; }; uint16_t GetLocalPort () const { return m_LocalPort; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -20,21 +20,16 @@ namespace i2p
namespace tunnel namespace tunnel
{ {
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const uint8_t * layerKey,const uint8_t * ivKey):
TunnelBase (receiveTunnelID, nextTunnelID, nextIdent), TunnelBase (receiveTunnelID, nextTunnelID, nextIdent)
m_LayerKey (layerKey), m_IVKey (ivKey)
{ {
m_Encryption.SetKeys (layerKey, ivKey);
} }
void TransitTunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out) void TransitTunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
{ {
if (!m_Encryption) m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4);
{
m_Encryption.reset (new i2p::crypto::TunnelEncryption);
m_Encryption->SetKeys (m_LayerKey, m_IVKey);
}
m_Encryption->Encrypt (in->GetPayload () + 4, out->GetPayload () + 4);
i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE); i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE);
} }
@@ -99,8 +94,8 @@ namespace tunnel
} }
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID, std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint) bool isGateway, bool isEndpoint)
{ {
if (isEndpoint) if (isEndpoint)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -28,8 +28,8 @@ namespace tunnel
public: public:
TransitTunnel (uint32_t receiveTunnelID, TransitTunnel (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey); const uint8_t * layerKey,const uint8_t * ivKey);
virtual size_t GetNumTransmittedBytes () const { return 0; }; virtual size_t GetNumTransmittedBytes () const { return 0; };
@@ -39,8 +39,7 @@ namespace tunnel
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out); void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out);
private: private:
i2p::crypto::AESKey m_LayerKey, m_IVKey; i2p::crypto::TunnelEncryption m_Encryption;
std::unique_ptr<i2p::crypto::TunnelEncryption> m_Encryption;
}; };
class TransitTunnelParticipant: public TransitTunnel class TransitTunnelParticipant: public TransitTunnel
@@ -48,8 +47,8 @@ namespace tunnel
public: public:
TransitTunnelParticipant (uint32_t receiveTunnelID, TransitTunnelParticipant (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const uint8_t * layerKey,const uint8_t * ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID,
layerKey, ivKey), m_NumTransmittedBytes (0) {}; layerKey, ivKey), m_NumTransmittedBytes (0) {};
~TransitTunnelParticipant (); ~TransitTunnelParticipant ();
@@ -69,8 +68,8 @@ namespace tunnel
public: public:
TransitTunnelGateway (uint32_t receiveTunnelID, TransitTunnelGateway (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const uint8_t * layerKey,const uint8_t * ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID,
layerKey, ivKey), m_Gateway(this) {}; layerKey, ivKey), m_Gateway(this) {};
@@ -89,8 +88,8 @@ namespace tunnel
public: public:
TransitTunnelEndpoint (uint32_t receiveTunnelID, TransitTunnelEndpoint (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const uint8_t * layerKey,const uint8_t * ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
m_Endpoint (false) {}; // transit endpoint is always outbound m_Endpoint (false) {}; // transit endpoint is always outbound
@@ -105,8 +104,8 @@ namespace tunnel
}; };
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID, std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint); bool isGateway, bool isEndpoint);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -74,8 +74,7 @@ namespace transport
public: public:
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout): TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ())
{ {
if (router) if (router)
@@ -101,7 +100,6 @@ namespace transport
size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumSentBytes () const { return m_NumSentBytes; };
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
size_t GetSendQueueSize () const { return m_SendQueueSize; };
bool IsOutgoing () const { return m_IsOutgoing; }; bool IsOutgoing () const { return m_IsOutgoing; };
int GetTerminationTimeout () const { return m_TerminationTimeout; }; int GetTerminationTimeout () const { return m_TerminationTimeout; };
@@ -116,12 +114,12 @@ namespace transport
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0; virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
virtual bool IsEstablished () const = 0; virtual bool IsEstablished () const = 0;
protected: protected:
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity; std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
mutable std::mutex m_RemoteIdentityMutex; mutable std::mutex m_RemoteIdentityMutex;
size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize; size_t m_NumSentBytes, m_NumReceivedBytes;
bool m_IsOutgoing; bool m_IsOutgoing;
int m_TerminationTimeout; int m_TerminationTimeout;
uint64_t m_LastActivityTimestamp; uint64_t m_LastActivityTimestamp;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -168,7 +168,7 @@ namespace transport
m_Work = new boost::asio::io_service::work (*m_Service); m_Work = new boost::asio::io_service::work (*m_Service);
m_PeerCleanupTimer = new boost::asio::deadline_timer (*m_Service); m_PeerCleanupTimer = new boost::asio::deadline_timer (*m_Service);
m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service);
m_UpdateBandwidthTimer = new boost::asio::deadline_timer (*m_Service); m_UpdateBandwidthTimer = new boost::asio::steady_timer (*m_Service);
} }
bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv4; i2p::config::GetOption("ipv4", ipv4);
@@ -210,8 +210,8 @@ namespace transport
} }
// create SSU2 server // create SSU2 server
if (enableSSU2) if (enableSSU2)
{ {
m_SSU2Server = new SSU2Server (); m_SSU2Server = new SSU2Server ();
std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy); std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy);
if (!ssu2proxy.empty()) if (!ssu2proxy.empty())
@@ -219,18 +219,18 @@ namespace transport
if (proxyurl.parse (ssu2proxy) && proxyurl.schema == "socks") if (proxyurl.parse (ssu2proxy) && proxyurl.schema == "socks")
{ {
if (m_SSU2Server->SetProxy (proxyurl.host, proxyurl.port)) if (m_SSU2Server->SetProxy (proxyurl.host, proxyurl.port))
{ {
i2p::context.SetStatus (eRouterStatusProxy); i2p::context.SetStatus (eRouterStatusProxy);
if (ipv6) if (ipv6)
i2p::context.SetStatusV6 (eRouterStatusProxy); i2p::context.SetStatusV6 (eRouterStatusProxy);
} }
else else
LogPrint(eLogError, "Transports: Can't set SSU2 proxy ", ssu2proxy); LogPrint(eLogError, "Transports: Can't set SSU2 proxy ", ssu2proxy);
} }
else else
LogPrint(eLogError, "Transports: Invalid SSU2 proxy URL ", ssu2proxy); LogPrint(eLogError, "Transports: Invalid SSU2 proxy URL ", ssu2proxy);
} }
} }
// bind to interfaces // bind to interfaces
if (ipv4) if (ipv4)
@@ -251,12 +251,12 @@ namespace transport
{ {
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu); uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu);
if (mtu) if (mtu)
{ {
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
i2p::context.SetMTU (mtu, true); i2p::context.SetMTU (mtu, true);
} }
} }
} }
if (ipv6) if (ipv6)
@@ -277,12 +277,12 @@ namespace transport
{ {
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu); uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu);
if (mtu) if (mtu)
{ {
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
i2p::context.SetMTU (mtu, false); i2p::context.SetMTU (mtu, false);
} }
} }
} }
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
@@ -306,7 +306,7 @@ namespace transport
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT)); 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)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->expires_from_now (std::chrono::seconds(1));
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
if (m_IsNAT) if (m_IsNAT)
@@ -374,7 +374,7 @@ namespace transport
m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes; m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes;
m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes; m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes;
m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes; m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes;
m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes; m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes;
m_LastOutBandwidthUpdateBytes = m_TotalSentBytes; m_LastOutBandwidthUpdateBytes = m_TotalSentBytes;
m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes; m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes;
@@ -393,7 +393,7 @@ namespace transport
m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes; m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes;
} }
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->expires_from_now (std::chrono::seconds(1));
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
} }
} }
@@ -716,8 +716,7 @@ namespace transport
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first; m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts }));
it->second.sessions.push_back (session);
} }
}); });
} }
@@ -823,9 +822,7 @@ namespace transport
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
auto it = m_Peers.begin (); auto it = m_Peers.begin ();
std::advance (it, rand () % m_Peers.size ()); std::advance (it, rand () % m_Peers.size ());
if (it == m_Peers.end () || it->second.router || it->second.sessions.empty () || if (it == m_Peers.end () || it->second.router) return nullptr; // not connected
it->second.sessions.front ()->GetSendQueueSize () > PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE)
return nullptr; // not connected or overloaded
ident = it->first; ident = it->first;
} }
return i2p::data::netdb.FindRouter (ident); return i2p::data::netdb.FindRouter (ident);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -63,7 +63,6 @@ namespace transport
const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds
const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds
const size_t PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE = 25;
struct Peer struct Peer
{ {
int numAttempts; int numAttempts;
@@ -170,7 +169,8 @@ namespace transport
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service * m_Service; boost::asio::io_service * m_Service;
boost::asio::io_service::work * m_Work; boost::asio::io_service::work * m_Work;
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer, * m_UpdateBandwidthTimer; boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
boost::asio::steady_timer * m_UpdateBandwidthTimer;
SSU2Server * m_SSU2Server; SSU2Server * m_SSU2Server;
NTCP2Server * m_NTCP2Server; NTCP2Server * m_NTCP2Server;

View File

@@ -472,7 +472,6 @@ namespace tunnel
auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
if (msg) if (msg)
{ {
int numMsgs = 0;
uint32_t prevTunnelID = 0, tunnelID = 0; uint32_t prevTunnelID = 0, tunnelID = 0;
std::shared_ptr<TunnelBase> prevTunnel; std::shared_ptr<TunnelBase> prevTunnel;
do do
@@ -516,12 +515,11 @@ namespace tunnel
LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID);
} }
msg = (numMsgs <= MAX_TUNNEL_MSGS_BATCH_SIZE) ? m_Queue.Get () : nullptr; msg = m_Queue.Get ();
if (msg) if (msg)
{ {
prevTunnelID = tunnelID; prevTunnelID = tunnelID;
prevTunnel = tunnel; prevTunnel = tunnel;
numMsgs++;
} }
else if (tunnel) else if (tunnel)
tunnel->FlushTunnelDataMsgs (); tunnel->FlushTunnelDataMsgs ();
@@ -532,17 +530,17 @@ namespace tunnel
if (i2p::transport::transports.IsOnline()) if (i2p::transport::transports.IsOnline())
{ {
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL) // manage tunnels every 15 seconds if (ts - lastTs >= 15) // manage tunnels every 15 seconds
{ {
ManageTunnels (); ManageTunnels ();
lastTs = ts; lastTs = ts;
} }
if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL) // manage pools every 5 seconds if (ts - lastPoolsTs >= 5) // manage pools every 5 seconds
{ {
ManageTunnelPools (ts); ManageTunnelPools (ts);
lastPoolsTs = ts; lastPoolsTs = ts;
} }
if (ts - lastMemoryPoolTs >= TUNNEL_MEMORY_POOL_MANAGE_INTERVAL) // manage memory pool every 2 minutes if (ts - lastMemoryPoolTs >= 120) // manage memory pool every 2 minutes
{ {
m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt (); m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt ();
m_I2NPTunnelMessagesMemoryPool.CleanUpMt (); m_I2NPTunnelMessagesMemoryPool.CleanUpMt ();

View File

@@ -40,10 +40,6 @@ namespace tunnel
const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message
const int MAX_NUM_RECORDS = 8; const int MAX_NUM_RECORDS = 8;
const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds
const int MAX_TUNNEL_MSGS_BATCH_SIZE = 100; // handle messages without interrupt
const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds
const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds
const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds
const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12
const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2020, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -41,7 +41,7 @@ namespace tunnel
{ {
public: public:
TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, const i2p::data::IdentHash& nextIdent): TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent):
m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent),
m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {}; m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {};
virtual ~TunnelBase () {}; virtual ~TunnelBase () {};

View File

@@ -282,13 +282,8 @@ namespace tunnel
for (const auto& it : m_OutboundTunnels) for (const auto& it : m_OutboundTunnels)
if (it->IsEstablished ()) num++; if (it->IsEstablished ()) num++;
} }
num = m_NumOutboundTunnels - num; for (int i = num; i < m_NumOutboundTunnels; i++)
if (num > 0) CreateOutboundTunnel ();
{
if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS;
for (int i = 0; i < num; i++)
CreateOutboundTunnel ();
}
num = 0; num = 0;
{ {
@@ -305,13 +300,8 @@ namespace tunnel
if (num >= m_NumInboundTunnels) break; if (num >= m_NumInboundTunnels) break;
} }
} }
num = m_NumInboundTunnels - num; for (int i = num; i < m_NumInboundTunnels; i++)
if (num > 0) CreateInboundTunnel ();
{
if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS;
for (int i = 0; i < num; i++)
CreateInboundTunnel ();
}
if (num < m_NumInboundTunnels && m_NumInboundHops <= 0 && m_LocalDestination) // zero hops IB if (num < m_NumInboundTunnels && m_NumInboundHops <= 0 && m_LocalDestination) // zero hops IB
m_LocalDestination->SetLeaseSetUpdated (); // update LeaseSet immediately m_LocalDestination->SetLeaseSetUpdated (); // update LeaseSet immediately

View File

@@ -30,7 +30,6 @@ namespace tunnel
const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds
const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16;
const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16;
const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 2;
class Tunnel; class Tunnel;
class InboundTunnel; class InboundTunnel;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -16,7 +16,7 @@
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 45 #define I2PD_VERSION_MINOR 44
#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0 #define I2PD_VERSION_PATCH 0
#ifdef GITVER #ifdef GITVER
@@ -31,7 +31,7 @@
#define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9 #define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 57 #define I2P_VERSION_MICRO 56
#define I2P_VERSION_PATCH 0 #define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #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) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

View File

@@ -833,7 +833,7 @@ namespace client
} }
else else
m_Ident = addr->identHash; m_Ident = addr->identHash;
// save url parts for later use // save url parts for later use
std::string dest_host = url.host; std::string dest_host = url.host;
int dest_port = url.port ? url.port : 80; int dest_port = url.port ? url.port : 80;
// try to create stream to addressbook site // try to create stream to addressbook site
@@ -842,13 +842,13 @@ namespace client
{ {
LogPrint (eLogError, "Addressbook: LeaseSet for address ", url.host, " not found"); LogPrint (eLogError, "Addressbook: LeaseSet for address ", url.host, " not found");
return false; return false;
} }
if (m_Etag.empty() && m_LastModified.empty()) if (m_Etag.empty() && m_LastModified.empty())
{ {
m_Book.GetEtag (m_Ident, m_Etag, m_LastModified); m_Book.GetEtag (m_Ident, m_Etag, m_LastModified);
LogPrint (eLogDebug, "Addressbook: Loaded for ", url.host, ": ETag: ", m_Etag, ", Last-Modified: ", m_LastModified); LogPrint (eLogDebug, "Addressbook: Loaded for ", url.host, ": ETag: ", m_Etag, ", Last-Modified: ", m_LastModified);
} }
// create http request & send it // create http request & send it
i2p::http::HTTPReq req; i2p::http::HTTPReq req;
req.AddHeader("Host", dest_host); req.AddHeader("Host", dest_host);
req.AddHeader("User-Agent", "Wget/1.11.4"); req.AddHeader("User-Agent", "Wget/1.11.4");
@@ -859,7 +859,7 @@ namespace client
req.AddHeader("If-None-Match", m_Etag); req.AddHeader("If-None-Match", m_Etag);
if (!m_LastModified.empty()) if (!m_LastModified.empty())
req.AddHeader("If-Modified-Since", m_LastModified); req.AddHeader("If-Modified-Since", m_LastModified);
// convert url to relative // convert url to relative
url.schema = ""; url.schema = "";
url.host = ""; url.host = "";
req.uri = url.to_string(); req.uri = url.to_string();
@@ -878,7 +878,7 @@ namespace client
{ {
response.append ((char *)recv_buf, received); response.append ((char *)recv_buf, received);
if (!stream->IsOpen ()) end = true; if (!stream->IsOpen ()) end = true;
} }
else if (!stream->IsOpen ()) else if (!stream->IsOpen ())
end = true; end = true;
else else
@@ -886,12 +886,12 @@ namespace client
LogPrint (eLogError, "Addressbook: Subscriptions request timeout expired"); LogPrint (eLogError, "Addressbook: Subscriptions request timeout expired");
numAttempts++; numAttempts++;
if (numAttempts > 5) end = true; if (numAttempts > 5) end = true;
} }
} }
// process remaining buffer // process remaining buffer
while (size_t len = stream->ReadSome (recv_buf, sizeof(recv_buf))) while (size_t len = stream->ReadSome (recv_buf, sizeof(recv_buf)))
response.append ((char *)recv_buf, len); response.append ((char *)recv_buf, len);
// parse response // parse response
i2p::http::HTTPRes res; i2p::http::HTTPRes res;
int res_head_len = res.parse(response); int res_head_len = res.parse(response);
if (res_head_len < 0) if (res_head_len < 0)
@@ -904,7 +904,7 @@ namespace client
LogPrint(eLogError, "Addressbook: Incomplete http response from ", dest_host, ", interrupted by timeout"); LogPrint(eLogError, "Addressbook: Incomplete http response from ", dest_host, ", interrupted by timeout");
return false; return false;
} }
// assert: res_head_len > 0 // assert: res_head_len > 0
response.erase(0, res_head_len); response.erase(0, res_head_len);
if (res.code == 304) if (res.code == 304)
{ {
@@ -927,7 +927,7 @@ namespace client
LogPrint(eLogError, "Addressbook: Response size mismatch, expected: ", len, ", got: ", response.length(), "bytes"); LogPrint(eLogError, "Addressbook: Response size mismatch, expected: ", len, ", got: ", response.length(), "bytes");
return false; return false;
} }
// assert: res.code == 200 // assert: res.code == 200
auto it = res.headers.find("ETag"); auto it = res.headers.find("ETag");
if (it != res.headers.end()) m_Etag = it->second; if (it != res.headers.end()) m_Etag = it->second;
it = res.headers.find("Last-Modified"); it = res.headers.find("Last-Modified");

View File

@@ -252,6 +252,7 @@ namespace proxy {
req.RemoveHeader("From"); req.RemoveHeader("From");
req.RemoveHeader("Forwarded"); req.RemoveHeader("Forwarded");
req.RemoveHeader("DNT"); // Useless DoNotTrack flag req.RemoveHeader("DNT"); // Useless DoNotTrack flag
req.RemoveHeader("X-Requested-With"); // Android Webview send this with the value set to the application ID
req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding
/* drop proxy-disclosing headers */ /* drop proxy-disclosing headers */
req.RemoveHeader("X-Forwarded"); req.RemoveHeader("X-Forwarded");
@@ -259,18 +260,6 @@ namespace proxy {
/* replace headers */ /* replace headers */
req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)"); req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)");
/**
* i2pd PR #1816:
* Android Webview send this with the value set to the application ID, so we drop it,
* but only if it does not belong to an AJAX request (*HttpRequest, like XMLHttpRequest).
*/
if(req.GetHeader("X-Requested-With") != "") {
auto h = req.GetHeader ("X-Requested-With");
auto x = h.find("HttpRequest");
if (x == std::string::npos) // not found
req.RemoveHeader("X-Requested-With");
}
/** /**
* according to i2p ticket #1862: * according to i2p ticket #1862:
* leave Referer if requested URL with same schema, host and port, * leave Referer if requested URL with same schema, host and port,

View File

@@ -27,7 +27,7 @@ namespace proxy
static const size_t socks_buffer_size = 8192; 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 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_FORWARDER_BUFFER_SIZE = 8192;
static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8;

View File

@@ -372,6 +372,6 @@ namespace client
else else
LogPrint (eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort); LogPrint (eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort);
} }
} }
} }

View File

@@ -180,7 +180,7 @@ namespace client
bool isUpdated; // transient, used during reload only bool isUpdated; // transient, used during reload only
}; };
} }
} }

View File

@@ -1,138 +0,0 @@
enable_testing()
find_package(Check 0.9.10 REQUIRED)
include_directories(${CHECK_INCLUDE_DIRS})
# Compiler flags:
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -Wl,-undefined,dynamic_lookup")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -D_GLIBCXX_USE_NANOSLEEP=1 -Wl,--unresolved-symbols=ignore-in-object-files")
endif()
set(TEST_PATH ${CMAKE_CURRENT_BINARY_DIR})
include_directories(
../libi2pd
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
)
set(test-http-merge_chunked_SRCS
../libi2pd/HTTP.cpp
test-http-merge_chunked.cpp
)
set(test-http-req_SRCS
../libi2pd/HTTP.cpp
test-http-req.cpp
)
set(test-http-res_SRCS
../libi2pd/HTTP.cpp
test-http-res.cpp
)
set(test-http-url_decode_SRCS
../libi2pd/HTTP.cpp
test-http-url_decode.cpp
)
set(test-http-url_SRCS
../libi2pd/HTTP.cpp
test-http-url.cpp
)
set(test-base-64_SRCS
../libi2pd/Base.cpp
test-base-64.cpp
)
set(test-gost_SRCS
../libi2pd/Gost.cpp
../libi2pd/I2PEndian.cpp
test-gost.cpp
)
set(test-gost-sig_SRCS
../libi2pd/Gost.cpp
../libi2pd/I2PEndian.cpp
../libi2pd/Crypto.cpp
../libi2pd/Log.cpp
test-gost-sig.cpp
)
set(test-x25519_SRCS
../libi2pd/Ed25519.cpp
../libi2pd/I2PEndian.cpp
../libi2pd/Log.cpp
../libi2pd/Crypto.cpp
test-x25519.cpp
)
set(test-aeadchacha20poly1305_SRCS
../libi2pd/Crypto.cpp
../libi2pd/ChaCha20.cpp
../libi2pd/Poly1305.cpp
test-aeadchacha20poly1305.cpp
)
set(test-blinding_SRCS
../libi2pd/Crypto.cpp
../libi2pd/Blinding.cpp
../libi2pd/Ed25519.cpp
../libi2pd/I2PEndian.cpp
../libi2pd/Log.cpp
../libi2pd/util.cpp
../libi2pd/Identity.cpp
../libi2pd/Signature.cpp
../libi2pd/Timestamp.cpp
test-blinding.cpp
)
SET(test-elligator_SRCS
../libi2pd/Elligator.cpp
../libi2pd/Crypto.cpp
test-elligator.cpp
)
add_executable(test-http-merge_chunked ${test-http-merge_chunked_SRCS})
add_executable(test-http-req ${test-http-req_SRCS})
add_executable(test-http-res ${test-http-res_SRCS})
add_executable(test-http-url_decode ${test-http-url_decode_SRCS})
add_executable(test-http-url ${test-http-url_SRCS})
add_executable(test-base-64 ${test-base-64_SRCS})
add_executable(test-gost ${test-gost_SRCS})
add_executable(test-gost-sig ${test-gost-sig_SRCS})
add_executable(test-x25519 ${test-x25519_SRCS})
add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS})
add_executable(test-blinding ${test-blinding_SRCS})
add_executable(test-elligator ${test-elligator_SRCS})
set(LIBS
${Boost_LIBRARIES}
${CHECK_LDFLAGS}
${CMAKE_REQUIRED_LIBRARIES}
OpenSSL::SSL
OpenSSL::Crypto
Threads::Threads
)
target_link_libraries(test-gost OpenSSL::Crypto Threads::Threads)
target_link_libraries(test-gost-sig ${LIBS})
target_link_libraries(test-x25519 ${LIBS})
target_link_libraries(test-aeadchacha20poly1305 ${LIBS})
target_link_libraries(test-blinding ${LIBS})
target_link_libraries(test-elligator ${LIBS})
add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked)
add_test(test-http-req ${TEST_PATH}/test-http-req)
add_test(test-http-res ${TEST_PATH}/test-http-res)
add_test(test-http-url_decode ${TEST_PATH}/test-http-url_decode)
add_test(test-http-url ${TEST_PATH}/test-http-url)
add_test(test-base-64 ${TEST_PATH}/test-base-64)
add_test(test-gost ${TEST_PATH}/test-gost)
add_test(test-gost-sig ${TEST_PATH}/test-gost-sig)
add_test(test-x25519 ${TEST_PATH}/test-x25519)
add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305)
add_test(test-blinding ${TEST_PATH}/test-blinding)
add_test(test-elligator ${TEST_PATH}/test-elligator)

View File

@@ -17,7 +17,7 @@ test-gost: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp test-gost.cpp
test-gost-sig: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Crypto.cpp ../libi2pd/Log.cpp test-gost-sig.cpp test-gost-sig: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Crypto.cpp ../libi2pd/Log.cpp test-gost-sig.cpp
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system
test-x25519: ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/Crypto.cpp test-x25519.cpp test-x25519: ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/Crypto.cpp test-x25519.cpp
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system
test-aeadchacha20poly1305: ../libi2pd/Crypto.cpp ../libi2pd/ChaCha20.cpp ../libi2pd/Poly1305.cpp test-aeadchacha20poly1305.cpp test-aeadchacha20poly1305: ../libi2pd/Crypto.cpp ../libi2pd/ChaCha20.cpp ../libi2pd/Poly1305.cpp test-aeadchacha20poly1305.cpp

View File

@@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
#include "HTTP.h" #include "../HTTP.h"
using namespace i2p::http; using namespace i2p::http;

View File

@@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
#include "HTTP.h" #include "../HTTP.h"
using namespace i2p::http; using namespace i2p::http;

View File

@@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
#include "HTTP.h" #include "../HTTP.h"
using namespace i2p::http; using namespace i2p::http;

View File

@@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
#include "HTTP.h" #include "../HTTP.h"
using namespace i2p::http; using namespace i2p::http;

View File

@@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
#include "HTTP.h" #include "../HTTP.h"
using namespace i2p::http; using namespace i2p::http;