From ae309ca63219db15bb3e4a11feb844cfe9ce3d83 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Aug 2024 21:49:23 -0400 Subject: [PATCH 001/131] use std::filesystem for C++17 --- libi2pd/FS.cpp | 96 ++++++++++++++++++++-------------- libi2pd/FS.h | 6 ++- libi2pd_client/AddressBook.cpp | 17 ++++-- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 47a3e52ce62..9bb7aee2ebd 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -7,7 +7,6 @@ */ #include -#include #if defined(MAC_OSX) #include @@ -25,6 +24,14 @@ #include "Log.h" #include "Garlic.h" +#if STD_FILESYSTEM +#include +namespace fs_lib = std::filesystem; +#else +#include +namespace fs_lib = boost::filesystem; +#endif + namespace i2p { namespace fs { std::string appName = "i2pd"; @@ -55,13 +62,13 @@ namespace fs { const std::string GetUTF8DataDir () { #ifdef _WIN32 #if (BOOST_VERSION >= 108500) - boost::filesystem::path path (dataDir); + fs_lib::path path (dataDir); #else - boost::filesystem::wpath path (dataDir); + fs_lib::wpath path (dataDir); #endif - auto loc = boost::filesystem::path::imbue(std::locale( std::locale(), new std::codecvt_utf8_utf16() ) ); // convert path to UTF-8 + auto loc = fs_lib::path::imbue(std::locale( std::locale(), new std::codecvt_utf8_utf16() ) ); // convert path to UTF-8 auto dataDirUTF8 = path.string(); - boost::filesystem::path::imbue(loc); // Return locale settings back + fs_lib::path::imbue(loc); // Return locale settings back return dataDirUTF8; #else return dataDir; // linux, osx, android uses UTF-8 by default @@ -92,9 +99,9 @@ namespace fs { else { #if (BOOST_VERSION >= 108500) - dataDir = boost::filesystem::path(commonAppData).string() + "\\" + appName; + dataDir = fs_lib::path(commonAppData).string() + "\\" + appName; #else - dataDir = boost::filesystem::wpath(commonAppData).string() + "\\" + appName; + dataDir = fs_lib::wpath(commonAppData).string() + "\\" + appName; #endif } #else @@ -121,13 +128,13 @@ namespace fs { else { #if (BOOST_VERSION >= 108500) - auto execPath = boost::filesystem::path(localAppData).parent_path(); + auto execPath = fs_lib::path(localAppData).parent_path(); #else - auto execPath = boost::filesystem::wpath(localAppData).parent_path(); + auto execPath = fs_lib::wpath(localAppData).parent_path(); #endif // if config file exists in .exe's folder use it - if(boost::filesystem::exists(execPath/"i2pd.conf")) // TODO: magic string + if(fs_lib::exists(execPath/"i2pd.conf")) // TODO: magic string { dataDir = execPath.string (); } else // otherwise %appdata% @@ -144,9 +151,9 @@ namespace fs { else { #if (BOOST_VERSION >= 108500) - dataDir = boost::filesystem::path(localAppData).string() + "\\" + appName; + dataDir = fs_lib::path(localAppData).string() + "\\" + appName; #else - dataDir = boost::filesystem::wpath(localAppData).string() + "\\" + appName; + dataDir = fs_lib::wpath(localAppData).string() + "\\" + appName; #endif } } @@ -169,7 +176,7 @@ namespace fs { #if defined(ANDROID) const char * ext = getenv("EXTERNAL_STORAGE"); if (!ext) ext = "/sdcard"; - if (boost::filesystem::exists(ext)) + if (fs_lib::exists(ext)) { dataDir = std::string (ext) + "/" + appName; return; @@ -202,16 +209,16 @@ namespace fs { } bool Init() { - if (!boost::filesystem::exists(dataDir)) - boost::filesystem::create_directory(dataDir); + if (!fs_lib::exists(dataDir)) + fs_lib::create_directory(dataDir); std::string destinations = DataDirPath("destinations"); - if (!boost::filesystem::exists(destinations)) - boost::filesystem::create_directory(destinations); + if (!fs_lib::exists(destinations)) + fs_lib::create_directory(destinations); std::string tags = DataDirPath("tags"); - if (!boost::filesystem::exists(tags)) - boost::filesystem::create_directory(tags); + if (!fs_lib::exists(tags)) + fs_lib::create_directory(tags); else i2p::garlic::CleanUpTagsFiles (); @@ -219,13 +226,13 @@ namespace fs { } bool ReadDir(const std::string & path, std::vector & files) { - if (!boost::filesystem::exists(path)) + if (!fs_lib::exists(path)) return false; - boost::filesystem::directory_iterator it(path); - boost::filesystem::directory_iterator end; + fs_lib::directory_iterator it(path); + fs_lib::directory_iterator end; for ( ; it != end; it++) { - if (!boost::filesystem::is_regular_file(it->status())) + if (!fs_lib::is_regular_file(it->status())) continue; files.push_back(it->path().string()); } @@ -234,29 +241,38 @@ namespace fs { } bool Exists(const std::string & path) { - return boost::filesystem::exists(path); + return fs_lib::exists(path); } uint32_t GetLastUpdateTime (const std::string & path) { - if (!boost::filesystem::exists(path)) + if (!fs_lib::exists(path)) return 0; +#if STD_FILESYSTEM + std::error_code ec; + auto t = std::filesystem::last_write_time (path, ec); + if (ec) return 0; + auto sctp = std::chrono::time_point_cast( + t - decltype(t)::clock::now() + std::chrono::system_clock::now()); + return std::chrono::system_clock::to_time_t(sctp); +#else boost::system::error_code ec; auto t = boost::filesystem::last_write_time (path, ec); return ec ? 0 : t; +#endif } bool Remove(const std::string & path) { - if (!boost::filesystem::exists(path)) + if (!fs_lib::exists(path)) return false; - return boost::filesystem::remove(path); + return fs_lib::remove(path); } bool CreateDirectory (const std::string& path) { - if (boost::filesystem::exists(path) && boost::filesystem::is_directory (boost::filesystem::status (path))) + if (fs_lib::exists(path) && fs_lib::is_directory (fs_lib::status (path))) return true; - return boost::filesystem::create_directory(path); + return fs_lib::create_directory(path); } void HashedStorage::SetPlace(const std::string &path) { @@ -264,18 +280,18 @@ namespace fs { } bool HashedStorage::Init(const char * chars, size_t count) { - if (!boost::filesystem::exists(root)) { - boost::filesystem::create_directories(root); + if (!fs_lib::exists(root)) { + fs_lib::create_directories(root); } for (size_t i = 0; i < count; i++) { auto p = root + i2p::fs::dirSep + prefix1 + chars[i]; - if (boost::filesystem::exists(p)) + if (fs_lib::exists(p)) continue; #if TARGET_OS_SIMULATOR // ios simulator fs says it is case sensitive, but it is not boost::system::error_code ec; - if (boost::filesystem::create_directory(p, ec)) + if (fs_lib::create_directory(p, ec)) continue; switch (ec.value()) { case boost::system::errc::file_exists: @@ -285,7 +301,7 @@ namespace fs { throw boost::system::system_error( ec, __func__ ); } #else - if (boost::filesystem::create_directory(p)) + if (fs_lib::create_directory(p)) continue; /* ^ throws exception on failure */ #endif return false; @@ -308,9 +324,9 @@ namespace fs { void HashedStorage::Remove(const std::string & ident) { std::string path = Path(ident); - if (!boost::filesystem::exists(path)) + if (!fs_lib::exists(path)) return; - boost::filesystem::remove(path); + fs_lib::remove(path); } void HashedStorage::Traverse(std::vector & files) { @@ -321,12 +337,12 @@ namespace fs { void HashedStorage::Iterate(FilenameVisitor v) { - boost::filesystem::path p(root); - boost::filesystem::recursive_directory_iterator it(p); - boost::filesystem::recursive_directory_iterator end; + fs_lib::path p(root); + fs_lib::recursive_directory_iterator it(p); + fs_lib::recursive_directory_iterator end; for ( ; it != end; it++) { - if (!boost::filesystem::is_regular_file( it->status() )) + if (!fs_lib::is_regular_file( it->status() )) continue; const std::string & t = it->path().string(); v(t); diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 7911c6a0d2f..de5db9d3ea0 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,6 +15,10 @@ #include #include +#if (!defined(_WIN32) && !TARGET_OS_SIMULATOR && (__cplusplus >= 201703L)) // C++ 17 or higher +# define STD_FILESYSTEM 1 +#endif + namespace i2p { namespace fs { extern std::string dirSep; diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 8f2117a71df..928aaa0501b 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,7 +15,6 @@ #include #include #include -#include #include "Base.h" #include "util.h" #include "Identity.h" @@ -27,6 +26,14 @@ #include "AddressBook.h" #include "Config.h" +#if STD_FILESYSTEM +#include +namespace fs_lib = std::filesystem; +#else +#include +namespace fs_lib = boost::filesystem; +#endif + namespace i2p { namespace client @@ -266,11 +273,11 @@ namespace client void AddressBookFilesystemStorage::ResetEtags () { LogPrint (eLogError, "Addressbook: Resetting eTags"); - for (boost::filesystem::directory_iterator it (etagsPath); it != boost::filesystem::directory_iterator (); ++it) + for (fs_lib::directory_iterator it (etagsPath); it != fs_lib::directory_iterator (); ++it) { - if (!boost::filesystem::is_regular_file (it->status ())) + if (!fs_lib::is_regular_file (it->status ())) continue; - boost::filesystem::remove (it->path ()); + fs_lib::remove (it->path ()); } } From a93043f0641181341f013aa49d15db73523934b0 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Aug 2024 22:12:13 -0400 Subject: [PATCH 002/131] check for __cpp_lib_filesystem --- libi2pd/FS.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index de5db9d3ea0..7ba692dd3c6 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,7 +15,8 @@ #include #include -#if (!defined(_WIN32) && !TARGET_OS_SIMULATOR && (__cplusplus >= 201703L)) // C++ 17 or higher +#if (!defined(_WIN32) && !TARGET_OS_SIMULATOR && \ + (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem # define STD_FILESYSTEM 1 #endif From 4a4b76141a8f132bab4f74da6c3774e0831d647f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 11:34:07 -0400 Subject: [PATCH 003/131] C++20 support --- Makefile.linux | 6 ++++-- build/CMakeLists.txt | 9 ++++++--- libi2pd/FS.cpp | 6 +++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index 86527b9a409..ddb3692b6a6 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -23,10 +23,12 @@ else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "1[0-9]"),2) # gcc 10+ -# NEEDED_CXXFLAGS += -std=c++20 +else ifeq ($(shell expr match ${CXXVER} "10"),2) # gcc 10 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic +else ifeq ($(shell expr match ${CXXVER} "1[1-9]"),2) # gcc 11+ + NEEDED_CXXFLAGS += -std=c++20 + LDLIBS = -latomic else # not supported $(error Compiler too old) endif diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index be75ca3cdd1..daf43e6d62e 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -157,18 +157,21 @@ else() set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above - # check for c++17 & c++11 support + # check for с++20 & c++17 & c++11 support include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) - if(CXX17_SUPPORTED) + if(CXX20_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") + elseif(CXX17_SUPPORTED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") elseif(CXX11_SUPPORTED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() - message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") + message(SEND_ERROR "C++20 nor C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") endif() endif() diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 9bb7aee2ebd..eb17af5573e 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -252,8 +252,12 @@ namespace fs { std::error_code ec; auto t = std::filesystem::last_write_time (path, ec); if (ec) return 0; - auto sctp = std::chrono::time_point_cast( +#if __cplusplus >= 202002L // C++ 20 or higher + const auto sctp = std::chrono::clock_cast(t); +#else + const auto sctp = std::chrono::time_point_cast( t - decltype(t)::clock::now() + std::chrono::system_clock::now()); +#endif return std::chrono::system_clock::to_time_t(sctp); #else boost::system::error_code ec; From d85cb6e30a7f10f38a52fb27fc986980121de22a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 12:01:19 -0400 Subject: [PATCH 004/131] fixed build for Debian Bookworm --- Makefile.linux | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index ddb3692b6a6..6cd2a94984b 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -23,10 +23,10 @@ else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "10"),2) # gcc 10 +else ifeq ($(shell expr match ${CXXVER} "1[0-2]"),2) # gcc 10-12 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "1[1-9]"),2) # gcc 11+ +else ifeq ($(shell expr match ${CXXVER} "1[3-9]"),2) # gcc 13+ NEEDED_CXXFLAGS += -std=c++20 LDLIBS = -latomic else # not supported From ac876a0cd5da5a598197c059eacc1b3a4f69fce4 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 13:43:01 -0400 Subject: [PATCH 005/131] use boost::filesystem for Mac OS X --- libi2pd/FS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 7ba692dd3c6..01fa101fcf6 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,7 +15,7 @@ #include #include -#if (!defined(_WIN32) && !TARGET_OS_SIMULATOR && \ +#if (!defined(_WIN32) && !defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem # define STD_FILESYSTEM 1 #endif From b3aa5ad998c0f932f264f6c6e01145641a6d0d33 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 15:12:29 -0400 Subject: [PATCH 006/131] don't link with boost::filesystem in newer versions --- Makefile.bsd | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile.bsd b/Makefile.bsd index f9a47375852..59374f9d650 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -1,5 +1,10 @@ CXX = clang++ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation +DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1 +INCFLAGS = -I/usr/include/ -I/usr/local/include/ +LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib +LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options + ## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time ## **without** overwriting the CXXFLAGS which we need in order to build. ## For example, when adding 'hardening flags' to the build @@ -9,10 +14,7 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl CXXVER := $(shell $(CXX) -dumpversion) ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 NEEDED_CXXFLAGS = -std=c++11 + LDLIBS += -lboost_filesystem else # newer versions support C++17 NEEDED_CXXFLAGS = -std=c++17 endif -DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1 -INCFLAGS = -I/usr/include/ -I/usr/local/include/ -LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib -LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_filesystem -lboost_program_options -lpthread From e957d7bbfb4a3e73a332309be4051987dd265935 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 17:52:08 -0400 Subject: [PATCH 007/131] use std::filesystem for windows --- libi2pd/FS.cpp | 8 ++++---- libi2pd/FS.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index eb17af5573e..61bdefe0ffa 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -61,7 +61,7 @@ namespace fs { const std::string GetUTF8DataDir () { #ifdef _WIN32 -#if (BOOST_VERSION >= 108500) +#if ((BOOST_VERSION >= 108500) || STD_FILESYSTEM) fs_lib::path path (dataDir); #else fs_lib::wpath path (dataDir); @@ -98,7 +98,7 @@ namespace fs { } else { -#if (BOOST_VERSION >= 108500) +#if ((BOOST_VERSION >= 108500) || STD_FILESYSTEM) dataDir = fs_lib::path(commonAppData).string() + "\\" + appName; #else dataDir = fs_lib::wpath(commonAppData).string() + "\\" + appName; @@ -127,7 +127,7 @@ namespace fs { } else { -#if (BOOST_VERSION >= 108500) +#if ((BOOST_VERSION >= 108500) || STD_FILESYSTEM) auto execPath = fs_lib::path(localAppData).parent_path(); #else auto execPath = fs_lib::wpath(localAppData).parent_path(); @@ -150,7 +150,7 @@ namespace fs { } else { -#if (BOOST_VERSION >= 108500) +#if ((BOOST_VERSION >= 108500) || STD_FILESYSTEM) dataDir = fs_lib::path(localAppData).string() + "\\" + appName; #else dataDir = fs_lib::wpath(localAppData).string() + "\\" + appName; diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 01fa101fcf6..a46821995ad 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,7 +15,7 @@ #include #include -#if (!defined(_WIN32) && !defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ +#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem # define STD_FILESYSTEM 1 #endif From bc48e6881dc5b20c96aada6fa89701af5bb9dd1f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Aug 2024 18:25:42 -0400 Subject: [PATCH 008/131] use boost::filesystem for Win32 and clang --- libi2pd/FS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index a46821995ad..2c44285bde6 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,7 +15,7 @@ #include #include -#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ +#if (!(defined(_WIN32) && defined(__clang__)) && !defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem # define STD_FILESYSTEM 1 #endif From e87ace0c3d013a5fff9473741983af545ad7672e Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 29 Aug 2024 16:52:25 +0300 Subject: [PATCH 009/131] implement UTF-8 conversion with WinAPI for Windows platform --- Win32/Win32App.cpp | 2 +- libi2pd/FS.cpp | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 742ad30dbb0..0c701c59658 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -313,7 +313,7 @@ namespace win32 } case ID_DATADIR: { - std::string datadir(i2p::fs::GetUTF8DataDir()); + std::string datadir(i2p::fs::GetDataDir()); ShellExecute(NULL, "explore", datadir.c_str(), NULL, NULL, SW_SHOWNORMAL); return 0; } diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 61bdefe0ffa..a370bc2f540 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -61,15 +61,17 @@ namespace fs { const std::string GetUTF8DataDir () { #ifdef _WIN32 -#if ((BOOST_VERSION >= 108500) || STD_FILESYSTEM) - fs_lib::path path (dataDir); -#else - fs_lib::wpath path (dataDir); -#endif - auto loc = fs_lib::path::imbue(std::locale( std::locale(), new std::codecvt_utf8_utf16() ) ); // convert path to UTF-8 - auto dataDirUTF8 = path.string(); - fs_lib::path::imbue(loc); // Return locale settings back - return dataDirUTF8; + int size = MultiByteToWideChar(CP_ACP, 0, + dataDir.c_str(), dataDir.size(), nullptr, 0); + std::wstring utf16Str(size, L'\0'); + MultiByteToWideChar(CP_ACP, 0, + dataDir.c_str(), dataDir.size(), &utf16Str[0], size); + int utf8Size = WideCharToMultiByte(CP_UTF8, 0, + utf16Str.c_str(), utf16Str.size(), nullptr, 0, nullptr, nullptr); + std::string utf8Str(utf8Size, '\0'); + WideCharToMultiByte(CP_UTF8, 0, + utf16Str.c_str(), utf16Str.size(), &utf8Str[0], utf8Size, nullptr, nullptr); + return utf8Str; #else return dataDir; // linux, osx, android uses UTF-8 by default #endif From 937809bc0f69689a51223803410951ca6767a437 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 29 Aug 2024 15:14:17 -0400 Subject: [PATCH 010/131] don't use clock_cast with clang --- libi2pd/FS.cpp | 2 +- libi2pd/FS.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index a370bc2f540..f700f8db322 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -254,7 +254,7 @@ namespace fs { std::error_code ec; auto t = std::filesystem::last_write_time (path, ec); if (ec) return 0; -#if __cplusplus >= 202002L // C++ 20 or higher +#if !defined(__clang__) && __cplusplus >= 202002L // C++ 20 or higher const auto sctp = std::chrono::clock_cast(t); #else const auto sctp = std::chrono::time_point_cast( diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 2c44285bde6..a46821995ad 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,7 +15,7 @@ #include #include -#if (!(defined(_WIN32) && defined(__clang__)) && !defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ +#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem # define STD_FILESYSTEM 1 #endif From 604bdf314f0b074c0f5ed49d887138cb9dcb79ee Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 29 Aug 2024 18:57:14 -0400 Subject: [PATCH 011/131] improved window size reculculation algorithm --- libi2pd/Streaming.cpp | 198 +++++++++++++++++++++++------------------- libi2pd/Streaming.h | 11 ++- 2 files changed, 115 insertions(+), 94 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index d6f0441c217..2866f945062 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -68,18 +68,19 @@ namespace stream Stream::Stream (boost::asio::io_service& service, StreamingDestination& local, std::shared_ptr remote, int port): m_Service (service), - m_SendStreamID (0), m_SequenceNumber (0), + m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (0), m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsTimeOutResend (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), + m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), + m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), - m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0), m_LastSendTime (0), + m_Jitter (0), m_MinPacingTime (0), + m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) { @@ -95,18 +96,18 @@ namespace stream } Stream::Stream (boost::asio::io_service& service, StreamingDestination& local): - m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), + m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (0), m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsTimeOutResend (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), - m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0), + m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), - m_PrevRTTSample (INITIAL_RTT), m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0), m_LastSendTime (0), + m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), + m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) { @@ -339,8 +340,15 @@ namespace stream } if (delayRequested >= DELAY_CHOKING) { - m_WindowSize = 1; - m_WindowIncCounter = 0; + if (!m_IsWinDropped) + { + m_WindowDropTargetSize = MIN_WINDOW_SIZE; + m_LastWindowDropSize = 0; + m_WindowIncCounter = 0; + m_IsWinDropped = true; // don't drop window twice + m_DropWindowDelaySequenceNumber = m_SequenceNumber; + UpdatePacingTime (); + } } } optionData += 2; @@ -451,6 +459,7 @@ namespace stream void Stream::ProcessAck (Packet * packet) { + srand (time(NULL)); bool acknowledged = false; auto ts = i2p::util::GetMillisecondsSinceEpoch (); uint32_t ackThrough = packet->GetAckThrough (); @@ -464,6 +473,7 @@ namespace stream m_IsNAcked = false; m_IsResendNeeded = false; int nackCount = packet->GetNACKCount (); + int ackCount = 0; for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();) { auto seqn = (*it)->GetSeqn (); @@ -502,59 +512,42 @@ namespace stream m_SentPackets.erase (it++); m_LocalDestination.DeletePacket (sentPacket); acknowledged = true; + ackCount++; if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK) - m_WindowIncCounter++; + if (m_RTT < rand () % INITIAL_RTT) // dirty + m_WindowIncCounter++; } else break; } if (rttSample != INT_MAX) { - if (m_IsFirstRttSample) + if (m_IsFirstRttSample && !m_IsFirstACK) { m_RTT = rttSample; m_SlowRTT = rttSample; m_PrevRTTSample = rttSample; - if (m_RoutingSession) - m_RoutingSession->SetSharedRoutingPath ( - std::make_shared ( - i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0})); m_IsFirstRttSample = false; } else - m_RTT = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * rttSample; + m_RTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_RTT; // calculate jitter - int jitter = 0; + double jitter = 0; if (rttSample > m_PrevRTTSample) jitter = rttSample - m_PrevRTTSample; else if (rttSample < m_PrevRTTSample) jitter = m_PrevRTTSample - rttSample; else jitter = std::round (rttSample / 10); // 10% - jitter += 5; // for low-latency connections - m_Jitter = std::round (RTT_EWMA_ALPHA * jitter + (1.0 - RTT_EWMA_ALPHA) * m_Jitter); - m_PrevRTTSample = rttSample; + jitter += 1; // for low-latency connections + m_Jitter = (0.025 * jitter) + (1.0 - 0.025) * m_Jitter; // // delay-based CC - if ((m_PrevRTT > m_SlowRTT + m_Jitter) && (m_RTT > m_SlowRTT + m_Jitter) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection - { - if (m_LastWindowDropSize) - m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize) / 2; - else - m_LastWindowDropSize = m_WindowSize; - m_WindowSize = m_WindowSize / 2; // /2 - if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; - m_WindowIncCounter = 0; - m_DropWindowDelayTime = ts + m_SlowRTT; - m_IsFirstACK = true; - m_IsWinDropped = true; // don't drop window twice - } + if ((m_RTT > m_SlowRTT + m_Jitter && rttSample > m_RTT && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection + ProcessWindowDrop (); UpdatePacingTime (); - if (rttSample < m_RTT) // need for delay-based CC - m_SlowRTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT; - else - m_SlowRTT = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT; - m_PrevRTT = m_RTT; + m_SlowRTT = SLOWRTT_EWMA_ALPHA * rttSample + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT; + m_PrevRTTSample = rttSample; bool wasInitial = m_RTO == INITIAL_RTO; m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.3 + m_Jitter)); // TODO: implement it better @@ -562,8 +555,21 @@ namespace stream if (wasInitial) ScheduleResend (); } - if ( ts > m_DropWindowDelayTime) + if (ackThrough > m_DropWindowDelaySequenceNumber && m_WindowSize <= m_WindowDropTargetSize) m_IsWinDropped = false; + if (acknowledged && m_IsWinDropped && m_WindowSize > m_WindowDropTargetSize) + { + if (ackCount > 1) + m_WindowSize = m_SentPackets.size () + 1; + else + { + m_WindowSize = m_SentPackets.size (); + m_IsResendNeeded = true; + } + if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; + m_WindowIncCounter = 0; + UpdatePacingTime (); + } if (acknowledged || m_IsNAcked) { ScheduleResend (); @@ -578,10 +584,18 @@ namespace stream m_ResendTimer.cancel (); m_SendTimer.cancel (); } + if (acknowledged && m_IsFirstACK) + { + if (m_RoutingSession) + m_RoutingSession->SetSharedRoutingPath ( + std::make_shared ( + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0})); + m_IsFirstACK = false; + } if (acknowledged) { m_NumResendAttempts = 0; - m_IsFirstACK = false; + m_IsTimeOutResend = false; SendBuffer (); } if (m_Status == eStreamStatusClosed) @@ -1135,45 +1149,37 @@ namespace stream { if (ecode != boost::asio::error::operation_aborted) { - if (m_WindowIncCounter && m_WindowSize < MAX_WINDOW_SIZE) - { - if (m_LastWindowDropSize && (m_LastWindowDropSize > m_WindowSize)) - { - m_WindowSize += 2.001-(2/((m_LastWindowDropSize+(1/m_WindowSize))/m_WindowSize)); // some magic here - m_WindowIncCounter --; - } - else - { - m_WindowSize += 1; - m_WindowIncCounter --; - } - if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE; - UpdatePacingTime (); - } auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (m_LastSendTime && ts*1000 > m_LastSendTime*1000 + m_PacingTime) { m_NumPacketsToSend = ((ts*1000 - m_LastSendTime*1000) + m_PacingTimeRem) / m_PacingTime; m_PacingTimeRem = ((ts*1000 - m_LastSendTime*1000) + m_PacingTimeRem) - (m_NumPacketsToSend * m_PacingTime); m_IsSendTime = true; - if (m_IsNAcked || m_IsResendNeeded) // resend packets + if (m_WindowIncCounter && m_WindowSize < MAX_WINDOW_SIZE && !m_SendBuffer.IsEmpty ()) + { + for (int i = 0; i < m_NumPacketsToSend; i++) + { + if (m_WindowIncCounter) + { + if (m_LastWindowDropSize && (m_LastWindowDropSize >= m_WindowSize)) + m_WindowSize += 1 - (1 / ((m_LastWindowDropSize + PREV_SPEED_KEEP_TIME_COEFF) / m_WindowSize)); // some magic here + else if (m_LastWindowDropSize && (m_LastWindowDropSize < m_WindowSize)) + m_WindowSize += (m_WindowSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize; // some magic here + else + m_WindowSize += (m_WindowSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize; + if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE; + m_WindowIncCounter --; + UpdatePacingTime (); + } + } + } + if (m_IsNAcked) + ResendPacket (); + else if (m_IsResendNeeded) // resend packets ResendPacket (); // delay-based CC else if (!m_IsWinDropped && int(m_SentPackets.size ()) == m_WindowSize) // we sending packets too fast, early detection - { - auto ts = i2p::util::GetMillisecondsSinceEpoch (); - if (m_LastWindowDropSize) - m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize) / 2; - else - m_LastWindowDropSize = m_WindowSize; - m_WindowSize = m_WindowSize / 2; // /2 - if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; - m_WindowIncCounter = 0; - m_DropWindowDelayTime = ts + m_SlowRTT; - m_IsFirstACK = true; - m_IsWinDropped = true; // don't drop window twice - UpdatePacingTime (); - } + ProcessWindowDrop (); else if (m_WindowSize > int(m_SentPackets.size ())) // send packets SendBuffer (); } @@ -1266,30 +1272,18 @@ namespace stream { // loss-based CC if (!m_IsWinDropped) - { - if (m_LastWindowDropSize) - m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize) / 2; - else - m_LastWindowDropSize = m_WindowSize; - m_WindowSize = m_WindowSize / 2; // /2 - if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; - m_WindowIncCounter = 0; - m_IsWinDropped = true; // don't drop window twice - m_DropWindowDelayTime = ts + m_SlowRTT; - m_IsFirstACK = true; - UpdatePacingTime (); - } + ProcessWindowDrop (); } else if (m_IsTimeOutResend) { m_IsTimeOutResend = false; m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change - m_WindowSize = INITIAL_WINDOW_SIZE; + m_WindowDropTargetSize = INITIAL_WINDOW_SIZE; m_LastWindowDropSize = 0; m_WindowIncCounter = 0; m_IsWinDropped = true; m_IsFirstRttSample = true; - m_DropWindowDelayTime = 0; + m_DropWindowDelaySequenceNumber = 0; m_IsFirstACK = true; UpdatePacingTime (); if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); @@ -1438,12 +1432,16 @@ namespace stream } // drop window to initial upon RemoteLease change m_RTO = INITIAL_RTO; - m_WindowSize = INITIAL_WINDOW_SIZE; + if (m_WindowSize > INITIAL_WINDOW_SIZE) + { + m_WindowDropTargetSize = INITIAL_WINDOW_SIZE; + m_IsWinDropped = true; + } + else + m_WindowSize = INITIAL_WINDOW_SIZE; m_LastWindowDropSize = 0; m_WindowIncCounter = 0; - m_IsWinDropped = true; m_IsFirstRttSample = true; - m_DropWindowDelayTime = 0; m_IsFirstACK = true; UpdatePacingTime (); } @@ -1464,6 +1462,24 @@ namespace stream if (m_MinPacingTime && m_PacingTime < m_MinPacingTime) m_PacingTime = m_MinPacingTime; } + + void Stream::ProcessWindowDrop () + { + if (m_WindowSize > m_LastWindowDropSize) + m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize) / 2; + else + m_LastWindowDropSize = m_WindowSize; + m_WindowDropTargetSize = m_LastWindowDropSize - (m_LastWindowDropSize / 4); // -25%; + if (m_WindowDropTargetSize < MIN_WINDOW_SIZE + 1) + m_WindowDropTargetSize = MIN_WINDOW_SIZE + 1; + m_WindowSize = m_SentPackets.size (); // stop sending now + if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; + m_WindowIncCounter = 0; // disable window growth + m_DropWindowDelaySequenceNumber = m_SequenceNumber; + m_IsFirstACK = true; // ignore first RTT sample + m_IsWinDropped = true; // don't drop window twice + UpdatePacingTime (); + } StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index a0229483d67..204d4ef97cc 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -56,7 +56,9 @@ namespace stream const int INITIAL_WINDOW_SIZE = 10; const int MIN_WINDOW_SIZE = 1; const int MAX_WINDOW_SIZE = 1024; - const double RTT_EWMA_ALPHA = 0.125; + const double RTT_EWMA_ALPHA = 0.25; + const double SLOWRTT_EWMA_ALPHA = 0.125; + const double PREV_SPEED_KEEP_TIME_COEFF = 0.1; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const int MIN_RTO = 20; // in milliseconds const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds @@ -241,11 +243,13 @@ namespace stream void HandleAckSendTimer (const boost::system::error_code& ecode); void UpdatePacingTime (); + void ProcessWindowDrop (); private: boost::asio::io_service& m_Service; uint32_t m_SendStreamID, m_RecvStreamID, m_SequenceNumber; + uint32_t m_DropWindowDelaySequenceNumber; uint32_t m_TunnelsChangeSequenceNumber; int32_t m_LastReceivedSequenceNumber; int32_t m_PreviousReceivedSequenceNumber; @@ -276,8 +280,9 @@ namespace stream SendBufferQueue m_SendBuffer; double m_RTT, m_SlowRTT; - float m_WindowSize, m_LastWindowDropSize; - int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_PrevRTT, m_Jitter; + float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; + int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; + double m_Jitter; uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_DropWindowDelayTime, m_LastSendTime; // microseconds uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed int m_NumResendAttempts, m_NumPacketsToSend; From 3679c6aea03ca00a70734497a46dc4db90dfc392 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 11:03:06 -0400 Subject: [PATCH 012/131] switch to C++17 --- Makefile.haiku | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.haiku b/Makefile.haiku index b5ecb1e8662..d0824d73537 100644 --- a/Makefile.haiku +++ b/Makefile.haiku @@ -1,8 +1,8 @@ CXX = g++ -CXXFLAGS := -Wall -std=c++11 +CXXFLAGS := -Wall -std=c++17 INCFLAGS = -I/system/develop/headers DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE -LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread +LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_program_options -lpthread ifeq ($(USE_UPNP),yes) DEFINES += -DUSE_UPNP From 2679e8cfd8586e180c78866a2fb2d91683e9af85 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 13:28:01 -0400 Subject: [PATCH 013/131] removed dependency from boost::filesystem --- Makefile.mingw | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.mingw b/Makefile.mingw index 4a9d033b5ea..8db38e8f409 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -18,7 +18,6 @@ endif LDLIBS += \ $(MINGW_PREFIX)/lib/libboost_system-mt.a \ - $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ $(MINGW_PREFIX)/lib/libssl.a \ $(MINGW_PREFIX)/lib/libcrypto.a \ From 8189ff0f48f83b7d5b87e5b184110764632f177d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 14:36:56 -0400 Subject: [PATCH 014/131] innclude before _cpp_lib_filesystem check --- libi2pd/FS.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index a46821995ad..aa81955162c 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -15,10 +15,14 @@ #include #include -#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ - (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting filesystem +#ifndef STD_FILESYSTEM +#include +#if __cplusplus >= 201703L // C++ 17 or higher +#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && defined(__cpp_lib_filesystem)) // supports std::filesystem # define STD_FILESYSTEM 1 #endif +#endif +#endif namespace i2p { namespace fs { From ea3f356856a8ce5190a2ae581a4ee67f6528bbd3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 14:40:44 -0400 Subject: [PATCH 015/131] removed dependency from boost::filesystem --- libi2pd/FS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index aa81955162c..987e0aa9ac9 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,8 +16,8 @@ #include #ifndef STD_FILESYSTEM -#include #if __cplusplus >= 201703L // C++ 17 or higher +#include #if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && defined(__cpp_lib_filesystem)) // supports std::filesystem # define STD_FILESYSTEM 1 #endif From 5cc15fac31a7a79c50ce1cd99a31323119f9723d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 15:03:50 -0400 Subject: [PATCH 016/131] rollback --- Makefile.mingw | 1 + libi2pd/FS.h | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile.mingw b/Makefile.mingw index 8db38e8f409..4a9d033b5ea 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -18,6 +18,7 @@ endif LDLIBS += \ $(MINGW_PREFIX)/lib/libboost_system-mt.a \ + $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ $(MINGW_PREFIX)/lib/libssl.a \ $(MINGW_PREFIX)/lib/libcrypto.a \ diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 987e0aa9ac9..451554514cf 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,12 +16,13 @@ #include #ifndef STD_FILESYSTEM -#if __cplusplus >= 201703L // C++ 17 or higher -#include -#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && defined(__cpp_lib_filesystem)) // supports std::filesystem +#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ + (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting std::filesystem # define STD_FILESYSTEM 1 +#else +# define STD_FILESYSTEM 0 #endif -#endif + #endif namespace i2p { From 2f5f39aaf2676aa20b1fc7048eaebd4ee633d3cf Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 17:51:03 -0400 Subject: [PATCH 017/131] disable clock_cast iuntil implemented --- libi2pd/FS.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index f700f8db322..21993958147 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -254,12 +254,12 @@ namespace fs { std::error_code ec; auto t = std::filesystem::last_write_time (path, ec); if (ec) return 0; -#if !defined(__clang__) && __cplusplus >= 202002L // C++ 20 or higher +/*#if __cplusplus >= 202002L // C++ 20 or higher const auto sctp = std::chrono::clock_cast(t); -#else +#else */ // TODO: wait until implemented const auto sctp = std::chrono::time_point_cast( t - decltype(t)::clock::now() + std::chrono::system_clock::now()); -#endif +/*#endif */ return std::chrono::system_clock::to_time_t(sctp); #else boost::system::error_code ec; From 83c0764ed43df29f14fb07fda45a03654ff9ce8a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 17:54:56 -0400 Subject: [PATCH 018/131] link with stdc++fs for g++8 and g++9 --- Makefile.linux | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index 6cd2a94984b..5ac73b8bc6d 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -17,13 +17,13 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9 NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 +else ifeq ($(shell expr match ${CXXVER} "[5-7]"),1) # gcc 5 - 7 NEEDED_CXXFLAGS += -std=c++11 LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9 +else ifeq ($(shell expr match ${CXXVER} "[8-9]"),1) # gcc 8 - 9 NEEDED_CXXFLAGS += -std=c++17 - LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "1[0-2]"),2) # gcc 10-12 + LDLIBS = -latomic -lstdc++fs +else ifeq ($(shell expr match ${CXXVER} "1[0-2]"),2) # gcc 10 - 12 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic else ifeq ($(shell expr match ${CXXVER} "1[3-9]"),2) # gcc 13+ From a1f40d30488b21ec064416da6792c92e33263708 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 17:56:34 -0400 Subject: [PATCH 019/131] use __has_include()) to detect if std::filesystem can be used --- libi2pd/FS.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 451554514cf..006ee68d35e 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,13 +16,12 @@ #include #ifndef STD_FILESYSTEM -#if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ - (__cplusplus >= 201703L) && defined(__cpp_lib_filesystem)) // C++ 17 or higher supporting std::filesystem -# define STD_FILESYSTEM 1 -#else -# define STD_FILESYSTEM 0 -#endif - +# if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ + (__cplusplus >= 201703L) && __has_include()) // C++ 17 or higher and supports std::filesystem +# define STD_FILESYSTEM 1 +# else +# define STD_FILESYSTEM 0 +# endif #endif namespace i2p { From 8cf9cc1a01bd348b68e741958d2be6f66c2fc0cc Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Aug 2024 18:25:16 -0400 Subject: [PATCH 020/131] removed dependency from boost::filesystem --- Makefile.mingw | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.mingw b/Makefile.mingw index 4a9d033b5ea..8db38e8f409 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -18,7 +18,6 @@ endif LDLIBS += \ $(MINGW_PREFIX)/lib/libboost_system-mt.a \ - $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ $(MINGW_PREFIX)/lib/libssl.a \ $(MINGW_PREFIX)/lib/libcrypto.a \ From 509c039e2f42666f1c73f0f986635c51e2aba563 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 31 Aug 2024 08:02:56 -0400 Subject: [PATCH 021/131] use Rng from pool if possible --- libi2pd/Datagram.cpp | 4 ++-- libi2pd/Streaming.cpp | 15 ++++++++++++--- libi2pd/Streaming.h | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 5db072a4ce0..1e0c06ccbdb 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -422,7 +422,7 @@ namespace datagram { auto pool = m_LocalDestination->GetTunnelPool (); if (pool) - idx = m_LocalDestination->GetTunnelPool ()->GetRng ()() % sz; + idx = pool->GetRng ()() % sz; } if (idx < 0) idx = rand () % sz; path->remoteLease = ls[idx]; @@ -455,7 +455,7 @@ namespace datagram { auto pool = m_LocalDestination->GetTunnelPool (); if (pool) - idx = m_LocalDestination->GetTunnelPool ()->GetRng ()() % sz; + idx = pool->GetRng ()() % sz; } if (idx < 0) idx = rand () % sz; path->remoteLease = ls[idx]; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 2866f945062..c099e538cb7 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -459,7 +459,6 @@ namespace stream void Stream::ProcessAck (Packet * packet) { - srand (time(NULL)); bool acknowledged = false; auto ts = i2p::util::GetMillisecondsSinceEpoch (); uint32_t ackThrough = packet->GetAckThrough (); @@ -514,7 +513,7 @@ namespace stream acknowledged = true; ackCount++; if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK) - if (m_RTT < rand () % INITIAL_RTT) // dirty + if (m_RTT < m_LocalDestination.GetRandom () % INITIAL_RTT) // dirty m_WindowIncCounter++; } else @@ -1410,7 +1409,7 @@ namespace stream } if (!updated) { - uint32_t i = rand () % leases.size (); + uint32_t i = m_LocalDestination.GetRandom () % leases.size (); if (m_CurrentRemoteLease && leases[i]->tunnelID == m_CurrentRemoteLease->tunnelID) // make sure we don't select previous i = (i + 1) % leases.size (); // if so, pick next @@ -1811,5 +1810,15 @@ namespace stream return msg; } + uint32_t StreamingDestination::GetRandom () + { + if (m_Owner) + { + auto pool = m_Owner->GetTunnelPool (); + if (pool) + return pool->GetRng ()(); + } + return rand (); + } } } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 204d4ef97cc..c251d8229d6 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -321,6 +321,7 @@ namespace stream Packet * NewPacket () { return m_PacketsPool.Acquire(); } void DeletePacket (Packet * p) { return m_PacketsPool.Release(p); } + uint32_t GetRandom (); private: From bbadbdbfdbd60bcf0bbeaa983bc9ef3abc68cd6f Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Sep 2024 15:23:14 -0400 Subject: [PATCH 022/131] Switch to C++17 for Mac OS X --- Makefile.homebrew | 2 +- Makefile.osx | 2 +- libi2pd/FS.cpp | 2 ++ libi2pd/FS.h | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.homebrew b/Makefile.homebrew index f19d64bb496..e14ea955ec4 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -5,7 +5,7 @@ SSLROOT = ${BREWROOT}/opt/openssl@1.1 UPNPROOT = ${BREWROOT}/opt/miniupnpc CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wno-overloaded-virtual -NEEDED_CXXFLAGS ?= -std=c++11 +NEEDED_CXXFLAGS ?= -std=c++17 INCFLAGS ?= -I${SSLROOT}/include -I${BOOSTROOT}/include LDFLAGS ?= ${LD_DEBUG} DEFINES += -DMAC_OSX diff --git a/Makefile.osx b/Makefile.osx index 963d4898730..48eb1a511f8 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -1,5 +1,5 @@ CXX = clang++ -CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 +CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++17 INCFLAGS = -I/usr/local/include DEFINES := -DMAC_OSX LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 21993958147..fdfd577efcd 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -9,7 +9,9 @@ #include #if defined(MAC_OSX) +#if !STD_FILESYSTEM #include +#endif #include #endif diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 006ee68d35e..455012ba9b3 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,7 +16,7 @@ #include #ifndef STD_FILESYSTEM -# if (!defined(MAC_OSX) && !TARGET_OS_SIMULATOR && \ +# if (!TARGET_OS_SIMULATOR && \ (__cplusplus >= 201703L) && __has_include()) // C++ 17 or higher and supports std::filesystem # define STD_FILESYSTEM 1 # else From a837e5c50239665cf5ca25c080107cf48ba987c9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Sep 2024 16:39:19 -0400 Subject: [PATCH 023/131] use rng from pool for lease selection --- libi2pd_client/I2CP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 12d2d0c96d1..fc6d1b4005e 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -226,7 +226,8 @@ namespace client leases = remote->GetNonExpiredLeases (true); // with threshold if (!leases.empty ()) { - remoteLease = leases[rand () % leases.size ()]; + auto pool = GetTunnelPool (); + remoteLease = leases[(pool ? pool->GetRng ()() : rand ()) % leases.size ()]; auto leaseRouter = i2p::data::netdb.FindRouter (remoteLease->tunnelGateway); outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (nullptr, leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports); From 9668ea9338fe8524781d6966f576227775129769 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 10:18:08 -0400 Subject: [PATCH 024/131] removed C++11 support --- Makefile.bsd | 3 +-- Makefile.linux | 18 ++++-------------- tests/Makefile | 4 ++-- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Makefile.bsd b/Makefile.bsd index 59374f9d650..edcc0b58e9b 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -13,8 +13,7 @@ LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options ## custom FLAGS to work at build-time. CXXVER := $(shell $(CXX) -dumpversion) ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 - NEEDED_CXXFLAGS = -std=c++11 - LDLIBS += -lboost_filesystem + $(error Compiler too old) else # newer versions support C++17 NEEDED_CXXFLAGS = -std=c++17 endif diff --git a/Makefile.linux b/Makefile.linux index 5ac73b8bc6d..88abdcbf179 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -9,26 +9,17 @@ LDFLAGS ?= ${LD_DEBUG} ## -std=c++11. If you want to remove this variable please do so in a way that allows setting ## custom FDLAGS to work at build-time. -# detect proper flag for c++11 support by compilers +# detect proper flag for c++17 support by compilers CXXVER := $(shell $(CXX) -dumpversion) ifeq ($(shell expr match $(CXX) 'clang'),5) - NEEDED_CXXFLAGS += -std=c++11 -else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 - NEEDED_CXXFLAGS += -std=c++11 -else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9 - NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -else ifeq ($(shell expr match ${CXXVER} "[5-7]"),1) # gcc 5 - 7 - NEEDED_CXXFLAGS += -std=c++11 - LDLIBS = -latomic + NEEDED_CXXFLAGS += -std=c++17 else ifeq ($(shell expr match ${CXXVER} "[8-9]"),1) # gcc 8 - 9 NEEDED_CXXFLAGS += -std=c++17 - LDLIBS = -latomic -lstdc++fs + LDLIBS = -lstdc++fs else ifeq ($(shell expr match ${CXXVER} "1[0-2]"),2) # gcc 10 - 12 NEEDED_CXXFLAGS += -std=c++17 - LDLIBS = -latomic else ifeq ($(shell expr match ${CXXVER} "1[3-9]"),2) # gcc 13+ NEEDED_CXXFLAGS += -std=c++20 - LDLIBS = -latomic else # not supported $(error Compiler too old) endif @@ -41,7 +32,6 @@ ifeq ($(USE_STATIC),yes) # the shared libraries from the glibc version used for linking LIBDIR := /usr/lib/$(SYS) LDLIBS += $(LIBDIR)/libboost_system.a - LDLIBS += $(LIBDIR)/libboost_filesystem.a LDLIBS += $(LIBDIR)/libboost_program_options.a LDLIBS += $(LIBDIR)/libssl.a LDLIBS += $(LIBDIR)/libcrypto.a @@ -51,7 +41,7 @@ ifeq ($(USE_UPNP),yes) endif LDLIBS += -lpthread -ldl else - LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_filesystem -lboost_program_options -lpthread + LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_program_options -lpthread -latomic ifeq ($(USE_UPNP),yes) LDLIBS += -lminiupnpc endif diff --git a/tests/Makefile b/tests/Makefile index 7c44e467354..798fab42153 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,6 @@ SYS := $(shell $(CXX) -dumpmachine) -CXXFLAGS += -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -DOPENSSL_SUPPRESS_DEPRECATED -pthread -Wl,--unresolved-symbols=ignore-in-object-files +CXXFLAGS += -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -std=c++17 -D_GLIBCXX_USE_NANOSLEEP=1 -DOPENSSL_SUPPRESS_DEPRECATED -pthread -Wl,--unresolved-symbols=ignore-in-object-files INCFLAGS += -I../libi2pd LIBI2PD = ../libi2pd.a @@ -18,7 +18,7 @@ ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstrin endif LDLIBS = \ - -lboost_filesystem$(BOOST_SUFFIX) \ + -lboost_system$(BOOST_SUFFIX) \ -lboost_program_options$(BOOST_SUFFIX) \ -lssl \ -lcrypto \ From c21cf0565b7b331712dbeb0ff4940f216c0706f1 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 10:55:22 -0400 Subject: [PATCH 025/131] removed C++11 support --- build/CMakeLists.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index daf43e6d62e..19c51dfdd45 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -157,21 +157,19 @@ else() set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above - # check for с++20 & c++17 & c++11 support + # check for с++20 & c++17 support include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) - CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) + if(CXX20_SUPPORTED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") elseif(CXX17_SUPPORTED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - elseif(CXX11_SUPPORTED) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() - message(SEND_ERROR "C++20 nor C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") + message(SEND_ERROR "C++20 nor C++17 standard not seems to be supported by compiler. Too old version?") endif() endif() From 56b8534e0c911147a38964e97aebf218e55bdad7 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 15:00:25 -0400 Subject: [PATCH 026/131] gcc7 support --- Makefile.linux | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.linux b/Makefile.linux index 88abdcbf179..2955d3011cc 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -13,6 +13,9 @@ LDFLAGS ?= ${LD_DEBUG} CXXVER := $(shell $(CXX) -dumpversion) ifeq ($(shell expr match $(CXX) 'clang'),5) NEEDED_CXXFLAGS += -std=c++17 +else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 + NEEDED_CXXFLAGS += -std=c++17 + LDLIBS = -lboost_filesystem else ifeq ($(shell expr match ${CXXVER} "[8-9]"),1) # gcc 8 - 9 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -lstdc++fs From a3e0b3710c66b854eee33d7532cbe262e9a72ba0 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 17:34:15 -0400 Subject: [PATCH 027/131] pass std::string_view to parse --- libi2pd/HTTP.cpp | 90 ++++++++++++++++++++++++++++++------------------ libi2pd/HTTP.h | 11 +++--- 2 files changed, 63 insertions(+), 38 deletions(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index f4c3dcb91b8..ecb1d550453 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,12 +40,13 @@ namespace http inline bool is_http_method(const std::string & str) { return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS); } - - void strsplit(const std::string & line, std::vector &tokens, char delim, std::size_t limit = 0) { + + static void strsplit(std::stringstream& ss, std::vector &tokens, char delim, std::size_t limit = 0) + { std::size_t count = 0; - std::stringstream ss(line); std::string token; - while (1) { + while (1) + { count++; if (limit > 0 && count >= limit) delim = '\n'; /* reset delimiter */ @@ -55,7 +56,19 @@ namespace http } } - static std::pair parse_header_line(const std::string& line) + static void strsplit(const std::string & line, std::vector &tokens, char delim, std::size_t limit = 0) + { + std::stringstream ss(line); + strsplit (ss, tokens, delim, limit); + } + + static void strsplit(std::string_view line, std::vector &tokens, char delim, std::size_t limit = 0) + { + std::stringstream ss(std::move(std::string(line))); + strsplit (ss, tokens, delim, limit); + } + + static std::pair parse_header_line(std::string_view line) { std::size_t pos = 0; std::size_t len = 1; /*: */ @@ -69,7 +82,8 @@ namespace http if (len == 1) return std::make_pair("", ""); // no following space, but something else } - return std::make_pair(line.substr(0, pos), line.substr(pos + len)); + return std::make_pair(std::move (std::string (line.substr(0, pos))), + std::move (std::string (line.substr(pos + len)))); } void gen_rfc7231_date(std::string & out) { @@ -83,15 +97,17 @@ namespace http out = buf; } - bool URL::parse(const char *str, std::size_t len) { - std::string url(str, len ? len : strlen(str)); - return parse(url); + bool URL::parse(const char *str, std::size_t len) + { + return parse({str, len ? len : strlen(str)}); } - bool URL::parse(const std::string& url) { + bool URL::parse(std::string_view url) + { std::size_t pos_p = 0; /* < current parse position */ std::size_t pos_c = 0; /* < work position */ - if(url.at(0) != '/' || pos_p > 0) { + if(url.at(0) != '/' || pos_p > 0) + { std::size_t pos_s = 0; /* schema */ @@ -141,7 +157,7 @@ namespace http /* port[/path] */ pos_p = pos_c + 1; pos_c = url.find('/', pos_p); - std::string port_str = (pos_c == std::string::npos) + std::string_view port_str = (pos_c == std::string::npos) ? url.substr(pos_p, std::string::npos) : url.substr(pos_p, pos_c - pos_p); /* stoi throws exception on failure, we don't need it */ @@ -272,12 +288,13 @@ namespace http headers.erase(name); } - int HTTPReq::parse(const char *buf, size_t len) { - std::string str(buf, len); - return parse(str); + int HTTPReq::parse(const char *buf, size_t len) + { + return parse({buf, len}); } - int HTTPReq::parse(const std::string& str) { + int HTTPReq::parse(std::string_view str) + { enum { REQ_LINE, HEADER_LINE } expect = REQ_LINE; std::size_t eoh = str.find(HTTP_EOH); /* request head size */ std::size_t eol = 0, pos = 0; @@ -286,9 +303,11 @@ namespace http if (eoh == std::string::npos) return 0; /* str not contains complete request */ - while ((eol = str.find(CRLF, pos)) != std::string::npos) { - if (expect == REQ_LINE) { - std::string line = str.substr(pos, eol - pos); + while ((eol = str.find(CRLF, pos)) != std::string::npos) + { + if (expect == REQ_LINE) + { + std::string_view line = str.substr(pos, eol - pos); std::vector tokens; strsplit(line, tokens, ' '); if (tokens.size() != 3) @@ -307,7 +326,7 @@ namespace http } else { - std::string line = str.substr(pos, eol - pos); + std::string_view line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) headers.push_back (p); @@ -413,12 +432,13 @@ namespace http return length; } - int HTTPRes::parse(const char *buf, size_t len) { - std::string str(buf, len); - return parse(str); + int HTTPRes::parse(const char *buf, size_t len) + { + return parse({buf,len}); } - int HTTPRes::parse(const std::string& str) { + int HTTPRes::parse(std::string_view str) + { enum { RES_LINE, HEADER_LINE } expect = RES_LINE; std::size_t eoh = str.find(HTTP_EOH); /* request head size */ std::size_t eol = 0, pos = 0; @@ -426,9 +446,11 @@ namespace http if (eoh == std::string::npos) return 0; /* str not contains complete request */ - while ((eol = str.find(CRLF, pos)) != std::string::npos) { - if (expect == RES_LINE) { - std::string line = str.substr(pos, eol - pos); + while ((eol = str.find(CRLF, pos)) != std::string::npos) + { + if (expect == RES_LINE) + { + std::string_view line = str.substr(pos, eol - pos); std::vector tokens; strsplit(line, tokens, ' ', 3); if (tokens.size() != 3) @@ -442,8 +464,10 @@ namespace http version = tokens[0]; status = tokens[2]; expect = HEADER_LINE; - } else { - std::string line = str.substr(pos, eol - pos); + } + else + { + std::string_view line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) headers.insert (p); @@ -508,14 +532,14 @@ namespace http return ptr; } - std::string UrlDecode(const std::string& data, bool allow_null) + std::string UrlDecode(std::string_view data, bool allow_null) { std::string decoded(data); size_t pos = 0; while ((pos = decoded.find('%', pos)) != std::string::npos) { - char c = strtol(decoded.substr(pos + 1, 2).c_str(), NULL, 16); - if (c == '\0' && !allow_null) + char c = std::stol(decoded.substr(pos + 1, 2), nullptr, 16); + if (!c && !allow_null) { pos += 3; continue; diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 41f0560aef2..d71c75050df 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace i2p @@ -45,7 +46,7 @@ namespace http * @return true on success, false on invalid url */ bool parse (const char *str, std::size_t len = 0); - bool parse (const std::string& url); + bool parse (std::string_view url); /** * @brief Parse query part of url to key/value map @@ -92,7 +93,7 @@ namespace http * @note Positive return value is a size of header */ int parse(const char *buf, size_t len); - int parse(const std::string& buf); + int parse(std::string_view buf); /** @brief Serialize HTTP request to string */ std::string to_string(); @@ -128,7 +129,7 @@ namespace http * @note Positive return value is a size of header */ int parse(const char *buf, size_t len); - int parse(const std::string& buf); + int parse(const std::string_view buf); /** * @brief Serialize HTTP response to string @@ -161,7 +162,7 @@ namespace http * @param null If set to true - decode also %00 sequence, otherwise - skip * @return Decoded string */ - std::string UrlDecode(const std::string& data, bool null = false); + std::string UrlDecode(std::string_view data, bool null = false); /** * @brief Merge HTTP response content with Transfer-Encoding: chunked From cc590035606f0fb07b21f660a878ae48f4ca13ce Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 18:22:33 -0400 Subject: [PATCH 028/131] removed C++17 check --- Win32/Win32App.cpp | 4 +--- libi2pd/ECIESX25519AEADRatchetSession.cpp | 2 -- libi2pd/FS.h | 3 +-- libi2pd/Garlic.cpp | 2 -- libi2pd/Log.h | 20 -------------------- libi2pd/NetDb.cpp | 17 ++--------------- libi2pd/RouterContext.cpp | 2 -- libi2pd/SSU2Session.cpp | 4 ---- libi2pd_client/SOCKS.cpp | 2 -- 9 files changed, 4 insertions(+), 52 deletions(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 0c701c59658..5234b03256a 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -355,9 +355,7 @@ namespace win32 } } } -#if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif + [fallthrough]]; } case WM_TRAYICON: { diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 9f23482ba2f..138d21e9be4 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -801,9 +801,7 @@ namespace garlic m_State = eSessionStateEstablished; m_NSRSendTagset = nullptr; m_EphemeralKeys = nullptr; -#if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; -#endif case eSessionStateEstablished: if (m_SendReverseKey && receiveTagset->GetTagSetID () == m_NextReceiveRatchet->GetReceiveTagSetID ()) m_SendReverseKey = false; // tag received on new tagset diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 455012ba9b3..8bf8101ec20 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,8 +16,7 @@ #include #ifndef STD_FILESYSTEM -# if (!TARGET_OS_SIMULATOR && \ - (__cplusplus >= 201703L) && __has_include()) // C++ 17 or higher and supports std::filesystem +# if (!TARGET_OS_SIMULATOR && __has_include()) // supports std::filesystem # define STD_FILESYSTEM 1 # else # define STD_FILESYSTEM 0 diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 54fc781e4f7..fb99ce6d833 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1031,9 +1031,7 @@ namespace garlic case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: Type destination"); buf += 32; // TODO: check destination -#if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; -#endif // no break here case eGarlicDeliveryTypeLocal: { diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 0164ea4fe73..18592c9e988 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -172,16 +172,6 @@ void LogPrint (std::stringstream& s, TValue&& arg) noexcept s << std::forward(arg); } -#if (__cplusplus < 201703L) // below C++ 17 -/** internal usage only -- folding args array to single string */ -template -void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept -{ - LogPrint (s, std::forward(arg)); - LogPrint (s, std::forward(args)...); -} -#endif - /** * @brief Create log message and send it to queue * @param level Message level (eLogError, eLogInfo, ...) @@ -194,13 +184,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept // fold message to single string std::stringstream ss; - -#if (__cplusplus >= 201703L) // C++ 17 or higher (LogPrint (ss, std::forward(args)), ...); -#else - LogPrint (ss, std::forward(args)...); -#endif - auto msg = std::make_shared(level, std::time(nullptr), std::move(ss).str()); msg->tid = std::this_thread::get_id(); i2p::log::Logger().Append(msg); @@ -217,11 +201,7 @@ void ThrowFatal (TArgs&&... args) noexcept if (!f) return; // fold message to single string std::stringstream ss(""); -#if (__cplusplus >= 201703L) // C++ 17 or higher (LogPrint (ss, std::forward(args)), ...); -#else - LogPrint (ss, std::forward(args)...); -#endif f (ss.str ()); } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9bd787769d9..b222ac88957 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1314,12 +1314,8 @@ namespace data { // update selection m_ExploratorySelection.clear (); -#if (__cplusplus >= 201703L) // C++ 17 or higher std::vector > eligible; - eligible.reserve (m_RouterInfos.size ()); -#else - auto& eligible = m_ExploratorySelection; -#endif + eligible.reserve (m_RouterInfos.size ()); { // collect eligible from current netdb bool checkIsReal = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD; // too low rate @@ -1329,22 +1325,13 @@ namespace data (!checkIsReal || (it.second->HasProfile () && it.second->GetProfile ()->IsReal ()))) eligible.push_back (it.second); } -#if (__cplusplus >= 201703L) // C++ 17 or higher if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE) { std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection), NETDB_MAX_EXPLORATORY_SELECTION_SIZE, std::mt19937(ts)); } else - std::swap (m_ExploratorySelection, eligible); -#else - if (m_ExploratorySelection.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE) - { - // reduce number of eligible to max selection size - std::shuffle (m_ExploratorySelection.begin(), m_ExploratorySelection.end(), std::mt19937(ts)); - m_ExploratorySelection.resize (NETDB_MAX_EXPLORATORY_SELECTION_SIZE); - } -#endif + std::swap (m_ExploratorySelection, eligible); m_LastExploratorySelectionUpdateTime = ts; } diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 5461cdfdf7d..89c46c45041 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -626,9 +626,7 @@ namespace i2p case low : /* not set */; break; case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P' case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; -#if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; -#endif // no break here, extra + high means 'X' case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 92fe2d468bf..62bbf41feb1 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -587,11 +587,7 @@ namespace transport if (!resentPackets.empty ()) { m_LastResendTime = ts; -#if (__cplusplus >= 201703L) // C++ 17 or higher m_SentPackets.merge (resentPackets); -#else - m_SentPackets.insert (resentPackets.begin (), resentPackets.end ()); -#endif m_WindowSize >>= 1; // /2 if (m_WindowSize < SSU2_MIN_WINDOW_SIZE) m_WindowSize = SSU2_MIN_WINDOW_SIZE; return resentPackets.size (); diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 3174bdb35b9..0961690bb26 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -444,9 +444,7 @@ namespace proxy break; case CMD_UDP: if (m_socksv == SOCKS5) break; -#if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; -#endif default: LogPrint(eLogError, "SOCKS: Invalid command: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); From 06e3a1b57aaa612bbfa84696a9c2daea896df32d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 18:32:52 -0400 Subject: [PATCH 029/131] fixed typo --- Win32/Win32App.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 5234b03256a..0e29c5173b9 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -355,7 +355,7 @@ namespace win32 } } } - [fallthrough]]; + [[fallthrough]]; } case WM_TRAYICON: { From 0046a8b3ecd0f926f1767042e01ce78c412ee2c6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Sep 2024 21:05:40 -0400 Subject: [PATCH 030/131] pass const strings for HTTP headers --- libi2pd/HTTP.cpp | 2 +- libi2pd/HTTP.h | 2 +- libi2pd_client/HTTPProxy.cpp | 23 +++++++++++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index ecb1d550453..6e427298e94 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -269,7 +269,7 @@ namespace http return host.rfind(".i2p") == ( host.size() - 4 ); } - void HTTPMsg::add_header(const char *name, std::string & value, bool replace) { + void HTTPMsg::add_header(const char *name, const std::string & value, bool replace) { add_header(name, value.c_str(), replace); } diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index d71c75050df..438ef953a80 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -70,7 +70,7 @@ namespace http { std::map headers; - void add_header(const char *name, std::string & value, bool replace = false); + void add_header(const char *name, const std::string & value, bool replace = false); void add_header(const char *name, const char *value, bool replace = false); void del_header(const char *name); diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 01678f4afb6..67ee2c5e6d5 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,8 @@ namespace proxy { "\r\n" ; - bool str_rmatch(std::string & str, const char *suffix) { + static bool str_rmatch(std::string & str, const char *suffix) + { auto pos = str.rfind (suffix); if (pos == std::string::npos) return false; /* not found */ @@ -77,16 +79,16 @@ namespace proxy { void Terminate(); void AsyncSockRead(); static bool ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm); - static bool VerifyAddressHelper (const std::string& jump); + static bool VerifyAddressHelper (std::string_view jump); static void SanitizeHTTPRequest(i2p::http::HTTPReq& req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); /* error helpers */ void GenericProxyError(const std::string& title, const std::string& description); void GenericProxyInfo(const std::string& title, const std::string& description); - void HostNotFound(std::string& host); - void SendProxyError(std::string& content); - void SendRedirect(std::string& address); + void HostNotFound(const std::string& host); + void SendProxyError(const std::string& content); + void SendRedirect(const std::string& address); void ForwardToUpstreamProxy(); void HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec); @@ -175,7 +177,8 @@ namespace proxy { SendProxyError(content); } - void HTTPReqHandler::HostNotFound(std::string& host) { + void HTTPReqHandler::HostNotFound(const std::string& host) + { std::stringstream ss; ss << "

" << tr("Proxy error: Host not found") << "

\r\n" << "

" << tr("Remote host not found in router's addressbook") << "

\r\n" @@ -192,7 +195,7 @@ namespace proxy { SendProxyError(content); } - void HTTPReqHandler::SendProxyError(std::string& content) + void HTTPReqHandler::SendProxyError(const std::string& content) { i2p::http::HTTPRes res; res.code = 500; @@ -208,7 +211,7 @@ namespace proxy { std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPReqHandler::SendRedirect(std::string& address) + void HTTPReqHandler::SendRedirect(const std::string& address) { i2p::http::HTTPRes res; res.code = 302; @@ -272,7 +275,7 @@ namespace proxy { return true; } - bool HTTPReqHandler::VerifyAddressHelper (const std::string& jump) + bool HTTPReqHandler::VerifyAddressHelper (std::string_view jump) { auto pos = jump.find(".b32.i2p"); if (pos != std::string::npos) @@ -441,7 +444,7 @@ namespace proxy { bool useConnect = false; if(m_ClientRequest.method == "CONNECT") { - std::string uri(m_ClientRequest.uri); + const std::string& uri = m_ClientRequest.uri; auto pos = uri.find(":"); if(pos == std::string::npos || pos == uri.size() - 1) { From ae65af07c27163d9d462d628f189458067430788 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Sep 2024 13:00:04 -0400 Subject: [PATCH 031/131] handle immediate ack request --- libi2pd/Streaming.cpp | 12 +++++++++--- libi2pd/Streaming.h | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c099e538cb7..1974cd10bb1 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -326,12 +326,16 @@ namespace stream LogPrint (eLogInfo, "Streaming: Invalid option size ", optionSize, " Discarded"); return false; } + if (!flags) return true; + bool immediateAckRequested = false; if (flags & PACKET_FLAG_DELAY_REQUESTED) { - if (!m_IsAckSendScheduled) + uint16_t delayRequested = bufbe16toh (optionData); + if (!delayRequested) // 0 requests an immediate ack + immediateAckRequested = true; + else if (!m_IsAckSendScheduled) { - uint16_t delayRequested = bufbe16toh (optionData); - if (delayRequested > 0 && delayRequested < m_RTT) + if (delayRequested < m_RTT) { m_IsAckSendScheduled = true; m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(delayRequested)); @@ -432,6 +436,8 @@ namespace stream return false; } } + if (immediateAckRequested) + SendQuickAck (); return true; } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index c251d8229d6..c0b73162378 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -283,7 +283,7 @@ namespace stream float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; - uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_DropWindowDelayTime, m_LastSendTime; // microseconds + uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_LastSendTime; // microseconds uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed int m_NumResendAttempts, m_NumPacketsToSend; size_t m_MTU; From ead1b72886b01a418828c1774987ae5213cf80d0 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Sep 2024 15:20:33 -0400 Subject: [PATCH 032/131] set half of window on remote lease change --- libi2pd/Streaming.cpp | 2 +- libi2pd/Streaming.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 1974cd10bb1..881818d542a 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1439,7 +1439,7 @@ namespace stream m_RTO = INITIAL_RTO; if (m_WindowSize > INITIAL_WINDOW_SIZE) { - m_WindowDropTargetSize = INITIAL_WINDOW_SIZE; + m_WindowDropTargetSize = std::max (m_WindowSize/2, (float)INITIAL_WINDOW_SIZE); m_IsWinDropped = true; } else diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index c0b73162378..84b92c9fd7e 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -58,7 +58,7 @@ namespace stream const int MAX_WINDOW_SIZE = 1024; const double RTT_EWMA_ALPHA = 0.25; const double SLOWRTT_EWMA_ALPHA = 0.125; - const double PREV_SPEED_KEEP_TIME_COEFF = 0.1; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer + const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const int MIN_RTO = 20; // in milliseconds const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds From 53db54dafba455a5a63999681c32fd299909145b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Sep 2024 18:36:50 -0400 Subject: [PATCH 033/131] consider N routers as low bandwidth --- libi2pd/RouterInfo.cpp | 8 ++++---- libi2pd/RouterInfo.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index d819999e213..c24d0957a6a 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -538,10 +538,10 @@ namespace data case CAPS_FLAG_LOW_BANDWIDTH1: case CAPS_FLAG_LOW_BANDWIDTH2: case CAPS_FLAG_LOW_BANDWIDTH3: + case CAPS_FLAG_LOW_BANDWIDTH4: m_BandwidthCap = *cap; break; - case CAPS_FLAG_HIGH_BANDWIDTH1: - case CAPS_FLAG_HIGH_BANDWIDTH2: + case CAPS_FLAG_HIGH_BANDWIDTH: m_Caps |= Caps::eHighBandwidth; m_BandwidthCap = *cap; break; @@ -1224,7 +1224,7 @@ namespace data CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' else - caps += CAPS_FLAG_HIGH_BANDWIDTH2; // 'O' + caps += CAPS_FLAG_HIGH_BANDWIDTH; // 'O' caps += CAPS_FLAG_FLOODFILL; // floodfill } else @@ -1232,7 +1232,7 @@ namespace data if (c & eExtraBandwidth) caps += (c & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ else - caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH2 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth + caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth } if (c & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index c2668bc451a..16f072d0b7c 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -40,8 +40,8 @@ namespace data const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH3 = 'M'; /* 48-64 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'N'; /* 64-128 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'O'; /* 128-256 KBps */ + const char CAPS_FLAG_LOW_BANDWIDTH4 = 'N'; /* 64-128 KBps */ + const char CAPS_FLAG_HIGH_BANDWIDTH = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */ // bandwidth limits in kBps From d1620d70bbb6ce1afe3b38ecc2a9ea0dd0d8045a Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Sep 2024 18:43:25 -0400 Subject: [PATCH 034/131] consider N routers as low bandwidth --- libi2pd/RouterContext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 89c46c45041..efbfee65c1e 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -610,8 +610,8 @@ namespace i2p case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48 case i2p::data::CAPS_FLAG_LOW_BANDWIDTH3 : limit = 64; type = low; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 128; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH4 : limit = 128; type = low; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s default: From 911620bcd317ba2f20510dc63f7f2cf93e856199 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Sep 2024 13:21:13 -0400 Subject: [PATCH 035/131] C++20 for clang >= 16 --- Makefile.bsd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.bsd b/Makefile.bsd index edcc0b58e9b..03b504838e4 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -14,6 +14,8 @@ LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options CXXVER := $(shell $(CXX) -dumpversion) ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 $(error Compiler too old) -else # newer versions support C++17 +else ifeq ($(shell expr match ${CXXVER} "1[6-9]"),2) # clang 16 - 19 + NEEDED_CXXFLAGS += -std=c++20 +else NEEDED_CXXFLAGS = -std=c++17 endif From 2ee5af0c061b4e43dc1ad43d00023bdc5065da57 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Sep 2024 13:23:12 -0400 Subject: [PATCH 036/131] C++20 for clang >= 16 --- Makefile.bsd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.bsd b/Makefile.bsd index 03b504838e4..eb528799123 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -15,7 +15,8 @@ CXXVER := $(shell $(CXX) -dumpversion) ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 $(error Compiler too old) else ifeq ($(shell expr match ${CXXVER} "1[6-9]"),2) # clang 16 - 19 - NEEDED_CXXFLAGS += -std=c++20 + NEEDED_CXXFLAGS = -std=c++20 else NEEDED_CXXFLAGS = -std=c++17 endif + From cab671e177d27b5e60541d571f5bbbf21ad0077d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Sep 2024 13:28:34 -0400 Subject: [PATCH 037/131] use gexpr instead expr --- Makefile.bsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.bsd b/Makefile.bsd index eb528799123..c97527b4ea5 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -14,7 +14,7 @@ LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options CXXVER := $(shell $(CXX) -dumpversion) ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 $(error Compiler too old) -else ifeq ($(shell expr match ${CXXVER} "1[6-9]"),2) # clang 16 - 19 +else ifeq ($(shell gexpr match ${CXXVER} "1[6-9]"),2) # clang 16 - 19 NEEDED_CXXFLAGS = -std=c++20 else NEEDED_CXXFLAGS = -std=c++17 From 306ea2df37b7ad8ca216a93a54d995a53c13f83e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Sep 2024 14:12:30 -0400 Subject: [PATCH 038/131] don't apply std::move to prvalue --- libi2pd/HTTP.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 6e427298e94..990781bcac7 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -58,13 +58,13 @@ namespace http static void strsplit(const std::string & line, std::vector &tokens, char delim, std::size_t limit = 0) { - std::stringstream ss(line); + std::stringstream ss{line}; strsplit (ss, tokens, delim, limit); } static void strsplit(std::string_view line, std::vector &tokens, char delim, std::size_t limit = 0) { - std::stringstream ss(std::move(std::string(line))); + std::stringstream ss{std::string(line)}; strsplit (ss, tokens, delim, limit); } @@ -74,16 +74,15 @@ namespace http std::size_t len = 1; /*: */ std::size_t max = line.length(); if ((pos = line.find(':', pos)) == std::string::npos) - return std::make_pair("", ""); // no ':' found + return std::pair{"", ""}; // no ':' found if (pos + 1 < max) // ':' at the end of header is valid { while ((pos + len) < max && isspace(line.at(pos + len))) len++; if (len == 1) - return std::make_pair("", ""); // no following space, but something else + return std::pair{"", ""}; // no following space, but something else } - return std::make_pair(std::move (std::string (line.substr(0, pos))), - std::move (std::string (line.substr(pos + len)))); + return std::pair{std::string (line.substr(0, pos)), std::string (line.substr(pos + len))}; } void gen_rfc7231_date(std::string & out) { From 9a77c0a4b13f158aa68dab55d228673a637d62b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Sep 2024 07:43:24 -0400 Subject: [PATCH 039/131] recognize compiler version without gexpr --- Makefile.bsd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.bsd b/Makefile.bsd index c97527b4ea5..4cf8f80ae67 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -11,10 +11,10 @@ LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options ## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove ## -std=c++11. If you want to remove this variable please do so in a way that allows setting ## custom FLAGS to work at build-time. -CXXVER := $(shell $(CXX) -dumpversion) -ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1 +CXXVER := $(shell $(CXX) -dumpversion|cut -c 1-2) +ifeq (${CXXVER}, "4.") # older clang always returned 4.2.1 $(error Compiler too old) -else ifeq ($(shell gexpr match ${CXXVER} "1[6-9]"),2) # clang 16 - 19 +else ifeq (${CXXVER}, ${filter ${CXXVER},16 17 18 19}) # clang 16 - 19 NEEDED_CXXFLAGS = -std=c++20 else NEEDED_CXXFLAGS = -std=c++17 From fde301deaf7277109694b50bc9c901d7d667f049 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Sep 2024 19:24:23 -0400 Subject: [PATCH 040/131] check for duplicated routers in NTCP2. Insert router into netdb right a way --- libi2pd/I2NPProtocol.h | 1 - libi2pd/NTCP2.cpp | 39 ++++++++++++++++++++++++++++++++------- libi2pd/NetDb.cpp | 4 ---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 1acd4242708..4e26fc949d4 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -107,7 +107,6 @@ namespace i2p enum I2NPMessageType { - eI2NPDummyMsg = 0, eI2NPDatabaseStore = 1, eI2NPDatabaseLookup = 2, eI2NPDatabaseSearchReply = 3, diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 7f0f2189704..de14d3b0da3 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -724,8 +724,24 @@ namespace transport SendTerminationAndTerminate (eNTCP2Message3Error); return; } - auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () : - (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ()); + // update RouterInfo in netdb + auto ri1 = i2p::data::netdb.AddRouterInfo (ri.GetBuffer (), ri.GetBufferLen ()); // ri1 points to one from netdb now + if (!ri1) + { + LogPrint (eLogError, "NTCP2: Couldn't update RouterInfo from SessionConfirmed in netdb"); + return; + } + std::shared_ptr profile; // not null if older + if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ()) + { + // received RouterInfo is older than one in netdb + profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile + if (profile && profile->IsDuplicated ()) + return; + } + + auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri1->GetNTCP2V4Address () : + (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri1->GetYggdrasilAddress () : ri1->GetNTCP2V6Address ()); if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32)) { LogPrint (eLogError, "NTCP2: Wrong static key in SessionConfirmed"); @@ -737,16 +753,17 @@ namespace transport memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address { - LogPrint (eLogError, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ()); + if (profile) // older router? + profile->Duplicated (); // mark router as duplicated in profile + else + LogPrint (eLogError, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ()); Terminate (); return; } - i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options // ready to communicate - auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already - SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); + SetRemoteIdentity (ri1->GetRouterIdentity ()); if (m_Server.AddNTCP2Session (shared_from_this (), true)) { Established (); @@ -939,7 +956,15 @@ namespace transport case eNTCP2BlkRouterInfo: { LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset, size)); + i2p::data::RouterInfo ri (frame + offset + 1, size - 1); + auto newRi = i2p::data::netdb.AddRouterInfo (ri.GetBuffer (), ri.GetBufferLen ()); + if (newRi) + { + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity && remoteIdentity->GetIdentHash () == newRi->GetIdentHash ()) + // peer's RouterInfo update + SetRemoteIdentity (newRi->GetIdentity ()); + } break; } case eNTCP2BlkI2NPMessage: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index b222ac88957..ccc43d7a822 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -141,10 +141,6 @@ namespace data case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); break; - case eI2NPDummyMsg: - // plain RouterInfo from NTCP2 with flags for now - HandleNTCP2RouterInfoMsg (msg); - break; default: // WTF? LogPrint (eLogError, "NetDb: Unexpected message type ", (int) msg->GetTypeID ()); //i2p::HandleI2NPMessage (msg); From e0af7b077fe9ad4aeeb01de8a79cabf815d1b9ca Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Sep 2024 20:28:40 -0400 Subject: [PATCH 041/131] set max number of tags adequate to max window size --- libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- libi2pd/Streaming.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 10645251309..bcc07b3031e 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -35,7 +35,7 @@ namespace garlic const int ECIESX25519_ACK_REQUEST_MAX_NUM_ATTEMPTS = 3; const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24; - const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 320; + const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 800; const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12; const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */ diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 84b92c9fd7e..6a983520de8 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -54,8 +54,8 @@ namespace stream const size_t COMPRESSION_THRESHOLD_SIZE = 66; const int MAX_NUM_RESEND_ATTEMPTS = 10; const int INITIAL_WINDOW_SIZE = 10; - const int MIN_WINDOW_SIZE = 1; - const int MAX_WINDOW_SIZE = 1024; + const int MIN_WINDOW_SIZE = 2; + const int MAX_WINDOW_SIZE = 512; const double RTT_EWMA_ALPHA = 0.25; const double SLOWRTT_EWMA_ALPHA = 0.125; const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer From 855fd4d471421cec5e482b3fadd23aa5da53f489 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Sep 2024 09:49:24 -0400 Subject: [PATCH 042/131] eliminate extra parsing of RouterInfo coming as RouterInfo block --- libi2pd/NTCP2.cpp | 5 ++--- libi2pd/SSU2Session.cpp | 40 +++++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index de14d3b0da3..f7d81671229 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -955,9 +955,8 @@ namespace transport break; case eNTCP2BlkRouterInfo: { - LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - i2p::data::RouterInfo ri (frame + offset + 1, size - 1); - auto newRi = i2p::data::netdb.AddRouterInfo (ri.GetBuffer (), ri.GetBufferLen ()); + LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); + auto newRi = i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1); if (newRi) { auto remoteIdentity = GetRemoteIdentity (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 62bbf41feb1..eb662716d7f 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1750,28 +1750,34 @@ namespace transport void SSU2Session::HandleRouterInfo (const uint8_t * buf, size_t len) { - auto ri = ExtractRouterInfo (buf, len); - if (ri) + if (len < 2) return; + // not from SessionConfirmed, we must add it instantly to use in next block + std::shared_ptr newRi; + if (buf[0] & SSU2_ROUTER_INFO_FLAG_GZIP) // compressed? { - // not from SessionConfirmed, we must add it instantly to use in next block - auto newRi = i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); // TODO: add ri - if (newRi) + auto ri = ExtractRouterInfo (buf, len); + if (ri) + newRi = i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); + } + else // use buffer directly. TODO: handle frag + newRi = i2p::data::netdb.AddRouterInfo (buf + 2, len - 2); + + if (newRi) + { + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity && remoteIdentity->GetIdentHash () == newRi->GetIdentHash ()) { - auto remoteIdentity = GetRemoteIdentity (); - if (remoteIdentity && remoteIdentity->GetIdentHash () == newRi->GetIdentHash ()) + // peer's RouterInfo update + SetRemoteIdentity (newRi->GetIdentity ()); + auto address = m_RemoteEndpoint.address ().is_v6 () ? newRi->GetSSU2V6Address () : newRi->GetSSU2V4Address (); + if (address) { - // peer's RouterInfo update - SetRemoteIdentity (newRi->GetIdentity ()); - auto address = m_RemoteEndpoint.address ().is_v6 () ? newRi->GetSSU2V6Address () : newRi->GetSSU2V4Address (); - if (address) - { - m_Address = address; - if (IsOutgoing () && m_RelayTag && !address->IsIntroducer ()) - m_RelayTag = 0; // not longer introducer - } + m_Address = address; + if (IsOutgoing () && m_RelayTag && !address->IsIntroducer ()) + m_RelayTag = 0; // not longer introducer } } - } + } } void SSU2Session::HandleAck (const uint8_t * buf, size_t len) From d539c9677e83434471d82733d13640f44af9f6be Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Sep 2024 19:04:07 -0400 Subject: [PATCH 043/131] don't accept tunnels if connected through proxy --- libi2pd/RouterContext.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index efbfee65c1e..c9bc5229515 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -323,6 +323,9 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (true, false); // ipv4 break; + case eRouterStatusProxy: + m_AcceptsTunnels = false; + break; default: ; } From 8d1c18666593cfae9e3585756437b6ea6025ef0f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Sep 2024 16:25:26 -0400 Subject: [PATCH 044/131] limited connectivity mode --- libi2pd/NetDb.cpp | 3 ++- libi2pd/RouterContext.h | 1 + libi2pd/Transports.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index ccc43d7a822..55e17b234f3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -759,7 +759,8 @@ namespace data void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { - if (direct && i2p::transport::transports.RoutesRestricted ()) direct = false; // always use tunnels for restricted routes + if (direct && (i2p::transport::transports.RoutesRestricted () || i2p::context.IsLimitedConnectivity ())) + direct = false; // always use tunnels for restricted routes or limited connectivity if (m_Requests) m_Requests->PostRequestDestination (destination, requestComplete, direct); else diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 09c3678f340..03f1d10d5ad 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -177,6 +177,7 @@ namespace garlic void SetMTU (int mtu, bool v4); void SetHidden(bool hide) { m_IsHiddenMode = hide; }; bool IsHidden() const { return m_IsHiddenMode; }; + bool IsLimitedConnectivity () const { return m_Status == eRouterStatusProxy; }; // TODO: implement other cases i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; }; void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index cf30b428605..549efb63527 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -599,7 +599,7 @@ namespace transport } LogPrint (eLogInfo, "Transports: No compatible addresses available"); - if (peer->router->IsReachableFrom (i2p::context.GetRouterInfo ())) + if (!i2p::context.IsLimitedConnectivity () && peer->router->IsReachableFrom (i2p::context.GetRouterInfo ())) i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed but router claimed them peer->Done (); std::unique_lock l(m_PeersMutex); From ba451eeca5ebf13f48b50cf3b44abe84a5f3269d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Sep 2024 18:01:48 -0400 Subject: [PATCH 045/131] set congestion cap G immediately if through proxy --- libi2pd/RouterContext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index c9bc5229515..f9548139894 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -325,6 +325,7 @@ namespace i2p break; case eRouterStatusProxy: m_AcceptsTunnels = false; + UpdateCongestion (); break; default: ; From cd648b9b3fb7c5ee3aed89d71728dba3c12f4f27 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Sep 2024 16:30:27 -0400 Subject: [PATCH 046/131] use std::atomic> instead boost::shared_ptr if applicable --- libi2pd/NetDb.hpp | 6 +- libi2pd/RouterInfo.cpp | 123 ++++++++++++++++++++++------------------- libi2pd/RouterInfo.h | 21 +++++-- 3 files changed, 84 insertions(+), 66 deletions(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 8efba61aa8b..1797c04d153 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -127,12 +127,12 @@ namespace data } bool PopulateRouterInfoBuffer (std::shared_ptr r); std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; - boost::shared_ptr NewRouterInfoAddresses () + RouterInfo::AddressesPtr NewRouterInfoAddresses () { - return boost::shared_ptr(m_RouterInfoAddressVectorsPool.AcquireMt (), + return RouterInfo::AddressesPtr{m_RouterInfoAddressVectorsPool.AcquireMt (), std::bind ::*)(RouterInfo::Addresses *)> (&i2p::util::MemoryPoolMt::ReleaseMt, - &m_RouterInfoAddressVectorsPool, std::placeholders::_1)); + &m_RouterInfoAddressVectorsPool, std::placeholders::_1)}; }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); }; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index c24d0957a6a..b6abb48a61e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -10,10 +10,10 @@ #include #include "I2PEndian.h" #include +#include #include -#include #include // for boost::to_lower -#if (BOOST_VERSION >= 105300) +#ifndef __cpp_lib_atomic_shared_ptr #include #endif #include "version.h" @@ -40,7 +40,7 @@ namespace data RouterInfo::RouterInfo (): m_Buffer (nullptr) { - m_Addresses = boost::make_shared(); // create empty list + m_Addresses = AddressesPtr(new Addresses ()); // create empty list } RouterInfo::RouterInfo (const std::string& fullPath): @@ -48,7 +48,7 @@ namespace data m_SupportedTransports (0),m_ReachableTransports (0), m_PublishedTransports (0), m_Caps (0), m_Version (0), m_Congestion (eLowCongestion) { - m_Addresses = boost::make_shared(); // create empty list + m_Addresses = AddressesPtr(new Addresses ()); // create empty list m_Buffer = NewBuffer (); // always RouterInfo's ReadFromFile (fullPath); } @@ -60,7 +60,7 @@ namespace data { if (len <= MAX_RI_BUFFER_SIZE) { - m_Addresses = boost::make_shared(); // create empty list + m_Addresses = AddressesPtr(new Addresses ()); // create empty list m_Buffer = buf; if (m_Buffer) m_Buffer->SetBufferLen (len); ReadFromBuffer (true); @@ -439,10 +439,10 @@ namespace data } m_ReachableTransports |= m_PublishedTransports; // update addresses -#if (BOOST_VERSION >= 105300) +#ifdef __cpp_lib_atomic_shared_ptr + m_Addresses = addresses; +#else boost::atomic_store (&m_Addresses, addresses); -#else - m_Addresses = addresses; // race condition #endif // read peers uint8_t numPeers; @@ -692,12 +692,12 @@ namespace data if (addr->IsV4 ()) { m_SupportedTransports |= eNTCP2V4; - (*m_Addresses)[eNTCP2V4Idx] = addr; + (*GetAddresses ())[eNTCP2V4Idx] = addr; } if (addr->IsV6 ()) { m_SupportedTransports |= eNTCP2V6; - (*m_Addresses)[eNTCP2V6Idx] = addr; + (*GetAddresses ())[eNTCP2V6Idx] = addr; } } @@ -718,11 +718,12 @@ namespace data if (host.is_v4 ()) addr->caps |= eV4; if (host.is_v6 ()) addr->caps |= eV6; } + auto addresses = GetAddresses (); if (addr->IsV4 ()) { m_SupportedTransports |= eNTCP2V4; m_ReachableTransports |= eNTCP2V4; - (*m_Addresses)[eNTCP2V4Idx] = addr; + (*addresses)[eNTCP2V4Idx] = addr; } if (addr->IsV6 ()) { @@ -730,30 +731,31 @@ namespace data { m_SupportedTransports |= eNTCP2V6Mesh; m_ReachableTransports |= eNTCP2V6Mesh; - (*m_Addresses)[eNTCP2V6MeshIdx] = addr; + (*addresses)[eNTCP2V6MeshIdx] = addr; } else { m_SupportedTransports |= eNTCP2V6; m_ReachableTransports |= eNTCP2V6; - (*m_Addresses)[eNTCP2V6Idx] = addr; + (*addresses)[eNTCP2V6Idx] = addr; } } } void RouterInfo::RemoveNTCP2Address (bool v4) { + auto addresses = GetAddresses (); if (v4) { - if ((*m_Addresses)[eNTCP2V6Idx]) - (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; - (*m_Addresses)[eNTCP2V4Idx].reset (); + if ((*addresses)[eNTCP2V6Idx]) + (*addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; + (*addresses)[eNTCP2V4Idx].reset (); } else { - if ((*m_Addresses)[eNTCP2V4Idx]) - (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; - (*m_Addresses)[eNTCP2V6Idx].reset (); + if ((*addresses)[eNTCP2V4Idx]) + (*addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; + (*addresses)[eNTCP2V6Idx].reset (); } UpdateSupportedTransports (); } @@ -769,15 +771,16 @@ namespace data addr->ssu->mtu = 0; memcpy (addr->s, staticKey, 32); memcpy (addr->i, introKey, 32); + auto addresses = GetAddresses (); if (addr->IsV4 ()) { m_SupportedTransports |= eSSU2V4; - (*m_Addresses)[eSSU2V4Idx] = addr; + (*addresses)[eSSU2V4Idx] = addr; } if (addr->IsV6 ()) { m_SupportedTransports |= eSSU2V6; - (*m_Addresses)[eSSU2V6Idx] = addr; + (*addresses)[eSSU2V6Idx] = addr; } } @@ -802,33 +805,35 @@ namespace data if (host.is_v4 ()) addr->caps |= eV4; if (host.is_v6 ()) addr->caps |= eV6; } + auto addresses = GetAddresses (); if (addr->IsV4 ()) { m_SupportedTransports |= eSSU2V4; m_ReachableTransports |= eSSU2V4; - (*m_Addresses)[eSSU2V4Idx] = addr; + (*addresses)[eSSU2V4Idx] = addr; } if (addr->IsV6 ()) { m_SupportedTransports |= eSSU2V6; m_ReachableTransports |= eSSU2V6; - (*m_Addresses)[eSSU2V6Idx] = addr; + (*addresses)[eSSU2V6Idx] = addr; } } void RouterInfo::RemoveSSU2Address (bool v4) { + auto addresses = GetAddresses (); if (v4) { - if ((*m_Addresses)[eSSU2V6Idx]) - (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; - (*m_Addresses)[eSSU2V4Idx].reset (); + if ((*addresses)[eSSU2V6Idx]) + (*addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; + (*addresses)[eSSU2V4Idx].reset (); } else { - if ((*m_Addresses)[eSSU2V4Idx]) - (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; - (*m_Addresses)[eSSU2V6Idx].reset (); + if ((*addresses)[eSSU2V4Idx]) + (*addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; + (*addresses)[eSSU2V6Idx].reset (); } UpdateSupportedTransports (); } @@ -869,17 +874,18 @@ namespace data { if (IsV6 ()) { - if ((*m_Addresses)[eNTCP2V6Idx]) + auto addresses = GetAddresses (); + if ((*addresses)[eNTCP2V6Idx]) { - if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 () && (*m_Addresses)[eNTCP2V4Idx]) - (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; - (*m_Addresses)[eNTCP2V6Idx].reset (); + if ((*addresses)[eNTCP2V6Idx]->IsV4 () && (*addresses)[eNTCP2V4Idx]) + (*addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; + (*addresses)[eNTCP2V6Idx].reset (); } - if ((*m_Addresses)[eSSU2V6Idx]) + if ((*addresses)[eSSU2V6Idx]) { - if ((*m_Addresses)[eSSU2V6Idx]->IsV4 () && (*m_Addresses)[eSSU2V4Idx]) - (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; - (*m_Addresses)[eSSU2V6Idx].reset (); + if ((*addresses)[eSSU2V6Idx]->IsV4 () && (*addresses)[eSSU2V4Idx]) + (*addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; + (*addresses)[eSSU2V6Idx].reset (); } UpdateSupportedTransports (); } @@ -889,17 +895,18 @@ namespace data { if (IsV4 ()) { - if ((*m_Addresses)[eNTCP2V4Idx]) + auto addresses = GetAddresses (); + if ((*addresses)[eNTCP2V4Idx]) { - if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 () && (*m_Addresses)[eNTCP2V6Idx]) - (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; - (*m_Addresses)[eNTCP2V4Idx].reset (); + if ((*addresses)[eNTCP2V4Idx]->IsV6 () && (*addresses)[eNTCP2V6Idx]) + (*addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; + (*addresses)[eNTCP2V4Idx].reset (); } - if ((*m_Addresses)[eSSU2V4Idx]) + if ((*addresses)[eSSU2V4Idx]) { - if ((*m_Addresses)[eSSU2V4Idx]->IsV6 () && (*m_Addresses)[eSSU2V6Idx]) - (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; - (*m_Addresses)[eSSU2V4Idx].reset (); + if ((*addresses)[eSSU2V4Idx]->IsV6 () && (*addresses)[eSSU2V6Idx]) + (*addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; + (*addresses)[eSSU2V4Idx].reset (); } UpdateSupportedTransports (); } @@ -920,7 +927,7 @@ namespace data { m_SupportedTransports &= ~eNTCP2V6Mesh; m_ReachableTransports &= ~eNTCP2V6Mesh; - (*m_Addresses)[eNTCP2V6MeshIdx].reset (); + (*GetAddresses ())[eNTCP2V6MeshIdx].reset (); } } @@ -949,12 +956,12 @@ namespace data return nullptr; } - boost::shared_ptr RouterInfo::GetAddresses () const + RouterInfo::AddressesPtr RouterInfo::GetAddresses () const { -#if (BOOST_VERSION >= 105300) - return boost::atomic_load (&m_Addresses); -#else +#ifdef __cpp_lib_atomic_shared_ptr return m_Addresses; +#else + return boost::atomic_load (&m_Addresses); #endif } @@ -962,10 +969,10 @@ namespace data std::shared_ptr RouterInfo::GetAddress (Filter filter) const { // TODO: make it more generic using comparator -#if (BOOST_VERSION >= 105300) +#ifdef __cpp_lib_atomic_shared_ptr + AddressesPtr addresses = m_Addresses; +#else auto addresses = boost::atomic_load (&m_Addresses); -#else - auto addresses = m_Addresses; #endif for (const auto& address : *addresses) if (address && filter (address)) return address; @@ -1062,7 +1069,7 @@ namespace data void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) { - for (auto& addr: *m_Addresses) + for (auto& addr: *GetAddresses ()) { if (addr && !addr->published) { @@ -1076,7 +1083,7 @@ namespace data { m_SupportedTransports = 0; m_ReachableTransports = 0; - for (const auto& addr: *m_Addresses) + for (const auto& addr: *GetAddresses ()) { if (!addr) continue; uint8_t transports = 0; @@ -1151,7 +1158,7 @@ namespace data return netdb.NewRouterInfoAddress (); } - boost::shared_ptr RouterInfo::NewAddresses () const + RouterInfo::AddressesPtr RouterInfo::NewAddresses () const { return netdb.NewRouterInfoAddresses (); } @@ -1503,9 +1510,9 @@ namespace data return std::make_shared
(); } - boost::shared_ptr LocalRouterInfo::NewAddresses () const + RouterInfo::AddressesPtr LocalRouterInfo::NewAddresses () const { - return boost::make_shared (); + return RouterInfo::AddressesPtr(new RouterInfo::Addresses ()); } std::shared_ptr LocalRouterInfo::NewIdentity (const uint8_t * buf, size_t len) const diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 16f072d0b7c..68d6b0f032e 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -15,8 +15,11 @@ #include #include #include +#include #include +#ifndef __cpp_lib_atomic_shared_ptr #include +#endif #include "Identity.h" #include "Profiling.h" #include "Family.h" @@ -199,7 +202,11 @@ namespace data }; typedef std::array, eNumTransports> Addresses; - +#ifdef __cpp_lib_atomic_shared_ptr + typedef std::shared_ptr AddressesPtr; +#else + typedef boost::shared_ptr AddressesPtr; +#endif RouterInfo (const std::string& fullPath); RouterInfo (const RouterInfo& ) = default; RouterInfo& operator=(const RouterInfo& ) = default; @@ -214,7 +221,7 @@ namespace data int GetVersion () const { return m_Version; }; virtual void SetProperty (const std::string& key, const std::string& value) {}; virtual void ClearProperties () {}; - boost::shared_ptr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr + AddressesPtr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr std::shared_ptr GetNTCP2V4Address () const; std::shared_ptr GetNTCP2V6Address () const; std::shared_ptr GetPublishedNTCP2V4Address () const; @@ -333,7 +340,7 @@ namespace data std::shared_ptr GetAddress (Filter filter) const; virtual std::shared_ptr NewBuffer () const; virtual std::shared_ptr
NewAddress () const; - virtual boost::shared_ptr NewAddresses () const; + virtual AddressesPtr NewAddresses () const; virtual std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) const; private: @@ -342,7 +349,11 @@ namespace data std::shared_ptr m_RouterIdentity; std::shared_ptr m_Buffer; uint64_t m_Timestamp; // in milliseconds - boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 +#ifdef __cpp_lib_atomic_shared_ptr + std::atomic m_Addresses; +#else + AddressesPtr m_Addresses; +#endif bool m_IsUpdated, m_IsUnreachable, m_IsFloodfill; CompatibleTransports m_SupportedTransports, m_ReachableTransports, m_PublishedTransports; uint8_t m_Caps; @@ -377,7 +388,7 @@ namespace data void WriteString (const std::string& str, std::ostream& s) const; std::shared_ptr NewBuffer () const override; std::shared_ptr
NewAddress () const override; - boost::shared_ptr NewAddresses () const override; + RouterInfo::AddressesPtr NewAddresses () const override; std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) const override; private: From bcace3fb295bbe2ad971347e29fb237f4bd33929 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Sep 2024 17:53:41 -0400 Subject: [PATCH 047/131] use -std=c++17 --- build/cmake_modules/CheckAtomic.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/cmake_modules/CheckAtomic.cmake b/build/cmake_modules/CheckAtomic.cmake index d5ec6a0ab40..4954e3e5842 100644 --- a/build/cmake_modules/CheckAtomic.cmake +++ b/build/cmake_modules/CheckAtomic.cmake @@ -8,7 +8,7 @@ INCLUDE(CheckLibraryExists) function(check_working_cxx_atomics varname) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++17") CHECK_CXX_SOURCE_COMPILES(" #include std::atomic x; @@ -25,7 +25,7 @@ endfunction(check_working_cxx_atomics) function(check_working_cxx_atomics64 varname) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "-std=c++17 ${CMAKE_REQUIRED_FLAGS}") CHECK_CXX_SOURCE_COMPILES(" #include #include From 07d108bb6f8b4cc9398c18e3e5d23d146344aa79 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Sep 2024 18:40:06 -0400 Subject: [PATCH 048/131] send immediate ack request if no packet being sent --- libi2pd/Streaming.cpp | 11 ++++++++--- libi2pd/Streaming.h | 7 +++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 881818d542a..4ee3eb85097 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -877,13 +877,18 @@ namespace stream } packet[size] = 0; size++; // resend delay - htobuf16 (packet + size, choking ? PACKET_FLAG_DELAY_REQUESTED : 0); // no flags set or delay + bool requestImmediateAck = false; + if (!choking) + requestImmediateAck = m_LastSendTime && ts > m_LastSendTime + REQUEST_IMMEDIATE_ACK_INTERVAL && + ts > m_LastSendTime + REQUEST_IMMEDIATE_ACK_INTERVAL + m_LocalDestination.GetRandom () % REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE; + htobuf16 (packet + size, (choking || requestImmediateAck) ? PACKET_FLAG_DELAY_REQUESTED : 0); // no flags set or delay requested size += 2; // flags - if (choking) + if (choking || requestImmediateAck) { htobuf16 (packet + size, 2); // 2 bytes delay interval - htobuf16 (packet + size + 2, DELAY_CHOKING); // set choking interval + htobuf16 (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval size += 2; + if (requestImmediateAck) m_LastSendTime = ts; // ack request sent } else htobuf16 (packet + size, 0); // no options diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 6a983520de8..699410408e2 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -70,7 +70,9 @@ namespace stream const int MAX_RECEIVE_TIMEOUT = 20; // in seconds const uint16_t DELAY_CHOKING = 60000; // in milliseconds const uint64_t SEND_INTERVAL = 1000; // in microseconds - + const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds + const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds + struct Packet { size_t len, offset; @@ -283,7 +285,8 @@ namespace stream float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; - uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_LastSendTime; // microseconds + uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds + m_LastSendTime; // miliseconds uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed int m_NumResendAttempts, m_NumPacketsToSend; size_t m_MTU; From 699e17b594de6ac6378c9649e97a6db973fd4c65 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Sep 2024 22:26:03 -0400 Subject: [PATCH 049/131] handle plain ack with options --- libi2pd/Streaming.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 4ee3eb85097..d5ec57ceabf 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -184,10 +184,15 @@ namespace stream ProcessAck (packet); int32_t receivedSeqn = packet->GetSeqn (); - if (!receivedSeqn && !packet->GetFlags ()) + if (!receivedSeqn) { - // plain ack - LogPrint (eLogDebug, "Streaming: Plain ACK received"); + uint16_t flags = packet->GetFlags (); + if (flags) + // plain ack with options + ProcessOptions (flags, packet); + else + // plain ack + LogPrint (eLogDebug, "Streaming: Plain ACK received"); m_LocalDestination.DeletePacket (packet); return; } From 50d297fa29cd0c17f8096cebc313a7b5dc0f8c0e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Sep 2024 22:37:35 -0400 Subject: [PATCH 050/131] check if first packet --- libi2pd/Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index d5ec57ceabf..ba886ab9c25 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -184,7 +184,7 @@ namespace stream ProcessAck (packet); int32_t receivedSeqn = packet->GetSeqn (); - if (!receivedSeqn) + if (!receivedSeqn && m_LastReceivedSequenceNumber >= 0) { uint16_t flags = packet->GetFlags (); if (flags) From a65dd218da008d6420ef322bc47e527583929511 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Sep 2024 10:27:26 -0400 Subject: [PATCH 051/131] correct endianess in SendQuickAck --- libi2pd/Streaming.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index ba886ab9c25..e75aa39b027 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -886,12 +886,12 @@ namespace stream if (!choking) requestImmediateAck = m_LastSendTime && ts > m_LastSendTime + REQUEST_IMMEDIATE_ACK_INTERVAL && ts > m_LastSendTime + REQUEST_IMMEDIATE_ACK_INTERVAL + m_LocalDestination.GetRandom () % REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE; - htobuf16 (packet + size, (choking || requestImmediateAck) ? PACKET_FLAG_DELAY_REQUESTED : 0); // no flags set or delay requested + htobe16buf (packet + size, (choking || requestImmediateAck) ? PACKET_FLAG_DELAY_REQUESTED : 0); // no flags set or delay requested size += 2; // flags if (choking || requestImmediateAck) { - htobuf16 (packet + size, 2); // 2 bytes delay interval - htobuf16 (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval + htobe16buf (packet + size, 2); // 2 bytes delay interval + htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval size += 2; if (requestImmediateAck) m_LastSendTime = ts; // ack request sent } From 261acbbd6609f724ace3278cc527fcf079ba15eb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Sep 2024 12:22:42 -0400 Subject: [PATCH 052/131] recalculate RTT for one way communications --- libi2pd/Streaming.cpp | 20 ++++++++++++++++---- libi2pd/Streaming.h | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index e75aa39b027..5c9dc6dce02 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -73,7 +73,7 @@ namespace stream m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), - m_IsTimeOutResend (false), m_LocalDestination (local), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), @@ -101,7 +101,7 @@ namespace stream m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), - m_IsTimeOutResend (false), m_LocalDestination (local), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), @@ -192,7 +192,15 @@ namespace stream ProcessOptions (flags, packet); else // plain ack - LogPrint (eLogDebug, "Streaming: Plain ACK received"); + { + LogPrint (eLogDebug, "Streaming: Plain ACK received"); + if (m_IsImmediateAckRequested) + { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + m_RTT = (m_RTT + (ts - m_LastSendTime)) / 2; + m_IsImmediateAckRequested = false; + } + } m_LocalDestination.DeletePacket (packet); return; } @@ -893,7 +901,11 @@ namespace stream htobe16buf (packet + size, 2); // 2 bytes delay interval htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval size += 2; - if (requestImmediateAck) m_LastSendTime = ts; // ack request sent + if (requestImmediateAck) // ack request sent + { + m_LastSendTime = ts; + m_IsImmediateAckRequested = true; + } } else htobuf16 (packet + size, 0); // no options diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 699410408e2..70853d64556 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -265,6 +265,7 @@ namespace stream bool m_IsSendTime; bool m_IsWinDropped; bool m_IsTimeOutResend; + bool m_IsImmediateAckRequested; StreamingDestination& m_LocalDestination; std::shared_ptr m_RemoteIdentity; std::shared_ptr m_TransientVerifier; // in case of offline key From 272bf7dbc199de9e45beb04da7538266b31edc02 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Sep 2024 12:35:36 -0400 Subject: [PATCH 053/131] terminate NTCP2 session from duplicated router properly --- libi2pd/NTCP2.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f7d81671229..a33d4fef667 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -729,6 +729,7 @@ namespace transport if (!ri1) { LogPrint (eLogError, "NTCP2: Couldn't update RouterInfo from SessionConfirmed in netdb"); + Terminate (); return; } std::shared_ptr profile; // not null if older @@ -737,7 +738,10 @@ namespace transport // received RouterInfo is older than one in netdb profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile if (profile && profile->IsDuplicated ()) + { + SendTerminationAndTerminate (eNTCP2Banned); return; + } } auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri1->GetNTCP2V4Address () : @@ -756,8 +760,8 @@ namespace transport if (profile) // older router? profile->Duplicated (); // mark router as duplicated in profile else - LogPrint (eLogError, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ()); - Terminate (); + LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ()); + SendTerminationAndTerminate (eNTCP2Banned); return; } // TODO: process options From 78ec5b2c6e375f5552fe273f7121e0abb58ab680 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Sep 2024 11:24:51 -0400 Subject: [PATCH 054/131] faster RTT recalculation if bad sample --- libi2pd/Streaming.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 5c9dc6dce02..ba71f0acdd9 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -197,7 +197,13 @@ namespace stream if (m_IsImmediateAckRequested) { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - m_RTT = (m_RTT + (ts - m_LastSendTime)) / 2; + if (m_IsFirstRttSample) + { + m_RTT = ts - m_LastSendTime; + m_IsFirstRttSample = false; + } + else + m_RTT = (m_RTT + (ts - m_LastSendTime)) / 2; m_IsImmediateAckRequested = false; } } From 3d0a1afd64826fe582d4e87475f8d61d66cbfb47 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Sep 2024 12:06:55 -0400 Subject: [PATCH 055/131] check if addressbook is enabled --- libi2pd_client/AddressBook.cpp | 18 +++++++++++------- libi2pd_client/AddressBook.h | 5 +++-- libi2pd_client/HTTPProxy.cpp | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 928aaa0501b..14599cf74bf 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -441,7 +441,7 @@ namespace client auto ident = std::make_shared(); if (ident->FromBase64 (jump)) { - m_Storage->AddAddress (ident); + if (m_Storage) m_Storage->AddAddress (ident); m_Addresses[address] = std::make_shared
(ident->GetIdentHash ()); LogPrint (eLogInfo, "Addressbook: Added ", address," -> ", ToAddress(ident->GetIdentHash ())); } @@ -452,18 +452,19 @@ namespace client void AddressBook::InsertFullAddress (std::shared_ptr address) { - m_Storage->AddAddress (address); + if (m_Storage) m_Storage->AddAddress (address); } std::shared_ptr AddressBook::GetFullAddress (const std::string& address) { auto addr = GetAddress (address); if (!addr || !addr->IsIdentHash ()) return nullptr; - return m_Storage->GetAddress (addr->identHash); + return m_Storage ? m_Storage->GetAddress (addr->identHash) : nullptr; } void AddressBook::LoadHosts () { + if (!m_Storage) return; if (m_Storage->Load (m_Addresses) > 0) { m_IsLoaded = true; @@ -534,15 +535,18 @@ namespace client ident->GetSigningKeyType () != i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) // don't replace by DSA { it->second->identHash = ident->GetIdentHash (); - m_Storage->AddAddress (ident); - m_Storage->RemoveAddress (it->second->identHash); + if (m_Storage) + { + m_Storage->AddAddress (ident); + m_Storage->RemoveAddress (it->second->identHash); + } LogPrint (eLogInfo, "Addressbook: Updated host: ", name); } } else { m_Addresses.emplace (name, std::make_shared
(ident->GetIdentHash ())); - m_Storage->AddAddress (ident); + if (m_Storage) m_Storage->AddAddress (ident); if (is_update) LogPrint (eLogInfo, "Addressbook: Added new host: ", name); } @@ -554,7 +558,7 @@ namespace client if (numAddresses > 0) { if (!incomplete) m_IsLoaded = true; - m_Storage->Save (m_Addresses); + if (m_Storage) m_Storage->Save (m_Addresses); } return !incomplete; } diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 9b2c7e7e1b6..fc4f19a725a 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -99,7 +99,8 @@ namespace client std::string ToAddress(std::shared_ptr ident) { return ToAddress(ident->GetIdentHash ()); } bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified); - + bool IsEnabled () const { return m_IsEnabled; } + private: void StartSubscriptions (); diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 67ee2c5e6d5..30a4e18113e 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -376,7 +376,7 @@ namespace proxy { std::string jump; if (ExtractAddressHelper(m_RequestURL, jump, m_Confirm)) { - if (!m_Addresshelper) + if (!m_Addresshelper || !i2p::client::context.GetAddressBook ().IsEnabled ()) { LogPrint(eLogWarning, "HTTPProxy: Addresshelper request rejected"); GenericProxyError(tr("Invalid request"), tr("Addresshelper is not supported")); From a5e9d9c6a3bc35b0b8128b779cfb8296fb860a0f Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 11 Sep 2024 20:18:05 +0300 Subject: [PATCH 056/131] [gha] winxp build fix --- .github/workflows/build-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 06bc898c3c0..536d16e0ec2 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -205,6 +205,7 @@ jobs: run: | cd MINGW-packages/mingw-w64-openssl gpg --recv-keys D894E2CE8B3D79F5 + gpg --recv-keys 216094DFD0CB81EF MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck - name: Install openssl package run: pacman --noconfirm -U MINGW-packages/mingw-w64-openssl/mingw-w64-i686-*-any.pkg.tar.zst From cb0801fc16b691c516ecac725224c0df66c9a348 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Sep 2024 20:54:22 -0400 Subject: [PATCH 057/131] reduce number of retransmits --- libi2pd/Streaming.cpp | 66 +++++++++++++++++++++++++------------------ libi2pd/Streaming.h | 7 +++-- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index ba71f0acdd9..5cabc36cb84 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -76,7 +76,7 @@ namespace stream m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), + m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), @@ -103,7 +103,7 @@ namespace stream m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), - m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), + m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), @@ -550,27 +550,34 @@ namespace stream { m_RTT = rttSample; m_SlowRTT = rttSample; + m_SlowRTT2 = rttSample; m_PrevRTTSample = rttSample; + m_Jitter = rttSample / 10; // 10% + m_Jitter += 5; // for low-latency connections m_IsFirstRttSample = false; } else - m_RTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_RTT; - // calculate jitter - double jitter = 0; - if (rttSample > m_PrevRTTSample) - jitter = rttSample - m_PrevRTTSample; - else if (rttSample < m_PrevRTTSample) - jitter = m_PrevRTTSample - rttSample; - else - jitter = std::round (rttSample / 10); // 10% - jitter += 1; // for low-latency connections - m_Jitter = (0.025 * jitter) + (1.0 - 0.025) * m_Jitter; + m_RTT = (m_PrevRTTSample + rttSample) / 2; + if (!m_IsWinDropped) + { + m_SlowRTT = SLOWRTT_EWMA_ALPHA * m_RTT + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT; + m_SlowRTT2 = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT2; + // calculate jitter + double jitter = 0; + if (rttSample > m_PrevRTTSample) + jitter = rttSample - m_PrevRTTSample; + else if (rttSample < m_PrevRTTSample) + jitter = m_PrevRTTSample - rttSample; + else + jitter = rttSample / 10; // 10% + jitter += 5; // for low-latency connections + m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter; + } // // delay-based CC - if ((m_RTT > m_SlowRTT + m_Jitter && rttSample > m_RTT && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection + if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection ProcessWindowDrop (); UpdatePacingTime (); - m_SlowRTT = SLOWRTT_EWMA_ALPHA * rttSample + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT; m_PrevRTTSample = rttSample; bool wasInitial = m_RTO == INITIAL_RTO; @@ -579,18 +586,23 @@ namespace stream if (wasInitial) ScheduleResend (); } - if (ackThrough > m_DropWindowDelaySequenceNumber && m_WindowSize <= m_WindowDropTargetSize) + if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber) + { + m_IsFirstRttSample = true; m_IsWinDropped = false; - if (acknowledged && m_IsWinDropped && m_WindowSize > m_WindowDropTargetSize) + } + if (m_WindowDropTargetSize && m_WindowSize <= m_WindowDropTargetSize) { - if (ackCount > 1) - m_WindowSize = m_SentPackets.size () + 1; - else - { - m_WindowSize = m_SentPackets.size (); - m_IsResendNeeded = true; - } + m_WindowDropTargetSize = 0; + m_DropWindowDelaySequenceNumber = m_SequenceNumber; + } + if (acknowledged && m_WindowDropTargetSize && m_WindowSize > m_WindowDropTargetSize) + { + m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.5 + m_Jitter)); // we assume that the next rtt sample may be much larger than the current + m_IsResendNeeded = true; + m_WindowSize = m_SentPackets.size () + 1; // if there are no packets to resend, just send one regular packet if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; + if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE; m_WindowIncCounter = 0; UpdatePacingTime (); } @@ -598,10 +610,10 @@ namespace stream { ScheduleResend (); } - if ((m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss - || int(m_SentPackets.size ()) > m_WindowSize) // or we drop window + if (m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss { m_IsResendNeeded = true; + m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.5 + m_Jitter)); // to prevent spurious retransmit } if (m_SentPackets.empty () && m_SendBuffer.IsEmpty ()) { @@ -1304,7 +1316,7 @@ namespace stream if (m_NumResendAttempts == 1 && m_RTO != INITIAL_RTO) { // loss-based CC - if (!m_IsWinDropped) + if (!m_IsWinDropped && LOSS_BASED_CONTROL_ENABLED) ProcessWindowDrop (); } else if (m_IsTimeOutResend) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 70853d64556..63fe20338f6 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -56,8 +56,8 @@ namespace stream const int INITIAL_WINDOW_SIZE = 10; const int MIN_WINDOW_SIZE = 2; const int MAX_WINDOW_SIZE = 512; - const double RTT_EWMA_ALPHA = 0.25; - const double SLOWRTT_EWMA_ALPHA = 0.125; + const double RTT_EWMA_ALPHA = 0.5; + const double SLOWRTT_EWMA_ALPHA = 0.05; const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const int MIN_RTO = 20; // in milliseconds const int INITIAL_RTT = 8000; // in milliseconds @@ -72,6 +72,7 @@ namespace stream const uint64_t SEND_INTERVAL = 1000; // in microseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds + const bool LOSS_BASED_CONTROL_ENABLED = 1; // 0/1 struct Packet { @@ -282,7 +283,7 @@ namespace stream uint16_t m_Port; SendBufferQueue m_SendBuffer; - double m_RTT, m_SlowRTT; + double m_RTT, m_SlowRTT, m_SlowRTT2; float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; From ebec4d8a5ea6ec425aec38b71707035a5a7d213e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Sep 2024 18:56:23 -0400 Subject: [PATCH 058/131] set default i2cp.leaseSetEncType to 0,4 and to 4 for server tunnels --- libi2pd/Destination.cpp | 14 +++++--------- libi2pd/Destination.h | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9285b05d057..05c4be0059c 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1013,18 +1013,15 @@ namespace client } } // if no param or valid crypto type use from identity - bool isSingleKey = false; if (encryptionKeyTypes.empty ()) - { - isSingleKey = true; - encryptionKeyTypes.insert (GetIdentity ()->GetCryptoKeyType ()); - } + encryptionKeyTypes.insert ( { GetIdentity ()->GetCryptoKeyType (), + i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD }); // usually 0,4 for (auto& it: encryptionKeyTypes) { auto encryptionKey = new EncryptionKey (it); if (IsPublic ()) - PersistTemporaryKeys (encryptionKey, isSingleKey); + PersistTemporaryKeys (encryptionKey); else encryptionKey->GenerateKeys (); encryptionKey->CreateDecryptor (); @@ -1383,12 +1380,11 @@ namespace client return ret; } - void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey) + void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys) { if (!keys) return; std::string ident = GetIdentHash().ToBase32(); - std::string path = i2p::fs::DataDirPath("destinations", - isSingleKey ? (ident + ".dat") : (ident + "." + std::to_string (keys->keyType) + ".dat")); + std::string path = i2p::fs::DataDirPath("destinations", ident + "." + std::to_string (keys->keyType) + ".dat"); std::ifstream f(path, std::ifstream::binary); if (f) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 9dcc64c67eb..1cd004a4059 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -289,7 +289,7 @@ namespace client std::shared_ptr GetSharedFromThis () { return std::static_pointer_cast(shared_from_this ()); } - void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey); + void PersistTemporaryKeys (EncryptionKey * keys); void ReadAuthKey (const std::string& group, const std::map * params); template From d20475e3d0a16028ac6c5fb53615ab33940dd8aa Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Sep 2024 19:11:13 -0400 Subject: [PATCH 059/131] set default i2cp.leaseSetEncType to 0,4 and to 4 for server tunnels --- libi2pd_client/ClientContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 4f91c564e62..b8c4e335a55 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -475,7 +475,7 @@ namespace client options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); - std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "0,4"); + std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "0,4"); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; std::string privKey = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); if (privKey.length () > 0) options[I2CP_PARAM_LEASESET_PRIV_KEY] = privKey; From 17d0e59d02ed2c0880853243e35d624e95ebee18 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Sep 2024 20:30:26 -0400 Subject: [PATCH 060/131] fixed warning --- libi2pd/Streaming.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 5cabc36cb84..29b0406915d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -497,7 +497,6 @@ namespace stream m_IsNAcked = false; m_IsResendNeeded = false; int nackCount = packet->GetNACKCount (); - int ackCount = 0; for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();) { auto seqn = (*it)->GetSeqn (); @@ -536,7 +535,6 @@ namespace stream m_SentPackets.erase (it++); m_LocalDestination.DeletePacket (sentPacket); acknowledged = true; - ackCount++; if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK) if (m_RTT < m_LocalDestination.GetRandom () % INITIAL_RTT) // dirty m_WindowIncCounter++; From d5aca85a35e1dea4771044866b88e0fcb3cd7a7b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Sep 2024 21:03:46 -0400 Subject: [PATCH 061/131] don't try to generate more ECIES-X25519-AEAD-Ratchet tags if decryption failed --- libi2pd/Garlic.cpp | 35 ++--------------------------------- libi2pd/Garlic.h | 1 - 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index fb99ce6d833..1705b03a7f1 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -541,34 +541,7 @@ namespace garlic // otherwise ECIESx25519 auto session = std::make_shared (this, false); // incoming if (!session->HandleNextMessage (buf, length, nullptr, 0)) - { - // try to generate more tags for last tagset - if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS)) - { - uint64_t missingTag; memcpy (&missingTag, buf, 8); - auto maxTags = std::max (m_NumRatchetInboundTags, ECIESX25519_MAX_NUM_GENERATED_TAGS); - LogPrint (eLogWarning, "Garlic: Trying to generate more ECIES-X25519-AEAD-Ratchet tags"); - for (int i = 0; i < maxTags; i++) - { - auto nextTag = AddECIESx25519SessionNextTag (m_LastTagset); - if (!nextTag) - { - LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset"); - break; - } - if (nextTag == missingTag) - { - LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated"); - if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[nextTag].index)) - found = true; - break; - } - } - if (!found) m_LastTagset = nullptr; - } - if (!found) - LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); - } + LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); } else LogPrint (eLogError, "Garlic: Failed to decrypt message"); @@ -583,9 +556,7 @@ namespace garlic auto it = m_ECIESx25519Tags.find (tag); if (it != m_ECIESx25519Tags.end ()) { - if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index)) - m_LastTagset = it->second.tagset; - else + if (!it->second.tagset || !it->second.tagset->HandleNextMessage (buf, len, it->second.index)) LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it); return true; @@ -893,8 +864,6 @@ namespace garlic } if (numExpiredTags > 0) LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ()); - if (m_LastTagset && m_LastTagset->IsExpired (ts)) - m_LastTagset = nullptr; } void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index d1b97ade4a0..a4475dc7e54 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -288,7 +288,6 @@ namespace garlic int m_NumRatchetInboundTags; std::unordered_map, std::hash > > m_Tags; std::unordered_map m_ECIESx25519Tags; // session tag -> session - ReceiveRatchetTagSetPtr m_LastTagset; // tagset last message came for // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session From d4c1a1c0bbe26682415427047657857abc31b0d1 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Sep 2024 13:39:11 -0400 Subject: [PATCH 062/131] cleanup streaming destination's pools --- libi2pd/Streaming.cpp | 7 +++++-- libi2pd/Streaming.h | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 29b0406915d..ca3c431a859 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1526,7 +1526,8 @@ namespace stream StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), - m_PendingIncomingTimer (m_Owner->GetService ()) + m_PendingIncomingTimer (m_Owner->GetService ()), + m_LastCleanupTime (i2p::util::GetSecondsSinceEpoch ()) { } @@ -1715,10 +1716,12 @@ namespace stream m_IncomingStreams.erase (stream->GetSendStreamID ()); if (m_LastStream == stream) m_LastStream = nullptr; } - if (m_Streams.empty ()) + auto ts = i2p::util::GetSecondsSinceEpoch (); + if (m_Streams.empty () || ts > m_LastCleanupTime + STREAMING_DESTINATION_POOLS_CLEANUP_INTERVAL) { m_PacketsPool.CleanUp (); m_I2NPMsgsPool.CleanUp (); + m_LastCleanupTime = ts; } } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 63fe20338f6..4d246453b52 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -73,6 +73,7 @@ namespace stream const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds const bool LOSS_BASED_CONTROL_ENABLED = 1; // 0/1 + const uint64_t STREAMING_DESTINATION_POOLS_CLEANUP_INTERVAL = 646; // in seconds struct Packet { @@ -350,7 +351,8 @@ namespace stream i2p::util::MemoryPool m_PacketsPool; i2p::util::MemoryPool > m_I2NPMsgsPool; - + uint64_t m_LastCleanupTime; // in seconds + public: i2p::data::GzipInflator m_Inflator; From 13b2fc326686372c47113553e93ce7e6511f8375 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Sep 2024 19:09:18 -0400 Subject: [PATCH 063/131] drop window size only when lease changes --- libi2pd/Streaming.cpp | 40 +++++++++++++++++++++++++++------------- libi2pd/Streaming.h | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index ca3c431a859..75dce5fa197 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -835,7 +835,15 @@ namespace stream numPackets = (passedTime + m_PacketACKIntervalRem) / m_PacketACKInterval; m_PacketACKIntervalRem = (passedTime + m_PacketACKIntervalRem) - (numPackets * m_PacketACKInterval); if (m_LastConfirmedReceivedSequenceNumber + numPackets < m_LastReceivedSequenceNumber) + { lastReceivedSeqn = m_LastConfirmedReceivedSequenceNumber + numPackets; + if (!m_IsAckSendScheduled) + { + auto ackTimeout = m_RTT/10; + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; + ScheduleAck (ackTimeout); + } + } if (numPackets == 0) return; // for limit inbound speed if (!m_SavedPackets.empty ()) @@ -1396,6 +1404,7 @@ namespace stream void Stream::UpdateCurrentRemoteLease (bool expired) { + bool isLeaseChanged = true; if (!m_RemoteLeaseSet || m_RemoteLeaseSet->IsExpired ()) { auto remoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); @@ -1451,7 +1460,7 @@ namespace stream break; } } - if (!updated) + if (!updated && leases.size () > 1) { uint32_t i = m_LocalDestination.GetRandom () % leases.size (); if (m_CurrentRemoteLease && leases[i]->tunnelID == m_CurrentRemoteLease->tunnelID) @@ -1459,6 +1468,8 @@ namespace stream i = (i + 1) % leases.size (); // if so, pick next m_CurrentRemoteLease = leases[i]; } + else + isLeaseChanged = false; } else { @@ -1473,20 +1484,23 @@ namespace stream LogPrint (eLogWarning, "Streaming: Remote LeaseSet not found"); m_CurrentRemoteLease = nullptr; } - // drop window to initial upon RemoteLease change - m_RTO = INITIAL_RTO; - if (m_WindowSize > INITIAL_WINDOW_SIZE) + if (isLeaseChanged) { - m_WindowDropTargetSize = std::max (m_WindowSize/2, (float)INITIAL_WINDOW_SIZE); - m_IsWinDropped = true; + // drop window to initial upon RemoteLease change + m_RTO = INITIAL_RTO; + if (m_WindowSize > INITIAL_WINDOW_SIZE) + { + m_WindowDropTargetSize = std::max (m_WindowSize/2, (float)INITIAL_WINDOW_SIZE); + m_IsWinDropped = true; + } + else + m_WindowSize = INITIAL_WINDOW_SIZE; + m_LastWindowDropSize = 0; + m_WindowIncCounter = 0; + m_IsFirstRttSample = true; + m_IsFirstACK = true; + UpdatePacingTime (); } - else - m_WindowSize = INITIAL_WINDOW_SIZE; - m_LastWindowDropSize = 0; - m_WindowIncCounter = 0; - m_IsFirstRttSample = true; - m_IsFirstACK = true; - UpdatePacingTime (); } void Stream::ResetRoutingPath () diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 4d246453b52..9ac84990e23 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -56,7 +56,7 @@ namespace stream const int INITIAL_WINDOW_SIZE = 10; const int MIN_WINDOW_SIZE = 2; const int MAX_WINDOW_SIZE = 512; - const double RTT_EWMA_ALPHA = 0.5; + const double RTT_EWMA_ALPHA = 0.25; const double SLOWRTT_EWMA_ALPHA = 0.05; const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const int MIN_RTO = 20; // in milliseconds From ca4db7aab21057aab8d3fd2e023420c9d4809bb2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Sep 2024 20:56:00 -0400 Subject: [PATCH 064/131] handle siuatuion if only one lease in remote LeaseSet --- libi2pd/Streaming.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 75dce5fa197..08347623f1e 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1460,16 +1460,19 @@ namespace stream break; } } - if (!updated && leases.size () > 1) + if (!updated) { uint32_t i = m_LocalDestination.GetRandom () % leases.size (); if (m_CurrentRemoteLease && leases[i]->tunnelID == m_CurrentRemoteLease->tunnelID) + { // make sure we don't select previous - i = (i + 1) % leases.size (); // if so, pick next + if (leases.size () > 1) + i = (i + 1) % leases.size (); // if so, pick next + else + isLeaseChanged = false; + } m_CurrentRemoteLease = leases[i]; } - else - isLeaseChanged = false; } else { From f20391d4600d41279e2b473470d98239ce7e52f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Sep 2024 21:49:23 -0400 Subject: [PATCH 065/131] check if we connected recently to an endpoint before sending peer test --- libi2pd/SSU2.cpp | 24 ++++++++++++++++++++++++ libi2pd/SSU2.h | 8 ++++++-- libi2pd/SSU2Session.cpp | 28 +++++++++++++++------------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index b86e3743350..ebaeb741bc9 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -210,6 +210,22 @@ namespace transport return ep.port (); } + bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const + { + if (!ep.port () || ep.address ().is_unspecified ()) return false; + auto it = m_ConnectedRecently.find (ep); + if (it != m_ConnectedRecently.end ()) + return i2p::util::GetSecondsSinceEpoch () <= it->second + SSU2_HOLE_PUNCH_EXPIRATION; + return false; + } + + void SSU2Server::AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts) + { + if (!ep.port () || ep.address ().is_unspecified () || + i2p::util::GetSecondsSinceEpoch () > ts + SSU2_HOLE_PUNCH_EXPIRATION) return; + m_ConnectedRecently.try_emplace (ep, ts); + } + void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr from) { if (offset) @@ -1001,6 +1017,14 @@ namespace transport it++; } + for (auto it = m_ConnectedRecently.begin (); it != m_ConnectedRecently.end (); ) + { + if (ts > it->second + SSU2_HOLE_PUNCH_EXPIRATION) + it = m_ConnectedRecently.erase (it); + else + it++; + } + m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); m_IncompleteMessagesPool.CleanUp (); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index fd071e8d61c..023f072eecb 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -39,6 +39,7 @@ namespace transport const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds + const int SSU2_HOLE_PUNCH_EXPIRATION = 20; // in seconds class SSU2Server: private i2p::util::RunnableServiceWithWork { @@ -72,6 +73,8 @@ namespace transport bool UsesProxy () const { return m_IsThroughProxy; }; bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; + bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const; + void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts); std::mt19937& GetRng () { return m_Rng; } bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; } bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; @@ -160,7 +163,7 @@ namespace transport std::map > m_PendingOutgoingSessions; mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) - std::map > m_Relays; // we are introducer, relay tag -> session + std::unordered_map > m_Relays; // we are introducer, relay tag -> session std::list m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPool m_SentPacketsPool; @@ -174,7 +177,8 @@ namespace transport int64_t m_PendingTimeOffset; // during peer test std::shared_ptr m_PendingTimeOffsetFrom; std::mt19937 m_Rng; - + std::map m_ConnectedRecently; // endpoint -> last activity time in seconds + // proxy bool m_IsThroughProxy; uint8_t m_UDPRequestHeader[SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE]; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index eb662716d7f..d98b06c3855 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -265,6 +265,7 @@ namespace transport m_OnEstablished = nullptr; if (m_RelayTag) m_Server.RemoveRelay (m_RelayTag); + m_Server.AddConnectedRecently (m_RemoteEndpoint, GetLastActivityTimestamp ()); m_SentHandshakePacket.reset (nullptr); m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); @@ -281,14 +282,10 @@ namespace transport transports.PeerDisconnected (shared_from_this ()); auto remoteIdentity = GetRemoteIdentity (); if (remoteIdentity) - { LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); - } else - { LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated"); - } } } @@ -1153,7 +1150,7 @@ namespace transport if (profile) // older router? profile->Duplicated (); // mark router as duplicated in profile else - LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, + LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host, " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } @@ -2276,14 +2273,19 @@ namespace transport if (addr && m_Server.IsSupported (ep.address ()) && i2p::context.GetRouterInfo ().IsSSU2PeerTesting (ep.address ().is_v4 ())) { - // send msg 5 to Alice - auto session = std::make_shared (m_Server, r, addr); - session->SetState (eSSU2SessionStatePeerTest); - session->m_RemoteEndpoint = ep; // might be different - session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); - session->m_SourceConnID = ~session->m_DestConnID; - m_Server.AddSession (session); - session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); + if (!m_Server.IsConnectedRecently (ep)) // no alive hole punch + { + // send msg 5 to Alice + auto session = std::make_shared (m_Server, r, addr); + session->SetState (eSSU2SessionStatePeerTest); + session->m_RemoteEndpoint = ep; // might be different + session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); + session->m_SourceConnID = ~session->m_DestConnID; + m_Server.AddSession (session); + session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); + } + else + code = eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected; } else code = eSSU2PeerTestCodeCharlieUnsupportedAddress; From a723405fb095d063b87a3889bad65f04c9b1b703 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 08:38:29 -0400 Subject: [PATCH 066/131] check max RouterInfo size --- libi2pd/NTCP2.cpp | 21 +++++++++++++-------- libi2pd/SSU2Session.cpp | 6 ++++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a33d4fef667..728ac01d8f5 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,7 +695,7 @@ namespace transport return; } auto size = bufbe16toh (buf.data () + 1); - if (size > buf.size () - 3) + if (size > buf.size () - 3 || size > i2p::data::MAX_RI_BUFFER_SIZE + 1) { LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed"); Terminate (); @@ -960,14 +960,19 @@ namespace transport case eNTCP2BlkRouterInfo: { LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - auto newRi = i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1); - if (newRi) - { - auto remoteIdentity = GetRemoteIdentity (); - if (remoteIdentity && remoteIdentity->GetIdentHash () == newRi->GetIdentHash ()) - // peer's RouterInfo update - SetRemoteIdentity (newRi->GetIdentity ()); + if (size <= i2p::data::MAX_RI_BUFFER_SIZE + 1) + { + auto newRi = i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1); + if (newRi) + { + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity && remoteIdentity->GetIdentHash () == newRi->GetIdentHash ()) + // peer's RouterInfo update + SetRemoteIdentity (newRi->GetIdentity ()); + } } + else + LogPrint (eLogInfo, "NTCP2: RouterInfo block is too long ", size); break; } case eNTCP2BlkI2NPMessage: diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index d98b06c3855..192a2db2019 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2937,13 +2937,15 @@ namespace transport i2p::data::GzipInflator inflator; uint8_t uncompressed[i2p::data::MAX_RI_BUFFER_SIZE]; size_t uncompressedSize = inflator.Inflate (buf + 2, size - 2, uncompressed, i2p::data::MAX_RI_BUFFER_SIZE); - if (uncompressedSize && uncompressedSize < i2p::data::MAX_RI_BUFFER_SIZE) + if (uncompressedSize && uncompressedSize <= i2p::data::MAX_RI_BUFFER_SIZE) ri = std::make_shared(uncompressed, uncompressedSize); else LogPrint (eLogInfo, "SSU2: RouterInfo decompression failed ", uncompressedSize); } - else + else if (size <= i2p::data::MAX_RI_BUFFER_SIZE + 2) ri = std::make_shared(buf + 2, size - 2); + else + LogPrint (eLogInfo, "SSU2: RouterInfo is too long ", size); return ri; } From ae267581707db1f51096dac2e393b4e44497492f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 08:40:22 -0400 Subject: [PATCH 067/131] allocate RouterInfo's buffer from pool --- libi2pd/RouterInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index b6abb48a61e..ce1ae72c5dd 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -49,7 +49,7 @@ namespace data m_Caps (0), m_Version (0), m_Congestion (eLowCongestion) { m_Addresses = AddressesPtr(new Addresses ()); // create empty list - m_Buffer = NewBuffer (); // always RouterInfo's + m_Buffer = RouterInfo::NewBuffer (); // always RouterInfo's ReadFromFile (fullPath); } @@ -74,7 +74,7 @@ namespace data } RouterInfo::RouterInfo (const uint8_t * buf, size_t len): - RouterInfo (std::make_shared (buf, len), len) + RouterInfo (netdb.NewRouterInfoBuffer (buf, len), len) { } From 2fa4237acd2d2432294aeb4d6b2db77fa908c5f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 14:35:59 -0400 Subject: [PATCH 068/131] renew connected receintly timestamp, add endpoint to the list if hole punch is being sent --- libi2pd/SSU2.cpp | 13 ++++++++++--- libi2pd/SSU2.h | 4 ++-- libi2pd/SSU2Session.cpp | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index ebaeb741bc9..94fc2dc3841 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -210,12 +210,17 @@ namespace transport return ep.port (); } - bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const + bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) { if (!ep.port () || ep.address ().is_unspecified ()) return false; auto it = m_ConnectedRecently.find (ep); if (it != m_ConnectedRecently.end ()) - return i2p::util::GetSecondsSinceEpoch () <= it->second + SSU2_HOLE_PUNCH_EXPIRATION; + { + if (i2p::util::GetSecondsSinceEpoch () <= it->second + SSU2_HOLE_PUNCH_EXPIRATION) + return true; + else + m_ConnectedRecently.erase (it); + } return false; } @@ -223,7 +228,9 @@ namespace transport { if (!ep.port () || ep.address ().is_unspecified () || i2p::util::GetSecondsSinceEpoch () > ts + SSU2_HOLE_PUNCH_EXPIRATION) return; - m_ConnectedRecently.try_emplace (ep, ts); + auto [it, added] = m_ConnectedRecently.try_emplace (ep, ts); + if (!added && ts > it->second) + it->second = ts; // renew timestamp of existing endpoint } void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr from) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 023f072eecb..a650425ef05 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -39,7 +39,7 @@ namespace transport const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds - const int SSU2_HOLE_PUNCH_EXPIRATION = 20; // in seconds + const int SSU2_HOLE_PUNCH_EXPIRATION = 150; // in seconds class SSU2Server: private i2p::util::RunnableServiceWithWork { @@ -73,7 +73,7 @@ namespace transport bool UsesProxy () const { return m_IsThroughProxy; }; bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; - bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const; + bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep); void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts); std::mt19937& GetRng () { return m_Rng; } bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 192a2db2019..98b6c6f602f 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2054,6 +2054,7 @@ namespace transport token = m_Server.GetIncomingToken (ep); isV4 = ep.address ().is_v4 (); SendHolePunch (bufbe32toh (buf + 33), ep, addr->i, token); + m_Server.AddConnectedRecently (ep, i2p::util::GetSecondsSinceEpoch ()); } else { From ac1c28cb39a3509d2f5e55b0e55aa8657b2d0487 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 15:19:18 -0400 Subject: [PATCH 069/131] don't send ack in case of lost packet and incoming speed limitation --- libi2pd/Streaming.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 08347623f1e..c30c5d39de1 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -829,6 +829,7 @@ namespace stream // for limit inbound speed auto ts = i2p::util::GetMillisecondsSinceEpoch (); int numPackets = 0; + bool lostPackets = false; int64_t passedTime = m_PacketACKInterval * INITIAL_WINDOW_SIZE; // in microseconds // while m_LastACKSendTime == 0 if (m_LastACKSendTime) passedTime = (ts - m_LastACKSendTime)*1000; // in microseconds @@ -851,8 +852,26 @@ namespace stream for (auto it: m_SavedPackets) { auto seqn = it->GetSeqn (); - if (m_LastConfirmedReceivedSequenceNumber + numPackets < int(seqn)) break; // for limit inbound speed - if ((int)seqn > lastReceivedSeqn) lastReceivedSeqn = seqn; + // for limit inbound speed + if (m_LastConfirmedReceivedSequenceNumber + numPackets < int(seqn)) + { + if (!m_IsAckSendScheduled) + { + auto ackTimeout = m_RTT/10; + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; + ScheduleAck (ackTimeout); + } + if (lostPackets) + break; + else + return; + } + // for limit inbound speed + if ((int)seqn > lastReceivedSeqn) + { + lastReceivedSeqn = seqn; + lostPackets = true; // for limit inbound speed + } } } if (lastReceivedSeqn < 0) From db19c323819d8065dabd3a96d2192cead02710e1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 15:42:30 -0400 Subject: [PATCH 070/131] require minimal boost 1.83 for c++20 --- build/CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 19c51dfdd45..415a45da224 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -125,6 +125,11 @@ if(WIN32) endif() +find_package(Boost REQUIRED COMPONENTS system filesystem program_options) +if(NOT DEFINED Boost_FOUND) + message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") +endif() + if(WITH_UPNP) add_definitions(-DUSE_UPNP) endif() @@ -157,10 +162,12 @@ else() set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above - # check for с++20 & c++17 support + # check for c++20 & c++17 support include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) + if(Boost_VERSION VERSION_GREATER_EQUAL "1.83") # min boost version for c++20 + CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) + endif() CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) @@ -285,11 +292,6 @@ else() endif() endif() -find_package(Boost REQUIRED COMPONENTS system filesystem program_options OPTIONAL_COMPONENTS atomic) -if(NOT DEFINED Boost_FOUND) - message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") -endif() - find_package(OpenSSL REQUIRED) if(NOT DEFINED OPENSSL_FOUND) message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!") From 7ef1fdf6340ec252969e332874205b5b336956d1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Sep 2024 18:48:18 -0400 Subject: [PATCH 071/131] exclude false position OK peer test if comes from recently connected endpoint --- libi2pd/SSU2Session.cpp | 10 ++++++---- libi2pd/SSU2Session.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 98b6c6f602f..789b42e49ba 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2365,10 +2365,11 @@ namespace transport if (addr) { it->second.first->m_Address = addr; - if (it->second.first->m_State == eSSU2SessionStatePeerTestReceived) + auto state = it->second.first->m_State; + if (state == eSSU2SessionStatePeerTestReceived || state == eSSU2SessionStateVoidPeerTestReceived) { // msg 5 already received. send msg 6 - SetRouterStatus (eRouterStatusOK); + SetRouterStatus (state == eSSU2SessionStatePeerTestReceived ? eRouterStatusOK : eRouterStatusUnknown); it->second.first->m_State = eSSU2SessionStatePeerTest; it->second.first->SendPeerTest (6, buf + offset, len - offset, addr->i); } @@ -2426,14 +2427,15 @@ namespace transport case 5: // Alice from Charlie 1 if (htobe64 (((uint64_t)nonce << 32) | nonce) == m_SourceConnID) { + bool isConnectedRecently = m_Server.IsConnectedRecently (m_RemoteEndpoint); if (m_Address) { - SetRouterStatus (eRouterStatusOK); + SetRouterStatus (isConnectedRecently ? eRouterStatusUnknown : eRouterStatusOK); SendPeerTest (6, buf + offset, len - offset, m_Address->i); } else // we received msg 5 before msg 4 - m_State = eSSU2SessionStatePeerTestReceived; + m_State = isConnectedRecently ? eSSU2SessionStateVoidPeerTestReceived : eSSU2SessionStatePeerTestReceived; } else LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce, " connID=", m_SourceConnID); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index cd6793d3cdd..eaeda949460 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -114,6 +114,7 @@ namespace transport eSSU2SessionStateIntroduced, eSSU2SessionStatePeerTest, eSSU2SessionStatePeerTestReceived, // 5 before 4 + eSSU2SessionStateVoidPeerTestReceived, // 5 before 4, but from connected recently eSSU2SessionStateTokenRequestReceived }; From 715e063550f3e07751ae404d9b4a0243fe9431c0 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Sep 2024 08:02:37 -0400 Subject: [PATCH 072/131] set boost flags before finding --- build/CMakeLists.txt | 48 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 415a45da224..534f87468fa 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -125,11 +125,6 @@ if(WIN32) endif() -find_package(Boost REQUIRED COMPONENTS system filesystem program_options) -if(NOT DEFINED Boost_FOUND) - message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") -endif() - if(WITH_UPNP) add_definitions(-DUSE_UPNP) endif() @@ -161,23 +156,6 @@ else() endif() set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above - - # check for c++20 & c++17 support - include(CheckCXXCompilerFlag) - - if(Boost_VERSION VERSION_GREATER_EQUAL "1.83") # min boost version for c++20 - CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) - endif() - CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) - - - if(CXX20_SUPPORTED) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") - elseif(CXX17_SUPPORTED) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - else() - message(SEND_ERROR "C++20 nor C++17 standard not seems to be supported by compiler. Too old version?") - endif() endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") @@ -292,6 +270,11 @@ else() endif() endif() +find_package(Boost REQUIRED COMPONENTS system filesystem program_options) +if(NOT DEFINED Boost_FOUND) + message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") +endif() + find_package(OpenSSL REQUIRED) if(NOT DEFINED OPENSSL_FOUND) message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!") @@ -315,6 +298,26 @@ if(ZLIB_FOUND) link_directories(${ZLIB_ROOT}/lib) endif() +# C++ standard to use, based on compiler and version of boost +if(NOT MSVC) +# check for c++20 & c++17 support + include(CheckCXXCompilerFlag) + + if(Boost_VERSION VERSION_GREATER_EQUAL "1.83") # min boost version for c++20 + CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) + endif() + CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) + + + if(CXX20_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") + elseif(CXX17_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + else() + message(SEND_ERROR "C++20 nor C++17 standard not seems to be supported by compiler. Too old version?") + endif() +endif() + # load includes include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) @@ -325,6 +328,7 @@ message(STATUS "Compiler vendor : ${CMAKE_CXX_COMPILER_ID}") message(STATUS "Compiler version : ${CMAKE_CXX_COMPILER_VERSION}") message(STATUS "Compiler path : ${CMAKE_CXX_COMPILER}") message(STATUS "Architecture : ${ARCHITECTURE}") +message(STATUS "Compiler flags : ${CMAKE_CXX_FLAGS}") message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}") message(STATUS "Options:") message(STATUS " AESNI : ${WITH_AESNI}") From 5324197e4360b4fc462a466da0ed22aba5dc47cc Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Sep 2024 15:27:04 -0400 Subject: [PATCH 073/131] don't change router status if peer test came from recent endpoint --- libi2pd/SSU2Session.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 789b42e49ba..9c4345dcead 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2365,12 +2365,13 @@ namespace transport if (addr) { it->second.first->m_Address = addr; - auto state = it->second.first->m_State; + auto& state = it->second.first->m_State; if (state == eSSU2SessionStatePeerTestReceived || state == eSSU2SessionStateVoidPeerTestReceived) { // msg 5 already received. send msg 6 - SetRouterStatus (state == eSSU2SessionStatePeerTestReceived ? eRouterStatusOK : eRouterStatusUnknown); - it->second.first->m_State = eSSU2SessionStatePeerTest; + if (state == eSSU2SessionStatePeerTestReceived) + SetRouterStatus (eRouterStatusOK); + state = eSSU2SessionStatePeerTest; it->second.first->SendPeerTest (6, buf + offset, len - offset, addr->i); } else @@ -2430,7 +2431,8 @@ namespace transport bool isConnectedRecently = m_Server.IsConnectedRecently (m_RemoteEndpoint); if (m_Address) { - SetRouterStatus (isConnectedRecently ? eRouterStatusUnknown : eRouterStatusOK); + if (!isConnectedRecently) + SetRouterStatus (eRouterStatusOK); SendPeerTest (6, buf + offset, len - offset, m_Address->i); } else From 9f30499984d8f854024fe751fadc284af8f74cec Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Sep 2024 21:16:16 -0400 Subject: [PATCH 074/131] implement i2p.streaming.profile to specify high or low bandwidth tunnel pools --- libi2pd/Destination.cpp | 8 ++++++-- libi2pd/Destination.h | 4 ++++ libi2pd/NetDb.cpp | 11 +++++++---- libi2pd/NetDb.hpp | 2 +- libi2pd/Tunnel.cpp | 14 ++++++++------ libi2pd/Tunnel.h | 5 +++-- libi2pd/TunnelPool.cpp | 18 ++++++++++-------- libi2pd/TunnelPool.h | 4 ++-- libi2pd_client/ClientContext.cpp | 3 +++ 9 files changed, 44 insertions(+), 25 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 05c4be0059c..28b23950570 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -37,6 +37,7 @@ namespace client int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE; int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE; int numTags = DEFAULT_TAGS_TO_SEND; + bool isHighBandwidth = true; std::shared_ptr > explicitPeers; try { @@ -92,7 +93,7 @@ namespace client it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET); if (it != params->end ()) { - // oveeride isPublic + // override isPublic m_IsPublic = (it->second != "true"); } it = params->find (I2CP_PARAM_LEASESET_TYPE); @@ -121,6 +122,9 @@ namespace client m_LeaseSetPrivKey.reset (nullptr); } } + it = params->find (I2CP_PARAM_STREAMING_PROFILE); + if (it != params->end ()) + isHighBandwidth = std::stoi (it->second) != STREAMING_PROFILE_INTERACTIVE; } } catch (std::exception & ex) @@ -128,7 +132,7 @@ namespace client LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); } SetNumTags (numTags); - m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar, isHighBandwidth); if (explicitPeers) m_Pool->SetExplicitPeers (explicitPeers); if(params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 1cd004a4059..4a51a257cc4 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -90,6 +90,10 @@ namespace client const int DEFAULT_MAX_INBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings"; const int DEFAULT_ANSWER_PINGS = true; + const char I2CP_PARAM_STREAMING_PROFILE[] = "i2p.streaming.profile"; + const int STREAMING_PROFILE_BULK = 1; // high bandwidth + const int STREAMING_PROFILE_INTERACTIVE = 2; // low bandwidth + const int DEFAULT_STREAMING_PROFILE = STREAMING_PROFILE_BULK; typedef std::function stream)> StreamRequestComplete; diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 55e17b234f3..f6067ce37cc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -69,7 +69,7 @@ namespace data { Reseed (); } - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false)) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false, false)) Reseed (); // we don't have a router we can connect to. Trying to reseed auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); @@ -1130,15 +1130,18 @@ namespace data } std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, - bool reverse, bool endpoint) const + bool reverse, bool endpoint, bool clientTunnel) const { + bool checkIsReal = clientTunnel && i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD && // too low rate + context.GetUptime () > NETDB_CHECK_FOR_EXPIRATION_UPTIME; // after 10 minutes uptime return GetRandomRouter ( - [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint, clientTunnel, checkIsReal](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && !router->IsNAT2NATOnly (*compatibleWith) && - router->IsECIES () && !router->IsHighCongestion (false) && + router->IsECIES () && !router->IsHighCongestion (clientTunnel) && + (!checkIsReal || router->GetProfile ()->IsReal ()) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 1797c04d153..b84387de161 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -87,7 +87,7 @@ namespace data void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; + std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint, bool clientTunnel) const; std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::unordered_set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::unordered_set& excluded) const; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 55c4d38cb19..1b63b7a7cad 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -411,10 +411,12 @@ namespace tunnel return tunnel; } - std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, - int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance) + std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, + int numOutboundHops, int numInboundTunnels, int numOutboundTunnels, + int inboundVariance, int outboundVariance, bool isHighBandwidth) { - auto pool = std::make_shared (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance); + auto pool = std::make_shared (numInboundHops, numOutboundHops, + numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance, isHighBandwidth); std::unique_lock l(m_PoolsMutex); m_Pools.push_back (pool); return pool; @@ -705,7 +707,7 @@ namespace tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true, false); // reachable by us if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); CreateTunnel ( @@ -765,7 +767,7 @@ namespace tunnel int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen); int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum); int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum); - m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0); + m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0, false); m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ()); } return; @@ -777,7 +779,7 @@ namespace tunnel auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : // should be reachable by us because we send build request directly - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true, false); if (!router) { LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); return; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index d3de272d19e..6b014af2b67 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -232,8 +232,9 @@ namespace tunnel void PostTunnelData (const std::vector >& msgs); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); - std::shared_ptr CreateTunnelPool (int numInboundHops, int numOuboundHops, - int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance); + std::shared_ptr CreateTunnelPool (int numInboundHops, + int numOuboundHops, int numInboundTunnels, int numOutboundTunnels, + int inboundVariance, int outboundVariance, bool isHighBandwidth); void DeleteTunnelPool (std::shared_ptr pool); void StopTunnelPool (std::shared_ptr pool); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 0a855350cdb..e17932f96fd 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -41,11 +41,11 @@ namespace tunnel } TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, - int numOutboundTunnels, int inboundVariance, int outboundVariance): + int numOutboundTunnels, int inboundVariance, int outboundVariance, bool isHighBandwidth): m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance), - m_IsActive (true), m_CustomPeerSelector(nullptr), + m_IsActive (true), m_IsHighBandwidth (isHighBandwidth), m_CustomPeerSelector(nullptr), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL) { if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) @@ -549,20 +549,22 @@ namespace tunnel std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const { - bool tryHighBandwidth = !IsExploratory (); + bool tryClient = !IsExploratory (); std::shared_ptr hop; for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) { - hop = tryHighBandwidth ? - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : - i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + hop = tryClient ? + (m_IsHighBandwidth ? + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, true)): + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false); if (hop) { if (!hop->GetProfile ()->IsBad ()) break; } - else if (tryHighBandwidth) - tryHighBandwidth = false; + else if (tryClient) + tryClient = false; else return nullptr; } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index c19114e2221..0ebfd1ac54b 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -62,7 +62,7 @@ namespace tunnel public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, - int numOutboundTunnels, int inboundVariance, int outboundVariance); + int numOutboundTunnels, int inboundVariance, int outboundVariance, bool isHighBandwidth); ~TunnelPool (); std::shared_ptr GetLocalDestination () const { return m_LocalDestination; }; @@ -146,7 +146,7 @@ namespace tunnel std::set, TunnelCreationTimeCmp> m_OutboundTunnels; mutable std::mutex m_TestsMutex; std::map, std::shared_ptr > > m_Tests; - bool m_IsActive; + bool m_IsActive, m_IsHighBandwidth; uint64_t m_NextManageTime; // in seconds std::mutex m_CustomPeerSelectorMutex; ITunnelPeerSelector * m_CustomPeerSelector; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b8c4e335a55..8cb4b67bc34 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -474,6 +474,7 @@ namespace client options[I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED); options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); + options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "0,4"); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; @@ -519,6 +520,8 @@ namespace client options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_PRIV_KEY, value) && !value.empty ()) options[I2CP_PARAM_LEASESET_PRIV_KEY] = value; + if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_PROFILE, value)) + options[I2CP_PARAM_STREAMING_PROFILE] = value; } void ClientContext::ReadTunnels () From e4962b855f14d1f0baa7a017fbd422c9ef9ca7e7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 20 Sep 2024 10:34:55 -0400 Subject: [PATCH 075/131] pick first hop based on pool's bandwidth requirements --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index e17932f96fd..5ac85d59137 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -587,7 +587,7 @@ namespace tunnel else if (i2p::transport::transports.GetNumPeers () > 100 || (inbound && i2p::transport::transports.GetNumPeers () > 25)) { - auto r = i2p::transport::transports.GetRandomPeer (!IsExploratory ()); + auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4 { From c8958d71a227d26a2736281790b03fe20627ce7f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Sep 2024 12:59:11 -0400 Subject: [PATCH 076/131] pick routers with any bandwidth if limited connectivity --- libi2pd/TunnelPool.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5ac85d59137..5af423736cb 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -549,12 +549,12 @@ namespace tunnel std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const { - bool tryClient = !IsExploratory (); + bool tryClient = !IsExploratory () && !i2p::context.IsLimitedConnectivity (); std::shared_ptr hop; for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) { hop = tryClient ? - (m_IsHighBandwidth ? + (m_IsHighBandwidth ? i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, true)): i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false); @@ -587,7 +587,7 @@ namespace tunnel else if (i2p::transport::transports.GetNumPeers () > 100 || (inbound && i2p::transport::transports.GetNumPeers () > 25)) { - auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth); + auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4 { From fd2b15fe81a94d36e2019a08c7f52106fa925cb1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Sep 2024 17:58:14 -0400 Subject: [PATCH 077/131] don't drop too old router if low uptime --- libi2pd/NetDb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f6067ce37cc..24269015b89 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -295,7 +295,8 @@ namespace data { auto mts = i2p::util::GetMillisecondsSinceEpoch (); isValid = mts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp () && // from future - mts < r->GetTimestamp () + NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; // too old + (mts < r->GetTimestamp () + NETDB_MAX_EXPIRATION_TIMEOUT*1000LL || // too old + context.GetUptime () < NETDB_CHECK_FOR_EXPIRATION_UPTIME/10); // enough uptime } if (isValid) { From f733f0a63625ad5a234b7d3038f47aaaebf5116f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Sep 2024 19:04:03 -0400 Subject: [PATCH 078/131] added i2p.streaming.maxOutboundSpeed, i2p.streaming.maxInboundSpeed and i2p.streaming.profile to HTTP and SOCKS proxy configs --- libi2pd/Config.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index a3fe63c7da5..d644023c2d9 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -120,6 +120,10 @@ namespace config { ("httpproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("httpproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") + ("httpproxy.i2p.streaming.maxOutboundSpeed", value()->default_value(1730000000), "Max outbound speed of HTTP proxy stream in bytes/sec") + ("httpproxy.i2p.streaming.maxInboundSpeed", value()->default_value(1730000000), "Max inbound speed of HTTP proxy stream in bytes/sec") + ("httpproxy.i2p.streaming.profile", value()->default_value(1), "HTTP Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") + ; options_description socksproxy("SOCKS Proxy options"); @@ -144,6 +148,9 @@ namespace config { ("socksproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") ("socksproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("socksproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") + ("socksproxy.i2p.streaming.maxOutboundSpeed", value()->default_value(1730000000), "Max outbound speed of SOCKS proxy stream in bytes/sec") + ("socksproxy.i2p.streaming.maxInboundSpeed", value()->default_value(1730000000), "Max inbound speed of SOCKS proxy stream in bytes/sec") + ("socksproxy.i2p.streaming.profile", value()->default_value(1), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") ; options_description sam("SAM bridge options"); From 018fa0ec00b1c79adc270b8b8ceb236d66dd1608 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Sep 2024 19:48:45 -0400 Subject: [PATCH 079/131] added i2p.streaming.maxOutboundSpeed, i2p.streaming.maxInboundSpeed and i2p.streaming.profile to HTTP and SOCKS proxy configs --- libi2pd/Config.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index d644023c2d9..4efcb16e13f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -120,9 +120,9 @@ namespace config { ("httpproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("httpproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") - ("httpproxy.i2p.streaming.maxOutboundSpeed", value()->default_value(1730000000), "Max outbound speed of HTTP proxy stream in bytes/sec") - ("httpproxy.i2p.streaming.maxInboundSpeed", value()->default_value(1730000000), "Max inbound speed of HTTP proxy stream in bytes/sec") - ("httpproxy.i2p.streaming.profile", value()->default_value(1), "HTTP Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") + ("httpproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of HTTP proxy stream in bytes/sec") + ("httpproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of HTTP proxy stream in bytes/sec") + ("httpproxy.i2p.streaming.profile", value()->default_value("1"), "HTTP Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") ; @@ -148,9 +148,9 @@ namespace config { ("socksproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") ("socksproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("socksproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") - ("socksproxy.i2p.streaming.maxOutboundSpeed", value()->default_value(1730000000), "Max outbound speed of SOCKS proxy stream in bytes/sec") - ("socksproxy.i2p.streaming.maxInboundSpeed", value()->default_value(1730000000), "Max inbound speed of SOCKS proxy stream in bytes/sec") - ("socksproxy.i2p.streaming.profile", value()->default_value(1), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") + ("socksproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of SOCKS proxy stream in bytes/sec") + ("socksproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of SOCKS proxy stream in bytes/sec") + ("socksproxy.i2p.streaming.profile", value()->default_value("1"), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") ; options_description sam("SAM bridge options"); From 9d1e5268125f91b20a6a741be1fc8cbf024f3d0b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Sep 2024 17:22:08 -0400 Subject: [PATCH 080/131] separate SSU2PeerTestSession for peer tests msgs 5,6 and 7 --- libi2pd/SSU2Session.cpp | 107 ++++++++++++++++++++++------------------ libi2pd/SSU2Session.h | 79 ++++++++++++++++++----------- 2 files changed, 111 insertions(+), 75 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9c4345dcead..53ed899a00e 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -18,6 +18,12 @@ namespace i2p { namespace transport { + static inline void CreateNonce (uint64_t seqn, uint8_t * nonce) + { + memset (nonce, 0, 4); + htole64buf (nonce + 4, seqn); + } + void SSU2IncompleteMessage::AttachNextFragment (const uint8_t * fragment, size_t fragmentSize) { if (msg->len + fragmentSize > msg->maxLen) @@ -227,11 +233,9 @@ namespace transport RAND_bytes ((uint8_t *)&nonce, 4); auto ts = i2p::util::GetMillisecondsSinceEpoch (); // session for message 5 - auto session = std::make_shared (m_Server); - session->SetState (eSSU2SessionStatePeerTest); + auto session = std::make_shared (m_Server, + htobe64 (((uint64_t)nonce << 32) | nonce), 0, shared_from_this ()); m_PeerTests.emplace (nonce, std::make_pair (session, ts/1000)); - session->m_SourceConnID = htobe64 (((uint64_t)nonce << 32) | nonce); - session->m_DestConnID = ~session->m_SourceConnID; m_Server.AddSession (session); // peer test block auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); @@ -1456,39 +1460,8 @@ namespace transport bool SSU2Session::ProcessPeerTest (uint8_t * buf, size_t len) { - // we are Alice or Charlie - Header header; - memcpy (header.buf, buf, 16); - header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 24)); - header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 12)); - if (header.h.type != eSSU2PeerTest) - { - LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type, " instead ", (int)eSSU2PeerTest); - return false; - } - if (len < 48) - { - LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len); - return false; - } - uint8_t nonce[12] = {0}; - uint64_t headerX[2]; // sourceConnID, token - i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); - m_DestConnID = headerX[0]; - // decrypt and handle payload - uint8_t * payload = buf + 32; - CreateNonce (be32toh (header.h.packetNum), nonce); - uint8_t h[32]; - memcpy (h, header.buf, 16); - memcpy (h + 16, &headerX, 16); - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 48, h, 32, - i2p::context.GetSSU2IntroKey (), nonce, payload, len - 48, false)) - { - LogPrint (eLogWarning, "SSU2: PeerTest AEAD verification failed "); - return false; - } - HandlePayload (payload, len - 48); - return true; + LogPrint (eLogWarning, "SSU2: Unexpected peer test message for this session type"); + return false; } uint32_t SSU2Session::SendData (const uint8_t * buf, size_t len, uint8_t flags) @@ -2277,11 +2250,10 @@ namespace transport if (!m_Server.IsConnectedRecently (ep)) // no alive hole punch { // send msg 5 to Alice - auto session = std::make_shared (m_Server, r, addr); - session->SetState (eSSU2SessionStatePeerTest); + auto session = std::make_shared (m_Server, + 0, htobe64 (((uint64_t)nonce << 32) | nonce), shared_from_this ()); + session->m_Address = addr; session->m_RemoteEndpoint = ep; // might be different - session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); - session->m_SourceConnID = ~session->m_DestConnID; m_Server.AddSession (session); session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); } @@ -2954,12 +2926,6 @@ namespace transport return ri; } - void SSU2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) - { - memset (nonce, 0, 4); - htole64buf (nonce + 4, seqn); - } - bool SSU2Session::UpdateReceivePacketNum (uint32_t packetNum) { if (packetNum <= m_ReceivePacketNum) return false; // duplicate @@ -3148,5 +3114,52 @@ namespace transport Resend (i2p::util::GetMillisecondsSinceEpoch ()); // than right time to resend } + SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, + uint64_t destConnID, std::shared_ptr mainSession): SSU2Session (server), + m_MainSession (mainSession) + { + if (!sourceConnID) sourceConnID = ~destConnID; + if (!destConnID) destConnID = ~sourceConnID; + SetSourceConnID (sourceConnID); + SetDestConnID (destConnID); + SetState (eSSU2SessionStatePeerTest); + } + + bool SSU2PeerTestSession::ProcessPeerTest (uint8_t * buf, size_t len) + { + // we are Alice or Charlie, msgs 5,6,7 + Header header; + memcpy (header.buf, buf, 16); + header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 24)); + header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 12)); + if (header.h.type != eSSU2PeerTest) + { + LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type, " instead ", (int)eSSU2PeerTest); + return false; + } + if (len < 48) + { + LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len); + return false; + } + uint8_t nonce[12] = {0}; + uint64_t headerX[2]; // sourceConnID, token + i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); + SetDestConnID (headerX[0]); + // decrypt and handle payload + uint8_t * payload = buf + 32; + CreateNonce (be32toh (header.h.packetNum), nonce); + uint8_t h[32]; + memcpy (h, header.buf, 16); + memcpy (h + 16, &headerX, 16); + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 48, h, 32, + i2p::context.GetSSU2IntroKey (), nonce, payload, len - 48, false)) + { + LogPrint (eLogWarning, "SSU2: PeerTest AEAD verification failed "); + return false; + } + HandlePayload (payload, len - 48); + return true; + } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index eaeda949460..a247a9e6a6e 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -207,36 +207,40 @@ namespace transport class SSU2Server; class SSU2Session: public TransportSession, public std::enable_shared_from_this { - union Header - { - uint64_t ll[2]; - uint8_t buf[16]; - struct + protected: + + union Header { - uint64_t connID; - uint32_t packetNum; - uint8_t type; - uint8_t flags[3]; - } h; - }; + uint64_t ll[2]; + uint8_t buf[16]; + struct + { + uint64_t connID; + uint32_t packetNum; + uint8_t type; + uint8_t flags[3]; + } h; + }; - struct HandshakePacket - { - Header header; - uint8_t headerX[48]; // part1 for SessionConfirmed - uint8_t payload[SSU2_MAX_PACKET_SIZE*2]; - size_t payloadSize = 0; - uint64_t sendTime = 0; // in milliseconds - bool isSecondFragment = false; // for SessionConfirmed - }; + private: + + struct HandshakePacket + { + Header header; + uint8_t headerX[48]; // part1 for SessionConfirmed + uint8_t payload[SSU2_MAX_PACKET_SIZE*2]; + size_t payloadSize = 0; + uint64_t sendTime = 0; // in milliseconds + bool isSecondFragment = false; // for SessionConfirmed + }; - typedef std::function OnEstablished; + typedef std::function OnEstablished; public: SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter = nullptr, std::shared_ptr addr = nullptr); - ~SSU2Session (); + virtual ~SSU2Session (); void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; }; const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; }; @@ -271,9 +275,16 @@ namespace transport bool ProcessSessionConfirmed (uint8_t * buf, size_t len); bool ProcessRetry (uint8_t * buf, size_t len); bool ProcessHolePunch (uint8_t * buf, size_t len); - bool ProcessPeerTest (uint8_t * buf, size_t len); + virtual bool ProcessPeerTest (uint8_t * buf, size_t len); void ProcessData (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from); + protected: + + void SetSourceConnID (uint64_t sourceConnID) { m_SourceConnID = sourceConnID; } + void SetDestConnID (uint64_t destConnID) { m_DestConnID = destConnID; } + + void HandlePayload (const uint8_t * buf, size_t len); + private: void Terminate (); @@ -303,7 +314,6 @@ namespace transport void SendPathResponse (const uint8_t * data, size_t len); void SendPathChallenge (); - void HandlePayload (const uint8_t * buf, size_t len); void HandleDateTime (const uint8_t * buf, size_t len); void HandleRouterInfo (const uint8_t * buf, size_t len); void HandleAck (const uint8_t * buf, size_t len); @@ -318,7 +328,6 @@ namespace transport bool GetTestingState () const; void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); - void CreateNonce (uint64_t seqn, uint8_t * nonce); bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate void HandleFirstFragment (const uint8_t * buf, size_t len); void HandleFollowOnFragment (const uint8_t * buf, size_t len); @@ -341,7 +350,7 @@ namespace transport size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice size_t CreateTerminationBlock (uint8_t * buf, size_t len); - + private: SSU2Server& m_Server; @@ -359,8 +368,8 @@ namespace transport std::set m_OutOfSequencePackets; // packet nums > receive packet num std::map > m_SentPackets; // packetNum -> packet std::unordered_map > m_IncompleteMessages; // msgID -> I2NP - std::map, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice - std::map, uint64_t > > m_PeerTests; // same as for relay sessions + std::unordered_map, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice + std::unordered_map, uint64_t > > m_PeerTests; // same as for relay sessions std::list > m_SendQueue; i2p::I2NPMessagesHandler m_Handler; bool m_IsDataReceived; @@ -378,6 +387,20 @@ namespace transport uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds }; + class SSU2PeerTestSession: public SSU2Session // for PeerTest msgs 5,6,7 + { + public: + + SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID, + std::shared_ptr mainSession); + + bool ProcessPeerTest (uint8_t * buf, size_t len) override; + + private: + + std::weak_ptr m_MainSession; + }; + inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) { uint64_t data = 0; From 11bca5c3cd91ca2504dd885eca54ac70b0c43f59 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Sep 2024 18:02:12 -0400 Subject: [PATCH 081/131] don't initialize Noise state for peer test sessions --- libi2pd/SSU2Session.cpp | 14 +++++++++----- libi2pd/SSU2Session.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 53ed899a00e..399f5e718c7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -85,7 +85,7 @@ namespace transport } SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter, - std::shared_ptr addr): + std::shared_ptr addr, bool noise): TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), m_Server (server), m_Address (addr), m_RemoteTransports (0), m_RemotePeerTestTransports (0), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), @@ -99,11 +99,13 @@ namespace transport m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32), // min size m_LastResendTime (0), m_LastResendAttemptTime (0) { - m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); + if (noise) + m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); if (in_RemoteRouter && m_Address) { // outgoing - InitNoiseXKState1 (*m_NoiseState, m_Address->s); + if (noise) + InitNoiseXKState1 (*m_NoiseState, m_Address->s); m_RemoteEndpoint = boost::asio::ip::udp::endpoint (m_Address->host, m_Address->port); m_RemoteTransports = in_RemoteRouter->GetCompatibleTransports (false); if (in_RemoteRouter->IsSSU2PeerTesting (true)) m_RemotePeerTestTransports |= i2p::data::RouterInfo::eSSU2V4; @@ -114,7 +116,8 @@ namespace transport else { // incoming - InitNoiseXKState1 (*m_NoiseState, i2p::context.GetSSU2StaticPublicKey ()); + if (noise) + InitNoiseXKState1 (*m_NoiseState, i2p::context.GetSSU2StaticPublicKey ()); } } @@ -3115,7 +3118,8 @@ namespace transport } SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, - uint64_t destConnID, std::shared_ptr mainSession): SSU2Session (server), + uint64_t destConnID, std::shared_ptr mainSession): + SSU2Session (server, nullptr, nullptr, false), m_MainSession (mainSession) { if (!sourceConnID) sourceConnID = ~destConnID; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index a247a9e6a6e..59e3e577783 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -239,7 +239,7 @@ namespace transport public: SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter = nullptr, - std::shared_ptr addr = nullptr); + std::shared_ptr addr = nullptr, bool noise = true); virtual ~SSU2Session (); void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; }; From 2c594dc67af1be7796aa0e8cf7b9e0ee8300dc25 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Sep 2024 20:25:41 -0400 Subject: [PATCH 082/131] moved peer test 5-7 to SSU2PeerTestSession --- libi2pd/SSU2Session.cpp | 82 ++++++++++++++++++++++++++--------------- libi2pd/SSU2Session.h | 16 ++++++-- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 399f5e718c7..7aa6af4022e 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2165,6 +2165,7 @@ namespace transport void SSU2Session::HandlePeerTest (const uint8_t * buf, size_t len) { + // msgs 1-4 if (len < 3) return; uint8_t msg = buf[0]; size_t offset = 3; // points to signed data @@ -2400,35 +2401,6 @@ namespace transport LogPrint (eLogWarning, "SSU2: Unknown peer test 4 nonce ", nonce); break; } - case 5: // Alice from Charlie 1 - if (htobe64 (((uint64_t)nonce << 32) | nonce) == m_SourceConnID) - { - bool isConnectedRecently = m_Server.IsConnectedRecently (m_RemoteEndpoint); - if (m_Address) - { - if (!isConnectedRecently) - SetRouterStatus (eRouterStatusOK); - SendPeerTest (6, buf + offset, len - offset, m_Address->i); - } - else - // we received msg 5 before msg 4 - m_State = isConnectedRecently ? eSSU2SessionStateVoidPeerTestReceived : eSSU2SessionStatePeerTestReceived; - } - else - LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce, " connID=", m_SourceConnID); - break; - case 6: // Charlie from Alice - if (m_Address) - SendPeerTest (7, buf + offset, len - offset, m_Address->i); - else - LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); - m_Server.RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); - break; - case 7: // Alice from Charlie 2 - if (m_Address->IsV6 ()) - i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 - m_Server.RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); - break; default: LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", buf[0]); } @@ -3165,5 +3137,57 @@ namespace transport HandlePayload (payload, len - 48); return true; } + + void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len) + { + // msgs 5-7 + if (len < 8) return; + uint8_t msg = buf[0]; + size_t offset = 3; // points to signed data after msg + code + flag + uint32_t nonce = bufbe32toh (buf + offset + 1); // 1 - ver + switch (msg) // msg + { + case 5: // Alice from Charlie 1 + { + if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ()) + { + bool isConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); + auto addr = GetAddress (); + if (addr) + { + if (!isConnectedRecently) + SetRouterStatus (eRouterStatusOK); + SendPeerTest (6, buf + offset, len - offset, addr->i); + } + else + // we received msg 5 before msg 4 + SetState (isConnectedRecently ? eSSU2SessionStateVoidPeerTestReceived : eSSU2SessionStatePeerTestReceived); + } + else + LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce, " connID=", GetSourceConnID ()); + break; + } + case 6: // Charlie from Alice + { + auto addr = GetAddress (); + if (addr) + SendPeerTest (7, buf + offset, len - offset, addr->i); + else + LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); + GetServer ().RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); + break; + } + case 7: // Alice from Charlie 2 + { + auto addr = GetAddress (); + if (addr && addr->IsV6 ()) + i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 + GetServer ().RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); + break; + } + default: + LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", msg); + } + } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 59e3e577783..5066f1a8c96 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -280,10 +280,17 @@ namespace transport protected: + SSU2Server& GetServer () { return m_Server; } + RouterStatus GetRouterStatus () const; + void SetRouterStatus (RouterStatus status) const; + + uint64_t GetSourceConnID () const { return m_SourceConnID; } void SetSourceConnID (uint64_t sourceConnID) { m_SourceConnID = sourceConnID; } + uint64_t GetDestConnID () const { return m_DestConnID; } void SetDestConnID (uint64_t destConnID) { m_DestConnID = destConnID; } void HandlePayload (const uint8_t * buf, size_t len); + void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message private: @@ -310,7 +317,6 @@ namespace transport void SendQuickAck (); void SendTermination (); void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey, uint64_t token); - void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message void SendPathResponse (const uint8_t * data, size_t len); void SendPathChallenge (); @@ -323,8 +329,6 @@ namespace transport size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); std::shared_ptr FindLocalAddress () const; void AdjustMaxPayloadSize (); - RouterStatus GetRouterStatus () const; - void SetRouterStatus (RouterStatus status) const; bool GetTestingState () const; void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); @@ -334,7 +338,7 @@ namespace transport void HandleRelayRequest (const uint8_t * buf, size_t len); void HandleRelayIntro (const uint8_t * buf, size_t len, int attempts = 0); void HandleRelayResponse (const uint8_t * buf, size_t len); - void HandlePeerTest (const uint8_t * buf, size_t len); + virtual void HandlePeerTest (const uint8_t * buf, size_t len); void HandleI2NPMsg (std::shared_ptr&& msg); size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); @@ -395,6 +399,10 @@ namespace transport std::shared_ptr mainSession); bool ProcessPeerTest (uint8_t * buf, size_t len) override; + + private: + + void HandlePeerTest (const uint8_t * buf, size_t len) override; private: From 5073c9637eebf0c3ec85177cf84c6d5ee28ab0d5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Sep 2024 21:07:44 -0400 Subject: [PATCH 083/131] implement httpproxy.senduseragent --- libi2pd/Config.cpp | 1 + libi2pd_client/ClientContext.cpp | 8 ++++++-- libi2pd_client/HTTPProxy.cpp | 15 +++++++++------ libi2pd_client/HTTPProxy.h | 12 +++++++----- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 4efcb16e13f..ab2376136f0 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -117,6 +117,7 @@ namespace config { ("httpproxy.latency.max", value()->default_value("0"), "HTTP proxy max latency for tunnels") ("httpproxy.outproxy", value()->default_value(""), "HTTP proxy upstream out proxy url") ("httpproxy.addresshelper", value()->default_value(true), "Enable or disable addresshelper") + ("httpproxy.senduseragent", value()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by deafult") ("httpproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("httpproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 8cb4b67bc34..cf72d204c46 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -666,7 +666,9 @@ namespace client // http proxy std::string outproxy = section.second.get("outproxy", ""); bool addresshelper = section.second.get("addresshelper", true); - auto tun = std::make_shared(name, address, port, outproxy, addresshelper, localDestination); + bool senduseragent = section.second.get("senduseragent", false); + auto tun = std::make_shared(name, address, port, + outproxy, addresshelper, senduseragent, localDestination); clientTunnel = tun; clientEndpoint = tun->GetLocalEndpoint (); } @@ -882,6 +884,7 @@ namespace client uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper); + bool httpSendUserAgent; i2p::config::GetOption("httpproxy.senduseragent", httpSendUserAgent); if (httpAddresshelper) i2p::config::GetOption("addressbook.enabled", httpAddresshelper); // addresshelper is not supported without address book i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); @@ -901,7 +904,8 @@ namespace client } try { - m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, httpAddresshelper, localDestination); + m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, + httpOutProxyURL, httpAddresshelper, httpSendUserAgent, localDestination); m_HttpProxy->Start(); } catch (std::exception& e) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 30a4e18113e..4f96f9403f4 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -80,7 +80,7 @@ namespace proxy { void AsyncSockRead(); static bool ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm); static bool VerifyAddressHelper (std::string_view jump); - static void SanitizeHTTPRequest(i2p::http::HTTPReq& req); + void SanitizeHTTPRequest(i2p::http::HTTPReq& req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); /* error helpers */ @@ -110,7 +110,7 @@ namespace proxy { std::shared_ptr m_proxysock; boost::asio::ip::tcp::resolver m_proxy_resolver; std::string m_OutproxyUrl, m_Response; - bool m_Addresshelper; + bool m_Addresshelper, m_SendUserAgent; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; int m_req_len; @@ -126,7 +126,8 @@ namespace proxy { m_proxysock(std::make_shared(parent->GetService())), m_proxy_resolver(parent->GetService()), m_OutproxyUrl(parent->GetOutproxyURL()), - m_Addresshelper(parent->GetHelperSupport()) {} + m_Addresshelper(parent->GetHelperSupport()), + m_SendUserAgent (parent->GetSendUserAgent ()) {} ~HTTPReqHandler() { Terminate(); } void Handle () { AsyncSockRead(); } /* overload */ }; @@ -315,7 +316,8 @@ namespace proxy { req.RemoveHeader("X-Forwarded"); req.RemoveHeader("Proxy-"); // Proxy-* /* replace headers */ - req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)"); + if (!m_SendUserAgent) + req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)"); /** * i2pd PR #1816: @@ -751,9 +753,10 @@ namespace proxy { Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination): + HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, uint16_t port, + const std::string & outproxy, bool addresshelper, bool senduseragent, std::shared_ptr localDestination): TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), - m_Name (name), m_OutproxyUrl (outproxy), m_Addresshelper (addresshelper) + m_Name (name), m_OutproxyUrl (outproxy), m_Addresshelper (addresshelper), m_SendUserAgent (senduseragent) { } diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index d819a53c467..507a87e2ed2 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,13 +15,15 @@ namespace proxy { { public: - HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); + HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, + bool addresshelper, bool senduseragent, std::shared_ptr localDestination); HTTPProxy(const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : - HTTPProxy(name, address, port, "", true, localDestination) {} ; + HTTPProxy(name, address, port, "", true, false, localDestination) {} ; ~HTTPProxy() {}; std::string GetOutproxyURL() const { return m_OutproxyUrl; } - bool GetHelperSupport() { return m_Addresshelper; } + bool GetHelperSupport() const { return m_Addresshelper; } + bool GetSendUserAgent () const { return m_SendUserAgent; } protected: @@ -33,7 +35,7 @@ namespace proxy { std::string m_Name; std::string m_OutproxyUrl; - bool m_Addresshelper; + bool m_Addresshelper, m_SendUserAgent; }; } // http } // i2p From 9968afc03812a914f68f1452ad8a25db6bee7290 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Sep 2024 21:27:09 -0400 Subject: [PATCH 084/131] check senduseragent for outproxy. Update User-Agent for clearnet --- libi2pd_client/HTTPProxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 4f96f9403f4..dba658150c9 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -553,9 +553,9 @@ namespace proxy { std::string origURI = m_ClientRequest.uri; // TODO: what do we need to change uri for? m_ClientRequest.uri = m_ClientRequestURL.to_string(); - /* update User-Agent to ESR version of Firefox, same as Tor Browser below version 8, for non-HTTPS connections */ - if(m_ClientRequest.method != "CONNECT") - m_ClientRequest.UpdateHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0"); + /* update User-Agent to ESR version of Firefox, same as Tor Browser below version 13, for non-HTTPS connections */ + if(m_ClientRequest.method != "CONNECT" && !m_SendUserAgent) + m_ClientRequest.UpdateHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0"); m_ClientRequest.write(m_ClientRequestBuffer); m_ClientRequestBuffer << m_recv_buf.substr(m_req_len); From 2dfc9003a73586c70a1f6fea148becc40a6e9275 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Sep 2024 14:16:24 -0400 Subject: [PATCH 085/131] separate and move own peer test to SSU2Server --- libi2pd/SSU2.cpp | 27 +++++++++++++++++++++++++ libi2pd/SSU2.h | 4 ++++ libi2pd/SSU2Session.cpp | 44 +++++++++++++++++++++-------------------- libi2pd/SSU2Session.h | 8 ++++---- 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 94fc2dc3841..5e2533f4c59 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -154,6 +154,8 @@ namespace transport m_Relays.clear (); m_Introducers.clear (); m_IntroducersV6.clear (); + m_ConnectedRecently.clear (); + m_RequestedPeerTests.clear (); } void SSU2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) @@ -572,6 +574,23 @@ namespace transport return nullptr; } + bool SSU2Server::AddRequestedPeerTest (uint32_t nonce, std::shared_ptr session, uint64_t ts) + { + return m_RequestedPeerTests.emplace (nonce, std::pair{ session, ts }).second; + } + + std::shared_ptr SSU2Server::GetRequestedPeerTest (uint32_t nonce) + { + auto it = m_RequestedPeerTests.find (nonce); + if (it != m_RequestedPeerTests.end ()) + { + auto s = it->second.first.lock (); + m_RequestedPeerTests.erase (it); + return s; + } + return nullptr; + } + void SSU2Server::ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { if (len < 24) return; @@ -1031,6 +1050,14 @@ namespace transport else it++; } + + for (auto it = m_RequestedPeerTests.begin (); it != m_RequestedPeerTests.end ();) + { + if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT) + it = m_RequestedPeerTests.erase (it); + else + it++; + } m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index a650425ef05..913cc7475be 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -94,6 +94,9 @@ namespace transport void RemoveRelay (uint32_t tag); std::shared_ptr FindRelaySession (uint32_t tag); + bool AddRequestedPeerTest (uint32_t nonce, std::shared_ptr session, uint64_t ts); + std::shared_ptr GetRequestedPeerTest (uint32_t nonce); + void Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to); void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, @@ -178,6 +181,7 @@ namespace transport std::shared_ptr m_PendingTimeOffsetFrom; std::mt19937 m_Rng; std::map m_ConnectedRecently; // endpoint -> last activity time in seconds + std::unordered_map, uint64_t > > m_RequestedPeerTests; // nonce->(Alice, timestamp) // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 7aa6af4022e..307c82f24b7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -237,8 +237,8 @@ namespace transport auto ts = i2p::util::GetMillisecondsSinceEpoch (); // session for message 5 auto session = std::make_shared (m_Server, - htobe64 (((uint64_t)nonce << 32) | nonce), 0, shared_from_this ()); - m_PeerTests.emplace (nonce, std::make_pair (session, ts/1000)); + htobe64 (((uint64_t)nonce << 32) | nonce), 0); + m_Server.AddRequestedPeerTest (nonce, session, ts/1000); m_Server.AddSession (session); // peer test block auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); @@ -2255,7 +2255,7 @@ namespace transport { // send msg 5 to Alice auto session = std::make_shared (m_Server, - 0, htobe64 (((uint64_t)nonce << 32) | nonce), shared_from_this ()); + 0, htobe64 (((uint64_t)nonce << 32) | nonce)); session->m_Address = addr; session->m_RemoteEndpoint = ep; // might be different m_Server.AddSession (session); @@ -2318,15 +2318,15 @@ namespace transport } case 4: // Alice from Bob { - auto it = m_PeerTests.find (nonce); - if (it != m_PeerTests.end ()) + auto session = m_Server.GetRequestedPeerTest (nonce); + if (session) { if (buf[1] == eSSU2PeerTestCodeAccept) { if (GetRouterStatus () == eRouterStatusUnknown) SetTestingState (true); auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie - if (r && it->second.first) + if (r) { uint8_t asz = buf[offset + 9]; SignedData s; @@ -2336,19 +2336,19 @@ namespace transport s.Insert (buf + offset, asz + 10); // ver, nonce, ts, asz, Alice's endpoint if (s.Verify (r->GetIdentity (), buf + offset + asz + 10)) { - it->second.first->SetRemoteIdentity (r->GetIdentity ()); + session->SetRemoteIdentity (r->GetIdentity ()); auto addr = r->GetSSU2Address (m_Address->IsV4 ()); if (addr) { - it->second.first->m_Address = addr; - auto& state = it->second.first->m_State; + session->m_Address = addr; + auto& state = session->m_State; if (state == eSSU2SessionStatePeerTestReceived || state == eSSU2SessionStateVoidPeerTestReceived) { // msg 5 already received. send msg 6 if (state == eSSU2SessionStatePeerTestReceived) SetRouterStatus (eRouterStatusOK); state = eSSU2SessionStatePeerTest; - it->second.first->SendPeerTest (6, buf + offset, len - offset, addr->i); + session->SendPeerTest (6, buf + offset, len - offset, addr->i); } else { @@ -2371,20 +2371,19 @@ namespace transport else { LogPrint (eLogWarning, "SSU2: Peer test 4 address not found"); - it->second.first->Done (); + session->Done (); } } else { LogPrint (eLogWarning, "SSU2: Peer test 4 signature verification failed"); - it->second.first->Done (); + session->Done (); } } else { LogPrint (eLogWarning, "SSU2: Peer test 4 router not found"); - if (it->second.first) - it->second.first->Done (); + session->Done (); } } else @@ -2393,9 +2392,8 @@ namespace transport i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3))); if (GetTestingState ()) SetRouterStatus (eRouterStatusUnknown); - it->second.first->Done (); + session->Done (); } - m_PeerTests.erase (it); } else LogPrint (eLogWarning, "SSU2: Unknown peer test 4 nonce ", nonce); @@ -3089,10 +3087,8 @@ namespace transport Resend (i2p::util::GetMillisecondsSinceEpoch ()); // than right time to resend } - SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, - uint64_t destConnID, std::shared_ptr mainSession): - SSU2Session (server, nullptr, nullptr, false), - m_MainSession (mainSession) + SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID): + SSU2Session (server, nullptr, nullptr, false), m_MsgNumReceived (0) { if (!sourceConnID) sourceConnID = ~destConnID; if (!destConnID) destConnID = ~sourceConnID; @@ -3143,6 +3139,10 @@ namespace transport // msgs 5-7 if (len < 8) return; uint8_t msg = buf[0]; + if (msg < m_MsgNumReceived) + { + LogPrint (eLogInfo, "SSU2: PeerTest msg num ", msg, " received after ", m_MsgNumReceived, ". Ignored"); + } size_t offset = 3; // points to signed data after msg + code + flag uint32_t nonce = bufbe32toh (buf + offset + 1); // 1 - ver switch (msg) // msg @@ -3185,9 +3185,11 @@ namespace transport GetServer ().RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); break; } - default: + default: LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", msg); + return; } + m_MsgNumReceived = msg; } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 5066f1a8c96..13d0f26214b 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -395,18 +395,18 @@ namespace transport { public: - SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID, - std::shared_ptr mainSession); + SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID); + uint8_t GetMsgNumReceived () const { return m_MsgNumReceived; } bool ProcessPeerTest (uint8_t * buf, size_t len) override; private: void HandlePeerTest (const uint8_t * buf, size_t len) override; - + private: - std::weak_ptr m_MainSession; + uint8_t m_MsgNumReceived; }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) From 189d7179c0245242742e5481825a566ff14f738a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Sep 2024 15:34:14 -0400 Subject: [PATCH 086/131] check if msg 5 was received instead state --- libi2pd/SSU2Session.cpp | 28 +++++++++++++++------------- libi2pd/SSU2Session.h | 6 +++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 307c82f24b7..2142ba0dfd6 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2341,14 +2341,18 @@ namespace transport if (addr) { session->m_Address = addr; - auto& state = session->m_State; - if (state == eSSU2SessionStatePeerTestReceived || state == eSSU2SessionStateVoidPeerTestReceived) + if (session->GetMsgNumReceived () >= 5) { - // msg 5 already received. send msg 6 - if (state == eSSU2SessionStatePeerTestReceived) - SetRouterStatus (eRouterStatusOK); - state = eSSU2SessionStatePeerTest; - session->SendPeerTest (6, buf + offset, len - offset, addr->i); + // msg 5 already received + if (session->GetMsgNumReceived () == 5) + { + if (!session->IsConnectedRecently ()) + SetRouterStatus (eRouterStatusOK); + // send msg 6 + session->SendPeerTest (6, buf + offset, len - offset, addr->i); + } + else + LogPrint (eLogWarning, "SSU2: PeerTest 4 received, but msg ", session->GetMsgNumReceived (), " already received"); } else { @@ -3088,7 +3092,8 @@ namespace transport } SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID): - SSU2Session (server, nullptr, nullptr, false), m_MsgNumReceived (0) + SSU2Session (server, nullptr, nullptr, false), + m_MsgNumReceived (0), m_IsConnectedRecently (false) { if (!sourceConnID) sourceConnID = ~destConnID; if (!destConnID) destConnID = ~sourceConnID; @@ -3151,17 +3156,14 @@ namespace transport { if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ()) { - bool isConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); + m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); auto addr = GetAddress (); if (addr) { - if (!isConnectedRecently) + if (!m_IsConnectedRecently) SetRouterStatus (eRouterStatusOK); SendPeerTest (6, buf + offset, len - offset, addr->i); } - else - // we received msg 5 before msg 4 - SetState (isConnectedRecently ? eSSU2SessionStateVoidPeerTestReceived : eSSU2SessionStatePeerTestReceived); } else LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce, " connID=", GetSourceConnID ()); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 13d0f26214b..1449305a7f1 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -113,8 +113,6 @@ namespace transport eSSU2SessionStateFailed, eSSU2SessionStateIntroduced, eSSU2SessionStatePeerTest, - eSSU2SessionStatePeerTestReceived, // 5 before 4 - eSSU2SessionStateVoidPeerTestReceived, // 5 before 4, but from connected recently eSSU2SessionStateTokenRequestReceived }; @@ -397,7 +395,8 @@ namespace transport SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID); - uint8_t GetMsgNumReceived () const { return m_MsgNumReceived; } + uint8_t GetMsgNumReceived () const { return m_MsgNumReceived; } + bool IsConnectedRecently () const { return m_IsConnectedRecently; } bool ProcessPeerTest (uint8_t * buf, size_t len) override; private: @@ -407,6 +406,7 @@ namespace transport private: uint8_t m_MsgNumReceived; + bool m_IsConnectedRecently; }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) From 816771dd00e6b6ffe2e0793ff3925b23b36962b3 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Sep 2024 18:18:26 -0400 Subject: [PATCH 087/131] fixed build for gcc 8-9 --- build/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 534f87468fa..954f5de9bd2 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -209,6 +209,10 @@ if(WITH_THREADSANITIZER) endif() endif() +if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) # gcc 8-9 + list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++fs") +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 # This has been fixed in Boost 1.81, nevertheless we retain the setting for the sake of compatibility. From 5cd02484946c7594ef349c7dc7243a58622cefec Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Sep 2024 20:24:33 -0400 Subject: [PATCH 088/131] set router status to uknown if peer test msg 5 came from recently connected peer --- libi2pd/SSU2Session.cpp | 5 ++++- libi2pd/SSU2Session.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 2142ba0dfd6..2fde10929e7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2362,6 +2362,7 @@ namespace transport if (GetRouterStatus () != eRouterStatusFirewalled && addr->IsPeerTesting ()) { SetRouterStatus (eRouterStatusFirewalled); + session->SetStatusChanged (); if (m_Address->IsV4 ()) m_Server.RescheduleIntroducersUpdateTimer (); else @@ -3093,7 +3094,7 @@ namespace transport SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID): SSU2Session (server, nullptr, nullptr, false), - m_MsgNumReceived (0), m_IsConnectedRecently (false) + m_MsgNumReceived (0), m_IsConnectedRecently (false), m_IsStatusChanged (false) { if (!sourceConnID) sourceConnID = ~destConnID; if (!destConnID) destConnID = ~sourceConnID; @@ -3162,6 +3163,8 @@ namespace transport { if (!m_IsConnectedRecently) SetRouterStatus (eRouterStatusOK); + else if (m_IsStatusChanged && GetRouterStatus () == eRouterStatusFirewalled) + SetRouterStatus (eRouterStatusUnknown); SendPeerTest (6, buf + offset, len - offset, addr->i); } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 1449305a7f1..71c73101633 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -397,6 +397,7 @@ namespace transport uint8_t GetMsgNumReceived () const { return m_MsgNumReceived; } bool IsConnectedRecently () const { return m_IsConnectedRecently; } + void SetStatusChanged () { m_IsStatusChanged = true; } bool ProcessPeerTest (uint8_t * buf, size_t len) override; private: @@ -406,7 +407,7 @@ namespace transport private: uint8_t m_MsgNumReceived; - bool m_IsConnectedRecently; + bool m_IsConnectedRecently, m_IsStatusChanged; }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) From 74f0330730021d76b2a6c19d9662bf41f1ca01f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Sep 2024 14:37:27 -0400 Subject: [PATCH 089/131] moved SendPeerTest for msgs 5,6,7 to SSU2PeerTestSession --- libi2pd/SSU2Session.cpp | 98 ++++++++++++++++++++++------------------- libi2pd/SSU2Session.h | 16 ++++--- 2 files changed, 63 insertions(+), 51 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 2fde10929e7..45dedc168c3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1425,42 +1425,6 @@ namespace transport return true; } - void SSU2Session::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey) - { - Header header; - uint8_t h[32], payload[SSU2_MAX_PACKET_SIZE]; - // fill packet - header.h.connID = m_DestConnID; // dest id - RAND_bytes (header.buf + 8, 4); // random packet num - header.h.type = eSSU2PeerTest; - header.h.flags[0] = 2; // ver - header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID - header.h.flags[2] = 0; // flag - memcpy (h, header.buf, 16); - memcpy (h + 16, &m_SourceConnID, 8); // source id - // payload - payload[0] = eSSU2BlkDateTime; - htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); - size_t payloadSize = 7; - if (msg == 6 || msg == 7) - payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint); - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, - msg, eSSU2PeerTestCodeAccept, nullptr, signedData, signedDataLen); - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - // encrypt - uint8_t n[12]; - CreateNonce (be32toh (header.h.packetNum), n); - i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, h, 32, introKey, n, payload, payloadSize + 16, true); - payloadSize += 16; - header.ll[0] ^= CreateHeaderMask (introKey, payload + (payloadSize - 24)); - header.ll[1] ^= CreateHeaderMask (introKey, payload + (payloadSize - 12)); - memset (n, 0, 12); - i2p::crypto::ChaCha20 (h + 16, 16, introKey, n, h + 16); - // send - m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); - } - bool SSU2Session::ProcessPeerTest (uint8_t * buf, size_t len) { LogPrint (eLogWarning, "SSU2: Unexpected peer test message for this session type"); @@ -2256,10 +2220,9 @@ namespace transport // send msg 5 to Alice auto session = std::make_shared (m_Server, 0, htobe64 (((uint64_t)nonce << 32) | nonce)); - session->m_Address = addr; session->m_RemoteEndpoint = ep; // might be different m_Server.AddSession (session); - session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); + session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr); } else code = eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected; @@ -2340,7 +2303,6 @@ namespace transport auto addr = r->GetSSU2Address (m_Address->IsV4 ()); if (addr) { - session->m_Address = addr; if (session->GetMsgNumReceived () >= 5) { // msg 5 already received @@ -2349,7 +2311,7 @@ namespace transport if (!session->IsConnectedRecently ()) SetRouterStatus (eRouterStatusOK); // send msg 6 - session->SendPeerTest (6, buf + offset, len - offset, addr->i); + session->SendPeerTest (6, buf + offset, len - offset, addr); } else LogPrint (eLogWarning, "SSU2: PeerTest 4 received, but msg ", session->GetMsgNumReceived (), " already received"); @@ -3158,14 +3120,13 @@ namespace transport if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ()) { m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); - auto addr = GetAddress (); - if (addr) + if (GetAddress ()) { if (!m_IsConnectedRecently) SetRouterStatus (eRouterStatusOK); else if (m_IsStatusChanged && GetRouterStatus () == eRouterStatusFirewalled) SetRouterStatus (eRouterStatusUnknown); - SendPeerTest (6, buf + offset, len - offset, addr->i); + SendPeerTest (6, buf + offset, len - offset); } } else @@ -3174,9 +3135,8 @@ namespace transport } case 6: // Charlie from Alice { - auto addr = GetAddress (); - if (addr) - SendPeerTest (7, buf + offset, len - offset, addr->i); + if (GetAddress ()) + SendPeerTest (7, buf + offset, len - offset); else LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); GetServer ().RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); @@ -3195,6 +3155,52 @@ namespace transport return; } m_MsgNumReceived = msg; + } + + void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen) + { + auto addr = GetAddress (); + if (!addr) return; + Header header; + uint8_t h[32], payload[SSU2_MAX_PACKET_SIZE]; + // fill packet + header.h.connID = GetDestConnID (); // dest id + RAND_bytes (header.buf + 8, 4); // random packet num + header.h.type = eSSU2PeerTest; + header.h.flags[0] = 2; // ver + header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID + header.h.flags[2] = 0; // flag + memcpy (h, header.buf, 16); + htobuf64 (h + 16, GetSourceConnID ()); // source id + // payload + payload[0] = eSSU2BlkDateTime; + htobe16buf (payload + 1, 4); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); + size_t payloadSize = 7; + if (msg == 6 || msg == 7) + payloadSize += CreateAddressBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, GetRemoteEndpoint ()); + payloadSize += CreatePeerTestBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, + msg, eSSU2PeerTestCodeAccept, nullptr, signedData, signedDataLen); + payloadSize += CreatePaddingBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize); + // encrypt + uint8_t n[12]; + CreateNonce (be32toh (header.h.packetNum), n); + i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, h, 32, addr->i, n, payload, payloadSize + 16, true); + payloadSize += 16; + header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24)); + header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12)); + memset (n, 0, 12); + i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16); + // send + GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ()); + } + + void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, + std::shared_ptr addr) + { + if (!addr) return; + SetAddress (addr); + SendPeerTest (msg, signedData, signedDataLen); } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 71c73101633..eaf727cc85d 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -281,14 +281,19 @@ namespace transport SSU2Server& GetServer () { return m_Server; } RouterStatus GetRouterStatus () const; void SetRouterStatus (RouterStatus status) const; + size_t GetMaxPayloadSize () const { return m_MaxPayloadSize; } uint64_t GetSourceConnID () const { return m_SourceConnID; } void SetSourceConnID (uint64_t sourceConnID) { m_SourceConnID = sourceConnID; } uint64_t GetDestConnID () const { return m_DestConnID; } void SetDestConnID (uint64_t destConnID) { m_DestConnID = destConnID; } + void SetAddress (std::shared_ptr addr) { m_Address = addr; } void HandlePayload (const uint8_t * buf, size_t len); - void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message + + size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); + size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0); + size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); private: @@ -339,17 +344,14 @@ namespace transport virtual void HandlePeerTest (const uint8_t * buf, size_t len); void HandleI2NPMsg (std::shared_ptr&& msg); - size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); size_t CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr r); size_t CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr riBuffer); size_t CreateAckBlock (uint8_t * buf, size_t len); - size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0); size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr&& msg); size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr msg); size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr msg, uint8_t& fragmentNum, uint32_t msgID); size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen); size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4); - size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice size_t CreateTerminationBlock (uint8_t * buf, size_t len); @@ -398,12 +400,16 @@ namespace transport uint8_t GetMsgNumReceived () const { return m_MsgNumReceived; } bool IsConnectedRecently () const { return m_IsConnectedRecently; } void SetStatusChanged () { m_IsStatusChanged = true; } + + void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, + std::shared_ptr addr); bool ProcessPeerTest (uint8_t * buf, size_t len) override; private: + void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen); // PeerTest message void HandlePeerTest (const uint8_t * buf, size_t len) override; - + private: uint8_t m_MsgNumReceived; From edb2ba710732056a541767cbb5664e0b4d540852 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Sep 2024 15:20:10 -0400 Subject: [PATCH 090/131] set address when peer test msg 4 received --- libi2pd/SSU2Session.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 45dedc168c3..7d5763a27ff 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2318,6 +2318,7 @@ namespace transport } else { + session->m_Address = addr; if (GetTestingState ()) { SetTestingState (false); From 0912de5b7703fe9b0fd7adf1d6a60976aa376fac Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Sep 2024 20:03:15 -0400 Subject: [PATCH 091/131] don't connect peer test session. Use weak_ptr for seesions by hash --- libi2pd/SSU2.cpp | 84 +++++++++++++++++++++++------------------ libi2pd/SSU2.h | 2 +- libi2pd/SSU2Session.cpp | 15 +++++++- libi2pd/SSU2Session.h | 8 ++-- 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5e2533f4c59..2005294be47 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -450,7 +450,8 @@ namespace transport if (session) { m_Sessions.emplace (session->GetConnID (), session); - AddSessionByRouterHash (session); + if (session->GetState () != eSSU2SessionStatePeerTest) + AddSessionByRouterHash (session); } } @@ -459,13 +460,16 @@ namespace transport auto it = m_Sessions.find (connID); if (it != m_Sessions.end ()) { - auto ident = it->second->GetRemoteIdentity (); - if (ident) - { - auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ()); - if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second) - m_SessionsByRouterHash.erase (it1); - } + if (it->second->GetState () != eSSU2SessionStatePeerTest) + { + auto ident = it->second->GetRemoteIdentity (); + if (ident) + { + auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ()); + if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second.lock ()) + m_SessionsByRouterHash.erase (it1); + } + } if (m_LastSession == it->second) m_LastSession = nullptr; m_Sessions.erase (it); @@ -480,16 +484,20 @@ namespace transport if (ident) { auto ret = m_SessionsByRouterHash.emplace (ident->GetIdentHash (), session); - if (!ret.second && ret.first->second != session) + if (!ret.second) { - // session already exists - LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); - // move unsent msgs to new session - ret.first->second->MoveSendQueue (session); - // terminate existing - GetService ().post (std::bind (&SSU2Session::RequestTermination, ret.first->second, eSSU2TerminationReasonReplacedByNewSession)); - // update session - ret.first->second = session; + auto oldSession = ret.first->second.lock (); + if (oldSession != session) + { + // session already exists + LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); + // move unsent msgs to new session + oldSession->MoveSendQueue (session); + // terminate existing + GetService ().post (std::bind (&SSU2Session::RequestTermination, oldSession, eSSU2TerminationReasonReplacedByNewSession)); + // update session + ret.first->second = session; + } } } } @@ -506,7 +514,7 @@ namespace transport { auto it = m_SessionsByRouterHash.find (ident); if (it != m_SessionsByRouterHash.end ()) - return it->second; + return it->second.lock (); return nullptr; } @@ -761,11 +769,9 @@ namespace transport if (it != m_SessionsByRouterHash.end ()) { // session with router found, trying to send peer test if requested - if (peerTest && it->second->IsEstablished ()) - { - auto session = it->second; + auto session = it->second.lock (); + if (peerTest && session && session->IsEstablished ()) GetService ().post ([session]() { session->SendPeerTest (); }); - } return false; } // check is no pending session @@ -825,11 +831,15 @@ namespace transport auto it1 = m_SessionsByRouterHash.find (it.iH); if (it1 != m_SessionsByRouterHash.end ()) { - auto addr = it1->second->GetAddress (); - if (addr && addr->IsIntroducer ()) + auto s = it1->second.lock (); + if (s) { - it1->second->Introduce (session, it.iTag); - return; + auto addr = s->GetAddress (); + if (addr && addr->IsIntroducer ()) + { + s->Introduce (session, it.iTag); + return; + } } } else @@ -936,17 +946,19 @@ namespace transport if (!router) return false; auto addr = v4 ? router->GetSSU2V4Address () : router->GetSSU2V6Address (); if (!addr) return false; + std::shared_ptr session; auto it = m_SessionsByRouterHash.find (router->GetIdentHash ()); if (it != m_SessionsByRouterHash.end ()) + session = it->second.lock (); + if (session) { - auto remoteAddr = it->second->GetAddress (); + auto remoteAddr = session->GetAddress (); if (!remoteAddr || !remoteAddr->IsPeerTesting () || - (v4 && !remoteAddr->IsV4 ()) || (!v4 && !remoteAddr->IsV6 ())) return false; - auto s = it->second; - if (s->IsEstablished ()) - GetService ().post ([s]() { s->SendPeerTest (); }); + (v4 && !remoteAddr->IsV4 ()) || (!v4 && !remoteAddr->IsV6 ())) return false; + if (session->IsEstablished ()) + GetService ().post ([session]() { session->SendPeerTest (); }); else - s->SetOnEstablished ([s]() { s->SendPeerTest (); }); + session->SetOnEstablished ([session]() { session->SendPeerTest (); }); return true; } else @@ -997,7 +1009,7 @@ namespace transport for (auto it = m_SessionsByRouterHash.begin (); it != m_SessionsByRouterHash.begin ();) { - if (it->second && it->second->GetState () == eSSU2SessionStateTerminated) + if (it->second.expired ()) it = m_SessionsByRouterHash.erase (it); else it++; @@ -1183,7 +1195,7 @@ namespace transport auto it1 = m_SessionsByRouterHash.find (it); if (it1 != m_SessionsByRouterHash.end ()) { - session = it1->second; + session = it1->second.lock (); excluded.insert (it); } if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer? @@ -1217,8 +1229,8 @@ namespace transport auto it1 = m_SessionsByRouterHash.find (it); if (it1 != m_SessionsByRouterHash.end ()) { - auto session = it1->second; - if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) + auto session = it1->second.lock (); + if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 913cc7475be..54eca83ff43 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -162,7 +162,7 @@ namespace transport boost::asio::ip::udp::socket m_SocketV4, m_SocketV6; boost::asio::ip::address m_AddressV4, m_AddressV6; std::unordered_map > m_Sessions; - std::unordered_map > m_SessionsByRouterHash; + std::unordered_map > m_SessionsByRouterHash; std::map > m_PendingOutgoingSessions; mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 7d5763a27ff..7a7154a9b41 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -3140,7 +3140,7 @@ namespace transport SendPeerTest (7, buf + offset, len - offset); else LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); - GetServer ().RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); + GetServer ().RemoveSession (GetConnID ()); break; } case 7: // Alice from Charlie 2 @@ -3148,7 +3148,7 @@ namespace transport auto addr = GetAddress (); if (addr && addr->IsV6 ()) i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 - GetServer ().RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); + GetServer ().RemoveSession (GetConnID ()); break; } default: @@ -3203,5 +3203,16 @@ namespace transport SetAddress (addr); SendPeerTest (msg, signedData, signedDataLen); } + + void SSU2PeerTestSession::Connect () + { + LogPrint (eLogError, "SSU2: Can't connect peer test session"); + } + + bool SSU2PeerTestSession::ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len) + { + LogPrint (eLogError, "SSU2: Can't handle incoming message in peer test session"); + return false; + } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index eaf727cc85d..d261bc6dc1a 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -248,7 +248,7 @@ namespace transport void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; }; OnEstablished GetOnEstablished () const { return m_OnEstablished; }; - void Connect (); + virtual void Connect (); bool Introduce (std::shared_ptr session, uint32_t relayTag); void WaitForIntroduction (); void SendPeerTest (); // Alice, Data message @@ -268,7 +268,7 @@ namespace transport SSU2SessionState GetState () const { return m_State; }; void SetState (SSU2SessionState state) { m_State = state; }; - bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len); + virtual bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len); bool ProcessSessionCreated (uint8_t * buf, size_t len); bool ProcessSessionConfirmed (uint8_t * buf, size_t len); bool ProcessRetry (uint8_t * buf, size_t len); @@ -404,7 +404,9 @@ namespace transport void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, std::shared_ptr addr); bool ProcessPeerTest (uint8_t * buf, size_t len) override; - + void Connect () override; // outgoing + bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len) override; // incoming + private: void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen); // PeerTest message From 262a803d106d41782a4f2fd1429d78102a0b9a92 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Sep 2024 20:57:04 -0400 Subject: [PATCH 092/131] make sure we are done with session before remving it --- libi2pd/SSU2.cpp | 5 +++++ libi2pd/SSU2.h | 1 + libi2pd/SSU2Session.cpp | 6 +++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 2005294be47..cdc127b11fb 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -476,6 +476,11 @@ namespace transport } } + void SSU2Server::RequestRemoveSession (uint64_t connID) + { + GetService ().post ([connID, this]() { RemoveSession (connID); }); + } + void SSU2Server::AddSessionByRouterHash (std::shared_ptr session) { if (session) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 54eca83ff43..84a1307515c 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -82,6 +82,7 @@ namespace transport void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); + void RequestRemoveSession (uint64_t connID); void AddSessionByRouterHash (std::shared_ptr session); bool AddPendingOutgoingSession (std::shared_ptr session); void RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 7a7154a9b41..ce3f16372b8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -224,7 +224,7 @@ namespace transport // connect m_State = eSSU2SessionStateTokenReceived; m_Server.AddPendingOutgoingSession (shared_from_this ()); - m_Server.RemoveSession (oldConnID); + m_Server.RequestRemoveSession (oldConnID); Connect (); } } @@ -3140,7 +3140,7 @@ namespace transport SendPeerTest (7, buf + offset, len - offset); else LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); - GetServer ().RemoveSession (GetConnID ()); + GetServer ().RequestRemoveSession (GetConnID ()); break; } case 7: // Alice from Charlie 2 @@ -3148,7 +3148,7 @@ namespace transport auto addr = GetAddress (); if (addr && addr->IsV6 ()) i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 - GetServer ().RemoveSession (GetConnID ()); + GetServer ().RequestRemoveSession (GetConnID ()); break; } default: From 67763248cc088b179ca51ae728890e10c24bc0ec Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Sep 2024 22:06:44 -0400 Subject: [PATCH 093/131] add peer test session endpoint to connected recently after msg 6 and 7 --- libi2pd/SSU2Session.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index ce3f16372b8..bc47690dc45 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -3064,6 +3064,7 @@ namespace transport SetSourceConnID (sourceConnID); SetDestConnID (destConnID); SetState (eSSU2SessionStatePeerTest); + SetTerminationTimeout (SSU2_PEER_TEST_EXPIRATION_TIMEOUT); } bool SSU2PeerTestSession::ProcessPeerTest (uint8_t * buf, size_t len) @@ -3140,6 +3141,7 @@ namespace transport SendPeerTest (7, buf + offset, len - offset); else LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6"); + GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ()); GetServer ().RequestRemoveSession (GetConnID ()); break; } @@ -3148,6 +3150,7 @@ namespace transport auto addr = GetAddress (); if (addr && addr->IsV6 ()) i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 + GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ()); GetServer ().RequestRemoveSession (GetConnID ()); break; } From 98669eff4fe0a59b8e2c12651b9d5410d1c4a80e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Sep 2024 11:13:01 -0400 Subject: [PATCH 094/131] delete session by hash from table if expired or terminated --- libi2pd/SSU2.cpp | 12 ++++++++++-- libi2pd/SSU2.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index cdc127b11fb..17bc1912cdc 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -515,11 +515,19 @@ namespace transport return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second; } - std::shared_ptr SSU2Server::FindSession (const i2p::data::IdentHash& ident) const + std::shared_ptr SSU2Server::FindSession (const i2p::data::IdentHash& ident) { auto it = m_SessionsByRouterHash.find (ident); if (it != m_SessionsByRouterHash.end ()) - return it->second.lock (); + { + if (!it->second.expired ()) + { + auto s = it->second.lock (); + if (s && s->GetState () != eSSU2SessionStateTerminated) + return s; + } + m_SessionsByRouterHash.erase (it); + } return nullptr; } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 84a1307515c..2c5e8cc6fae 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -86,7 +86,7 @@ namespace transport void AddSessionByRouterHash (std::shared_ptr session); bool AddPendingOutgoingSession (std::shared_ptr session); void RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep); - std::shared_ptr FindSession (const i2p::data::IdentHash& ident) const; + std::shared_ptr FindSession (const i2p::data::IdentHash& ident); std::shared_ptr FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const; std::shared_ptr GetRandomPeerTestSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports, const i2p::data::IdentHash& excluded); From 32ad4b4858535472116b11de6981cc8cd21f67ed Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Sep 2024 14:34:52 -0400 Subject: [PATCH 095/131] fixed possible race conditions with m_SessionsByRouterHash --- libi2pd/SSU2.cpp | 155 +++++++++++++++++++++++------------------------ libi2pd/SSU2.h | 1 + 2 files changed, 78 insertions(+), 78 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 17bc1912cdc..b5b9d25c452 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -465,6 +465,7 @@ namespace transport auto ident = it->second->GetRemoteIdentity (); if (ident) { + std::lock_guard l(m_SessionsByRouterHashMutex); auto it1 = m_SessionsByRouterHash.find (ident->GetIdentHash ()); if (it1 != m_SessionsByRouterHash.end () && it->second == it1->second.lock ()) m_SessionsByRouterHash.erase (it1); @@ -488,22 +489,26 @@ namespace transport auto ident = session->GetRemoteIdentity (); if (ident) { - auto ret = m_SessionsByRouterHash.emplace (ident->GetIdentHash (), session); - if (!ret.second) + std::shared_ptr oldSession; { - auto oldSession = ret.first->second.lock (); - if (oldSession != session) - { - // session already exists - LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); - // move unsent msgs to new session - oldSession->MoveSendQueue (session); - // terminate existing - GetService ().post (std::bind (&SSU2Session::RequestTermination, oldSession, eSSU2TerminationReasonReplacedByNewSession)); + std::lock_guard l(m_SessionsByRouterHashMutex); + auto ret = m_SessionsByRouterHash.emplace (ident->GetIdentHash (), session); + if (!ret.second) + { + oldSession = ret.first->second.lock (); // update session ret.first->second = session; } - } + } + if (oldSession && oldSession != session) + { + // session already exists + LogPrint (eLogWarning, "SSU2: Session to ", ident->GetIdentHash ().ToBase64 (), " already exists"); + // move unsent msgs to new session + oldSession->MoveSendQueue (session); + // terminate existing + GetService ().post (std::bind (&SSU2Session::RequestTermination, oldSession, eSSU2TerminationReasonReplacedByNewSession)); + } } } } @@ -511,12 +516,13 @@ namespace transport bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr session) { if (!session) return false; - std::unique_lock l(m_PendingOutgoingSessionsMutex); + std::lock_guard l(m_PendingOutgoingSessionsMutex); return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second; } std::shared_ptr SSU2Server::FindSession (const i2p::data::IdentHash& ident) { + std::lock_guard l(m_SessionsByRouterHashMutex); auto it = m_SessionsByRouterHash.find (ident); if (it != m_SessionsByRouterHash.end ()) { @@ -533,7 +539,7 @@ namespace transport std::shared_ptr SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const { - std::unique_lock l(m_PendingOutgoingSessionsMutex); + std::lock_guard l(m_PendingOutgoingSessionsMutex); auto it = m_PendingOutgoingSessions.find (ep); if (it != m_PendingOutgoingSessions.end ()) return it->second; @@ -542,7 +548,7 @@ namespace transport void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) { - std::unique_lock l(m_PendingOutgoingSessionsMutex); + std::lock_guard l(m_PendingOutgoingSessionsMutex); m_PendingOutgoingSessions.erase (ep); } @@ -681,7 +687,7 @@ namespace transport if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && it1->second->ProcessSessionCreated (buf, len)) { - std::unique_lock l(m_PendingOutgoingSessionsMutex); + std::lock_guard l(m_PendingOutgoingSessionsMutex); m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint } else @@ -778,13 +784,12 @@ namespace transport if (router && address) { // check if no session - auto it = m_SessionsByRouterHash.find (router->GetIdentHash ()); - if (it != m_SessionsByRouterHash.end ()) + auto existingSession = FindSession (router->GetIdentHash ()); + if (existingSession) { // session with router found, trying to send peer test if requested - auto session = it->second.lock (); - if (peerTest && session && session->IsEstablished ()) - GetService ().post ([session]() { session->SendPeerTest (); }); + if (peerTest && existingSession->IsEstablished ()) + GetService ().post ([existingSession]() { existingSession->SendPeerTest (); }); return false; } // check is no pending session @@ -841,19 +846,15 @@ namespace transport { if (it.iTag && ts < it.iExp) { - auto it1 = m_SessionsByRouterHash.find (it.iH); - if (it1 != m_SessionsByRouterHash.end ()) + auto s = FindSession (it.iH); + if (s) { - auto s = it1->second.lock (); - if (s) + auto addr = s->GetAddress (); + if (addr && addr->IsIntroducer ()) { - auto addr = s->GetAddress (); - if (addr && addr->IsIntroducer ()) - { - s->Introduce (session, it.iTag); - return; - } - } + s->Introduce (session, it.iTag); + return; + } } else indices.push_back(i); @@ -959,10 +960,7 @@ namespace transport if (!router) return false; auto addr = v4 ? router->GetSSU2V4Address () : router->GetSSU2V6Address (); if (!addr) return false; - std::shared_ptr session; - auto it = m_SessionsByRouterHash.find (router->GetIdentHash ()); - if (it != m_SessionsByRouterHash.end ()) - session = it->second.lock (); + auto session = FindSession (router->GetIdentHash ()); if (session) { auto remoteAddr = session->GetAddress (); @@ -992,17 +990,20 @@ namespace transport if (ecode != boost::asio::error::operation_aborted) { auto ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it = m_PendingOutgoingSessions.begin (); it != m_PendingOutgoingSessions.end ();) + { - if (it->second->IsTerminationTimeoutExpired (ts)) + std::lock_guard l(m_PendingOutgoingSessionsMutex); + for (auto it = m_PendingOutgoingSessions.begin (); it != m_PendingOutgoingSessions.end ();) { - //it->second->Terminate (); - std::unique_lock l(m_PendingOutgoingSessionsMutex); - it = m_PendingOutgoingSessions.erase (it); + if (it->second->IsTerminationTimeoutExpired (ts)) + { + //it->second->Terminate (); + it = m_PendingOutgoingSessions.erase (it); + } + else + it++; } - else - it++; - } + } for (auto it: m_Sessions) { @@ -1020,14 +1021,6 @@ namespace transport it.second->CleanUp (ts); } - for (auto it = m_SessionsByRouterHash.begin (); it != m_SessionsByRouterHash.begin ();) - { - if (it->second.expired ()) - it = m_SessionsByRouterHash.erase (it); - else - it++; - } - ScheduleTermination (); } } @@ -1083,6 +1076,17 @@ namespace transport else it++; } + + { + std::lock_guard l(m_SessionsByRouterHashMutex); + for (auto it = m_SessionsByRouterHash.begin (); it != m_SessionsByRouterHash.begin ();) + { + if (it->second.expired ()) + it = m_SessionsByRouterHash.erase (it); + else + it++; + } + } m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); @@ -1204,27 +1208,26 @@ namespace transport std::unordered_set excluded; for (const auto& it : introducers) { - std::shared_ptr session; - auto it1 = m_SessionsByRouterHash.find (it); - if (it1 != m_SessionsByRouterHash.end ()) - { - session = it1->second.lock (); + std::shared_ptr session = FindSession (it); + if (session) excluded.insert (it); - } - if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer? - ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + if (session) { - session->SendKeepAlive (); - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) - newList.push_back (it); - else + if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer? + ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { - impliedList.push_back (it); // keep in introducers list, but not publish - session = nullptr; - } + session->SendKeepAlive (); + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + newList.push_back (it); + else + { + impliedList.push_back (it); // keep in introducers list, but not publish + session = nullptr; + } + } + else + session = nullptr; } - else - session = nullptr; if (!session) i2p::context.RemoveSSU2Introducer (it, v4); @@ -1239,16 +1242,12 @@ namespace transport impliedList.clear (); for (auto& it : introducers) { - auto it1 = m_SessionsByRouterHash.find (it); - if (it1 != m_SessionsByRouterHash.end ()) + auto session = FindSession (it); + if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { - auto session = it1->second.lock (); - if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) - { - session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); - if (std::find (newList.begin (), newList.end (), it) == newList.end ()) - sessions.push_back (session); - } + session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); + if (std::find (newList.begin (), newList.end (), it) == newList.end ()) + sessions.push_back (session); } } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 2c5e8cc6fae..06541010758 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -164,6 +164,7 @@ namespace transport boost::asio::ip::address m_AddressV4, m_AddressV6; std::unordered_map > m_Sessions; std::unordered_map > m_SessionsByRouterHash; + mutable std::mutex m_SessionsByRouterHashMutex; std::map > m_PendingOutgoingSessions; mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) From 75b1c144b4b5260b505bb6444f64cbd79d0e801f Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Sep 2024 08:48:17 -0400 Subject: [PATCH 096/131] drop too short follow on SSU2 packets --- libi2pd/SSU2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index b5b9d25c452..4293c2d5def 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -377,7 +377,10 @@ namespace transport if (!ec) { i2p::transport::transports.UpdateReceivedBytes (packet->len); - packets.push_back (packet); + if (packet->len >= SSU2_MIN_RECEIVED_PACKET_SIZE) + packets.push_back (packet); + else // drop too short packets + m_PacketsPool.ReleaseMt (packet); moreBytes = socket.available(ec); if (ec) break; } From a06cce0aaf3fcf4326dc51625c38df8453422e19 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Sep 2024 15:54:29 -0400 Subject: [PATCH 097/131] eliminate extra copy of vector of SSU2 packets --- libi2pd/SSU2.cpp | 9 ++++++--- libi2pd/SSU2.h | 2 +- libi2pd/util.h | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 4293c2d5def..80ddbed48c7 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -391,7 +391,10 @@ namespace transport break; } } - GetService ().post (std::bind (&SSU2Server::HandleReceivedPackets, this, packets)); + GetService ().post ([packets = std::move (packets), this]() mutable + { + HandleReceivedPackets (std::move (packets)); + }); } else GetService ().post (std::bind (&SSU2Server::HandleReceivedPacket, this, packet)); @@ -435,7 +438,7 @@ namespace transport } } - void SSU2Server::HandleReceivedPackets (std::vector packets) + void SSU2Server::HandleReceivedPackets (std::vector&& packets) { if (m_IsThroughProxy) for (auto& packet: packets) @@ -443,7 +446,7 @@ namespace transport else for (auto& packet: packets) ProcessNextPacket (packet->buf, packet->len, packet->from); - m_PacketsPool.ReleaseMt (packets); + m_PacketsPool.ReleaseMt (std::move (packets)); if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 06541010758..381b90c8c74 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -126,7 +126,7 @@ namespace transport void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred, Packet * packet, boost::asio::ip::udp::socket& socket); void HandleReceivedPacket (Packet * packet); - void HandleReceivedPackets (std::vector packets); + void HandleReceivedPackets (std::vector&& packets); void ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); void ScheduleTermination (); diff --git a/libi2pd/util.h b/libi2pd/util.h index e2037212f47..dbc69c250ce 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -132,7 +132,7 @@ namespace util } templateclass C, typename... R> - void ReleaseMt(const C& c) + void ReleaseMt(C&& c) { std::lock_guard l(m_Mutex); for (auto& it: c) From c3a1631319cb770bef735a5d28ce96f2ea44ba87 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Sep 2024 18:38:17 -0400 Subject: [PATCH 098/131] use weak_ptr for Bob's peer tests and relay tags --- libi2pd/SSU2.cpp | 15 +++++++------ libi2pd/SSU2.h | 3 ++- libi2pd/SSU2Session.cpp | 48 ++++++++++++++++++++++------------------- libi2pd/SSU2Session.h | 2 +- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 80ddbed48c7..6378d7b8d21 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -370,7 +370,7 @@ namespace transport { std::vector packets; packets.push_back (packet); - while (moreBytes && packets.size () < 32) + while (moreBytes && packets.size () < SSU2_MAX_NUM_PACKETS_PER_BATCH) { packet = m_PacketsPool.AcquireMt (); packet->len = socket.receive_from (boost::asio::buffer (packet->buf, SSU2_MAX_PACKET_SIZE), packet->from, 0, ec); @@ -599,10 +599,13 @@ namespace transport auto it = m_Relays.find (tag); if (it != m_Relays.end ()) { - if (it->second->IsEstablished ()) - return it->second; - else - m_Relays.erase (it); + if (!it->second.expired ()) + { + auto s = it->second.lock (); + if (s && s->IsEstablished ()) + return s; + } + m_Relays.erase (it); } return nullptr; } @@ -1045,7 +1048,7 @@ namespace transport auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_Relays.begin (); it != m_Relays.begin ();) { - if (it->second && it->second->GetState () == eSSU2SessionStateTerminated) + if (it->second.expired ()) it = m_Relays.erase (it); else it++; diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 381b90c8c74..bae33aa29e2 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -40,6 +40,7 @@ namespace transport const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds const int SSU2_HOLE_PUNCH_EXPIRATION = 150; // in seconds + const size_t SSU2_MAX_NUM_PACKETS_PER_BATCH = 32; class SSU2Server: private i2p::util::RunnableServiceWithWork { @@ -168,7 +169,7 @@ namespace transport std::map > m_PendingOutgoingSessions; mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) - std::unordered_map > m_Relays; // we are introducer, relay tag -> session + std::unordered_map > m_Relays; // we are introducer, relay tag -> session std::list m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPool m_SentPacketsPool; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bc47690dc45..e9994b9f34c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2252,27 +2252,31 @@ namespace transport case 3: // Bob from Charlie { auto it = m_PeerTests.find (nonce); - if (it != m_PeerTests.end () && it->second.first) + if (it != m_PeerTests.end ()) { - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - // Charlie's RouterInfo - auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); - if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; - size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; - if (!payloadSize && r) - it->second.first->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); - if (payloadSize + len + 16 > m_MaxPayloadSize) - { - // doesn't fit one message, send RouterInfo in separate message - it->second.first->SendData (payload, payloadSize); - payloadSize = 0; - } - // PeerTest to Alice - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, - (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); - if (payloadSize < m_MaxPayloadSize) - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - it->second.first->SendData (payload, payloadSize); + auto aliceSession = it->second.first.lock (); + if (aliceSession && aliceSession->IsEstablished ()) + { + uint8_t payload[SSU2_MAX_PACKET_SIZE]; + // Charlie's RouterInfo + auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); + if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; + size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; + if (!payloadSize && r) + aliceSession->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); + if (payloadSize + len + 16 > m_MaxPayloadSize) + { + // doesn't fit one message, send RouterInfo in separate message + aliceSession->SendData (payload, payloadSize); + payloadSize = 0; + } + // PeerTest to Alice + payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, + (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + aliceSession->SendData (payload, payloadSize); + } m_PeerTests.erase (it); } else @@ -3028,9 +3032,9 @@ namespace transport } for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();) { - if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT) + if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT || it->second.first.expired ()) { - LogPrint (eLogWarning, "SSU2: Peer test nonce ", it->first, " was not responded in ", SSU2_PEER_TEST_EXPIRATION_TIMEOUT, " seconds, deleted"); + LogPrint (eLogWarning, "SSU2: Peer test nonce ", it->first, " was not responded in ", SSU2_PEER_TEST_EXPIRATION_TIMEOUT, " seconds or session invalid. Deleted"); it = m_PeerTests.erase (it); } else diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index d261bc6dc1a..fdd7cc8eaec 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -373,7 +373,7 @@ namespace transport std::map > m_SentPackets; // packetNum -> packet std::unordered_map > m_IncompleteMessages; // msgID -> I2NP std::unordered_map, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice - std::unordered_map, uint64_t > > m_PeerTests; // same as for relay sessions + std::unordered_map, uint64_t > > m_PeerTests; // nonce->(Alice, timestamp). We are Bob std::list > m_SendQueue; i2p::I2NPMessagesHandler m_Handler; bool m_IsDataReceived; From 64e4b3871a99989cd5f731e50fa0904698251148 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 27 Sep 2024 13:32:20 -0400 Subject: [PATCH 099/131] update introducer's iTag is session to introducer was replaced to new one --- libi2pd/RouterContext.cpp | 6 ++++++ libi2pd/RouterContext.h | 1 + libi2pd/RouterInfo.cpp | 18 ++++++++++++++++++ libi2pd/RouterInfo.h | 1 + libi2pd/SSU2.cpp | 33 +++++++++++++++++++++------------ libi2pd/SSU2.h | 2 +- 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index f9548139894..1efb25db3be 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -557,6 +557,12 @@ namespace i2p UpdateRouterInfo (); } + void RouterContext::UpdateSSU2Introducer (const i2p::data::IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp) + { + if (m_RouterInfo.UpdateSSU2Introducer (h, v4, iTag, iExp)) + UpdateRouterInfo (); + } + void RouterContext::ClearSSU2Introducers (bool v4) { auto addr = m_RouterInfo.GetSSU2Address (v4); diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 03f1d10d5ad..c620f8b138d 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -154,6 +154,7 @@ namespace garlic void PublishSSU2Address (int port, bool publish, bool v4, bool v6); bool AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4); void RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4); + void UpdateSSU2Introducer (const i2p::data::IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp); void ClearSSU2Introducers (bool v4); bool IsUnreachable () const; void SetUnreachable (bool v4, bool v6); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index ce1ae72c5dd..2da40ae89fe 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1554,5 +1554,23 @@ namespace data } return false; } + + bool LocalRouterInfo::UpdateSSU2Introducer (const IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp) + { + auto addresses = GetAddresses (); + if (!addresses) return false; + auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; + if (addr) + { + for (auto& it: addr->ssu->introducers) + if (h == it.iH) + { + it.iTag = iTag; + it.iExp = iExp; + return true; + } + } + return false; + } } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 68d6b0f032e..72521797b01 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -380,6 +380,7 @@ namespace data bool AddSSU2Introducer (const Introducer& introducer, bool v4); bool RemoveSSU2Introducer (const IdentHash& h, bool v4); + bool UpdateSSU2Introducer (const IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp); private: diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6378d7b8d21..d661c33b3fb 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1212,14 +1212,14 @@ namespace transport void SSU2Server::UpdateIntroducers (bool v4) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - std::list newList, impliedList; + std::list > newList, impliedList; auto& introducers = v4 ? m_Introducers : m_IntroducersV6; std::unordered_set excluded; - for (const auto& it : introducers) + for (const auto& [ident, tag] : introducers) { - std::shared_ptr session = FindSession (it); + std::shared_ptr session = FindSession (ident); if (session) - excluded.insert (it); + excluded.insert (ident); if (session) { if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing () && // still session with introducer? @@ -1227,19 +1227,27 @@ namespace transport { session->SendKeepAlive (); if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) - newList.push_back (it); + { + newList.push_back ({ident, session->GetRelayTag ()}); + if (tag != session->GetRelayTag ()) + { + LogPrint (eLogDebug, "SSU2: Introducer session to ", session->GetIdentHashBase64() , " was replaced. iTag ", tag, "->", session->GetRelayTag ()); + i2p::context.UpdateSSU2Introducer (ident, v4, session->GetRelayTag (), + session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION); + } + } else { - impliedList.push_back (it); // keep in introducers list, but not publish + impliedList.push_back ({ident, session->GetRelayTag ()}); // keep in introducers list, but not publish session = nullptr; - } + } } else session = nullptr; } if (!session) - i2p::context.RemoveSSU2Introducer (it, v4); + i2p::context.RemoveSSU2Introducer (ident, v4); } if (newList.size () < SSU2_MAX_NUM_INTRODUCERS) { @@ -1249,13 +1257,14 @@ namespace transport // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); impliedList.clear (); - for (auto& it : introducers) + for (const auto& [ident, tag] : introducers) { - auto session = FindSession (it); + auto session = FindSession (ident); if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); - if (std::find (newList.begin (), newList.end (), it) == newList.end ()) + if (std::find_if (newList.begin (), newList.end (), + [&ident](const auto& s){ return ident == s.first; }) == newList.end ()) sessions.push_back (session); } } @@ -1276,7 +1285,7 @@ namespace transport { LogPrint (eLogDebug, "SSU2: Introducer added ", it->GetRelayTag (), " at ", i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ())); - newList.push_back (it->GetRemoteIdentity ()->GetIdentHash ()); + newList.push_back ({ it->GetRemoteIdentity ()->GetIdentHash (), tag }); if (newList.size () >= SSU2_MAX_NUM_INTRODUCERS) break; } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index bae33aa29e2..36b946c5f56 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -170,7 +170,7 @@ namespace transport mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) std::unordered_map > m_Relays; // we are introducer, relay tag -> session - std::list m_Introducers, m_IntroducersV6; // introducers we are connected to + std::list > m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPool m_SentPacketsPool; i2p::util::MemoryPool m_IncompleteMessagesPool; From 62b811c2c150dd502bde36f9960a8ece112c992c Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 28 Sep 2024 09:49:45 -0400 Subject: [PATCH 100/131] use memory pool for SSU2 received packets arrays --- libi2pd/SSU2.cpp | 36 ++++++++++++++++++++++++------------ libi2pd/SSU2.h | 18 +++++++++++++++++- libi2pd/util.h | 12 ++++++++++-- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index d661c33b3fb..ec36d6fbbcb 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -368,9 +368,9 @@ namespace transport size_t moreBytes = socket.available (ec); if (!ec && moreBytes) { - std::vector packets; - packets.push_back (packet); - while (moreBytes && packets.size () < SSU2_MAX_NUM_PACKETS_PER_BATCH) + auto packets = m_PacketsArrayPool.AcquireMt (); + packets->AddPacket (packet); + while (moreBytes && packets->numPackets < SSU2_MAX_NUM_PACKETS_PER_BATCH) { packet = m_PacketsPool.AcquireMt (); packet->len = socket.receive_from (boost::asio::buffer (packet->buf, SSU2_MAX_PACKET_SIZE), packet->from, 0, ec); @@ -378,7 +378,13 @@ namespace transport { i2p::transport::transports.UpdateReceivedBytes (packet->len); if (packet->len >= SSU2_MIN_RECEIVED_PACKET_SIZE) - packets.push_back (packet); + { + if (!packets->AddPacket (packet)) + { + LogPrint (eLogError, "SSU2: Received packets array is full"); + m_PacketsPool.ReleaseMt (packet); + } + } else // drop too short packets m_PacketsPool.ReleaseMt (packet); moreBytes = socket.available(ec); @@ -391,10 +397,7 @@ namespace transport break; } } - GetService ().post ([packets = std::move (packets), this]() mutable - { - HandleReceivedPackets (std::move (packets)); - }); + GetService ().post (std::bind (&SSU2Server::HandleReceivedPackets, this, packets)); } else GetService ().post (std::bind (&SSU2Server::HandleReceivedPacket, this, packet)); @@ -438,15 +441,23 @@ namespace transport } } - void SSU2Server::HandleReceivedPackets (std::vector&& packets) + void SSU2Server::HandleReceivedPackets (Packets * packets) { + if (!packets) return; if (m_IsThroughProxy) - for (auto& packet: packets) + for (size_t i = 0; i < packets->numPackets; i++) + { + auto& packet = (*packets)[i]; ProcessNextPacketFromProxy (packet->buf, packet->len); + } else - for (auto& packet: packets) + for (size_t i = 0; i < packets->numPackets; i++) + { + auto& packet = (*packets)[i]; ProcessNextPacket (packet->buf, packet->len, packet->from); - m_PacketsPool.ReleaseMt (std::move (packets)); + } + m_PacketsPool.ReleaseMt (packets->data (), packets->numPackets); + m_PacketsArrayPool.ReleaseMt (packets); if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) m_LastSession->FlushData (); } @@ -1098,6 +1109,7 @@ namespace transport } m_PacketsPool.CleanUpMt (); + m_PacketsArrayPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); m_IncompleteMessagesPool.CleanUp (); m_FragmentsPool.CleanUp (); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 36b946c5f56..97ef879ff64 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "util.h" @@ -51,6 +52,20 @@ namespace transport boost::asio::ip::udp::endpoint from; }; + struct Packets: public std::array + { + size_t numPackets = 0; + bool AddPacket (Packet *p) + { + if (p && numPackets < size ()) + { + data()[numPackets] = p; numPackets++; + return true; + } + return false; + } + }; + class ReceiveService: public i2p::util::RunnableService { public: @@ -127,7 +142,7 @@ namespace transport void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred, Packet * packet, boost::asio::ip::udp::socket& socket); void HandleReceivedPacket (Packet * packet); - void HandleReceivedPackets (std::vector&& packets); + void HandleReceivedPackets (Packets * packets); void ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); void ScheduleTermination (); @@ -172,6 +187,7 @@ namespace transport std::unordered_map > m_Relays; // we are introducer, relay tag -> session std::list > m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; + i2p::util::MemoryPoolMt m_PacketsArrayPool; i2p::util::MemoryPool m_SentPacketsPool; i2p::util::MemoryPool m_IncompleteMessagesPool; i2p::util::MemoryPool m_FragmentsPool; diff --git a/libi2pd/util.h b/libi2pd/util.h index dbc69c250ce..e39a9259789 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -131,14 +131,22 @@ namespace util this->Release (t); } + void ReleaseMt (T * * arr, size_t num) + { + if (!arr || !num) return; + std::lock_guard l(m_Mutex); + for (size_t i = 0; i < num; i++) + this->Release (arr[i]); + } + templateclass C, typename... R> - void ReleaseMt(C&& c) + void ReleaseMt(const C& c) { std::lock_guard l(m_Mutex); for (auto& it: c) this->Release (it); } - + template std::shared_ptr AcquireSharedMt (TArgs&&... args) { From abbe1fea64d669720b94dfb083204b284e8bdfd6 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 28 Sep 2024 16:20:59 -0400 Subject: [PATCH 101/131] fixed clang build error --- libi2pd/SSU2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index ec36d6fbbcb..86cd335f023 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1269,14 +1269,14 @@ namespace transport // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); impliedList.clear (); - for (const auto& [ident, tag] : introducers) + for (const auto& it : introducers) { - auto session = FindSession (ident); + auto session = FindSession (it.first); if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find_if (newList.begin (), newList.end (), - [&ident](const auto& s){ return ident == s.first; }) == newList.end ()) + [&ident = it.first](const auto& s){ return ident == s.first; }) == newList.end ()) sessions.push_back (session); } } From 15cd4feade93a217313a234deb0d40459280972d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 28 Sep 2024 22:05:25 -0400 Subject: [PATCH 102/131] move Bob's peer tests from SSU2 session to server --- libi2pd/SSU2.cpp | 29 +++++++++++++++++++ libi2pd/SSU2.h | 4 +++ libi2pd/SSU2Session.cpp | 62 +++++++++++++++-------------------------- libi2pd/SSU2Session.h | 1 - 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 86cd335f023..016802163a6 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -152,6 +152,7 @@ namespace transport m_SessionsByRouterHash.clear (); m_PendingOutgoingSessions.clear (); m_Relays.clear (); + m_PeerTests.clear (); m_Introducers.clear (); m_IntroducersV6.clear (); m_ConnectedRecently.clear (); @@ -621,6 +622,23 @@ namespace transport return nullptr; } + bool SSU2Server::AddPeerTest (uint32_t nonce, std::shared_ptr aliceSession, uint64_t ts) + { + return m_PeerTests.emplace (nonce, std::pair{ aliceSession, ts }).second; + } + + std::shared_ptr SSU2Server::GetPeerTest (uint32_t nonce) + { + auto it = m_PeerTests.find (nonce); + if (it != m_PeerTests.end ()) + { + auto s = it->second.first.lock (); + m_PeerTests.erase (it); + return s; + } + return nullptr; + } + bool SSU2Server::AddRequestedPeerTest (uint32_t nonce, std::shared_ptr session, uint64_t ts) { return m_RequestedPeerTests.emplace (nonce, std::pair{ session, ts }).second; @@ -1065,6 +1083,17 @@ namespace transport it++; } + for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();) + { + if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT || it->second.first.expired ()) + { + LogPrint (eLogInfo, "SSU2: Peer test nonce ", it->first, " was not responded in ", SSU2_PEER_TEST_EXPIRATION_TIMEOUT, " seconds or session invalid. Deleted"); + it = m_PeerTests.erase (it); + } + else + it++; + } + for (auto it = m_IncomingTokens.begin (); it != m_IncomingTokens.end (); ) { if (ts > it->second.second) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 97ef879ff64..06267ad47b8 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -111,6 +111,9 @@ namespace transport void RemoveRelay (uint32_t tag); std::shared_ptr FindRelaySession (uint32_t tag); + bool AddPeerTest (uint32_t nonce, std::shared_ptr aliceSession, uint64_t ts); + std::shared_ptr GetPeerTest (uint32_t nonce); + bool AddRequestedPeerTest (uint32_t nonce, std::shared_ptr session, uint64_t ts); std::shared_ptr GetRequestedPeerTest (uint32_t nonce); @@ -185,6 +188,7 @@ namespace transport mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) std::unordered_map > m_Relays; // we are introducer, relay tag -> session + std::unordered_map, uint64_t > > m_PeerTests; // nonce->(Alice, timestamp). We are Bob std::list > m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPoolMt m_PacketsArrayPool; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index e9994b9f34c..027c6d9aee6 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -283,7 +283,6 @@ namespace transport m_SentPackets.clear (); m_IncompleteMessages.clear (); m_RelaySessions.clear (); - m_PeerTests.clear (); m_ReceivedI2NPMsgIDs.clear (); m_Server.RemoveSession (m_SourceConnID); transports.PeerDisconnected (shared_from_this ()); @@ -2145,7 +2144,7 @@ namespace transport GetRemoteIdentity ()->GetIdentHash ()); if (session) // session with Charlie { - session->m_PeerTests.emplace (nonce, std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ())); + m_Server.AddPeerTest (nonce, shared_from_this (), ts/1000); auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); // Alice's RouterInfo auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); @@ -2251,34 +2250,29 @@ namespace transport } case 3: // Bob from Charlie { - auto it = m_PeerTests.find (nonce); - if (it != m_PeerTests.end ()) - { - auto aliceSession = it->second.first.lock (); - if (aliceSession && aliceSession->IsEstablished ()) - { - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - // Charlie's RouterInfo - auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); - if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; - size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; - if (!payloadSize && r) - aliceSession->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); - if (payloadSize + len + 16 > m_MaxPayloadSize) - { - // doesn't fit one message, send RouterInfo in separate message - aliceSession->SendData (payload, payloadSize); - payloadSize = 0; - } - // PeerTest to Alice - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, - (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); - if (payloadSize < m_MaxPayloadSize) - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + auto aliceSession = m_Server.GetPeerTest (nonce); + if (aliceSession && aliceSession->IsEstablished ()) + { + uint8_t payload[SSU2_MAX_PACKET_SIZE]; + // Charlie's RouterInfo + auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); + if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; + size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; + if (!payloadSize && r) + aliceSession->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); + if (payloadSize + len + 16 > m_MaxPayloadSize) + { + // doesn't fit one message, send RouterInfo in separate message aliceSession->SendData (payload, payloadSize); - } - m_PeerTests.erase (it); - } + payloadSize = 0; + } + // PeerTest to Alice + payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, + (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + aliceSession->SendData (payload, payloadSize); + } else LogPrint (eLogWarning, "SSU2: Unknown peer test 3 nonce ", nonce); break; @@ -3030,16 +3024,6 @@ namespace transport else ++it; } - for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();) - { - if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT || it->second.first.expired ()) - { - LogPrint (eLogWarning, "SSU2: Peer test nonce ", it->first, " was not responded in ", SSU2_PEER_TEST_EXPIRATION_TIMEOUT, " seconds or session invalid. Deleted"); - it = m_PeerTests.erase (it); - } - else - ++it; - } if (m_PathChallenge) RequestTermination (eSSU2TerminationReasonNormalClose); } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index fdd7cc8eaec..caa16c013e1 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -373,7 +373,6 @@ namespace transport std::map > m_SentPackets; // packetNum -> packet std::unordered_map > m_IncompleteMessages; // msgID -> I2NP std::unordered_map, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice - std::unordered_map, uint64_t > > m_PeerTests; // nonce->(Alice, timestamp). We are Bob std::list > m_SendQueue; i2p::I2NPMessagesHandler m_Handler; bool m_IsDataReceived; From 6ebb019e15fe796f3b5776f422964a24f7770cac Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 15:02:18 -0400 Subject: [PATCH 103/131] resend peer test msgs 5 and 6 --- libi2pd/SSU2Session.cpp | 59 ++++++++++++++++++++++++++++++++++++----- libi2pd/SSU2Session.h | 14 ++++++++-- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 027c6d9aee6..1ad80fae747 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -3045,7 +3045,8 @@ namespace transport SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID): SSU2Session (server, nullptr, nullptr, false), - m_MsgNumReceived (0), m_IsConnectedRecently (false), m_IsStatusChanged (false) + m_MsgNumReceived (0), m_NumResends (0),m_IsConnectedRecently (false), m_IsStatusChanged (false), + m_PeerTestResendTimer (server.GetService ()) { if (!sourceConnID) sourceConnID = ~destConnID; if (!destConnID) destConnID = ~sourceConnID; @@ -3097,9 +3098,10 @@ namespace transport // msgs 5-7 if (len < 8) return; uint8_t msg = buf[0]; - if (msg < m_MsgNumReceived) + if (msg <= m_MsgNumReceived) { - LogPrint (eLogInfo, "SSU2: PeerTest msg num ", msg, " received after ", m_MsgNumReceived, ". Ignored"); + LogPrint (eLogDebug, "SSU2: PeerTest msg num ", msg, " received after ", m_MsgNumReceived, ". Ignored"); + return; } size_t offset = 3; // points to signed data after msg + code + flag uint32_t nonce = bufbe32toh (buf + offset + 1); // 1 - ver @@ -3125,6 +3127,7 @@ namespace transport } case 6: // Charlie from Alice { + m_PeerTestResendTimer.cancel (); // no more msg 5 resends if (GetAddress ()) SendPeerTest (7, buf + offset, len - offset); else @@ -3135,6 +3138,7 @@ namespace transport } case 7: // Alice from Charlie 2 { + m_PeerTestResendTimer.cancel (); // no more msg 6 resends auto addr = GetAddress (); if (addr && addr->IsV6 ()) i2p::context.SetStatusV6 (eRouterStatusOK); // set status OK for ipv6 even if from SSU2 @@ -3149,7 +3153,7 @@ namespace transport m_MsgNumReceived = msg; } - void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen) + void SSU2PeerTestSession::SendPeerTest (uint8_t msg) { auto addr = GetAddress (); if (!addr) return; @@ -3172,7 +3176,7 @@ namespace transport if (msg == 6 || msg == 7) payloadSize += CreateAddressBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, GetRemoteEndpoint ()); payloadSize += CreatePeerTestBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, - msg, eSSU2PeerTestCodeAccept, nullptr, signedData, signedDataLen); + msg, eSSU2PeerTestCodeAccept, nullptr, m_SignedData.data (), m_SignedData.size ()); payloadSize += CreatePaddingBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize); // encrypt uint8_t n[12]; @@ -3187,12 +3191,26 @@ namespace transport GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ()); } + void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen) + { +#if __cplusplus >= 202002L // C++20 + m_SignedData.assign (signedData, signedData + signedDataLen); +#else + m_SignedData.resize (signedDataLen); + memcpy (m_SignedData.data (), signedData, signedDataLen); +#endif + SendPeerTest (msg); + // schedule resend for msgs 5 or 6 + if (msg == 5 || msg == 6) + ScheduleResend (); + } + void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, std::shared_ptr addr) { if (!addr) return; SetAddress (addr); - SendPeerTest (msg, signedData, signedDataLen); + SendPeerTest (msg, signedData, signedDataLen); } void SSU2PeerTestSession::Connect () @@ -3205,5 +3223,34 @@ namespace transport LogPrint (eLogError, "SSU2: Can't handle incoming message in peer test session"); return false; } + + void SSU2PeerTestSession::ScheduleResend () + { + if (m_NumResends < SSU2_PEER_TEST_MAX_NUM_RESENDS) + { + m_PeerTestResendTimer.expires_from_now (boost::posix_time::milliseconds( + SSU2_PEER_TEST_RESEND_INTERVAL + GetServer ().GetRng ()() % SSU2_PEER_TEST_RESEND_INTERVAL_VARIANCE)); + std::weak_ptr s(std::static_pointer_cast(shared_from_this ())); + m_PeerTestResendTimer.async_wait ([s](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto s1 = s.lock (); + if (s1) + { + int msg = 0; + if (s1->m_MsgNumReceived < 6) + msg = (s1->m_MsgNumReceived == 5) ? 6 : 5; + if (msg) // 5 or 6 + { + s1->SendPeerTest (msg); + s1->ScheduleResend (); + } + } + } + }); + m_NumResends++; + } + } } } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index caa16c013e1..6811d3a7d21 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -390,6 +390,11 @@ namespace transport uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds }; + + const int SSU2_PEER_TEST_RESEND_INTERVAL = 3000; // in milliseconds + const int SSU2_PEER_TEST_RESEND_INTERVAL_VARIANCE = 2000; // in milliseconds + const int SSU2_PEER_TEST_MAX_NUM_RESENDS = 3; + class SSU2PeerTestSession: public SSU2Session // for PeerTest msgs 5,6,7 { public: @@ -409,12 +414,17 @@ namespace transport private: void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen); // PeerTest message + void SendPeerTest (uint8_t msg); // send or resend m_SignedData void HandlePeerTest (const uint8_t * buf, size_t len) override; - + + void ScheduleResend (); + private: - uint8_t m_MsgNumReceived; + uint8_t m_MsgNumReceived, m_NumResends; bool m_IsConnectedRecently, m_IsStatusChanged; + std::vector m_SignedData; // for resends + boost::asio::deadline_timer m_PeerTestResendTimer; }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) From c2234599cd1ba9d3548d9f880c9f13106ce5ec2a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 17:11:54 -0400 Subject: [PATCH 104/131] exclude boost_system from linking because it's headers only now --- Makefile.mingw | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.mingw b/Makefile.mingw index 8db38e8f409..339cec4ef52 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -17,7 +17,6 @@ ifeq ($(USE_UPNP),yes) endif LDLIBS += \ - $(MINGW_PREFIX)/lib/libboost_system-mt.a \ $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ $(MINGW_PREFIX)/lib/libssl.a \ $(MINGW_PREFIX)/lib/libcrypto.a \ From ba41f7107d69ab1f2df5c1013f04dea580145530 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 18:17:49 -0400 Subject: [PATCH 105/131] resend peer test responses --- libi2pd/SSU2Session.cpp | 45 ++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 1ad80fae747..8874feea593 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2171,11 +2171,14 @@ namespace transport else { // Charlie not found, send error back to Alice - uint8_t payload[SSU2_MAX_PACKET_SIZE], zeroHash[32] = {0}; - size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 4, + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + uint8_t zeroHash[32] = {0}; + packet->payloadSize = CreatePeerTestBlock (packet->payload, m_MaxPayloadSize, 4, eSSU2PeerTestCodeBobNoCharlieAvailable, zeroHash, buf + offset, len - offset); - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - SendData (payload, payloadSize); + packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = SendData (packet->payload, packet->payloadSize); + packet->sendTime = ts; + m_SentPackets.emplace (packetNum, packet); } break; } @@ -2241,11 +2244,13 @@ namespace transport else code = eSSU2PeerTestCodeCharlieAliceIsUnknown; // send msg 3 back to Bob - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreatePeerTestBlock (payload, m_MaxPayloadSize, 3, + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + packet->payloadSize = CreatePeerTestBlock (packet->payload, m_MaxPayloadSize, 3, code, nullptr, newSignedData.data (), newSignedData.size ()); - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - SendData (payload, payloadSize); + packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = SendData (packet->payload, packet->payloadSize); + packet->sendTime = ts; + m_SentPackets.emplace (packetNum, packet); break; } case 3: // Bob from Charlie @@ -2253,25 +2258,29 @@ namespace transport auto aliceSession = m_Server.GetPeerTest (nonce); if (aliceSession && aliceSession->IsEstablished ()) { - uint8_t payload[SSU2_MAX_PACKET_SIZE]; + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); // Charlie's RouterInfo auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; - size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; - if (!payloadSize && r) + packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0; + if (!packet->payloadSize && r) aliceSession->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); - if (payloadSize + len + 16 > m_MaxPayloadSize) + if (packet->payloadSize + len + 16 > m_MaxPayloadSize) { // doesn't fit one message, send RouterInfo in separate message - aliceSession->SendData (payload, payloadSize); - payloadSize = 0; + uint32_t packetNum = aliceSession->SendData (packet->payload, packet->payloadSize); + packet->sendTime = ts; + aliceSession->m_SentPackets.emplace (packetNum, packet); + packet = m_Server.GetSentPacketsPool ().AcquireShared (); } // PeerTest to Alice - payloadSize += CreatePeerTestBlock (payload + payloadSize, m_MaxPayloadSize, 4, + packet->payloadSize += CreatePeerTestBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize, 4, (SSU2PeerTestCode)buf[1], GetRemoteIdentity ()->GetIdentHash (), buf + offset, len - offset); - if (payloadSize < m_MaxPayloadSize) - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - aliceSession->SendData (payload, payloadSize); + if (packet->payloadSize < m_MaxPayloadSize) + packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = aliceSession->SendData (packet->payload, packet->payloadSize); + packet->sendTime = ts; + aliceSession->m_SentPackets.emplace (packetNum, packet); } else LogPrint (eLogWarning, "SSU2: Unknown peer test 3 nonce ", nonce); From 5466983b36873db9bd23cbce73d9f2c1e6e83b9b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 20:57:18 -0400 Subject: [PATCH 106/131] resend relay messages --- libi2pd/SSU2Session.cpp | 58 +++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 8874feea593..288d11e13c7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -174,36 +174,38 @@ namespace transport // create nonce uint32_t nonce; RAND_bytes ((uint8_t *)&nonce, 4); - auto ts = i2p::util::GetSecondsSinceEpoch (); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); // payload - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = 0; + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + uint8_t * payload = packet->payload; payload[0] = eSSU2BlkRelayRequest; payload[3] = 0; // flag htobe32buf (payload + 4, nonce); htobe32buf (payload + 8, relayTag); - htobe32buf (payload + 12, ts); + htobe32buf (payload + 12, ts/1000); payload[16] = 2; // ver size_t asz = CreateEndpoint (payload + 18, m_MaxPayloadSize - 18, boost::asio::ip::udp::endpoint (localAddress->host, localAddress->port)); if (!asz) return false; payload[17] = asz; - payloadSize += asz + 18; + packet->payloadSize = asz + 18; SignedData s; s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (session->GetRemoteIdentity ()->GetIdentHash (), 32); // chash s.Insert (payload + 4, 14 + asz); // nonce, relay tag, timestamp, ver, asz and Alice's endpoint - s.Sign (i2p::context.GetPrivateKeys (), payload + payloadSize); - payloadSize += i2p::context.GetIdentity ()->GetSignatureLen (); - htobe16buf (payload + 1, payloadSize - 3); // size - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + s.Sign (i2p::context.GetPrivateKeys (), payload + packet->payloadSize); + packet->payloadSize += i2p::context.GetIdentity ()->GetSignatureLen (); + htobe16buf (payload + 1, packet->payloadSize - 3); // size + packet->payloadSize += CreatePaddingBlock (payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); // send - m_RelaySessions.emplace (nonce, std::make_pair (session, ts)); + m_RelaySessions.emplace (nonce, std::make_pair (session, ts/1000)); session->m_SourceConnID = htobe64 (((uint64_t)nonce << 32) | nonce); session->m_DestConnID = ~session->m_SourceConnID; m_Server.AddSession (session); - SendData (payload, payloadSize); - + int32_t packetNum = SendData (packet->payload, packet->payloadSize); + packet->sendTime = ts; + m_SentPackets.emplace (packetNum, packet); + return true; } @@ -1945,27 +1947,31 @@ namespace transport SendData (payload, payloadSize); return; } + auto mts = i2p::util::GetMillisecondsSinceEpoch (); session->m_RelaySessions.emplace (bufbe32toh (buf + 1), // nonce - std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ()) ); + std::make_pair (shared_from_this (), mts/1000) ); // send relay intro to Charlie auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; if (!r) LogPrint (eLogWarning, "SSU2: RelayRequest Alice's router info not found"); - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; - if (!payloadSize && r) + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0; + if (!packet->payloadSize && r) session->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); - payloadSize += CreateRelayIntroBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, buf + 1, len -1); - if (payloadSize < m_MaxPayloadSize) - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - session->SendData (payload, payloadSize); + packet->payloadSize += CreateRelayIntroBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize, buf + 1, len -1); + if (packet->payloadSize < m_MaxPayloadSize) + packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = session->SendData (packet->payload, packet->payloadSize); + packet->sendTime = mts; + session->m_SentPackets.emplace (packetNum, packet); } void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len, int attempts) { // we are Charlie + auto mts = i2p::util::GetMillisecondsSinceEpoch (); SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept; uint64_t token = 0; bool isV4 = false; @@ -1993,7 +1999,7 @@ namespace transport token = m_Server.GetIncomingToken (ep); isV4 = ep.address ().is_v4 (); SendHolePunch (bufbe32toh (buf + 33), ep, addr->i, token); - m_Server.AddConnectedRecently (ep, i2p::util::GetSecondsSinceEpoch ()); + m_Server.AddConnectedRecently (ep, mts/1000); } else { @@ -2038,11 +2044,13 @@ namespace transport code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; } // send relay response to Bob - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreateRelayResponseBlock (payload, m_MaxPayloadSize, + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + packet->payloadSize = CreateRelayResponseBlock (packet->payload, m_MaxPayloadSize, code, bufbe32toh (buf + 33), token, isV4); - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - SendData (payload, payloadSize); + packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = SendData (packet->payload, packet->payloadSize); + packet->sendTime = mts; + m_SentPackets.emplace (packetNum, packet); } void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len) From 237d9474d87331df1ccac2c9fd66b2f4f252570f Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 21:43:47 -0400 Subject: [PATCH 107/131] fixed incomplete response --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 7a6656dcd01..21c7b6c692a 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1480,7 +1480,7 @@ namespace http { reply.body = content; m_SendBuffer = reply.to_string(); - boost::asio::async_write (*m_Socket, boost::asio::buffer(m_SendBuffer), + boost::asio::async_write (*m_Socket, boost::asio::buffer(m_SendBuffer), boost::asio::transfer_all (), std::bind (&HTTPConnection::Terminate, shared_from_this (), std::placeholders::_1)); } From d5213505882207784cdde04f626541fb2f8742e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Sep 2024 22:15:03 -0400 Subject: [PATCH 108/131] resend relay response --- libi2pd/SSU2Session.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 288d11e13c7..ac0a828c34c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2078,13 +2078,16 @@ namespace transport if (it->second.first && it->second.first->IsEstablished ()) { // we are Bob, message from Charlie - uint8_t payload[SSU2_MAX_PACKET_SIZE]; + auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + uint8_t * payload = packet->payload; payload[0] = eSSU2BlkRelayResponse; htobe16buf (payload + 1, len); memcpy (payload + 3, buf, len); // forward to Alice as is - size_t payloadSize = len + 3; - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - it->second.first->SendData (payload, payloadSize); + packet->payloadSize = len + 3; + packet->payloadSize += CreatePaddingBlock (payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); + uint32_t packetNum = it->second.first->SendData (packet->payload, packet->payloadSize); + packet->sendTime = i2p::util::GetMillisecondsSinceEpoch (); + it->second.first->m_SentPackets.emplace (packetNum, packet); } else { From 0f5e8d842428c365b6346d43f201f78cd592434a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Sep 2024 14:54:20 -0400 Subject: [PATCH 109/131] don't print warning if duplicated nonce or peer test --- libi2pd/SSU2Session.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index ac0a828c34c..81367e4b9d3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2127,14 +2127,14 @@ namespace transport } else { - LogPrint (eLogInfo, "SSU2: RelayResponse status code=", (int)buf[1]); + LogPrint (eLogInfo, "SSU2: RelayResponse status code=", (int)buf[1], " nonce=", bufbe32toh (buf + 2)); it->second.first->Done (); } } m_RelaySessions.erase (it); } else - LogPrint (eLogWarning, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2)); + LogPrint (eLogDebug, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2)); } void SSU2Session::HandlePeerTest (const uint8_t * buf, size_t len) @@ -2294,7 +2294,7 @@ namespace transport aliceSession->m_SentPackets.emplace (packetNum, packet); } else - LogPrint (eLogWarning, "SSU2: Unknown peer test 3 nonce ", nonce); + LogPrint (eLogDebug, "SSU2: Unknown peer test 3 nonce ", nonce); break; } case 4: // Alice from Bob @@ -2382,7 +2382,7 @@ namespace transport } } else - LogPrint (eLogWarning, "SSU2: Unknown peer test 4 nonce ", nonce); + LogPrint (eLogDebug, "SSU2: Unknown peer test 4 nonce ", nonce); break; } default: From 98e93468a65175a4f2b6f0d068573c5522fe9465 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Sep 2024 18:12:42 -0400 Subject: [PATCH 110/131] send ack to relay messages --- libi2pd/SSU2Session.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 81367e4b9d3..47af9844abe 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1570,14 +1570,17 @@ namespace transport case eSSU2BlkRelayRequest: LogPrint (eLogDebug, "SSU2: RelayRequest"); HandleRelayRequest (buf + offset, size); + m_IsDataReceived = true; break; case eSSU2BlkRelayResponse: LogPrint (eLogDebug, "SSU2: RelayResponse"); HandleRelayResponse (buf + offset, size); + m_IsDataReceived = true; break; case eSSU2BlkRelayIntro: LogPrint (eLogDebug, "SSU2: RelayIntro"); HandleRelayIntro (buf + offset, size); + m_IsDataReceived = true; break; case eSSU2BlkPeerTest: LogPrint (eLogDebug, "SSU2: PeerTest msg=", (int)buf[offset], " code=", (int)buf[offset+1]); From e1e530b4a91e944fb001dc15b6adbaea9bbf603f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Sep 2024 18:27:13 -0400 Subject: [PATCH 111/131] never send Ack to HolePunch and PeerTest messages --- libi2pd/SSU2Session.cpp | 2 ++ libi2pd/SSU2Session.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 47af9844abe..fc11f556d87 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1420,6 +1420,7 @@ namespace transport return false; } HandlePayload (payload, len - 48); + m_IsDataReceived = false; // connect to Charlie ConnectAfterIntroduction (); @@ -3113,6 +3114,7 @@ namespace transport return false; } HandlePayload (payload, len - 48); + SetIsDataReceived (false); return true; } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 6811d3a7d21..49bd3be6a57 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -282,6 +282,7 @@ namespace transport RouterStatus GetRouterStatus () const; void SetRouterStatus (RouterStatus status) const; size_t GetMaxPayloadSize () const { return m_MaxPayloadSize; } + void SetIsDataReceived (bool dataReceived) { m_IsDataReceived = dataReceived; }; uint64_t GetSourceConnID () const { return m_SourceConnID; } void SetSourceConnID (uint64_t sourceConnID) { m_SourceConnID = sourceConnID; } From 600f36539fd2c0060ae3db3624469980097ddfc8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Sep 2024 22:38:42 -0400 Subject: [PATCH 112/131] don't change ConnIDs of just introduced session. Let Charlie recognize SessionRequest --- libi2pd/SSU2Session.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index fc11f556d87..d5423fae315 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -219,15 +219,22 @@ namespace transport { if (m_State == eSSU2SessionStateIntroduced) { - // create new connID - uint64_t oldConnID = GetConnID (); - RAND_bytes ((uint8_t *)&m_DestConnID, 8); - RAND_bytes ((uint8_t *)&m_SourceConnID, 8); - // connect + // we are Alice + // keep ConnIDs used for introduction, because Charlie waits for SessionRequest from us m_State = eSSU2SessionStateTokenReceived; - m_Server.AddPendingOutgoingSession (shared_from_this ()); - m_Server.RequestRemoveSession (oldConnID); - Connect (); + // move session to pending outgoing + if (m_Server.AddPendingOutgoingSession (shared_from_this ())) + { + m_Server.RemoveSession (GetConnID ()); + // connect + LogPrint (eLogDebug, "SSU2: Connecting after introduction to ", GetIdentHashBase64()); + Connect (); + } + else + { + LogPrint (eLogError, "SSU2: Session ", GetConnID (), " is already pending"); + m_Server.RequestRemoveSession (GetConnID ()); + } } } From eed48c43fd90e094ca00b4e0c4bd30a70c1d2051 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 1 Oct 2024 15:29:48 -0400 Subject: [PATCH 113/131] don't change Firewalled status to Unknown if peer test error --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index d5423fae315..93fc21023dc 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2387,7 +2387,7 @@ namespace transport { LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ", i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3))); - if (GetTestingState ()) + if (GetTestingState () && GetRouterStatus () != eRouterStatusFirewalled) SetRouterStatus (eRouterStatusUnknown); session->Done (); } From d5c40bb6bebeaf9ff9088c833c599ce6385f7433 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 1 Oct 2024 18:21:07 -0400 Subject: [PATCH 114/131] send keep-alive for newly selected introducer session --- libi2pd/SSU2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 016802163a6..f6c6226bfba 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1327,6 +1327,7 @@ namespace transport LogPrint (eLogDebug, "SSU2: Introducer added ", it->GetRelayTag (), " at ", i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ())); newList.push_back ({ it->GetRemoteIdentity ()->GetIdentHash (), tag }); + it->SendKeepAlive (); if (newList.size () >= SSU2_MAX_NUM_INTRODUCERS) break; } } From 8c292727dae0f81d40758d697fcf563037b83565 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 1 Oct 2024 20:35:46 -0400 Subject: [PATCH 115/131] introducer duration variance --- libi2pd/SSU2.cpp | 4 +++- libi2pd/SSU2.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index f6c6226bfba..a32eb1f4c5a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1267,7 +1267,9 @@ namespace transport ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { session->SendKeepAlive (); - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION || + ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION + + m_Rng () % SSU2_TO_INTRODUCER_SESSION_DURATION_VARIANCE) { newList.push_back ({ident, session->GetRelayTag ()}); if (tag != session->GetRelayTag ()) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 06267ad47b8..996c0979064 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -35,7 +35,8 @@ namespace transport const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 4 * 1024 * 1024; const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC - const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour + const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3480; // 58 minutes + const int SSU2_TO_INTRODUCER_SESSION_DURATION_VARIANCE = 330; // 5 minutes const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds From 514be6d0480756b8c53336e475b84153295de5a1 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 1 Oct 2024 21:26:54 -0400 Subject: [PATCH 116/131] introducer expiration time variance --- libi2pd/SSU2.cpp | 7 ++++--- libi2pd/SSU2.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index a32eb1f4c5a..1076a2de506 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1267,9 +1267,7 @@ namespace transport ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { session->SendKeepAlive (); - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION || - ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION + - m_Rng () % SSU2_TO_INTRODUCER_SESSION_DURATION_VARIANCE) + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) { newList.push_back ({ident, session->GetRelayTag ()}); if (tag != session->GetRelayTag ()) @@ -1316,6 +1314,9 @@ namespace transport for (const auto& it : sessions) { uint32_t tag = it->GetRelayTag (); + auto extraTime = std::min ((int)(ts - it->GetCreationTime ()), SSU2_TO_INTRODUCER_SESSION_EXPIRATION_VARIANCE); + if( extraTime > 1) + it->SetCreationTime (it->GetCreationTime () + m_Rng () % extraTime); uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) continue; // don't pick too old session for introducer diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 996c0979064..93d7e8e23ac 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -35,9 +35,9 @@ namespace transport const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 4 * 1024 * 1024; const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC - const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3480; // 58 minutes - const int SSU2_TO_INTRODUCER_SESSION_DURATION_VARIANCE = 330; // 5 minutes + const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3680; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes + const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION_VARIANCE = 120; // 2 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds From 1fb45c4b0d450d96ce54cbf33b22ce9b0c319274 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 2 Oct 2024 08:27:49 -0400 Subject: [PATCH 117/131] don't send HolePunch or PeerTest 5 to unspecified address --- libi2pd/SSU2Session.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 93fc21023dc..950ed2afe25 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2002,7 +2002,9 @@ namespace transport boost::asio::ip::udp::endpoint ep; if (ExtractEndpoint (buf + 47, asz, ep)) { - auto addr = ep.address ().is_v6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address (); + std::shared_ptr addr; + if (!ep.address ().is_unspecified () && ep.port ()) + addr = ep.address ().is_v6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address (); if (addr) { if (m_Server.IsSupported (ep.address ())) @@ -2234,7 +2236,7 @@ namespace transport { boost::asio::ip::udp::endpoint ep; std::shared_ptr addr; - if (ExtractEndpoint (buf + offset + 10, asz, ep)) + if (ExtractEndpoint (buf + offset + 10, asz, ep) && !ep.address ().is_unspecified () && ep.port ()) addr = r->GetSSU2Address (ep.address ().is_v4 ()); if (addr && m_Server.IsSupported (ep.address ()) && i2p::context.GetRouterInfo ().IsSSU2PeerTesting (ep.address ().is_v4 ())) From dc4cd34893b1332c76c2c90136bc0debcd608ede Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 2 Oct 2024 08:45:44 -0400 Subject: [PATCH 118/131] handle immediate ack requsted flag in data message. set it in keep-alive --- libi2pd/SSU2Session.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 950ed2afe25..d8171174e2e 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -268,7 +268,7 @@ namespace transport { uint8_t payload[20]; size_t payloadSize = CreatePaddingBlock (payload, 20, 8); - SendData (payload, payloadSize); + SendData (payload, payloadSize, SSU2_FLAG_IMMEDIATE_ACK_REQUESTED); } } @@ -1503,6 +1503,7 @@ namespace transport return; } UpdateNumReceivedBytes (len); + if (header.h.flags[0] & SSU2_FLAG_IMMEDIATE_ACK_REQUESTED) m_IsDataReceived = true; if (!packetNum || UpdateReceivePacketNum (packetNum)) HandlePayload (payload, payloadSize); } From 34f1ba5bd96238d7f21be3ff598fffce462d8a93 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 2 Oct 2024 12:45:12 -0400 Subject: [PATCH 119/131] don't send invalid local address in RelayRequest --- libi2pd/SSU2Session.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index d8171174e2e..6ce3a5e188f 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -170,7 +170,12 @@ namespace transport if (!session || !relayTag) return false; // find local address to introduce auto localAddress = session->FindLocalAddress (); - if (!localAddress) return false; + if (!localAddress || localAddress->host.is_unspecified () || !localAddress->port) + { + // can't introduce invalid endpoint + LogPrint (eLogWarning, "SSU2: Can't find local address to introduce"); + return false; + } // create nonce uint32_t nonce; RAND_bytes ((uint8_t *)&nonce, 4); From 7f3a04a72f81e078cc8f3f30960a36fede7b05fa Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 3 Oct 2024 18:44:09 -0400 Subject: [PATCH 120/131] select random introducer session. don't update creation time --- libi2pd/SSU2.cpp | 45 +++++++++++++++++---------------------------- libi2pd/SSU2.h | 5 ++--- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1076a2de506..87d45d0423b 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1222,31 +1222,25 @@ namespace transport } std::vector > SSU2Server::FindIntroducers (int maxNumIntroducers, - bool v4, const std::unordered_set& excluded) const + bool v4, const std::unordered_set& excluded) { std::vector > ret; - if (maxNumIntroducers <= 0) return ret; - auto newer = [](const std::shared_ptr& s1, const std::shared_ptr& s2) -> bool - { - auto t1 = s1->GetCreationTime (), t2 = s2->GetCreationTime (); - return (t1 != t2) ? (t1 > t2) : (s1->GetConnID () > s2->GetConnID ()); - }; - std::set, decltype (newer)> introducers(newer); + if (maxNumIntroducers <= 0 || m_Sessions.empty ()) return ret; + + std::vector > eligible; + eligible.reserve (m_Sessions.size ()/2); + auto ts = i2p::util::GetSecondsSinceEpoch (); for (const auto& s : m_Sessions) { if (s.second->IsEstablished () && (s.second->GetRelayTag () && s.second->IsOutgoing ()) && + ts < s.second->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION/2 && !excluded.count (s.second->GetRemoteIdentity ()->GetIdentHash ()) && ((v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V4)) || (!v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V6)))) - introducers.insert (s.second); + eligible.push_back (s.second); } - int i = 0; - for (auto it: introducers) - { - ret.push_back (it); - i++; - if (i >= maxNumIntroducers) break; - } + + std::sample (eligible.begin(), eligible.end(), std::back_inserter(ret), maxNumIntroducers, m_Rng); return ret; } @@ -1293,33 +1287,28 @@ namespace transport if (newList.size () < SSU2_MAX_NUM_INTRODUCERS) { auto sessions = FindIntroducers (SSU2_MAX_NUM_INTRODUCERS - newList.size (), v4, excluded); - if (sessions.empty () && !introducers.empty ()) + if (sessions.empty () && !impliedList.empty ()) { - // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); - impliedList.clear (); - for (const auto& it : introducers) + for (const auto& it : impliedList) { auto session = FindSession (it.first); - if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) + if (session) { - session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find_if (newList.begin (), newList.end (), [&ident = it.first](const auto& s){ return ident == s.first; }) == newList.end ()) sessions.push_back (session); } } + impliedList.clear (); } for (const auto& it : sessions) { - uint32_t tag = it->GetRelayTag (); - auto extraTime = std::min ((int)(ts - it->GetCreationTime ()), SSU2_TO_INTRODUCER_SESSION_EXPIRATION_VARIANCE); - if( extraTime > 1) - it->SetCreationTime (it->GetCreationTime () + m_Rng () % extraTime); + uint32_t tag = it->GetRelayTag (); uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; - if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) - continue; // don't pick too old session for introducer + if (!tag && ts >= exp) + continue; // don't publish expired introducer i2p::data::RouterInfo::Introducer introducer; introducer.iTag = tag; introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 93d7e8e23ac..2b97bd25352 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -35,9 +35,8 @@ namespace transport const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 4 * 1024 * 1024; const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC - const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3680; // 1 hour + const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes - const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION_VARIANCE = 120; // 2 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds @@ -160,7 +159,7 @@ namespace transport void ConnectThroughIntroducer (std::shared_ptr session); std::vector > FindIntroducers (int maxNumIntroducers, - bool v4, const std::unordered_set& excluded) const; + bool v4, const std::unordered_set& excluded); void UpdateIntroducers (bool v4); void ScheduleIntroducersUpdateTimer (); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4); From bce9630ff804862b5bc387ac562d422e8e493f5c Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 4 Oct 2024 08:26:32 -0400 Subject: [PATCH 121/131] try to create new sessions with introducers if existing are about to expire --- libi2pd/SSU2.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 87d45d0423b..5f2cb0cfbeb 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1284,6 +1284,7 @@ namespace transport if (!session) i2p::context.RemoveSSU2Introducer (ident, v4); } + int numOldSessions = 0; if (newList.size () < SSU2_MAX_NUM_INTRODUCERS) { auto sessions = FindIntroducers (SSU2_MAX_NUM_INTRODUCERS - newList.size (), v4, excluded); @@ -1297,7 +1298,10 @@ namespace transport { if (std::find_if (newList.begin (), newList.end (), [&ident = it.first](const auto& s){ return ident == s.first; }) == newList.end ()) + { sessions.push_back (session); + numOldSessions++; + } } } impliedList.clear (); @@ -1326,9 +1330,17 @@ namespace transport } introducers = newList; - if (introducers.size () < SSU2_MAX_NUM_INTRODUCERS) + if (introducers.size () < SSU2_MAX_NUM_INTRODUCERS || numOldSessions) { - for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS; i++) + // we need to create more sessions with relay tag + + // exclude all existing sessions + excluded.clear (); + for (const auto& [ident, s] : m_SessionsByRouterHash) + excluded.insert (ident); + + // sesssion about to expire are not counted + for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS + numOldSessions; i++) { auto introducer = i2p::data::netdb.GetRandomSSU2Introducer (v4, excluded); if (introducer) From 4436c49cccbcd19d1db7368f261650faa11840d0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 4 Oct 2024 11:30:56 -0400 Subject: [PATCH 122/131] temporary disable RelayResponse resend through introducer session --- libi2pd/SSU2Session.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 6ce3a5e188f..bf363f1e48d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2067,9 +2067,11 @@ namespace transport packet->payloadSize = CreateRelayResponseBlock (packet->payload, m_MaxPayloadSize, code, bufbe32toh (buf + 33), token, isV4); packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); - uint32_t packetNum = SendData (packet->payload, packet->payloadSize); - packet->sendTime = mts; - m_SentPackets.emplace (packetNum, packet); + /*uint32_t packetNum = */SendData (packet->payload, packet->payloadSize); + // for some reason Bob never ack this RelayResponse + // TODO: unccomend line below once the problem is resolved + //packet->sendTime = mts; + //m_SentPackets.emplace (packetNum, packet); } void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len) From 58245bf1214f4e87dfc21b3c1b6d7210bfe02b21 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 4 Oct 2024 14:06:02 -0400 Subject: [PATCH 123/131] temporary disable RelayRespond resend from Bob because it might be not acked --- libi2pd/SSU2Session.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bf363f1e48d..6213c614a63 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1982,6 +1982,7 @@ namespace transport packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); uint32_t packetNum = session->SendData (packet->payload, packet->payloadSize); packet->sendTime = mts; + // Charlie always responds with RelayResponse session->m_SentPackets.emplace (packetNum, packet); } @@ -2068,8 +2069,8 @@ namespace transport code, bufbe32toh (buf + 33), token, isV4); packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); /*uint32_t packetNum = */SendData (packet->payload, packet->payloadSize); - // for some reason Bob never ack this RelayResponse - // TODO: unccomend line below once the problem is resolved + // sometimes Bob doesn't ack this RelayResponse + // TODO: uncomment line below once the problem is resolved //packet->sendTime = mts; //m_SentPackets.emplace (packetNum, packet); } @@ -2106,9 +2107,11 @@ namespace transport memcpy (payload + 3, buf, len); // forward to Alice as is packet->payloadSize = len + 3; packet->payloadSize += CreatePaddingBlock (payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); - uint32_t packetNum = it->second.first->SendData (packet->payload, packet->payloadSize); - packet->sendTime = i2p::util::GetMillisecondsSinceEpoch (); - it->second.first->m_SentPackets.emplace (packetNum, packet); + /*uint32_t packetNum = */it->second.first->SendData (packet->payload, packet->payloadSize); + // sometimes Alice doesn't ack this RelayResponse + // TODO: uncomment line below once the problem is resolved + //packet->sendTime = i2p::util::GetMillisecondsSinceEpoch (); + //it->second.first->m_SentPackets.emplace (packetNum, packet); } else { From 0710f62948dec5d991caef70aa0021c58a6e5308 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 4 Oct 2024 20:44:58 -0400 Subject: [PATCH 124/131] fixed potential race condition --- libi2pd/SSU2.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5f2cb0cfbeb..1a1965e185e 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1336,8 +1336,11 @@ namespace transport // exclude all existing sessions excluded.clear (); - for (const auto& [ident, s] : m_SessionsByRouterHash) - excluded.insert (ident); + { + std::lock_guard l(m_SessionsByRouterHashMutex); + for (const auto& [ident, s] : m_SessionsByRouterHash) + excluded.insert (ident); + } // sesssion about to expire are not counted for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS + numOldSessions; i++) From e4c8cc300db80df406536ace58d51aff152403b4 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 6 Oct 2024 14:28:33 +0300 Subject: [PATCH 125/131] [gha] disable winxp build (it is broken in MSYS2) Signed-off-by: r4sas --- .github/workflows/build-windows.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 536d16e0ec2..b026cc21009 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -108,6 +108,7 @@ jobs: path: build/i2pd.exe build-xp: + if: false name: XP runs-on: windows-latest @@ -220,7 +221,7 @@ jobs: id: cache-boost with: path: MINGW-packages/mingw-w64-boost/*.zst - key: winxp-winpthreads-${{ steps.version-boost.outputs.version }} + key: winxp-boost-${{ steps.version-boost.outputs.version }} - name: Build WinXP-capable boost package if: steps.cache-boost.outputs.cache-hit != 'true' run: | From cc05f9c5d9d7efcdeb843b0bb6b29eb16b5caa15 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Oct 2024 07:34:18 -0400 Subject: [PATCH 126/131] 2.54.0 --- ChangeLog | 38 ++++++++++++++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 6 +++--- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13b8bf5067a..2f568e648f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,44 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.54.0] - 2024-10-06 +### Added +- Maintain recently connected routers list to avoid false-positive peer test +- Limited connectivity mode(through proxy) +- "i2p.streaming.profile" tunnel's param to let tunnel select also low-bandwidth routers +- Limit stream's inbound speed +- Periodic ack requests in ratchets session +- Set congestion cap G immediately if through proxy +- Show tunnel's routers bandwidth caps in web console +- Handle immediate ack requsted flag in SSU2 data packets +- Resend and ack peer test and relay messages +- "senduseragent" HTTP proxy's param to pass through user's User-Agent +### Changed +- Exclude 'N' routers from high-bandwidth routers for client tunnels +- C++11 support has been dropped, the minimal requirement is C++17 now, C++20 for some compilers +- Removed dependency from boost::date_time and boost::filesystem +- Set default i2cp.leaseSetEncType to 0,4 and to 4 for server tunnels +- Handle i2cp.inboundlimit and i2cp.outboundlimit params in I2CP +- Publish LeaseSet with new timestamp update if tunnel was replaced in the same second +- Increase max number of generated tags to 800 per tagset +- Routing path expiration by time instead num attempts +- Save timestamp from epoch instead local time to profiles +- Update introducer's iTag if session to introducer was replaced to new one +- RTT, window size and number of NACKs calculation for streaming +- Don't select same peer for tunnel too often +- Use WinApi for data path UTF-8 conversion for Windows +### Fixed +- Jump link crash if address book is disabled +- Race condition if connect through an introducer +- "Date" header in I2PControl response +- Incomplete response from web console +- AEAD verification with LibreSSL +- Number of generated tags and new keys for follow-on tagsets +- Expired leases in LeaseSet +- Attempts to send HolePunch to 0.0.0.0 +- Incorrect options size in quick ack streaming packet +- Low bandwidth router appeared as first peer in high-bandwidth client tunnel + ## [2.53.1] - 2024-07-29 ### Changed - I2CP performance improvement diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 862c618d60a..6853a504848 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.53.1 +Version: 2.54.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -148,6 +148,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sun Oct 6 2024 orignal - 2.54.0 +- update to 2.54.0 + * Tue Jul 30 2024 orignal - 2.53.1 - update to 2.53.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 6b999798b71..ece180f05d5 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.53.1 +Version: 2.54.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -146,6 +146,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sun Oct 6 2024 orignal - 2.54.0 +- update to 2.54.0 + * Tue Jul 30 2024 orignal - 2.53.1 - update to 2.53.1 diff --git a/debian/changelog b/debian/changelog index c5da4628726..0fe779da4a2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.54.0-1) unstable; urgency=medium + + * updated to version 2.54.0/0.9.64 + +-- orignal Sun, 6 Oct 2024 16:00:00 +0000 + i2pd (2.53.1-1) unstable; urgency=medium * updated to version 2.53.1 diff --git a/libi2pd/version.h b/libi2pd/version.h index f3e487c2dee..40d07845b3c 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,8 +18,8 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 53 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MINOR 54 +#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 63 +#define I2P_VERSION_MICRO 64 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From dc48fb0180fb3a4d8b45c42a77e8384fa19c85f4 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 6 Oct 2024 14:36:02 +0300 Subject: [PATCH 127/131] [rpm] try to fix Fedora ELN build Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 2 +- contrib/rpm/i2pd.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 6853a504848..05158bc929a 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -24,7 +24,7 @@ BuildRequires: openssl-devel BuildRequires: miniupnpc-devel BuildRequires: systemd-units -%if 0%{?fedora} > 40 || 0%{?eln} +%if 0%{?fedora} == 41 BuildRequires: openssl-devel-engine %endif diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index ece180f05d5..4b1e573b955 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -22,7 +22,7 @@ BuildRequires: openssl-devel BuildRequires: miniupnpc-devel BuildRequires: systemd-units -%if 0%{?fedora} > 40 || 0%{?eln} +%if 0%{?fedora} == 41 BuildRequires: openssl-devel-engine %endif From 0d224dfc54feeb0ce959167f60473f5c4af592ef Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Oct 2024 07:42:59 -0400 Subject: [PATCH 128/131] 2.54.0 --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2f568e648f3..b3559fb7e90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,7 +10,7 @@ - Periodic ack requests in ratchets session - Set congestion cap G immediately if through proxy - Show tunnel's routers bandwidth caps in web console -- Handle immediate ack requsted flag in SSU2 data packets +- Handle immediate ack requested flag in SSU2 data packets - Resend and ack peer test and relay messages - "senduseragent" HTTP proxy's param to pass through user's User-Agent ### Changed From d7c4d0ff3eeb63ab3348ba850e087fc8a8e29bfd Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 6 Oct 2024 16:36:52 +0300 Subject: [PATCH 129/131] [gha] xp build again Signed-off-by: r4sas --- .github/workflows/build-windows.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index b026cc21009..d587ba05d33 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -108,7 +108,6 @@ jobs: path: build/i2pd.exe build-xp: - if: false name: XP runs-on: windows-latest @@ -129,8 +128,11 @@ jobs: cache: true update: true - - name: Clone MinGW packages repository - run: git clone https://github.com/msys2/MINGW-packages + - name: Clone MinGW packages repository and revert boost to 1.85.0 + run: | + git clone https://github.com/msys2/MINGW-packages + cd MINGW-packages + git checkout 4cbb366edf2f268ac3146174b40ce38604646fc5 mingw-w64-boost # headers - name: Get headers package version @@ -212,16 +214,17 @@ jobs: run: pacman --noconfirm -U MINGW-packages/mingw-w64-openssl/mingw-w64-i686-*-any.pkg.tar.zst # Boost - - name: Get boost package version - id: version-boost - run: | - echo "version=$(pacman -Si mingw-w64-i686-boost | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT + #- name: Get boost package version + # id: version-boost + # run: | + # echo "version=$(pacman -Si mingw-w64-i686-boost | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT - name: Cache boost package uses: actions/cache@v4 id: cache-boost with: path: MINGW-packages/mingw-w64-boost/*.zst - key: winxp-boost-${{ steps.version-boost.outputs.version }} + key: winxp-boost-1.85.0+crt-${{ steps.version-headers.outputs.version }}+ossl-${{ steps.version-openssl.outputs.version }} + # Rebuild package if packages above has changed - name: Build WinXP-capable boost package if: steps.cache-boost.outputs.cache-hit != 'true' run: | From 905c6debf2a7f7e651a7916e646a2aee25ba57c7 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 6 Oct 2024 20:03:22 +0300 Subject: [PATCH 130/131] [win32] use boost filesystem for gcc builds Signed-off-by: r4sas --- Makefile.linux | 2 +- Makefile.mingw | 11 ++++++----- Win32/Win32NetState.cpp | 2 +- Win32/Win32NetState.h | 2 +- libi2pd/FS.cpp | 8 ++++---- libi2pd/FS.h | 4 +++- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index 2955d3011cc..aa67626a0ca 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -15,7 +15,7 @@ ifeq ($(shell expr match $(CXX) 'clang'),5) NEEDED_CXXFLAGS += -std=c++17 else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 NEEDED_CXXFLAGS += -std=c++17 - LDLIBS = -lboost_filesystem + LDLIBS = -lboost_filesystem else ifeq ($(shell expr match ${CXXVER} "[8-9]"),1) # gcc 8 - 9 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -lstdc++fs diff --git a/Makefile.mingw b/Makefile.mingw index 339cec4ef52..fc92e9b02fd 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -7,7 +7,7 @@ CXXFLAGS := $(CXX_DEBUG) -fPIC -msse INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32 LDFLAGS := ${LD_DEBUG} -static -fPIC -msse -NEEDED_CXXFLAGS += -std=c++17 +NEEDED_CXXFLAGS += -std=c++20 DEFINES += -DWIN32_LEAN_AND_MEAN # UPNP Support @@ -16,7 +16,12 @@ ifeq ($(USE_UPNP),yes) LDLIBS = -lminiupnpc endif +ifeq ($(USE_WINXP_FLAGS), yes) + DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 +endif + LDLIBS += \ + $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ $(MINGW_PREFIX)/lib/libssl.a \ $(MINGW_PREFIX)/lib/libcrypto.a \ @@ -37,10 +42,6 @@ ifeq ($(USE_WIN32_APP), yes) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) endif -ifeq ($(USE_WINXP_FLAGS), yes) - DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 -endif - ifeq ($(USE_AESNI),yes) NEEDED_CXXFLAGS += -maes LDFLAGS += -maes diff --git a/Win32/Win32NetState.cpp b/Win32/Win32NetState.cpp index 095afe4554a..4ef768c8622 100644 --- a/Win32/Win32NetState.cpp +++ b/Win32/Win32NetState.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/Win32/Win32NetState.h b/Win32/Win32NetState.h index 5006daadaab..c1f47a24878 100644 --- a/Win32/Win32NetState.h +++ b/Win32/Win32NetState.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index fdfd577efcd..a623a4ebb80 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -261,13 +261,13 @@ namespace fs { #else */ // TODO: wait until implemented const auto sctp = std::chrono::time_point_cast( t - decltype(t)::clock::now() + std::chrono::system_clock::now()); -/*#endif */ - return std::chrono::system_clock::to_time_t(sctp); -#else +/*#endif */ + return std::chrono::system_clock::to_time_t(sctp); +#else boost::system::error_code ec; auto t = boost::filesystem::last_write_time (path, ec); return ec ? 0 : t; -#endif +#endif } bool Remove(const std::string & path) { diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 8bf8101ec20..7af8f494623 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -16,7 +16,9 @@ #include #ifndef STD_FILESYSTEM -# if (!TARGET_OS_SIMULATOR && __has_include()) // supports std::filesystem +# if (_WIN32 && __GNUG__) // MinGW GCC somehow incorrectly converts paths +# define STD_FILESYSTEM 0 +# elif (!TARGET_OS_SIMULATOR && __has_include()) // supports std::filesystem # define STD_FILESYSTEM 1 # else # define STD_FILESYSTEM 0 From 1a6109109a2cec112d618ec45b078e39984ceb66 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Oct 2024 20:57:35 -0400 Subject: [PATCH 131/131] don't sample too small list of eligible introducers --- libi2pd/SSU2.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1a1965e185e..83d23dd2a37 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1239,8 +1239,11 @@ namespace transport (!v4 && (s.second->GetRemoteTransports () & i2p::data::RouterInfo::eSSU2V6)))) eligible.push_back (s.second); } - - std::sample (eligible.begin(), eligible.end(), std::back_inserter(ret), maxNumIntroducers, m_Rng); + + if (eligible.size () <= (size_t)maxNumIntroducers) + return eligible; + else + std::sample (eligible.begin(), eligible.end(), std::back_inserter(ret), maxNumIntroducers, m_Rng); return ret; }