From 61bcfebcc889cd2618be475b5800035a424cdc74 Mon Sep 17 00:00:00 2001 From: barracuda156 Date: Wed, 23 Nov 2022 11:28:33 +0800 Subject: [PATCH 001/179] Add CMake support for tests --- build/CMakeLists.txt | 13 ++- build/cmake_modules/FindCheck.cmake | 55 +++++++++++ tests/CMakeLists.txt | 138 ++++++++++++++++++++++++++++ tests/Makefile | 2 +- tests/test-http-merge_chunked.cpp | 2 +- tests/test-http-req.cpp | 2 +- tests/test-http-res.cpp | 2 +- tests/test-http-url.cpp | 2 +- tests/test-http-url_decode.cpp | 2 +- 9 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 build/cmake_modules/FindCheck.cmake create mode 100644 tests/CMakeLists.txt diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 11036f16..7f7cb4c8 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -20,12 +20,17 @@ option(WITH_UPNP "Include support for UPnP client" OFF) option(WITH_GIT_VERSION "Use git commit info as version" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) +option(BUILD_TESTING "Build tests" OFF) + +IF(BUILD_TESTING) + enable_testing() +ENDIF() # paths set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") -#Handle paths nicely +# Handle paths nicely include(GNUInstallDirs) # architecture @@ -275,9 +280,13 @@ if(WITH_BINARY) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin") endif() + +if(BUILD_TESTING) + add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests) +endif() diff --git a/build/cmake_modules/FindCheck.cmake b/build/cmake_modules/FindCheck.cmake new file mode 100644 index 00000000..8ad818f4 --- /dev/null +++ b/build/cmake_modules/FindCheck.cmake @@ -0,0 +1,55 @@ +# - Try to find the CHECK libraries +# Once done this will define +# +# CHECK_FOUND - system has check +# CHECK_INCLUDE_DIRS - the check include directory +# CHECK_LIBRARIES - check library +# +# Copyright (c) 2007 Daniel Gollub +# Copyright (c) 2007-2009 Bjoern Ricks +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +INCLUDE( FindPkgConfig ) + +IF ( Check_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "REQUIRED" ) +ELSE( Check_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "" ) +ENDIF ( Check_FIND_REQUIRED ) + +IF ( CHECK_MIN_VERSION ) + PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} ) +ELSE ( CHECK_MIN_VERSION ) + PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check ) +ENDIF ( CHECK_MIN_VERSION ) + +# Look for CHECK include dir and libraries +IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) + + FIND_PATH( CHECK_INCLUDE_DIRS check.h ) + + FIND_LIBRARY( CHECK_LIBRARIES NAMES check ) + + IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) + SET( CHECK_FOUND 1 ) + IF ( NOT Check_FIND_QUIETLY ) + MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" ) + ENDIF ( NOT Check_FIND_QUIETLY ) + ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) + IF ( Check_FIND_REQUIRED ) + MESSAGE( FATAL_ERROR "Could NOT find CHECK" ) + ELSE ( Check_FIND_REQUIRED ) + IF ( NOT Check_FIND_QUIETLY ) + MESSAGE( STATUS "Could NOT find CHECK" ) + ENDIF ( NOT Check_FIND_QUIETLY ) + ENDIF ( Check_FIND_REQUIRED ) + ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) +ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) + +# Hide advanced variables from CMake GUIs +MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES ) + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..c6eec047 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,138 @@ +enable_testing() +find_package(Check 0.9.10 REQUIRED) +include_directories(${CHECK_INCLUDE_DIRS}) + +# Compiler flags: +if(APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -Wl,-undefined,dynamic_lookup") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -D_GLIBCXX_USE_NANOSLEEP=1 -Wl,--unresolved-symbols=ignore-in-object-files") +endif() + +set(TEST_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +include_directories( + ../libi2pd + ${Boost_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIR} +) + +set(test-http-merge_chunked_SRCS + ../libi2pd/HTTP.cpp + test-http-merge_chunked.cpp +) + +set(test-http-req_SRCS + ../libi2pd/HTTP.cpp + test-http-req.cpp +) + +set(test-http-res_SRCS + ../libi2pd/HTTP.cpp + test-http-res.cpp +) + +set(test-http-url_decode_SRCS + ../libi2pd/HTTP.cpp + test-http-url_decode.cpp +) + +set(test-http-url_SRCS + ../libi2pd/HTTP.cpp + test-http-url.cpp +) + +set(test-base-64_SRCS + ../libi2pd/Base.cpp + test-base-64.cpp +) + +set(test-gost_SRCS + ../libi2pd/Gost.cpp + ../libi2pd/I2PEndian.cpp + test-gost.cpp +) + +set(test-gost-sig_SRCS + ../libi2pd/Gost.cpp + ../libi2pd/I2PEndian.cpp + ../libi2pd/Crypto.cpp + ../libi2pd/Log.cpp + test-gost-sig.cpp +) + +set(test-x25519_SRCS + ../libi2pd/Ed25519.cpp + ../libi2pd/I2PEndian.cpp + ../libi2pd/Log.cpp + ../libi2pd/Crypto.cpp + test-x25519.cpp +) + +set(test-aeadchacha20poly1305_SRCS + ../libi2pd/Crypto.cpp + ../libi2pd/ChaCha20.cpp + ../libi2pd/Poly1305.cpp + test-aeadchacha20poly1305.cpp +) + +set(test-blinding_SRCS + ../libi2pd/Crypto.cpp + ../libi2pd/Blinding.cpp + ../libi2pd/Ed25519.cpp + ../libi2pd/I2PEndian.cpp + ../libi2pd/Log.cpp + ../libi2pd/util.cpp + ../libi2pd/Identity.cpp + ../libi2pd/Signature.cpp + ../libi2pd/Timestamp.cpp + test-blinding.cpp +) + +SET(test-elligator_SRCS + ../libi2pd/Elligator.cpp + ../libi2pd/Crypto.cpp + test-elligator.cpp +) + +add_executable(test-http-merge_chunked ${test-http-merge_chunked_SRCS}) +add_executable(test-http-req ${test-http-req_SRCS}) +add_executable(test-http-res ${test-http-res_SRCS}) +add_executable(test-http-url_decode ${test-http-url_decode_SRCS}) +add_executable(test-http-url ${test-http-url_SRCS}) +add_executable(test-base-64 ${test-base-64_SRCS}) +add_executable(test-gost ${test-gost_SRCS}) +add_executable(test-gost-sig ${test-gost-sig_SRCS}) +add_executable(test-x25519 ${test-x25519_SRCS}) +add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS}) +add_executable(test-blinding ${test-blinding_SRCS}) +add_executable(test-elligator ${test-elligator_SRCS}) + +set(LIBS + ${Boost_LIBRARIES} + ${CHECK_LDFLAGS} + ${CMAKE_REQUIRED_LIBRARIES} + OpenSSL::SSL + OpenSSL::Crypto + Threads::Threads +) + +target_link_libraries(test-gost OpenSSL::Crypto Threads::Threads) +target_link_libraries(test-gost-sig ${LIBS}) +target_link_libraries(test-x25519 ${LIBS}) +target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) +target_link_libraries(test-blinding ${LIBS}) +target_link_libraries(test-elligator ${LIBS}) + +add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked) +add_test(test-http-req ${TEST_PATH}/test-http-req) +add_test(test-http-res ${TEST_PATH}/test-http-res) +add_test(test-http-url_decode ${TEST_PATH}/test-http-url_decode) +add_test(test-http-url ${TEST_PATH}/test-http-url) +add_test(test-base-64 ${TEST_PATH}/test-base-64) +add_test(test-gost ${TEST_PATH}/test-gost) +add_test(test-gost-sig ${TEST_PATH}/test-gost-sig) +add_test(test-x25519 ${TEST_PATH}/test-x25519) +add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305) +add_test(test-blinding ${TEST_PATH}/test-blinding) +add_test(test-elligator ${TEST_PATH}/test-elligator) diff --git a/tests/Makefile b/tests/Makefile index 8eb52fde..f8f6cf77 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -17,7 +17,7 @@ test-gost: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp test-gost.cpp test-gost-sig: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Crypto.cpp ../libi2pd/Log.cpp test-gost-sig.cpp $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system -test-x25519: ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/Crypto.cpp test-x25519.cpp +test-x25519: ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/Crypto.cpp test-x25519.cpp $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system test-aeadchacha20poly1305: ../libi2pd/Crypto.cpp ../libi2pd/ChaCha20.cpp ../libi2pd/Poly1305.cpp test-aeadchacha20poly1305.cpp diff --git a/tests/test-http-merge_chunked.cpp b/tests/test-http-merge_chunked.cpp index ba587a45..31b6a298 100644 --- a/tests/test-http-merge_chunked.cpp +++ b/tests/test-http-merge_chunked.cpp @@ -1,5 +1,5 @@ #include -#include "../HTTP.h" +#include "HTTP.h" using namespace i2p::http; diff --git a/tests/test-http-req.cpp b/tests/test-http-req.cpp index c857ca24..6deb66b0 100644 --- a/tests/test-http-req.cpp +++ b/tests/test-http-req.cpp @@ -1,5 +1,5 @@ #include -#include "../HTTP.h" +#include "HTTP.h" using namespace i2p::http; diff --git a/tests/test-http-res.cpp b/tests/test-http-res.cpp index 896a4403..270f32a3 100644 --- a/tests/test-http-res.cpp +++ b/tests/test-http-res.cpp @@ -1,5 +1,5 @@ #include -#include "../HTTP.h" +#include "HTTP.h" using namespace i2p::http; diff --git a/tests/test-http-url.cpp b/tests/test-http-url.cpp index 37e9c45e..1759a3a8 100644 --- a/tests/test-http-url.cpp +++ b/tests/test-http-url.cpp @@ -1,5 +1,5 @@ #include -#include "../HTTP.h" +#include "HTTP.h" using namespace i2p::http; diff --git a/tests/test-http-url_decode.cpp b/tests/test-http-url_decode.cpp index f72b2c50..7f08bbc6 100644 --- a/tests/test-http-url_decode.cpp +++ b/tests/test-http-url_decode.cpp @@ -1,5 +1,5 @@ #include -#include "../HTTP.h" +#include "HTTP.h" using namespace i2p::http; From aa5e6400e42e18014a7cfb7927554253610582d0 Mon Sep 17 00:00:00 2001 From: barracuda156 Date: Sat, 26 Nov 2022 06:35:28 +0800 Subject: [PATCH 002/179] CMakeLists: use a fix for atomics on macOS PPC, not PPC in general --- build/CMakeLists.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 7f7cb4c8..d9c50e9c 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -176,14 +176,12 @@ if(WITH_THREADSANITIZER) endif() endif() - -# Enable usage of STD's Atomic instead of Boost's on PowerPC -# For more information refer to https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111 -if(ARCHITECTURE MATCHES "ppc") +# Use std::atomic instead of GCC builtins on macOS PowerPC: +# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111 +if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc") add_definitions(-DBOOST_SP_USE_STD_ATOMIC) endif() - # libraries set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) From 84d9c8f1b882eec983fe160b18d5df7917a7dff6 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Dec 2022 15:12:30 -0500 Subject: [PATCH 003/179] access to RouterInfo's addresses by index --- daemon/HTTPServer.cpp | 1 + libi2pd/RouterContext.cpp | 55 +++++++-------- libi2pd/RouterInfo.cpp | 142 +++++++++++++++++++------------------- libi2pd/RouterInfo.h | 24 +++++-- 4 files changed, 116 insertions(+), 106 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 917acdb8..4743efc2 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -315,6 +315,7 @@ namespace http { { for (const auto& address : *addresses) { + if (!address) continue; s << "\r\n"; switch (address->transportStyle) { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 8928fc7f..5259a4f7 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -272,7 +272,7 @@ namespace i2p bool updated = false; for (auto& address : *addresses) { - if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) + if (address && address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) { address->port = port; updated = true; @@ -290,7 +290,7 @@ namespace i2p bool updated = false; for (auto& address : *addresses) { - if (address->IsNTCP2 () && (address->port != port || address->published != publish)) + if (address && address->IsNTCP2 () && (address->port != port || address->published != publish)) { bool isAddr = v4 && address->IsV4 (); if (!isAddr && (v6 || ygg)) @@ -319,23 +319,20 @@ namespace i2p auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; bool found = false, updated = false; - for (auto it = addresses->begin (); it != addresses->end ();) + for (auto& it: *addresses) { - if ((*it)->IsNTCP2 ()) + if (it && it->IsNTCP2 ()) { found = true; if (enable) { - (*it)->s = m_NTCP2Keys->staticPublicKey; - memcpy ((*it)->i, m_NTCP2Keys->iv, 16); - it++; + it->s = m_NTCP2Keys->staticPublicKey; + memcpy (it->i, m_NTCP2Keys->iv, 16); } else - it = addresses->erase (it); + it.reset (); updated = true; - } - else - it++; + } } if (enable && !found) { @@ -365,7 +362,7 @@ namespace i2p bool updated = false; for (auto& address : *addresses) { - if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) && + if (address && address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) && ((v4 && address->IsV4 ()) || (v6 && address->IsV6 ()))) { if (port) address->port = port; @@ -387,23 +384,20 @@ namespace i2p auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; bool found = false, updated = false; - for (auto it = addresses->begin (); it != addresses->end ();) + for (auto& it : *addresses) { - if ((*it)->IsSSU2 ()) + if (it && it->IsSSU2 ()) { found = true; if (enable) { - (*it)->s = m_SSU2Keys->staticPublicKey; - (*it)->i = m_SSU2Keys->intro; - it++; + it->s = m_SSU2Keys->staticPublicKey; + it->i = m_SSU2Keys->intro; } else - it = addresses->erase (it); + it.reset (); updated = true; } - else - it++; } if (enable && !found) { @@ -435,6 +429,7 @@ namespace i2p bool updated = false; for (auto& address : *addresses) { + if (!address) continue; if (address->host != host && address->IsCompatible (host) && !i2p::util::net::IsYggdrasilAddress (address->host)) { @@ -486,7 +481,7 @@ namespace i2p if (!addresses) return; bool updated = false; for (auto& addr : *addresses) - if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) && + if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) && addr->ssu && !addr->ssu->introducers.empty ()) { addr->ssu->introducers.clear (); @@ -612,7 +607,7 @@ namespace i2p if (addresses) { for (auto& addr : *addresses) - if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) + if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { addr->published = false; addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer @@ -648,7 +643,7 @@ namespace i2p if (addresses) { for (auto& addr : *addresses) - if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) + if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { addr->published = true; addr->caps |= i2p::data::RouterInfo::eSSUIntroducer; @@ -685,7 +680,7 @@ namespace i2p { for (auto& addr: *addresses) { - if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host)) + if (addr && addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host)) { switch (addr->transportStyle) { @@ -768,7 +763,7 @@ namespace i2p { for (auto& addr: *addresses) { - if (addr->IsV4 ()) + if (addr && addr->IsV4 ()) { switch (addr->transportStyle) { @@ -781,7 +776,7 @@ namespace i2p default: ; } } - if (addr->port) port = addr->port; + if (addr && addr->port) port = addr->port; } } if (!port) @@ -844,8 +839,8 @@ namespace i2p { for (auto& addr: *addresses) { - if (!port) port = addr->port; - if (i2p::util::net::IsYggdrasilAddress (addr->host)) + if (!port && addr) port = addr->port; + if (addr && i2p::util::net::IsYggdrasilAddress (addr->host)) { foundMesh = true; break; @@ -867,7 +862,7 @@ namespace i2p if (!addresses) return; for (auto& addr: *addresses) { - if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) + if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { addr->ssu->mtu = mtu; LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu); @@ -883,7 +878,7 @@ namespace i2p if (!addresses) return; for (auto& addr: *addresses) { - if (addr->IsPublishedNTCP2 ()) + if (addr && addr->IsPublishedNTCP2 ()) { bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host); if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1))) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 13a0731e..a83fd043 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -209,7 +209,6 @@ namespace data auto addresses = netdb.NewRouterInfoAddresses (); uint8_t numAddresses; s.read ((char *)&numAddresses, sizeof (numAddresses)); - addresses->reserve (numAddresses); for (int i = 0; i < numAddresses; i++) { uint8_t supportedTransports = 0; @@ -418,7 +417,11 @@ namespace data if (supportedTransports) { if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates - addresses->push_back(address); + { + for (uint8_t i = 0; i < eNumTransports; i++) + if ((1 << i) & supportedTransports) + (*addresses)[i] = address; + } m_SupportedTransports |= supportedTransports; } } @@ -633,13 +636,23 @@ namespace data { m_SupportedTransports |= eNTCP2V4; if (addr->published) m_ReachableTransports |= eNTCP2V4; + (*m_Addresses)[eNTCP2V4Idx] = addr; } if (addr->IsV6 ()) { - m_SupportedTransports |= eNTCP2V6; - if (addr->published) m_ReachableTransports |= eNTCP2V6; + if (i2p::util::net::IsYggdrasilAddress (addr->host)) + { + m_SupportedTransports |= eNTCP2V6Mesh; + m_ReachableTransports |= eNTCP2V6Mesh; + (*m_Addresses)[eNTCP2V6MeshIdx] = addr; + } + else + { + m_SupportedTransports |= eNTCP2V6; + if (addr->published) m_ReachableTransports |= eNTCP2V6; + (*m_Addresses)[eNTCP2V6Idx] = addr; + } } - m_Addresses->push_back(std::move(addr)); } void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps) @@ -653,9 +666,16 @@ namespace data addr->ssu->mtu = 0; memcpy (addr->s, staticKey, 32); memcpy (addr->i, introKey, 32); - if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4; - if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6; - m_Addresses->push_back(std::move(addr)); + if (addr->IsV4 ()) + { + m_SupportedTransports |= eSSU2V4; + (*m_Addresses)[eSSU2V4Idx] = addr; + } + if (addr->IsV6 ()) + { + m_SupportedTransports |= eSSU2V6; + (*m_Addresses)[eSSU2V6Idx] = addr; + } } void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, @@ -676,13 +696,14 @@ namespace data { m_SupportedTransports |= eSSU2V4; m_ReachableTransports |= eSSU2V4; + (*m_Addresses)[eSSU2V4Idx] = addr; } if (addr->IsV6 ()) { m_SupportedTransports |= eSSU2V6; m_ReachableTransports |= eSSU2V6; + (*m_Addresses)[eSSU2V6Idx] = addr; } - m_Addresses->push_back(std::move(addr)); } bool RouterInfo::IsNTCP2 (bool v4only) const @@ -721,21 +742,15 @@ namespace data { if (IsV6 ()) { - for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) + for (auto& it : *m_Addresses) { - auto addr = *it; - if (addr->IsV6 ()) + if (it && it->IsV6 ()) { - if (addr->IsV4 ()) - { - addr->caps &= ~AddressCaps::eV6; - ++it; - } + if (it->IsV4 ()) + it->caps &= ~AddressCaps::eV6; else - it = m_Addresses->erase (it); + it.reset (); } - else - ++it; } UpdateSupportedTransports (); } @@ -745,21 +760,15 @@ namespace data { if (IsV4 ()) { - for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) + for (auto& it : *m_Addresses) { - auto addr = *it; - if (addr->IsV4 ()) + if (it && it->IsV4 ()) { - if (addr->IsV6 ()) - { - addr->caps &= ~AddressCaps::eV4; - ++it; - } + if (it->IsV6 ()) + it->caps &= ~AddressCaps::eV4; else - it = m_Addresses->erase (it); + it.reset (); } - else - ++it; } UpdateSupportedTransports (); } @@ -780,33 +789,22 @@ namespace data { m_SupportedTransports &= ~eNTCP2V6Mesh; m_ReachableTransports &= ~eNTCP2V6Mesh; - for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) + for (auto& it: *m_Addresses) { - auto addr = *it; - if (i2p::util::net::IsYggdrasilAddress (addr->host)) - it = m_Addresses->erase (it); - else - ++it; + if (it && i2p::util::net::IsYggdrasilAddress (it->host)) + it.reset (); } } } std::shared_ptr RouterInfo::GetSSU2V4Address () const { - return GetAddress ( - [](std::shared_ptr address)->bool - { - return (address->transportStyle == eTransportSSU2) && address->IsV4(); - }); + return (*GetAddresses ())[eSSU2V4Idx]; } std::shared_ptr RouterInfo::GetSSU2V6Address () const { - return GetAddress ( - [](std::shared_ptr address)->bool - { - return (address->transportStyle == eTransportSSU2) && address->IsV6(); - }); + return (*GetAddresses ())[eSSU2V6Idx]; } std::shared_ptr RouterInfo::GetSSU2Address (bool v4) const @@ -843,7 +841,7 @@ namespace data auto addresses = m_Addresses; #endif for (const auto& address : *addresses) - if (filter (address)) return address; + if (address && filter (address)) return address; return nullptr; } @@ -871,30 +869,21 @@ namespace data std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const { - return GetAddress ( - [](std::shared_ptr address)->bool - { - return address->IsPublishedNTCP2 () && address->host.is_v4 (); - }); + auto addr = (*GetAddresses ())[eNTCP2V4Idx]; + if (addr && addr->IsPublishedNTCP2 ()) return addr; + return nullptr; } std::shared_ptr RouterInfo::GetPublishedNTCP2V6Address () const { - return GetAddress ( - [](std::shared_ptr address)->bool - { - return address->IsPublishedNTCP2 () && address->host.is_v6 () && - !i2p::util::net::IsYggdrasilAddress (address->host); - }); + auto addr = (*GetAddresses ())[eNTCP2V6Idx]; + if (addr && addr->IsPublishedNTCP2 ()) return addr; + return nullptr; } std::shared_ptr RouterInfo::GetYggdrasilAddress () const { - return GetAddress ( - [](std::shared_ptr address)->bool - { - return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host); - }); + return (*GetAddresses ())[eNTCP2V6MeshIdx]; } std::shared_ptr RouterInfo::GetProfile () const @@ -944,7 +933,7 @@ namespace data { for (auto& addr: *m_Addresses) { - if (!addr->published && (addr->transportStyle == eTransportNTCP2 || addr->transportStyle == eTransportSSU2)) + if (addr && !addr->published) { addr->caps &= ~(eV4 | eV6); addr->caps |= transports; @@ -958,6 +947,7 @@ namespace data m_ReachableTransports = 0; for (const auto& addr: *m_Addresses) { + if (!addr) continue; uint8_t transports = 0; switch (addr->transportStyle) { @@ -1061,10 +1051,22 @@ namespace data uint64_t ts = htobe64 (GetTimestamp ()); s.write ((const char *)&ts, sizeof (ts)); // addresses - uint8_t numAddresses = addresses->size (); - s.write ((char *)&numAddresses, sizeof (numAddresses)); - for (const auto& addr_ptr : *addresses) + uint8_t numAddresses = 0; + for (size_t idx = 0; idx < addresses->size(); idx++) { + auto addr_ptr = (*addresses)[idx]; + if (!addr_ptr) continue; + if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue; + if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue; + numAddresses++; + } + s.write ((char *)&numAddresses, sizeof (numAddresses)); + for (size_t idx = 0; idx < addresses->size(); idx++) + { + auto addr_ptr = (*addresses)[idx]; + if (!addr_ptr) continue; + if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue; + if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue; const Address& address = *addr_ptr; // calculate cost uint8_t cost = 0x7f; @@ -1269,7 +1271,7 @@ namespace data if (!addresses) return false; for (auto& addr : *addresses) { - if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) + if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { for (auto& intro: addr->ssu->introducers) if (intro.iTag == introducer.iTag) return false; // already presented @@ -1287,7 +1289,7 @@ namespace data if (!addresses) return false; for (auto& addr: *addresses) { - if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) + if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) if (h == it->iH) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 9e98769f..bd293d40 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -60,13 +60,25 @@ namespace data { public: + enum SupportedTransportsIdx + { + eNTCP2V4Idx = 0, + eNTCP2V6Idx, + eSSU2V4Idx, + eSSU2V6Idx, + eNTCP2V6MeshIdx, + eNumTransports + }; + +#define TransportBit(tr) e##tr = (1 << e##tr##Idx) + enum SupportedTransports { - eNTCP2V4 = 0x01, - eNTCP2V6 = 0x02, - eSSU2V4 = 0x04, - eSSU2V6 = 0x08, - eNTCP2V6Mesh = 0x10, + TransportBit(NTCP2V4), // 0x01 + TransportBit(NTCP2V6), // 0x02 + TransportBit(SSU2V4), // 0x04 + TransportBit(SSU2V6), // 0x08 + TransportBit(NTCP2V6Mesh), // 0x10 eAllTransports = 0xFF }; typedef uint8_t CompatibleTransports; @@ -160,7 +172,7 @@ namespace data Buffer (const uint8_t * buf, size_t len); }; - typedef std::vector > Addresses; + typedef std::array, eNumTransports> Addresses; RouterInfo (const std::string& fullPath); RouterInfo (const RouterInfo& ) = default; From d30ee99cf15b81cf9a22394a99b44f0b921b4672 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Dec 2022 15:33:56 -0500 Subject: [PATCH 004/179] fixed crash --- libi2pd/RouterContext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 5259a4f7..7568692f 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -352,7 +352,7 @@ namespace i2p if (!port) { for (const auto& address : *addresses) - if (address->port) + if (address && address->port) { newPort = address->port; break; @@ -693,7 +693,7 @@ namespace i2p default: ; } } - port = addr->port; + if (addr) port = addr->port; } } if (!port) From 476e6aae3590afba136d5469c8db6b3b8b0dc052 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Dec 2022 19:57:19 -0500 Subject: [PATCH 005/179] don't iterate through addresses when it's not necessary --- libi2pd/RouterContext.cpp | 102 +++++++++++++++++++---------------- libi2pd/RouterInfo.cpp | 110 +++++++++++++++++--------------------- 2 files changed, 105 insertions(+), 107 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 7568692f..9d696db9 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -427,35 +427,53 @@ namespace i2p auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; bool updated = false; - for (auto& address : *addresses) + if (host.is_v4 ()) { - if (!address) continue; - if (address->host != host && address->IsCompatible (host) && - !i2p::util::net::IsYggdrasilAddress (address->host)) + auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx]; + if (addr && addr->host != host) { - // update host - address->host = host; + addr->host = host; updated = true; - } - if (host.is_v6 () && address->IsV6 () && address->ssu && - (!address->ssu->mtu || updated) && m_StatusV6 != eRouterStatusProxy) + } + addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]; + if (addr && addr->host != host) { - // update MTU - auto mtu = i2p::util::net::GetMTU (host); - if (mtu) - { - LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu); - int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ()); - if (mtu > maxMTU) - { - mtu = maxMTU; - LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes"); - } - address->ssu->mtu = mtu; - updated = true; - } - } + addr->host = host; + updated = true; + } } + else if (host.is_v6 ()) + { + auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx]; + if (addr && addr->host != host) + { + addr->host = host; + updated = true; + } + addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]; + if (addr && (addr->host != host || !addr->ssu->mtu)) + { + addr->host = host; + if (m_StatusV6 != eRouterStatusProxy) + { + // update MTU + auto mtu = i2p::util::net::GetMTU (host); + if (mtu) + { + LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu); + int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ()); + if (mtu > maxMTU) + { + mtu = maxMTU; + LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes"); + } + addr->ssu->mtu = mtu; + } + } + updated = true; + } + } + auto ts = i2p::util::GetSecondsSinceEpoch (); if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL) UpdateRouterInfo (); @@ -477,18 +495,12 @@ namespace i2p void RouterContext::ClearSSU2Introducers (bool v4) { - auto addresses = m_RouterInfo.GetAddresses (); - if (!addresses) return; - bool updated = false; - for (auto& addr : *addresses) - if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) && - addr->ssu && !addr->ssu->introducers.empty ()) - { - addr->ssu->introducers.clear (); - updated = true; - } - if (updated) + auto addr = m_RouterInfo.GetSSU2Address (v4); + if (addr && !addr->ssu->introducers.empty ()) + { + addr->ssu->introducers.clear (); UpdateRouterInfo (); + } } void RouterContext::SetFloodfill (bool floodfill) @@ -829,26 +841,26 @@ namespace i2p { if (supportsmesh) { + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; m_RouterInfo.EnableMesh (); + if ((*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]) return; // we have mesh address already uint16_t port = 0; i2p::config::GetOption ("ntcp2.port", port); if (!port) i2p::config::GetOption("port", port); - bool foundMesh = false; - auto addresses = m_RouterInfo.GetAddresses (); - if (addresses) + if (!port) { for (auto& addr: *addresses) { - if (!port && addr) port = addr->port; - if (addr && i2p::util::net::IsYggdrasilAddress (addr->host)) - { - foundMesh = true; + if (addr && addr->port) + { + port = addr->port; break; - } + } } } - if (!foundMesh) - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); + if (!port) port = SelectRandomPort (); + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); } else m_RouterInfo.DisableMesh (); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index a83fd043..177ae8b3 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -742,16 +742,18 @@ namespace data { if (IsV6 ()) { - for (auto& it : *m_Addresses) + if ((*m_Addresses)[eNTCP2V6Idx]) { - if (it && it->IsV6 ()) - { - if (it->IsV4 ()) - it->caps &= ~AddressCaps::eV6; - else - it.reset (); - } - } + if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 ()) + (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV6; + (*m_Addresses)[eNTCP2V6Idx].reset (); + } + if ((*m_Addresses)[eSSU2V6Idx]) + { + if ((*m_Addresses)[eSSU2V6Idx]->IsV4 ()) + (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV6; + (*m_Addresses)[eSSU2V6Idx].reset (); + } UpdateSupportedTransports (); } } @@ -760,16 +762,18 @@ namespace data { if (IsV4 ()) { - for (auto& it : *m_Addresses) + if ((*m_Addresses)[eNTCP2V4Idx]) { - if (it && it->IsV4 ()) - { - if (it->IsV6 ()) - it->caps &= ~AddressCaps::eV4; - else - it.reset (); - } - } + if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 ()) + (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV4; + (*m_Addresses)[eNTCP2V4Idx].reset (); + } + if ((*m_Addresses)[eSSU2V4Idx]) + { + if ((*m_Addresses)[eSSU2V4Idx]->IsV6 ()) + (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV4; + (*m_Addresses)[eSSU2V4Idx].reset (); + } UpdateSupportedTransports (); } } @@ -789,11 +793,7 @@ namespace data { m_SupportedTransports &= ~eNTCP2V6Mesh; m_ReachableTransports &= ~eNTCP2V6Mesh; - for (auto& it: *m_Addresses) - { - if (it && i2p::util::net::IsYggdrasilAddress (it->host)) - it.reset (); - } + (*m_Addresses)[eNTCP2V6MeshIdx].reset (); } } @@ -859,12 +859,10 @@ namespace data std::shared_ptr RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const { if (!key) return nullptr; - return GetAddress ( - [key, isV6](std::shared_ptr address)->bool - { - return address->IsSSU2 () && !memcmp (address->s, key, 32) && - ((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ())); - }); + auto addr = (*GetAddresses ())[isV6 ? eSSU2V6Idx : eSSU2V4Idx]; + if (addr && !memcmp (addr->s, key, 32)) + return addr; + return nullptr; } std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const @@ -910,23 +908,15 @@ namespace data bool RouterInfo::IsSSU2PeerTesting (bool v4) const { if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; - return (bool)GetAddress ( - [v4](std::shared_ptr address)->bool - { - return (address->IsSSU2 ()) && address->IsPeerTesting () && - ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); - }); + auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; + return addr && addr->IsPeerTesting () && addr->IsReachableSSU (); } bool RouterInfo::IsSSU2Introducer (bool v4) const { if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; - return (bool)GetAddress ( - [v4](std::shared_ptr address)->bool - { - return (address->IsSSU2 ()) && address->IsIntroducer () && - ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); - }); + auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; + return addr && addr->IsIntroducer () && !addr->host.is_unspecified () && addr->port; } void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) @@ -1269,16 +1259,14 @@ namespace data { auto addresses = GetAddresses (); if (!addresses) return false; - for (auto& addr : *addresses) + auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; + if (addr) { - if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) - { - for (auto& intro: addr->ssu->introducers) - if (intro.iTag == introducer.iTag) return false; // already presented - addr->ssu->introducers.push_back (introducer); - SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6))); - return true; - } + for (auto& intro: addr->ssu->introducers) + if (intro.iTag == introducer.iTag) return false; // already presented + addr->ssu->introducers.push_back (introducer); + SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6))); + return true; } return false; } @@ -1287,19 +1275,17 @@ namespace data { auto addresses = GetAddresses (); if (!addresses) return false; - for (auto& addr: *addresses) + auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; + if (addr) { - if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) - { - for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) - if (h == it->iH) - { - addr->ssu->introducers.erase (it); - if (addr->ssu->introducers.empty ()) - SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6)); - return true; - } - } + for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) + if (h == it->iH) + { + addr->ssu->introducers.erase (it); + if (addr->ssu->introducers.empty ()) + SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6)); + return true; + } } return false; } From d869bb25ed2b22ba7c85d8ab3f15cd6825eea511 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 18 Dec 2022 22:32:23 +0300 Subject: [PATCH 006/179] fix missing override warning Signed-off-by: R4SAS --- libi2pd/SSU2Session.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index d12395d6..8a6e833f 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -245,7 +245,7 @@ namespace transport void SendI2NPMessages (const std::vector >& msgs) override; uint32_t GetRelayTag () const override { return m_RelayTag; }; size_t Resend (uint64_t ts); // return number or resent packets - bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; }; + override bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; }; uint64_t GetConnID () const { return m_SourceConnID; }; SSU2SessionState GetState () const { return m_State; }; void SetState (SSU2SessionState state) { m_State = state; }; From 96cfd9acc2e93f97ebf42bc6ce90c64c55d37083 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 18 Dec 2022 22:37:26 +0300 Subject: [PATCH 007/179] fix override Signed-off-by: R4SAS --- libi2pd/SSU2Session.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 8a6e833f..c9592a58 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -245,7 +245,7 @@ namespace transport void SendI2NPMessages (const std::vector >& msgs) override; uint32_t GetRelayTag () const override { return m_RelayTag; }; size_t Resend (uint64_t ts); // return number or resent packets - override bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; }; + bool IsEstablished () const override { return m_State == eSSU2SessionStateEstablished; }; uint64_t GetConnID () const { return m_SourceConnID; }; SSU2SessionState GetState () const { return m_State; }; void SetState (SSU2SessionState state) { m_State = state; }; From a315e4ce62d37d21909d41e6d768726cfae258f1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 18 Dec 2022 22:53:14 +0300 Subject: [PATCH 008/179] more overrides Signed-off-by: R4SAS --- libi2pd/NTCP2.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 754f5a6d..265b1f6b 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -134,7 +134,7 @@ namespace transport ~NTCP2Session (); void Terminate (); void TerminateByTimeout (); - void Done (); + void Done () override; void Close () { m_Socket.close (); }; // for accept void DeleteNextReceiveBuffer (uint64_t ts); @@ -142,14 +142,14 @@ namespace transport const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; void SetRemoteEndpoint (const boost::asio::ip::tcp::endpoint& ep) { m_RemoteEndpoint = ep; }; - bool IsEstablished () const { return m_IsEstablished; }; + bool IsEstablished () const override { return m_IsEstablished; }; bool IsTerminated () const { return m_IsTerminated; }; void ClientLogin (); // Alice void ServerLogin (); // Bob - void SendLocalRouterInfo (bool update); // after handshake or by update - void SendI2NPMessages (const std::vector >& msgs); + void SendLocalRouterInfo (bool update) override; // after handshake or by update + void SendI2NPMessages (const std::vector >& msgs) override; private: From c210553a3902ba7155033661f73865c6c37cd569 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 18 Dec 2022 23:26:18 +0300 Subject: [PATCH 009/179] getting rid of old c99 array designators Signed-off-by: R4SAS --- libi2pd/Log.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index e90b5e2b..94e65691 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -18,11 +18,11 @@ namespace log { /** * @brief Maps our loglevel to their symbolic name */ - static const char * g_LogLevelStr[eNumLogLevels] = + static const char *g_LogLevelStr[eNumLogLevels] = { "none", // eLogNone "error", // eLogError - "warn", // eLogWarn + "warn", // eLogWarning "info", // eLogInfo "debug" // eLogDebug }; @@ -35,12 +35,12 @@ namespace log { static const char *LogMsgColors[] = { "", "", "", "", "", "" }; #else /* UNIX */ static const char *LogMsgColors[] = { - [eLogNone] = "\033[0m", /* reset */ - [eLogError] = "\033[1;31m", /* red */ - [eLogWarning] = "\033[1;33m", /* yellow */ - [eLogInfo] = "\033[1;36m", /* cyan */ - [eLogDebug] = "\033[1;34m", /* blue */ - [eNumLogLevels] = "\033[0m", /* reset */ + "\033[1;32m", /* none: green */ + "\033[1;31m", /* error: red */ + "\033[1;33m", /* warning: yellow */ + "\033[1;36m", /* info: cyan */ + "\033[1;34m", /* debug: blue */ + "\033[0m" /* reset */ }; #endif From 5dfe483152149cf5dcae9c906585ed3f027f0c02 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 19 Dec 2022 00:56:41 +0300 Subject: [PATCH 010/179] [i18n] add Czech translation Signed-off-by: R4SAS --- contrib/i2pd.conf | 2 +- i18n/Czech.cpp | 216 ++++++++++++++++++++++++++++++++++++++++++++++ i18n/I18N_langs.h | 2 + 3 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 i18n/Czech.cpp diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index b281ce8f..b3048ff5 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -126,7 +126,7 @@ port = 7070 # user = i2pd # pass = changeme ## Select webconsole language -## Currently supported english (default), afrikaans, armenian, chinese, french, +## Currently supported english (default), afrikaans, armenian, chinese, czech, french, ## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages # lang = english diff --git a/i18n/Czech.cpp b/i18n/Czech.cpp new file mode 100644 index 00000000..f6ac7188 --- /dev/null +++ b/i18n/Czech.cpp @@ -0,0 +1,216 @@ +/* +* Copyright (c) 2022, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Czech localization file + +namespace i2p +{ +namespace i18n +{ +namespace czech // language namespace +{ + // language name in lowercase + static std::string language = "czech"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2; + } + + static std::map strings + { + {"KiB", "KiB"}, + {"MiB", "MiB"}, + {"GiB", "GiB"}, + {"building", "vytváří se"}, + {"failed", "selhalo"}, + {"expiring", "končící"}, + {"established", "vytvořeno"}, + {"unknown", "neznámý"}, + {"exploratory", "průzkumné"}, + {"Purple I2P Webconsole", "Purple I2P Webkonsole"}, + {"i2pd webconsole", "i2pd webkonsole"}, + {"Main page", "Hlavní stránka"}, + {"Router commands", "Router příkazy"}, + {"Local Destinations", "Lokální destinace"}, + {"LeaseSets", "LeaseSety"}, + {"Tunnels", "Tunely"}, + {"Transit Tunnels", "Transitní tunely"}, + {"Transports", "Transporty"}, + {"I2P tunnels", "I2P tunely"}, + {"SAM sessions", "SAM relace"}, + {"ERROR", "CHYBA"}, + {"OK", "OK"}, + {"Testing", "Testuji"}, + {"Firewalled", "Za Firewallem"}, + {"Unknown", "Neznámý"}, + {"Proxy", "Proxy"}, + {"Mesh", "Síť"}, + {"Error", "Chyba"}, + {"Clock skew", "Časová nesrovnalost"}, + {"Offline", "Offline"}, + {"Symmetric NAT", "Symetrický NAT"}, + {"Uptime", "Doba provozu"}, + {"Network status", "Status sítě"}, + {"Network status v6", "Status sítě v6"}, + {"Stopping in", "Zastavuji za"}, + {"Family", "Rodina"}, + {"Tunnel creation success rate", "Úspěšnost vytváření tunelů"}, + {"Received", "Přijato"}, + {"KiB/s", "KiB/s"}, + {"Sent", "Odesláno"}, + {"Transit", "Tranzit"}, + {"Data path", "Cesta k data souborům"}, + {"Hidden content. Press on text to see.", "Skrytý kontent. Pro zobrazení, klikni na text."}, + {"Router Ident", "Routerová Identita"}, + {"Router Family", "Rodina routerů"}, + {"Router Caps", "Omezení Routerů"}, + {"Version", "Verze"}, + {"Our external address", "Naše externí adresa"}, + {"supported", "podporováno"}, + {"Routers", "Routery"}, + {"Floodfills", "Floodfilly"}, + {"Client Tunnels", "Klientské tunely"}, + {"Services", "Služby"}, + {"Enabled", "Zapnuto"}, + {"Disabled", "Vypnuto"}, + {"Encrypted B33 address", "Šifrovaná adresa B33"}, + {"Address registration line", "Registrační řádek adresy"}, + {"Domain", "Doména"}, + {"Generate", "Vygenerovat"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Poznámka: výsledný řetězec může být použit pouze pro registraci 2LD domén (example.i2p). Pro registraci subdomén použijte prosím i2pd-tools."}, + {"Address", "Adresa"}, + {"Type", "Typ"}, + {"EncType", "EncType"}, + {"Inbound tunnels", "Příchozí tunely"}, + {"ms", "ms"}, + {"Outbound tunnels", "Odchozí tunely"}, + {"Tags", "Štítky"}, + {"Incoming", "Příchozí"}, + {"Outgoing", "Odchozí"}, + {"Destination", "Destinace"}, + {"Amount", "Množství"}, + {"Incoming Tags", "Příchozí štítky"}, + {"Tags sessions", "Relace štítků"}, + {"Status", "Status"}, + {"Local Destination", "Lokální Destinace"}, + {"Streams", "Toky"}, + {"Close stream", "Uzavřít tok"}, + {"I2CP session not found", "I2CP relace nenalezena"}, + {"I2CP is not enabled", "I2CP není zapnuto"}, + {"Invalid", "Neplatný"}, + {"Store type", "Druh uložení"}, + {"Expires", "Vyprší"}, + {"Non Expired Leases", "Nevypršené Leasy"}, + {"Gateway", "Brána"}, + {"TunnelID", "ID tunelu"}, + {"EndDate", "Datum ukončení"}, + {"not floodfill", "není floodfill"}, + {"Queue size", "Velikost fronty"}, + {"Run peer test", "Spustit peer test"}, + {"Decline transit tunnels", "Odmítnout tranzitní tunely"}, + {"Accept transit tunnels", "Přijmout tranzitní tunely"}, + {"Cancel graceful shutdown", "Zrušit hladké vypnutí"}, + {"Start graceful shutdown", "Zahájit hladké vypnutí"}, + {"Force shutdown", "Vynutit vypnutí"}, + {"Reload external CSS styles", "Znovu načíst externí CSS"}, + {"Note: any action done here are not persistent and not changes your config files.", "Poznámka: žádná vykonaná akce zde není trvalá a nemění konfigurační soubory."}, + {"Logging level", "Úroveň logování"}, + {"Transit tunnels limit", "Limit tranzitních tunelů"}, + {"Change", "Změnit"}, + {"Change language", "Změnit jazyk"}, + {"no transit tunnels currently built", "Žádný tranzitní tunel není momentálně vytvořen"}, + {"SAM disabled", "SAM vypnutý"}, + {"no sessions currently running", "Momentálně nejsou spuštěné žádné relace"}, + {"SAM session not found", "SAM relace nenalezena"}, + {"SAM Session", "SAM Relace"}, + {"Server Tunnels", "Server Tunely"}, + {"Client Forwards", "Přesměrování Klienta"}, + {"Server Forwards", "Přesměrování Serveru"}, + {"Unknown page", "Neznámá stránka"}, + {"Invalid token", "Neplatný token"}, + {"SUCCESS", "ÚSPĚCH"}, + {"Stream closed", "Tok uzavřen"}, + {"Stream not found or already was closed", "Tok nenalezen nebo byl již uzavřen"}, + {"Destination not found", "Destinace nenalezena"}, + {"StreamID can't be null", "StreamID nemůže být null"}, + {"Return to destination page", "Zpět na stránku destinací"}, + {"You will be redirected in 5 seconds", "Budete přesměrováni za 5 vteřin"}, + {"Transit tunnels count must not exceed 65535", "Počet tranzitních tunelů nesmí přesáhnout 65535"}, + {"Back to commands list", "Zpět na list příkazů"}, + {"Register at reg.i2p", "Zaregistrovat na reg.i2p"}, + {"Description", "Popis"}, + {"A bit information about service on domain", "Trochu informací o službě na doméně"}, + {"Submit", "Odeslat"}, + {"Domain can't end with .b32.i2p", "Doména nesmí končit na .b32.i2p"}, + {"Domain must end with .i2p", "Doména musí končit s .i2p"}, + {"Such destination is not found", "Takováto destinace nebyla nalezena"}, + {"Unknown command", "Neznámý příkaz"}, + {"Command accepted", "Příkaz přijat"}, + {"Proxy error", "Chyba proxy serveru"}, + {"Proxy info", "Proxy informace"}, + {"Proxy error: Host not found", "Chyba proxy serveru: Hostitel nenalezen"}, + {"Remote host not found in router's addressbook", "Vzdálený hostitel nebyl nalezen v adresáři routeru"}, + {"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"}, + {"Invalid request", "Neplatný požadavek"}, + {"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"}, + {"addresshelper is not supported", "Adresshelper není podporován"}, + {"Host", "Hostitel"}, + {"added to router's addressbook from helper", "přidáno do adresáře routeru od pomocníka"}, + {"Click here to proceed:", "Pro pokračování, klikněte zde:"}, + {"Continue", "Pokračovat"}, + {"Addresshelper found", "Adresář nalezen"}, + {"already in router's addressbook", "je již v adresáři routeru"}, + {"Click here to update record:", "Pro aktualizaci záznamu, klikněte zde:"}, + {"invalid request uri", "neplatný URI požadavek"}, + {"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"}, + {"Outproxy failure", "Outproxy selhání"}, + {"bad outproxy settings", "špatné outproxy nastavení"}, + {"not inside I2P network, but outproxy is not enabled", "není uvnitř I2P sítě a outproxy není nastavena"}, + {"unknown outproxy url", "neznámá outproxy URL"}, + {"cannot resolve upstream proxy", "nelze rozluštit upstream proxy server"}, + {"hostname too long", "Název hostitele je příliš dlouhý"}, + {"cannot connect to upstream socks proxy", "nelze se připojit k upstream socks proxy serveru"}, + {"Cannot negotiate with socks proxy", "Nelze vyjednávat se socks proxy serverem"}, + {"CONNECT error", "Chyba PŘIPOJENÍ"}, + {"Failed to Connect", "Připojení se nezdařilo"}, + {"socks proxy error", "chyba socks proxy serveru"}, + {"failed to send request to upstream", "odeslání žádosti upstream serveru se nezdařilo"}, + {"No Reply From socks proxy", "Žádná odpověď od socks proxy serveru"}, + {"cannot connect", "nelze se připojit"}, + {"http out proxy not implemented", "http out proxy není implementován"}, + {"cannot connect to upstream http proxy", "nelze se připojit k upstream socks proxy serveru"}, + {"Host is down", "Hostitel je nedostupný"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."}, + {"", ""}, + }; + + static std::map> plurals + { + {"days", {"den", "dny", "dní", "dní"}}, + {"hours", {"hodina", "hodiny", "hodin", "hodin"}}, + {"minutes", {"minuta", "minuty", "minut", "minut"}}, + {"seconds", {"vteřina", "vteřiny", "vteřin", "vteřin"}}, + {"", {"", "", "", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 42c7ba4e..1b03917d 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -26,6 +26,7 @@ namespace i18n namespace afrikaans { std::shared_ptr GetLocale (); } namespace armenian { std::shared_ptr GetLocale (); } namespace chinese { std::shared_ptr GetLocale (); } + namespace czech { std::shared_ptr GetLocale (); } namespace english { std::shared_ptr GetLocale (); } namespace french { std::shared_ptr GetLocale (); } namespace german { std::shared_ptr GetLocale (); } @@ -44,6 +45,7 @@ namespace i18n { "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} }, { "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} }, { "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} }, + { "czech", {"čeština ", "cs", i2p::i18n::czech::GetLocale} }, { "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, From 0e0cd555eb475efddf170e4d7712afc01b791b22 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 19 Dec 2022 01:00:50 +0300 Subject: [PATCH 011/179] [i18n] odd space in localized name Signed-off-by: R4SAS --- i18n/I18N_langs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 1b03917d..9a236d7a 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -45,7 +45,7 @@ namespace i18n { "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} }, { "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} }, { "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} }, - { "czech", {"čeština ", "cs", i2p::i18n::czech::GetLocale} }, + { "czech", {"čeština", "cs", i2p::i18n::czech::GetLocale} }, { "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, From eeea02d8345574b094fd63e28aa4f76a666118d9 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Dec 2022 12:56:19 -0500 Subject: [PATCH 012/179] rounded to seconds timestamps --- libi2pd/NTCP2.cpp | 4 ++-- libi2pd/SSU2Session.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f78999be..f2bdc466 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -139,7 +139,7 @@ namespace transport m3p2[3] = 0; // flag memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex // 2 bytes reserved - htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA + htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds // 4 bytes reserved // sign and encrypt options, use m_H as AD uint8_t nonce[12]; @@ -162,7 +162,7 @@ namespace transport uint8_t options[16]; memset (options, 0, 16); htobe16buf (options + 2, paddingLen); // padLen - htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsB + htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds // sign and encrypt options, use m_H as AD uint8_t nonce[12]; memset (nonce, 0, 12); // set nonce to zero diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 85c91f71..aedf346c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -570,7 +570,7 @@ namespace transport // payload payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, ts/1000); + htobe32buf (payload + 3, (ts + 500)/1000); size_t payloadSize = 7; if (GetRouterStatus () == eRouterStatusFirewalled && m_Address->IsIntroducer ()) { @@ -684,7 +684,7 @@ namespace transport size_t maxPayloadSize = m_MaxPayloadSize - 48; payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, ts/1000); + htobe32buf (payload + 3, (ts + 500)/1000); size_t payloadSize = 7; payloadSize += CreateAddressBlock (payload + payloadSize, maxPayloadSize - payloadSize, m_RemoteEndpoint); if (m_RelayTag) @@ -1046,7 +1046,7 @@ namespace transport // payload payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); size_t payloadSize = 7; payloadSize += CreatePaddingBlock (payload + payloadSize, 25 - payloadSize, 1); // encrypt @@ -1117,7 +1117,7 @@ namespace transport // payload payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); size_t payloadSize = 7; payloadSize += CreateAddressBlock (payload + payloadSize, 56 - payloadSize, m_RemoteEndpoint); if (m_TerminationReason != eSSU2TerminationReasonNormalClose) @@ -1205,7 +1205,7 @@ namespace transport // payload payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); size_t payloadSize = 7; payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, ep); payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, @@ -1281,7 +1281,7 @@ namespace transport // payload payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); + 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); From d6c101d261dc5c46140a07ddc9510d0d588e42e2 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Dec 2022 13:28:21 -0500 Subject: [PATCH 013/179] try to handle RelayIntro again is Alice's RouterInfo not found --- libi2pd/SSU2Session.cpp | 19 ++++++++++++++++--- libi2pd/SSU2Session.h | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index aedf346c..9c2153a6 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1836,7 +1836,7 @@ namespace transport session->SendData (payload, payloadSize); } - void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len) + void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len, int attempts) { // we are Charlie SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept; @@ -1891,9 +1891,22 @@ namespace transport code = eSSU2RelayResponseCodeCharlieSignatureFailure; } } - else + else if (!attempts) { - LogPrint (eLogError, "SSU2: RelayIntro unknown router to introduce"); + // RouterInfo migth come in the next packet, try again + auto vec = std::make_shared >(len); + memcpy (vec->data (), buf, len); + auto s = shared_from_this (); + m_Server.GetService ().post ([s, vec, attempts]() + { + LogPrint (eLogDebug, "SSU2: RelayIntro attempt ", attempts + 1); + s->HandleRelayIntro (vec->data (), vec->size (), attempts + 1); + }); + return; + } + else + { + LogPrint (eLogWarning, "SSU2: RelayIntro unknown router to introduce"); code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; } // send relay response to Bob diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index c9592a58..aab02127 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -305,7 +305,7 @@ namespace transport void HandleFollowOnFragment (const uint8_t * buf, size_t len); bool ConcatOutOfSequenceFragments (std::shared_ptr m); // true if message complete void HandleRelayRequest (const uint8_t * buf, size_t len); - void HandleRelayIntro (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); From d3656fcb3ff1353bab3c645d9197d5cec3d5ad77 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Dec 2022 14:16:23 -0500 Subject: [PATCH 014/179] don't publish ::1 --- libi2pd/RouterContext.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 9d696db9..9e17e1fa 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -125,7 +125,7 @@ namespace i2p } if (ipv6) { - std::string host = "::1"; + std::string host; if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only i2p::config::GetOption("host", host); else @@ -136,6 +136,7 @@ namespace i2p if (ntcp2) { + bool added = false; if (ntcp2Published) { std::string ntcp2Host; @@ -143,9 +144,13 @@ namespace i2p i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); else ntcp2Host = host; - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port); + if (!ntcp2Host.empty () && port) + { + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port); + added = true; + } } - else + if (!added) { if (!ipv4) // no other ntcp2 addresses yet routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); @@ -154,13 +159,18 @@ namespace i2p } if (ssu2) { + bool added = false; if (ssu2Published) { uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = port; - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port); + if (!host.empty () && ssu2Port) + { + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port); + added = true; + } } - else + if (!added) { if (!ipv4) // no other ssu2 addresses yet routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro); From 5ac01ddce84d7555866c5a048a91b86b889ed870 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Dec 2022 15:23:54 -0500 Subject: [PATCH 015/179] delete routers with timestmep from future --- libi2pd/NetDb.cpp | 10 ++++++++-- libi2pd/NetDb.hpp | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index d588b809..6f39072f 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -494,7 +494,8 @@ namespace data { auto r = std::make_shared(path); if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () && - ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL) + ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL && // too old + ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) // from future { r->DeleteBuffer (); if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) @@ -637,7 +638,12 @@ namespace data it.second->SetUnreachable (true); } else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) - it.second->SetUnreachable (true); + it.second->SetUnreachable (true); + else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) + { + LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); + it.second->SetUnreachable (true); + } if (it.second->IsUnreachable ()) { diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 95f6c692..e89cda92 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -44,6 +44,7 @@ namespace data const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days + const int NETDB_EXPIRATION_TIMEOUT_THRESHOLD = 2*60; // 2 minutes const int NETDB_PUBLISH_INTERVAL = 60 * 40; const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; From e4ddc883d2fdf29aa39a2ec278a180c650f9f6c4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Dec 2022 18:41:19 -0500 Subject: [PATCH 016/179] drop future RouterInfo and LeaseSet upon receive --- libi2pd/NetDb.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 6f39072f..867a4eb3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -295,7 +295,8 @@ namespace data else { r = std::make_shared (buf, len); - if (!r->IsUnreachable () && r->HasValidAddresses ()) + if (!r->IsUnreachable () && r->HasValidAddresses () && + i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) { bool inserted = false; { @@ -365,15 +366,16 @@ namespace data bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType) { - std::unique_lock lock(m_LeaseSetsMutex); auto leaseSet = std::make_shared (storeType, buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { + std::unique_lock lock(m_LeaseSetsMutex); auto it = m_LeaseSets.find(ident); if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType || leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ()) { - if (leaseSet->IsPublic () && !leaseSet->IsExpired ()) + if (leaseSet->IsPublic () && !leaseSet->IsExpired () && + i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ()) { // TODO: implement actual update LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); @@ -382,7 +384,7 @@ namespace data } else { - LogPrint (eLogWarning, "NetDb: Unpublished or expired LeaseSet2 received: ", ident.ToBase32()); + LogPrint (eLogWarning, "NetDb: Unpublished or expired or future LeaseSet2 received: ", ident.ToBase32()); m_LeaseSets.erase (ident); } } @@ -494,8 +496,7 @@ namespace data { auto r = std::make_shared(path); if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () && - ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL && // too old - ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) // from future + ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL) // too old { r->DeleteBuffer (); if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) From 36501fe31e908ca74eb54d0b08baa8841e427a88 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Dec 2022 18:14:19 -0500 Subject: [PATCH 017/179] change network status back to OK if port in msg 7 matches --- libi2pd/SSU2Session.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9c2153a6..9b1df3da 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1661,6 +1661,7 @@ namespace transport bool isV4 = ep.address ().is_v4 (); if (ep.port () != m_Server.GetPort (isV4)) { + LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4)); if (isV4) { if (i2p::context.GetStatus () == eRouterStatusTesting || @@ -1687,12 +1688,18 @@ namespace transport if (isV4) { if (i2p::context.GetError () == eRouterErrorSymmetricNAT) + { i2p::context.SetError (eRouterErrorNone); + if (m_State == eSSU2SessionStatePeerTest) + i2p::context.SetStatus (eRouterStatusOK); + } } else { if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) i2p::context.SetErrorV6 (eRouterErrorNone); + if (m_State == eSSU2SessionStatePeerTest) + i2p::context.SetStatusV6 (eRouterStatusOK); } } } From 3f728149ab0a7cf232a9d030be30f6c639064432 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Dec 2022 18:27:42 -0500 Subject: [PATCH 018/179] bump default max number of transit tunnels to 5000 --- libi2pd/Config.cpp | 2 +- libi2pd/I2NPProtocol.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 046f0a25..556b226b 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -77,7 +77,7 @@ namespace config { limits.add_options() ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.openfiles", value()->default_value(0), "Maximum number of open files (0 - use system default)") - ("limits.transittunnels", value()->default_value(2500), "Maximum active transit sessions (default:2500)") + ("limits.transittunnels", value()->default_value(5000), "Maximum active transit tunnels (default:5000)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") ("limits.ntcphard", value()->default_value(0), "Ignored") ("limits.ntcpthreads", value()->default_value(1), "Ignored") diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index e60f6a9c..a388dc52 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -309,7 +309,7 @@ namespace tunnel std::vector > m_TunnelMsgs, m_TunnelGatewayMsgs; }; - const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500; + const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000; void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels (); } From b6f83dfe9feca61576365964188fa59df61f5bfb Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 22 Dec 2022 08:36:07 -0500 Subject: [PATCH 019/179] set error before status --- libi2pd/SSU2Session.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9b1df3da..7c394101 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1667,8 +1667,8 @@ namespace transport if (i2p::context.GetStatus () == eRouterStatusTesting || m_State == eSSU2SessionStatePeerTest) { - i2p::context.SetError (eRouterErrorSymmetricNAT); i2p::context.SetStatus (eRouterStatusFirewalled); + i2p::context.SetError (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimer (); } } @@ -1677,8 +1677,8 @@ namespace transport if (i2p::context.GetStatusV6 () == eRouterStatusTesting || m_State == eSSU2SessionStatePeerTest) { - i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); i2p::context.SetStatusV6 (eRouterStatusFirewalled); + i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimerV6 (); } } @@ -1689,17 +1689,19 @@ namespace transport { if (i2p::context.GetError () == eRouterErrorSymmetricNAT) { - i2p::context.SetError (eRouterErrorNone); if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetStatus (eRouterStatusOK); + i2p::context.SetError (eRouterErrorNone); } } else { if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) + { + if (m_State == eSSU2SessionStatePeerTest) + i2p::context.SetStatusV6 (eRouterStatusOK); i2p::context.SetErrorV6 (eRouterErrorNone); - if (m_State == eSSU2SessionStatePeerTest) - i2p::context.SetStatusV6 (eRouterStatusOK); + } } } } From 6376328c98d54178290c5f659a7536f098d0a4ef Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 22 Dec 2022 17:55:51 +0000 Subject: [PATCH 020/179] [http proxy] do not remove X-Requested-With for *HttpRequest (#1816) Signed-off-by: R4SAS --- libi2pd_client/HTTPProxy.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 451c9c74..b9d4d48c 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -252,7 +252,6 @@ namespace proxy { req.RemoveHeader("From"); req.RemoveHeader("Forwarded"); req.RemoveHeader("DNT"); // Useless DoNotTrack flag - req.RemoveHeader("X-Requested-With"); // Android Webview send this with the value set to the application ID req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding /* drop proxy-disclosing headers */ req.RemoveHeader("X-Forwarded"); @@ -260,6 +259,18 @@ namespace proxy { /* replace headers */ req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)"); + /** + * i2pd PR #1816: + * Android Webview send this with the value set to the application ID, so we drop it, + * but only if it does not belong to an AJAX request (*HttpRequest, like XMLHttpRequest). + */ + if(req.GetHeader("X-Requested-With") != "") { + auto h = req.GetHeader ("X-Requested-With"); + auto x = h.find("HttpRequest"); + if (x == std::string::npos) // not found + req.RemoveHeader("X-Requested-With"); + } + /** * according to i2p ticket #1862: * leave Referer if requested URL with same schema, host and port, From 54b7d4ef326cb4973aa0ee266d3e31085a7b38d1 Mon Sep 17 00:00:00 2001 From: Eric Long Date: Sat, 24 Dec 2022 18:51:40 +0800 Subject: [PATCH 021/179] Fix CheckAtomic.cmake --- build/cmake_modules/CheckAtomic.cmake | 44 +++++++++++++++------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/build/cmake_modules/CheckAtomic.cmake b/build/cmake_modules/CheckAtomic.cmake index b8296a1c..d5ec6a0a 100644 --- a/build/cmake_modules/CheckAtomic.cmake +++ b/build/cmake_modules/CheckAtomic.cmake @@ -1,18 +1,23 @@ # atomic builtins are required for threading support. INCLUDE(CheckCXXSourceCompiles) +INCLUDE(CheckLibraryExists) # Sometimes linking against libatomic is required for atomic ops, if # the platform doesn't support lock-free atomics. function(check_working_cxx_atomics varname) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-std=c++11") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") CHECK_CXX_SOURCE_COMPILES(" #include std::atomic x; +std::atomic y; +std::atomic z; int main() { - return x; + ++z; + ++y; + return ++x; } " ${varname}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) @@ -27,6 +32,7 @@ function(check_working_cxx_atomics64 varname) std::atomic x (0); int main() { uint64_t i = x.load(std::memory_order_relaxed); + (void)i; return 0; } " ${varname}) @@ -34,15 +40,16 @@ int main() { endfunction(check_working_cxx_atomics64) -# This isn't necessary on MSVC, so avoid command-line switch annoyance -# by only running on GCC-like hosts. -if (LLVM_COMPILER_IS_GCC_COMPATIBLE) +# Check for (non-64-bit) atomic operations. +if(MSVC) + set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) +else() # First check if atomics work without the library. check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) # If not, check if the library exists, and atomics work with it. if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) - if( HAVE_LIBATOMIC ) + if(HAVE_LIBATOMIC) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) if (NOT HAVE_CXX_ATOMICS_WITH_LIB) @@ -58,20 +65,20 @@ endif() if(MSVC) set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) else() + # First check if atomics work without the library. check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) -endif() - -# If not, check if the library exists, and atomics work with it. -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) - check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) - if(HAVE_CXX_LIBATOMICS64) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) - if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) - message(FATAL_ERROR "Host compiler must support std::atomic!") + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) + if(HAVE_CXX_LIBATOMICS64) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) + message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") endif() - else() - message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") endif() endif() @@ -80,7 +87,6 @@ endif() ## assumes C++11 works. CHECK_CXX_SOURCE_COMPILES(" #ifdef _MSC_VER -#include /* Workaround for PR19898. */ #include #endif int main() { From 5ef5f5a170e0cbbd41fcf987fba7959fa025097e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Dec 2022 09:36:16 -0500 Subject: [PATCH 022/179] don't create encryption for new transit tunnel immediately --- libi2pd/I2NPProtocol.cpp | 3 ++- libi2pd/TransitTunnel.cpp | 21 +++++++++++++-------- libi2pd/TransitTunnel.h | 25 +++++++++++++------------ libi2pd/TunnelBase.h | 4 ++-- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index e19e782d..b8acbcbe 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -558,7 +558,8 @@ namespace i2p return; } auto& noiseState = i2p::context.GetCurrentNoiseState (); - uint8_t replyKey[32], layerKey[32], ivKey[32]; + uint8_t replyKey[32]; // AEAD/Chacha20/Poly1305 + i2p::crypto::AESKey layerKey, ivKey; // AES i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); memcpy (replyKey, noiseState.m_CK + 32, 32); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index c4f3fa19..7b9a2021 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -20,16 +20,21 @@ namespace i2p namespace tunnel { TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): - TunnelBase (receiveTunnelID, nextTunnelID, nextIdent) + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): + TunnelBase (receiveTunnelID, nextTunnelID, nextIdent), + m_LayerKey (layerKey), m_IVKey (ivKey) { - m_Encryption.SetKeys (layerKey, ivKey); } void TransitTunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) { - m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); + if (!m_Encryption) + { + m_Encryption.reset (new i2p::crypto::TunnelEncryption); + m_Encryption->SetKeys (m_LayerKey, m_IVKey); + } + m_Encryption->Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE); } @@ -94,8 +99,8 @@ namespace tunnel } std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, bool isGateway, bool isEndpoint) { if (isEndpoint) diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index bce90958..60e2f450 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,8 +28,8 @@ namespace tunnel public: TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey); + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey); virtual size_t GetNumTransmittedBytes () const { return 0; }; @@ -39,7 +39,8 @@ namespace tunnel void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); private: - i2p::crypto::TunnelEncryption m_Encryption; + i2p::crypto::AESKey m_LayerKey, m_IVKey; + std::unique_ptr m_Encryption; }; class TransitTunnelParticipant: public TransitTunnel @@ -47,8 +48,8 @@ namespace tunnel public: TransitTunnelParticipant (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_NumTransmittedBytes (0) {}; ~TransitTunnelParticipant (); @@ -68,8 +69,8 @@ namespace tunnel public: TransitTunnelGateway (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Gateway(this) {}; @@ -88,8 +89,8 @@ namespace tunnel public: TransitTunnelEndpoint (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Endpoint (false) {}; // transit endpoint is always outbound @@ -104,8 +105,8 @@ namespace tunnel }; std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, + const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, bool isGateway, bool isEndpoint); } } diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 8d0edff1..d58ec2d7 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -41,7 +41,7 @@ namespace tunnel { public: - TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent): + TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, const i2p::data::IdentHash& nextIdent): m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {}; virtual ~TunnelBase () {}; From 99356fd24dc0aed9359e8da95fb9dd11ac5179b3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Dec 2022 15:35:00 -0500 Subject: [PATCH 023/179] make sure that AsycReceive complete --- libi2pd/Streaming.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 5b4468fd..dda74015 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -478,22 +478,39 @@ namespace stream { if (!len) return 0; size_t ret = 0; + volatile bool done = false; std::condition_variable newDataReceived; std::mutex newDataReceivedMutex; std::unique_lock l(newDataReceivedMutex); AsyncReceive (boost::asio::buffer (buf, len), - [&ret, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred) + [&ret, &done, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode == boost::asio::error::timed_out) ret = 0; else ret = bytes_transferred; std::unique_lock l(newDataReceivedMutex); + done = true; newDataReceived.notify_all (); }, timeout); - if (newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) + if (newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) ret = 0; + if (!done) + { + // make sure that AsycReceive complete + auto s = shared_from_this(); + m_Service.post ([s]() + { + s->m_ReceiveTimer.cancel (); + }); + int i = 0; + while (!done && i < 100) // 1 sec + { + std::this_thread::sleep_for (std::chrono::milliseconds(10)); + i++; + } + } return ret; } From 445cff00257e399279e0bb3247d71cf9d1ae6582 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 26 Dec 2022 09:42:35 +0300 Subject: [PATCH 024/179] add editorconfig Signed-off-by: R4SAS --- .editorconfig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..97acf820 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,27 @@ +# editorconfig.org + +root = true + +[*] +# Unix style files +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[Makefile,Makefile.*] +indent_style = tab +indent_size = 4 + +[*.{h,cpp}] +indent_style = tab +indent_size = 4 + +[*.rc] +indent_style = space +indent_size = 4 + +[*.{md,markdown}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = false From 8500aaa26f793cfbaf52eadb929f9389ce3c46f0 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 26 Dec 2022 09:43:29 +0300 Subject: [PATCH 025/179] [gha] fix MacOS build More info: https://github.com/orgs/Homebrew/discussions/3895 Signed-off-by: R4SAS --- .github/workflows/build-osx.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index 50672d26..afddb7e9 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -14,6 +14,7 @@ jobs: - uses: actions/checkout@v2 - name: install packages run: | + find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete brew update brew install boost miniupnpc openssl@1.1 - name: build application From 9f9e8bfa147bf260cda7476995bdf1ab5c27701c Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Tue, 27 Dec 2022 10:44:23 +0200 Subject: [PATCH 026/179] Fix typos --- libi2pd/SSU2Session.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 7c394101..b37b2cb8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1902,7 +1902,7 @@ namespace transport } else if (!attempts) { - // RouterInfo migth come in the next packet, try again + // RouterInfo might come in the next packet, try again auto vec = std::make_shared >(len); memcpy (vec->data (), buf, len); auto s = shared_from_this (); @@ -2427,7 +2427,7 @@ namespace transport d.quot = maxNumRanges; d.rem = 0; } - // Acks only ragnes for acnt + // Acks only ranges for acnt for (int i = 0; i < d.quot; i++) { buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = 255; // NACKs 0, Acks 255 @@ -2476,7 +2476,7 @@ namespace transport } if (numRanges < maxNumRanges && it == m_OutOfSequencePackets.rend ()) { - // add range between out-of-seqence and received + // add range between out-of-sequence and received int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1; if (nacks > 0) { From edb7a0e23c8b8026febf75c7aac460dff4e2e6d3 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Dec 2022 21:54:32 -0500 Subject: [PATCH 027/179] Refuse dulicated incoming pending session from same IP --- libi2pd/NTCP2.cpp | 69 +++++++++++++++++++++++++++++++++-------------- libi2pd/NTCP2.h | 4 +-- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f2bdc466..a5e160fc 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -378,6 +378,13 @@ namespace transport } } + void NTCP2Session::Close () + { + m_Socket.close (); + SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + } + void NTCP2Session::TerminateByTimeout () { SendTerminationAndTerminate (eNTCP2IdleTimeout); @@ -395,7 +402,7 @@ namespace transport SetTerminationTimeout (NTCP2_TERMINATION_TIMEOUT); transports.PeerConnected (shared_from_this ()); } - + void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) { memset (nonce, 0, 4); @@ -1289,7 +1296,7 @@ namespace transport for (auto& it: ntcpSessions) it.second->Terminate (); for (auto& it: m_PendingIncomingSessions) - it->Terminate (); + it.second->Terminate (); } m_NTCP2Sessions.clear (); @@ -1305,7 +1312,7 @@ namespace transport { if (!session) return false; if (incoming) - m_PendingIncomingSessions.remove (session); + m_PendingIncomingSessions.erase (session->GetRemoteEndpoint ().address ()); if (!session->GetRemoteIdentity ()) return false; auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto it = m_NTCP2Sessions.find (ident); @@ -1413,13 +1420,22 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (conn) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - m_PendingIncomingSessions.push_back (conn); - conn = nullptr; - } + if (!i2p::util::net::IsInReservedRange(ep.address ())) + { + if (conn) + { + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) + { + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; + } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + } + } + else + LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); } else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); @@ -1454,12 +1470,22 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (conn) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - m_PendingIncomingSessions.push_back (conn); - } + if (!i2p::util::net::IsInReservedRange(ep.address ())) + { + if (conn) + { + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) + { + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; + } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + } + } + else + LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); } else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); @@ -1476,7 +1502,10 @@ namespace transport if (error != boost::asio::error::operation_aborted) { - conn = std::make_shared (*this); + if (!conn) // connection is used, create new one + conn = std::make_shared (*this); + else // reuse failed + conn->Close (); m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); } @@ -1507,12 +1536,12 @@ namespace transport // pending for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();) { - if ((*it)->IsEstablished () || (*it)->IsTerminationTimeoutExpired (ts)) + if (it->second->IsEstablished () || it->second->IsTerminationTimeoutExpired (ts)) { - (*it)->Terminate (); + it->second->Terminate (); it = m_PendingIncomingSessions.erase (it); // established of expired } - else if ((*it)->IsTerminated ()) + else if (it->second->IsTerminated ()) it = m_PendingIncomingSessions.erase (it); // already terminated else it++; diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 265b1f6b..ba1380c3 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -135,7 +135,7 @@ namespace transport void Terminate (); void TerminateByTimeout (); void Done () override; - void Close () { m_Socket.close (); }; // for accept + void Close (); // for accept void DeleteNextReceiveBuffer (uint64_t ts); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; @@ -277,7 +277,7 @@ namespace transport boost::asio::deadline_timer m_TerminationTimer; std::unique_ptr m_NTCP2Acceptor, m_NTCP2V6Acceptor; std::map > m_NTCP2Sessions; - std::list > m_PendingIncomingSessions; + std::map > m_PendingIncomingSessions; ProxyType m_ProxyType; std::string m_ProxyAddress, m_ProxyAuthorization; From 85e31f84ec236d87cd92839adb82a50fdd2c6597 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Dec 2022 22:07:26 -0500 Subject: [PATCH 028/179] reset termination timer for new incoming connection --- libi2pd/NTCP2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a5e160fc..0c37d3cc 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -380,9 +380,7 @@ namespace transport void NTCP2Session::Close () { - m_Socket.close (); - SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + m_Socket.close (); } void NTCP2Session::TerminateByTimeout () @@ -753,6 +751,8 @@ namespace transport void NTCP2Session::ServerLogin () { + SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_Establisher->CreateEphemeralKey (); boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), From 5a167316cbdd56635cead48dcc1ce3d5d925a7ca Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Dec 2022 22:24:20 -0500 Subject: [PATCH 029/179] don't filter yggdrasil address --- libi2pd/NTCP2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0c37d3cc..008386f3 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1470,7 +1470,8 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ())) + if (!i2p::util::net::IsInReservedRange(ep.address ()) || + i2p::util::net::IsYggdrasilAddress (ep.address ())) { if (conn) { From 099d9d977fde116ec9cf1650912e0bbe347d12f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Dec 2022 16:47:12 -0500 Subject: [PATCH 030/179] terminate duplcated session properly --- libi2pd/NTCP2.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 008386f3..4fa55f90 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1313,19 +1313,31 @@ namespace transport if (!session) return false; if (incoming) m_PendingIncomingSessions.erase (session->GetRemoteEndpoint ().address ()); - if (!session->GetRemoteIdentity ()) return false; + if (!session->GetRemoteIdentity ()) + { + LogPrint (eLogWarning, "NTCP2: Unknown identity for ", session->GetRemoteEndpoint ()); + session->Terminate (); + return false; + } auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto it = m_NTCP2Sessions.find (ident); if (it != m_NTCP2Sessions.end ()) { - LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists"); + LogPrint (eLogWarning, "NTCP2: Session with ", ident.ToBase64 (), " already exists. ", incoming ? "Replaced" : "Dropped"); if (incoming) + { // replace by new session - it->second->Terminate (); + auto s = it->second; + m_NTCP2Sessions.erase (it); + s->Terminate (); + } else + { + session->Terminate (); return false; + } } - m_NTCP2Sessions.insert (std::make_pair (ident, session)); + m_NTCP2Sessions.emplace (ident, session); return true; } From 126dc0ebe061f1d7fb1a5bd435a1a71ac7ba48b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 Dec 2022 16:47:50 -0500 Subject: [PATCH 031/179] inseer incoming session into sessions list --- libi2pd/Transports.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c571d45a..56fa4f39 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -716,7 +716,8 @@ namespace transport session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore auto ts = i2p::util::GetSecondsSinceEpoch (); std::unique_lock l(m_PeersMutex); - m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })); + auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first; + it->second.sessions.push_back (session); } }); } From 84d602845477e866ed75b9b44408da5d9ccf9bab Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 29 Dec 2022 17:26:57 -0500 Subject: [PATCH 032/179] limit number of message to handle at the time --- libi2pd/Tunnel.cpp | 10 ++++++---- libi2pd/Tunnel.h | 6 +++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index b578f6c1..519026e8 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -472,6 +472,7 @@ namespace tunnel auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec if (msg) { + int numMsgs = 0; uint32_t prevTunnelID = 0, tunnelID = 0; std::shared_ptr prevTunnel; do @@ -515,11 +516,12 @@ namespace tunnel LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); } - msg = m_Queue.Get (); + msg = (numMsgs <= MAX_NUM_TUNNEL_MSGS_AT_THE_TIME) ? m_Queue.Get () : nullptr; if (msg) { prevTunnelID = tunnelID; prevTunnel = tunnel; + numMsgs++; } else if (tunnel) tunnel->FlushTunnelDataMsgs (); @@ -530,17 +532,17 @@ namespace tunnel if (i2p::transport::transports.IsOnline()) { uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastTs >= 15) // manage tunnels every 15 seconds + if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL) // manage tunnels every 15 seconds { ManageTunnels (); lastTs = ts; } - if (ts - lastPoolsTs >= 5) // manage pools every 5 seconds + if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL) // manage pools every 5 seconds { ManageTunnelPools (ts); lastPoolsTs = ts; } - if (ts - lastMemoryPoolTs >= 120) // manage memory pool every 2 minutes + if (ts - lastMemoryPoolTs >= TUNNEL_MEMORY_POOL_MANAGE_INTERVAL) // manage memory pool every 2 minutes { m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt (); m_I2NPTunnelMessagesMemoryPool.CleanUpMt (); diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 503b7f9c..404dc2f1 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -40,7 +40,11 @@ namespace tunnel const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message const int MAX_NUM_RECORDS = 8; const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds - + const int MAX_NUM_TUNNEL_MSGS_AT_THE_TIME = 100; // handle message without break + const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds + const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds + const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 From cb139226df1a32b2cf9f3f18b6a47a5e521e4a25 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Dec 2022 18:06:47 -0500 Subject: [PATCH 033/179] ilimit umner of simultaneous tunnel build requests per pool --- libi2pd/Tunnel.cpp | 2 +- libi2pd/Tunnel.h | 2 +- libi2pd/TunnelPool.cpp | 22 ++++++++++++++++------ libi2pd/TunnelPool.h | 1 + 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 519026e8..f3b7152d 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -516,7 +516,7 @@ namespace tunnel LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); } - msg = (numMsgs <= MAX_NUM_TUNNEL_MSGS_AT_THE_TIME) ? m_Queue.Get () : nullptr; + msg = (numMsgs <= MAX_TUNNEL_MSGS_BATCH_SIZE) ? m_Queue.Get () : nullptr; if (msg) { prevTunnelID = tunnelID; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 404dc2f1..6032d35f 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -40,7 +40,7 @@ namespace tunnel const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message const int MAX_NUM_RECORDS = 8; const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds - const int MAX_NUM_TUNNEL_MSGS_AT_THE_TIME = 100; // handle message without break + const int MAX_TUNNEL_MSGS_BATCH_SIZE = 100; // handle messages without interrupt const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index b87ca048..ef52bf6d 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -282,9 +282,14 @@ namespace tunnel for (const auto& it : m_OutboundTunnels) if (it->IsEstablished ()) num++; } - for (int i = num; i < m_NumOutboundTunnels; i++) - CreateOutboundTunnel (); - + num = m_NumOutboundTunnels - num; + if (num > 0) + { + if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS; + for (int i = 0; i < num; i++) + CreateOutboundTunnel (); + } + num = 0; { std::unique_lock l(m_InboundTunnelsMutex); @@ -300,9 +305,14 @@ namespace tunnel if (num >= m_NumInboundTunnels) break; } } - for (int i = num; i < m_NumInboundTunnels; i++) - CreateInboundTunnel (); - + num = m_NumInboundTunnels - num; + if (num > 0) + { + if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS; + for (int i = 0; i < num; i++) + CreateInboundTunnel (); + } + if (num < m_NumInboundTunnels && m_NumInboundHops <= 0 && m_LocalDestination) // zero hops IB m_LocalDestination->SetLeaseSetUpdated (); // update LeaseSet immediately } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index d8c60d69..aed29eaf 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -30,6 +30,7 @@ namespace tunnel const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16; + const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 2; class Tunnel; class InboundTunnel; From 3e3e2c41bd7583bed7b8da46781ee6e6df0fc39b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Dec 2022 22:12:49 -0500 Subject: [PATCH 034/179] unlock mutex for good after wait --- libi2pd/Streaming.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index dda74015..0c584e2f 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -481,7 +481,6 @@ namespace stream volatile bool done = false; std::condition_variable newDataReceived; std::mutex newDataReceivedMutex; - std::unique_lock l(newDataReceivedMutex); AsyncReceive (boost::asio::buffer (buf, len), [&ret, &done, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred) { @@ -490,12 +489,15 @@ namespace stream else ret = bytes_transferred; std::unique_lock l(newDataReceivedMutex); - done = true; newDataReceived.notify_all (); + done = true; }, timeout); - if (newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) - ret = 0; + if (!done) + { std::unique_lock l(newDataReceivedMutex); + if (!done && newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) + ret = 0; + } if (!done) { // make sure that AsycReceive complete From 01fc21ffb96da58d62f306628420baebab0241b1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 31 Dec 2022 11:54:25 +0000 Subject: [PATCH 035/179] [webconsole] remove newline break Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 4743efc2..1f7f75da 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -236,7 +236,6 @@ namespace http { } if (error != eRouterErrorNone) { - s << "
"; switch (error) { case eRouterErrorClockSkew: From 2c19da9aa784ad042c3893e98718068b6556bc34 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 1 Jan 2023 10:48:11 +0000 Subject: [PATCH 036/179] fix warnings about unused code Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 8 +++----- libi2pd/Blinding.cpp | 2 +- libi2pd/Crypto.cpp | 2 ++ libi2pd/NTCP2.cpp | 34 +++++++++++++++++----------------- libi2pd_client/SOCKS.cpp | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 1f7f75da..7c62418e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -87,8 +87,6 @@ namespace http { const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string"; const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css"; - const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; - const char HTTP_PARAM_ADDRESS[] = "address"; static std::string ConvertTime (uint64_t time) { @@ -301,7 +299,7 @@ namespace http { if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { s << "\r\n\r\n
\r\n"; } - if (includeHiddenContent) + if (includeHiddenContent) { s << "" << tr("Router Ident") << ": " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; if (!i2p::context.GetRouterInfo().GetProperty("family").empty()) @@ -311,7 +309,7 @@ namespace http { s << ""<< tr("Our external address") << ":" << "
\r\n\r\n"; auto addresses = i2p::context.GetRouterInfo().GetAddresses (); if (addresses) - { + { for (const auto& address : *addresses) { if (!address) continue; @@ -344,7 +342,7 @@ namespace http { } s << "\r\n"; } - } + } s << "
\r\n"; } s << "
\r\n\r\n"; diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index 65e5f78c..ced086e1 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -135,7 +135,7 @@ namespace data //---------------------------------------------------------- const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01; - const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now + // const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04; BlindedPublicKey::BlindedPublicKey (std::shared_ptr identity, bool clientAuth): diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index b152cdd0..c9670f6c 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -159,8 +159,10 @@ namespace crypto // DH/ElGamal +#if !defined(__x86_64__) const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; +#endif const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048; const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8; diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 4fa55f90..b85ba1e4 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1453,17 +1453,17 @@ namespace transport LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } else - { + { LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); if (error == boost::asio::error::no_descriptors) { i2p::context.SetError (eRouterErrorNoDescriptors); - return; - } - } - + return; + } + } + if (error != boost::asio::error::operation_aborted) - { + { if (!conn) // connection is used, create new one conn = std::make_shared (*this); else // reuse failed @@ -1504,14 +1504,14 @@ namespace transport LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } else - { + { LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ()); if (error == boost::asio::error::no_descriptors) { i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); - return; - } - } + return; + } + } if (error != boost::asio::error::operation_aborted) { @@ -1560,23 +1560,23 @@ namespace transport it++; } ScheduleTermination (); - + // try to restart acceptors if no description - // we do it after timer to let timer take descriptor first + // we do it after timer to let timer take descriptor first if (i2p::context.GetError () == eRouterErrorNoDescriptors) { i2p::context.SetError (eRouterErrorNone); auto conn = std::make_shared (*this); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); - } + } if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors) { i2p::context.SetErrorV6 (eRouterErrorNone); auto conn = std::make_shared (*this); m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); - } + } } } @@ -1784,15 +1784,15 @@ namespace transport }); boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size - boost::asio::transfer_all(), - [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred) + boost::asio::transfer_all(), + [timer, conn, readbuff](const boost::system::error_code & e, std::size_t transferred) { if (e) LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message()); else if (!(*readbuff)[1]) // succeeded { boost::system::error_code ec; - size_t moreBytes = conn->GetSocket ().available(ec); + size_t moreBytes = conn->GetSocket ().available(ec); if (moreBytes) // read remaining portion of reply if ipv6 received boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); timer->cancel(); diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 961ff934..ca87e22a 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -27,7 +27,7 @@ namespace proxy static const size_t socks_buffer_size = 8192; static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse - static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; + //static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; From f8ba5b8c634f30f8e440a2063423cf9709f35f6e Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 1 Jan 2023 11:23:11 +0000 Subject: [PATCH 037/179] increase nofile limit in service Signed-off-by: R4SAS --- contrib/i2pd.service | 2 +- debian/i2pd.default | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.service b/contrib/i2pd.service index 45fe4cc6..79bf15c8 100644 --- a/contrib/i2pd.service +++ b/contrib/i2pd.service @@ -29,7 +29,7 @@ SendSIGKILL=yes #TimeoutStopSec=10m # If you have problems with hanging i2pd, you can try increase this -LimitNOFILE=4096 +LimitNOFILE=8192 # To enable write of coredump uncomment this #LimitCORE=infinity diff --git a/debian/i2pd.default b/debian/i2pd.default index bd1d073f..90392ede 100644 --- a/debian/i2pd.default +++ b/debian/i2pd.default @@ -8,4 +8,4 @@ I2PD_ENABLED="yes" DAEMON_OPTS="" # If you have problems with hunging i2pd, you can try enable this -ulimit -n 4096 +ulimit -n 8192 From af838196bedd4df8a648a2f3a3e4205e945a77bf Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 1 Jan 2023 14:29:31 +0300 Subject: [PATCH 038/179] [debian] remove #1210 patch Signed-off-by: R4SAS --- debian/patches/01-fix-1210.patch | 27 ------------------- .../patches/{02-upnp.patch => 01-upnp.patch} | 0 2 files changed, 27 deletions(-) delete mode 100644 debian/patches/01-fix-1210.patch rename debian/patches/{02-upnp.patch => 01-upnp.patch} (100%) diff --git a/debian/patches/01-fix-1210.patch b/debian/patches/01-fix-1210.patch deleted file mode 100644 index 9ad9bb0f..00000000 --- a/debian/patches/01-fix-1210.patch +++ /dev/null @@ -1,27 +0,0 @@ -Description: fix #1210 - Disables two options, which not presented in old systemd versions -Author: r4sas - -Bug: https://github.com/PurpleI2P/i2pd/issues/1210 -Reviewed-By: r4sas -Last-Update: 2020-05-25 - -Index: i2pd/contrib/i2pd.service -=================================================================== ---- i2pd.orig/contrib/i2pd.service -+++ i2pd/contrib/i2pd.service -@@ -6,10 +6,10 @@ After=network.target - [Service] - User=i2pd - Group=i2pd --RuntimeDirectory=i2pd --RuntimeDirectoryMode=0700 --LogsDirectory=i2pd --LogsDirectoryMode=0700 -+#RuntimeDirectory=i2pd -+#RuntimeDirectoryMode=0700 -+#LogsDirectory=i2pd -+#LogsDirectoryMode=0700 - Type=forking - ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service - ExecReload=/bin/sh -c "kill -HUP $MAINPID" diff --git a/debian/patches/02-upnp.patch b/debian/patches/01-upnp.patch similarity index 100% rename from debian/patches/02-upnp.patch rename to debian/patches/01-upnp.patch From e93718456f194c7acb528852bcb4e11d8f800a09 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 1 Jan 2023 14:32:53 +0300 Subject: [PATCH 039/179] [debian] update patch series list Signed-off-by: R4SAS --- debian/patches/series | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/patches/series b/debian/patches/series index 2f816712..f97fdf65 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1 @@ -01-fix-1210.patch -02-upnp.patch +01-upnp.patch From 7b341d5d30490369c43025f50c5400b3d1e656d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Jan 2023 16:03:53 -0500 Subject: [PATCH 040/179] update and show send queue size for transports --- daemon/HTTPServer.cpp | 6 +++++- libi2pd/NTCP2.cpp | 9 +++++++-- libi2pd/SSU2Session.cpp | 9 +++++++-- libi2pd/TransportSession.h | 8 +++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 7c62418e..281d3d53 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -805,6 +805,8 @@ namespace http { tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->GetRelayTag ()) tmp_s << " [itag:" << it.second->GetRelayTag () << "]"; + if (it.second->GetSendQueueSize () > 0) + tmp_s << " [queue:" << it.second->GetSendQueueSize () << "]"; tmp_s << "\r\n" << std::endl; cnt++; } @@ -818,6 +820,8 @@ namespace http { tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->GetRelayTag ()) tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]"; + if (it.second->GetSendQueueSize () > 0) + tmp_s6 << " [queue:" << it.second->GetSendQueueSize () << "]"; tmp_s6 << "\r\n" << std::endl; cnt6++; } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index b85ba1e4..c7553fca 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -374,6 +374,7 @@ namespace transport transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); + m_SendQueueSize = 0; LogPrint (eLogDebug, "NTCP2: Session terminated"); } } @@ -1057,7 +1058,10 @@ namespace transport SendRouterInfo (); } else + { SendQueue (); + m_SendQueueSize = m_SendQueue.size (); + } } } @@ -1165,7 +1169,7 @@ namespace transport { if (m_IsTerminated) return; for (auto it: msgs) - m_SendQueue.push_back (it); + m_SendQueue.push_back (std::move (it)); if (!m_IsSending) SendQueue (); else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) @@ -1174,6 +1178,7 @@ namespace transport GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); Terminate (); } + m_SendQueueSize = m_SendQueue.size (); } void NTCP2Session::SendLocalRouterInfo (bool update) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index b37b2cb8..c80f69b6 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -216,6 +216,7 @@ namespace transport m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); m_SendQueue.clear (); + m_SendQueueSize = 0; m_SentPackets.clear (); m_IncompleteMessages.clear (); m_RelaySessions.clear (); @@ -290,7 +291,7 @@ namespace transport { if (m_State == eSSU2SessionStateTerminated) return; for (auto it: msgs) - m_SendQueue.push_back (it); + m_SendQueue.push_back (std::move (it)); SendQueue (); if (m_SendQueue.size () > 0) // windows is full @@ -304,6 +305,7 @@ namespace transport RequestTermination (eSSU2TerminationReasonTimeout); } } + m_SendQueueSize = m_SendQueue.size (); } bool SSU2Session::SendQueue () @@ -463,6 +465,7 @@ namespace transport LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session"); m_SentPackets.clear (); m_SendQueue.clear (); + m_SendQueueSize = 0; RequestTermination (eSSU2TerminationReasonTimeout); return resentPackets.size (); } @@ -2838,6 +2841,8 @@ namespace transport void SSU2Session::FlushData () { bool sent = SendQueue (); // if we have something to send + if (sent) + m_SendQueueSize = m_SendQueue.size (); if (m_IsDataReceived) { if (!sent) SendQuickAck (); diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 87c730f4..15bffe11 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -74,7 +74,8 @@ namespace transport public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0), + m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) @@ -100,6 +101,7 @@ namespace transport size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; + size_t GetSendQueueSize () const { return m_SendQueueSize; }; bool IsOutgoing () const { return m_IsOutgoing; }; int GetTerminationTimeout () const { return m_TerminationTimeout; }; @@ -119,7 +121,7 @@ namespace transport std::shared_ptr m_RemoteIdentity; mutable std::mutex m_RemoteIdentityMutex; - size_t m_NumSentBytes, m_NumReceivedBytes; + size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize; bool m_IsOutgoing; int m_TerminationTimeout; uint64_t m_LastActivityTimestamp; From 6942c20879353819d0e90c96879d15d015517739 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Jan 2023 19:42:40 -0500 Subject: [PATCH 041/179] don't select overloaded peer --- libi2pd/Transports.cpp | 6 ++++-- libi2pd/Transports.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 56fa4f39..00076f53 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -823,7 +823,9 @@ namespace transport std::unique_lock l(m_PeersMutex); auto it = m_Peers.begin (); std::advance (it, rand () % m_Peers.size ()); - if (it == m_Peers.end () || it->second.router) return nullptr; // not connected + if (it == m_Peers.end () || it->second.router || it->second.sessions.empty () || + it->second.sessions.front ()->GetSendQueueSize () > PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE) + return nullptr; // not connected or overloaded ident = it->first; } return i2p::data::netdb.FindRouter (ident); diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 4723b752..bbe98bf3 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -63,6 +63,7 @@ namespace transport const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds + const size_t PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE = 25; struct Peer { int numAttempts; From cfb773351d5ccef338355834ba0a2302093de43c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 2 Jan 2023 21:36:51 +0300 Subject: [PATCH 042/179] [debian] update packaging files Signed-off-by: R4SAS --- debian/compat | 2 +- debian/conffiles | 2 ++ debian/control | 4 ++-- debian/copyright | 6 +++--- debian/i2pd.install | 1 - debian/i2pd.links | 3 +-- debian/watch | 3 ++- 7 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 debian/conffiles diff --git a/debian/compat b/debian/compat index ec635144..48082f72 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +12 diff --git a/debian/conffiles b/debian/conffiles new file mode 100644 index 00000000..6894732c --- /dev/null +++ b/debian/conffiles @@ -0,0 +1,2 @@ +/etc/i2pd/i2pd.conf +/etc/i2pd/tunnels.conf diff --git a/debian/control b/debian/control index 318463bc..48f5e680 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: i2pd Section: net Priority: optional Maintainer: r4sas -Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.17.2~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev -Standards-Version: 3.9.8 +Build-Depends: debhelper (>= 12~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev +Standards-Version: 4.3.0 Homepage: http://i2pd.website/ Vcs-Git: git://github.com/PurpleI2P/i2pd.git Vcs-Browser: https://github.com/PurpleI2P/i2pd diff --git a/debian/copyright b/debian/copyright index 73df9da0..352e260b 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,18 +3,18 @@ Upstream-Name: i2pd Source: https://github.com/PurpleI2P Files: * -Copyright: 2013-2020 PurpleI2P +Copyright: 2013-2023 PurpleI2P License: BSD-3-clause Files: debian/* Copyright: 2013-2015 Kill Your TV 2014-2016 hagen - 2016-2020 R4SAS + 2016-2023 R4SAS 2017-2020 Yangfl License: GPL-2+ License: BSD-3-clause - Copyright (c) 2013-2017, The PurpleI2P Project + Copyright (c) 2013-2023, The PurpleI2P Project . All rights reserved. . diff --git a/debian/i2pd.install b/debian/i2pd.install index 6eb6c8c2..93eee7a1 100644 --- a/debian/i2pd.install +++ b/debian/i2pd.install @@ -1,7 +1,6 @@ i2pd usr/sbin/ contrib/i2pd.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/ -contrib/subscriptions.txt etc/i2pd/ contrib/certificates/ usr/share/i2pd/ contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/ contrib/apparmor/usr.sbin.i2pd etc/apparmor.d diff --git a/debian/i2pd.links b/debian/i2pd.links index a149967f..16558791 100644 --- a/debian/i2pd.links +++ b/debian/i2pd.links @@ -1,5 +1,4 @@ -etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf +etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf -etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d usr/share/i2pd/certificates var/lib/i2pd/certificates diff --git a/debian/watch b/debian/watch index 64367c81..2ec6c29b 100644 --- a/debian/watch +++ b/debian/watch @@ -1,3 +1,4 @@ -version=4 opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \ +version=4 +opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \ https://github.com/PurpleI2P/i2pd/tags \ (?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate From d5b03f214bf425beaa8ebf3a0ce420051f8a43ef Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Jan 2023 15:03:00 -0500 Subject: [PATCH 043/179] double default number of transit tunnels for floodfill --- daemon/Daemon.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 2c120537..828d1e09 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -165,21 +165,22 @@ namespace util i2p::transport::InitTransports (); - bool transit; i2p::config::GetOption("notransit", transit); - i2p::context.SetAcceptsTunnels (!transit); - uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); - SetMaxNumTransitTunnels (transitTunnels); - bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); - if (isFloodfill) { + if (isFloodfill) + { LogPrint(eLogInfo, "Daemon: Router configured as floodfill"); i2p::context.SetFloodfill (true); } else - { i2p::context.SetFloodfill (false); - } + bool transit; i2p::config::GetOption("notransit", transit); + i2p::context.SetAcceptsTunnels (!transit); + uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); + if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels")) + transitTunnels *= 2; // double default number of transit tunnels for floodfill + SetMaxNumTransitTunnels (transitTunnels); + /* this section also honors 'floodfill' flag, if set above */ std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); if (bandwidth.length () > 0) From 1df67bd43c7fc0fd43e7e8fcb1937817f28eb587 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Jan 2023 18:59:13 -0500 Subject: [PATCH 044/179] 2.45.0 --- ChangeLog | 29 +++++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 6 +++--- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f3faf11..ae04a8c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,35 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.45.0] - 2023-01-02 +### Added +- Test for Symmnetric NAT with peer test msgs 6 and 7 +- Show non-zero send queue size for transports in web console +- Compressible padding for I2P addresses +- Localization to Czech +- Don't accept incoming session from invalid/reserved addresses for NTCP2 and SSU2 +- Limit simultaneous tunnel build requests by 4 per pool +### Changed +- Removed SSU support +- Reduced bandwidth caluclation interval from 60 to 15 seconds +- Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill +- NTCP2 and SSU2 timetamps are rounded to seconds +- Drop RouterInfos and LeaseSets with timestamp from future +- Don't delete unreachable routers if tunnel creation success rate is too low +- Refuse duplicated incoming pending NTCP2 session from same IP +- Don't send SSU2 termination again if termination received block received +- Handle standard network error for SSU2 without throwing an exception +- Don't select overloaded peer for next tunnel +- Remove "X-Requested-With" in HTTP Proxy +### Fixed +- File descriptors leak +- Random crash on AddressBook update +- Crash if incorrect LeaseSet size +- Spamming to log if no descriptors +- ::1 address in RouterInfo +- Race condition with pending outgoing SSU2 sessions +- RTT self-reduction for long-live streams + ## [2.44.0] - 2022-11-20 ### Added - SSL connection for server I2P tunnels diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 9183b529..273df455 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.44.0 +Version: 2.45.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jan 2 2023 orignal - 2.45.0 +- update to 2.45.0 + * Sun Nov 20 2022 orignal - 2.44.0 - update to 2.44.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 16734f3f..f83e85f3 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.44.0 +Version: 2.45.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jan 2 2023 orignal - 2.45.0 +- update to 2.45.0 + * Sun Nov 20 2022 orignal - 2.44.0 - update to 2.44.0 diff --git a/debian/changelog b/debian/changelog index accbf46a..10bb17de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.45.0-1) unstable; urgency=medium + + * updated to version 2.45.0/0.9.57 + + -- orignal Mon, 2 Jan 2023 19:00:00 +0000 + i2pd (2.44.0-1) unstable; urgency=medium * updated to version 2.44.0/0.9.56 diff --git a/libi2pd/version.h b/libi2pd/version.h index 94d14403..26f855be 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -16,7 +16,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 44 +#define I2PD_VERSION_MINOR 45 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -31,7 +31,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 56 +#define I2P_VERSION_MICRO 57 #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 66f82cb43fba0daf5d4548287b1eeed82ff6e7e5 Mon Sep 17 00:00:00 2001 From: Tomas Globis Date: Tue, 3 Jan 2023 03:07:07 +0300 Subject: [PATCH 045/179] Use moving average to calculate tunnel creation success rate --- libi2pd/Tunnel.cpp | 9 ++++----- libi2pd/Tunnel.h | 26 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index f3b7152d..5af4a9a4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -332,8 +332,7 @@ namespace tunnel Tunnels tunnels; Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), - m_NumSuccesiveTunnelCreations (0), m_NumFailedTunnelCreations (0) - { + m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) { } Tunnels::~Tunnels () @@ -630,7 +629,7 @@ namespace tunnel } // delete it = pendingTunnels.erase (it); - m_NumFailedTunnelCreations++; + FailedTunnelCreation(); } else ++it; @@ -638,7 +637,7 @@ namespace tunnel case eTunnelStateBuildFailed: LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " failed, deleted"); it = pendingTunnels.erase (it); - m_NumFailedTunnelCreations++; + FailedTunnelCreation(); break; case eTunnelStateBuildReplyReceived: // intermediate state, will be either established of build failed @@ -647,7 +646,7 @@ namespace tunnel default: // success it = pendingTunnels.erase (it); - m_NumSuccesiveTunnelCreations++; + SuccesiveTunnelCreation(); } } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 6032d35f..c252e303 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -44,10 +44,13 @@ namespace tunnel const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 + const double TCSR_SMOOTHING_CONSTANT = 0.0005; // smoothing constant in exponentially weighted moving average + const double TCSR_START_VALUE = 0.1; // start value of tunnel creation success rate + enum TunnelState { eTunnelStatePending, @@ -267,8 +270,19 @@ namespace tunnel i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - // some stats - int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations; + // Calculating of tunnel creation success rate + // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity + void SuccesiveTunnelCreation() { + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; + m_TunnelCreationSuccessRate = alpha * 1 + (1 - alpha) * m_TunnelCreationSuccessRate; + + }; + void FailedTunnelCreation() { + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; + m_TunnelCreationSuccessRate = alpha * 0 + (1 - alpha) * m_TunnelCreationSuccessRate; + }; + double m_TunnelCreationSuccessRate; + int m_TunnelCreationAttemptsNum; public: @@ -282,11 +296,7 @@ namespace tunnel size_t CountOutboundTunnels() const; int GetQueueSize () { return m_Queue.GetSize (); }; - int GetTunnelCreationSuccessRate () const // in percents - { - int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations; - return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0; - } + int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents }; extern Tunnels tunnels; From 22179400c77f7b61f6502a9d544308337167bd8c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 3 Jan 2023 18:16:34 +0000 Subject: [PATCH 046/179] 2.45.0 Signed-off-by: R4SAS --- ChangeLog | 19 +++++++++++-------- contrib/rpm/i2pd-git.spec | 2 +- contrib/rpm/i2pd.spec | 2 +- debian/changelog | 9 +++++++-- libi2pd/SSU2Session.cpp | 2 +- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index ae04a8c4..964c1c20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,11 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog -## [2.45.0] - 2023-01-02 +## [2.45.0] - 2023-01-03 ### Added -- Test for Symmnetric NAT with peer test msgs 6 and 7 +- Test for Symmetric NAT with peer test msgs 6 and 7 +- Webconsole "No Descriptors" router error state +- 1 and 15 seconds bandwidth calculation for i2pcontrol - Show non-zero send queue size for transports in web console - Compressible padding for I2P addresses - Localization to Czech @@ -11,23 +13,24 @@ - Limit simultaneous tunnel build requests by 4 per pool ### Changed - Removed SSU support -- Reduced bandwidth caluclation interval from 60 to 15 seconds +- Reduced bandwidth calculation interval from 60 to 15 seconds - Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill -- NTCP2 and SSU2 timetamps are rounded to seconds +- NTCP2 and SSU2 timestamps are rounded to seconds - Drop RouterInfos and LeaseSets with timestamp from future - Don't delete unreachable routers if tunnel creation success rate is too low - Refuse duplicated incoming pending NTCP2 session from same IP - Don't send SSU2 termination again if termination received block received - Handle standard network error for SSU2 without throwing an exception -- Don't select overloaded peer for next tunnel -- Remove "X-Requested-With" in HTTP Proxy +- Don't select overloaded peer for next tunnel +- Remove "X-Requested-With" in HTTP Proxy for non-AJAX requests ### Fixed - File descriptors leak - Random crash on AddressBook update - Crash if incorrect LeaseSet size - Spamming to log if no descriptors - ::1 address in RouterInfo -- Race condition with pending outgoing SSU2 sessions +- SSU2 network error handling (especially for Windows) +- Race condition with pending outgoing SSU2 sessions - RTT self-reduction for long-live streams ## [2.44.0] - 2022-11-20 @@ -40,7 +43,7 @@ - SSU2 send and verify path challenge - Configurable ssu2.mtu4 and ssu2.mtu6 ### Changed -- SSU2 is enbaled and SSU is disabled by default +- SSU2 is enabled and SSU is disabled by default - Separate network status and error - Random selection between NTCP2 and SSU2 priority - Added notbob.i2p to jump services diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 273df455..e3d487e2 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -158,7 +158,7 @@ getent passwd i2pd >/dev/null || \ %changelog -* Mon Jan 2 2023 orignal - 2.45.0 +* Mon Tue 3 2023 orignal - 2.45.0 - update to 2.45.0 * Sun Nov 20 2022 orignal - 2.44.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index f83e85f3..5a56989f 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -155,7 +155,7 @@ getent passwd i2pd >/dev/null || \ %changelog -* Mon Jan 2 2023 orignal - 2.45.0 +* Tue Jan 3 2023 orignal - 2.45.0 - update to 2.45.0 * Sun Nov 20 2022 orignal - 2.44.0 diff --git a/debian/changelog b/debian/changelog index 10bb17de..10ca4082 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,13 @@ -i2pd (2.45.0-1) unstable; urgency=medium +i2pd (2.45.0-1) unstable; urgency=high * updated to version 2.45.0/0.9.57 + * compat level 12 + * standards version 4.3.0 + * increased nofile limit in service and init.d to 8192 + * added conffiles + * removed #1210 patch - -- orignal Mon, 2 Jan 2023 19:00:00 +0000 + -- r4sas Tue, 3 Jan 2023 18:00:00 +0000 i2pd (2.44.0-1) unstable; urgency=medium diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index c80f69b6..3843df2a 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * From 503f522cc38e3eb6fe13dab28d6c9492c8351a9c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 3 Jan 2023 21:25:19 +0300 Subject: [PATCH 047/179] [style] clean trailing spaces and tabs Signed-off-by: R4SAS --- daemon/Daemon.cpp | 4 +-- libi2pd/Destination.cpp | 22 +++++++------- libi2pd/Destination.h | 4 +-- libi2pd/Identity.cpp | 4 +-- libi2pd/LeaseSet.cpp | 8 +++--- libi2pd/NTCP2.cpp | 42 +++++++++++++-------------- libi2pd/NetDb.cpp | 8 +++--- libi2pd/NetDb.hpp | 8 +++--- libi2pd/RouterContext.cpp | 52 +++++++++++++++++----------------- libi2pd/RouterInfo.cpp | 48 +++++++++++++++---------------- libi2pd/RouterInfo.h | 2 +- libi2pd/SSU2.cpp | 16 +++++------ libi2pd/SSU2.h | 6 ++-- libi2pd/SSU2Session.cpp | 52 +++++++++++++++++----------------- libi2pd/Streaming.cpp | 22 +++++++------- libi2pd/Streaming.h | 4 +-- libi2pd/TransitTunnel.cpp | 2 +- libi2pd/TransportSession.h | 2 +- libi2pd/Transports.cpp | 4 +-- libi2pd/Tunnel.h | 2 +- libi2pd/TunnelPool.cpp | 10 +++---- libi2pd_client/AddressBook.cpp | 20 ++++++------- libi2pd_client/UDPTunnel.cpp | 2 +- libi2pd_client/UDPTunnel.h | 2 +- 24 files changed, 173 insertions(+), 173 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 828d1e09..a0d7cf1a 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -166,7 +166,7 @@ namespace util i2p::transport::InitTransports (); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); - if (isFloodfill) + if (isFloodfill) { LogPrint(eLogInfo, "Daemon: Router configured as floodfill"); i2p::context.SetFloodfill (true); @@ -180,7 +180,7 @@ namespace util if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels")) transitTunnels *= 2; // double default number of transit tunnels for floodfill SetMaxNumTransitTunnels (transitTunnels); - + /* this section also honors 'floodfill' flag, if set above */ std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); if (bandwidth.length () > 0) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index c39a2533..4a2cc4ae 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1096,13 +1096,13 @@ namespace client } auto leaseSet = FindLeaseSet (dest); if (leaseSet) - { + { auto stream = CreateStream (leaseSet, port); - GetService ().post ([streamRequestComplete, stream]() - { + GetService ().post ([streamRequestComplete, stream]() + { streamRequestComplete(stream); }); - } + } else { auto s = GetSharedFromThis (); @@ -1135,8 +1135,8 @@ namespace client }); } - template - std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, int port) + template + std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, int port) { std::shared_ptr stream; std::condition_variable streamRequestComplete; @@ -1152,18 +1152,18 @@ namespace client dest, port); streamRequestComplete.wait (l); return stream; - } + } - std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) + std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) { return CreateStreamSync (dest, port); - } + } std::shared_ptr ClientDestination::CreateStream (std::shared_ptr dest, int port) { return CreateStreamSync (dest, port); - } - + } + std::shared_ptr ClientDestination::CreateStream (std::shared_ptr remote, int port) { if (m_StreamingDestination) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 9d369a92..9e2d171f 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -284,9 +284,9 @@ namespace client void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey); void ReadAuthKey (const std::string& group, const std::map * params); - template + template std::shared_ptr CreateStreamSync (const Dest& dest, int port); - + private: i2p::data::PrivateKeys m_Keys; diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 310e6081..bf9c26c5 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -64,7 +64,7 @@ namespace data else for (int i = 0; i < 8; i++) // 256 bytes memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32); - } + } if (type != SIGNING_KEY_TYPE_DSA_SHA1) { size_t excessLen = 0; @@ -717,7 +717,7 @@ namespace data uint8_t publicKey[256]; if (isDestination) RAND_bytes (keys.m_PrivateKey, 256); - else + else GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey); // identity keys.m_Public = std::make_shared (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType); diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 12b064b5..d23fdcb8 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -261,12 +261,12 @@ namespace data { LogPrint (eLogError, "LeaseSet: Buffer is too long ", len); len = MAX_LS_BUFFER_SIZE; - } - if (m_Buffer && len > m_BufferLen) - { + } + if (m_Buffer && len > m_BufferLen) + { delete[] m_Buffer; m_Buffer = nullptr; - } + } if (!m_Buffer) m_Buffer = new uint8_t[len]; m_BufferLen = len; diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index c7553fca..e5199bdc 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -379,11 +379,11 @@ namespace transport } } - void NTCP2Session::Close () + void NTCP2Session::Close () { - m_Socket.close (); + m_Socket.close (); } - + void NTCP2Session::TerminateByTimeout () { SendTerminationAndTerminate (eNTCP2IdleTimeout); @@ -401,7 +401,7 @@ namespace transport SetTerminationTimeout (NTCP2_TERMINATION_TIMEOUT); transports.PeerConnected (shared_from_this ()); } - + void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) { memset (nonce, 0, 4); @@ -1058,10 +1058,10 @@ namespace transport SendRouterInfo (); } else - { + { SendQueue (); m_SendQueueSize = m_SendQueue.size (); - } + } } } @@ -1318,29 +1318,29 @@ namespace transport if (!session) return false; if (incoming) m_PendingIncomingSessions.erase (session->GetRemoteEndpoint ().address ()); - if (!session->GetRemoteIdentity ()) + if (!session->GetRemoteIdentity ()) { LogPrint (eLogWarning, "NTCP2: Unknown identity for ", session->GetRemoteEndpoint ()); session->Terminate (); return false; - } + } auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto it = m_NTCP2Sessions.find (ident); if (it != m_NTCP2Sessions.end ()) { LogPrint (eLogWarning, "NTCP2: Session with ", ident.ToBase64 (), " already exists. ", incoming ? "Replaced" : "Dropped"); if (incoming) - { + { // replace by new session auto s = it->second; m_NTCP2Sessions.erase (it); s->Terminate (); - } + } else - { + { session->Terminate (); return false; - } + } } m_NTCP2Sessions.emplace (ident, session); return true; @@ -1438,19 +1438,19 @@ namespace transport { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); if (!i2p::util::net::IsInReservedRange(ep.address ())) - { + { if (conn) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { + { conn->SetRemoteEndpoint (ep); conn->ServerLogin (); conn = nullptr; - } + } else LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } - } + } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); } @@ -1487,21 +1487,21 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ()) || + if (!i2p::util::net::IsInReservedRange(ep.address ()) || i2p::util::net::IsYggdrasilAddress (ep.address ())) - { + { if (conn) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { + { conn->SetRemoteEndpoint (ep); conn->ServerLogin (); conn = nullptr; - } + } else LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } - } + } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 867a4eb3..9eafd586 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -658,8 +658,8 @@ namespace data m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); - m_RouterInfoAddressVectorsPool.CleanUpMt (); - + m_RouterInfoAddressVectorsPool.CleanUpMt (); + if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); if (deletedCount > 0) @@ -763,7 +763,7 @@ namespace data { LogPrint (eLogError, "NetDb: Database store msg is too short ", len, ". Dropped"); return; - } + } IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET); if (ident.IsZero ()) { @@ -778,7 +778,7 @@ namespace data { LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped"); return; - } + } auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index e89cda92..90ebe824 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -126,11 +126,11 @@ namespace data std::shared_ptr NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; void PopulateRouterInfoBuffer (std::shared_ptr r); std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; - boost::shared_ptr NewRouterInfoAddresses () - { - return boost::shared_ptr(m_RouterInfoAddressVectorsPool.AcquireMt (), + boost::shared_ptr NewRouterInfoAddresses () + { + return boost::shared_ptr(m_RouterInfoAddressVectorsPool.AcquireMt (), std::bind ::*)(RouterInfo::Addresses *)> - (&i2p::util::MemoryPoolMt::ReleaseMt, + (&i2p::util::MemoryPoolMt::ReleaseMt, &m_RouterInfoAddressVectorsPool, std::placeholders::_1)); }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 9e17e1fa..b1ebdec7 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -254,7 +254,7 @@ namespace i2p } } } - + void RouterContext::SetStatusV6 (RouterStatus status) { if (status != m_StatusV6) @@ -274,7 +274,7 @@ namespace i2p } } } - + void RouterContext::UpdatePort (int port) { auto addresses = m_RouterInfo.GetAddresses (); @@ -342,7 +342,7 @@ namespace i2p else it.reset (); updated = true; - } + } } if (enable && !found) { @@ -444,13 +444,13 @@ namespace i2p { addr->host = host; updated = true; - } + } addr = (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]; if (addr && addr->host != host) { addr->host = host; updated = true; - } + } } else if (host.is_v6 ()) { @@ -459,7 +459,7 @@ namespace i2p { addr->host = host; updated = true; - } + } addr = (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]; if (addr && (addr->host != host || !addr->ssu->mtu)) { @@ -479,11 +479,11 @@ namespace i2p } addr->ssu->mtu = mtu; } - } + } updated = true; - } - } - + } + } + auto ts = i2p::util::GetSecondsSinceEpoch (); if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL) UpdateRouterInfo (); @@ -510,7 +510,7 @@ namespace i2p { addr->ssu->introducers.clear (); UpdateRouterInfo (); - } + } } void RouterContext::SetFloodfill (bool floodfill) @@ -626,8 +626,8 @@ namespace i2p uint16_t port = 0; // delete previous introducers auto addresses = m_RouterInfo.GetAddresses (); - if (addresses) - { + if (addresses) + { for (auto& addr : *addresses) if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { @@ -636,7 +636,7 @@ namespace i2p addr->ssu->introducers.clear (); port = addr->port; } - } + } // unpublish NTCP2 addreeses bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) @@ -662,8 +662,8 @@ namespace i2p // delete previous introducers bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published); auto addresses = m_RouterInfo.GetAddresses (); - if (addresses) - { + if (addresses) + { for (auto& addr : *addresses) if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) { @@ -672,7 +672,7 @@ namespace i2p addr->ssu->introducers.clear (); if (addr->port) port = addr->port; } - } + } // publish NTCP2 bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) @@ -698,7 +698,7 @@ namespace i2p bool foundNTCP2 = false, foundSSU2 = false; uint16_t port = 0; auto addresses = m_RouterInfo.GetAddresses (); - if (addresses) + if (addresses) { for (auto& addr: *addresses) { @@ -781,7 +781,7 @@ namespace i2p std::string host = "127.0.0.1"; uint16_t port = 0; auto addresses = m_RouterInfo.GetAddresses (); - if (addresses) + if (addresses) { for (auto& addr: *addresses) { @@ -800,7 +800,7 @@ namespace i2p } if (addr && addr->port) port = addr->port; } - } + } if (!port) { i2p::config::GetOption("port", port); @@ -858,17 +858,17 @@ namespace i2p uint16_t port = 0; i2p::config::GetOption ("ntcp2.port", port); if (!port) i2p::config::GetOption("port", port); - if (!port) + if (!port) { for (auto& addr: *addresses) { - if (addr && addr->port) - { + if (addr && addr->port) + { port = addr->port; break; - } + } } - } + } if (!port) port = SelectRandomPort (); m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); } @@ -885,7 +885,7 @@ namespace i2p for (auto& addr: *addresses) { if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) - { + { addr->ssu->mtu = mtu; LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 177ae8b3..4667be98 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -329,9 +329,9 @@ namespace data } Introducer& introducer = address->ssu->introducers.at (index); if (!strcmp (key, "ihost")) - introducer.isH = false; // SSU1 + introducer.isH = false; // SSU1 else if (!strcmp (key, "iport")) - introducer.isH = false; // SSU1 + introducer.isH = false; // SSU1 else if (!strcmp (key, "itag")) { try @@ -344,10 +344,10 @@ namespace data } } else if (!strcmp (key, "ih")) - { + { Base64ToByteStream (value, strlen (value), introducer.iH, 32); - introducer.isH = true; - } + introducer.isH = true; + } else if (!strcmp (key, "iexp")) { try @@ -421,7 +421,7 @@ namespace data for (uint8_t i = 0; i < eNumTransports; i++) if ((1 << i) & supportedTransports) (*addresses)[i] = address; - } + } m_SupportedTransports |= supportedTransports; } } @@ -647,11 +647,11 @@ namespace data (*m_Addresses)[eNTCP2V6MeshIdx] = addr; } else - { + { m_SupportedTransports |= eNTCP2V6; if (addr->published) m_ReachableTransports |= eNTCP2V6; (*m_Addresses)[eNTCP2V6Idx] = addr; - } + } } } @@ -666,13 +666,13 @@ namespace data addr->ssu->mtu = 0; memcpy (addr->s, staticKey, 32); memcpy (addr->i, introKey, 32); - if (addr->IsV4 ()) - { + if (addr->IsV4 ()) + { m_SupportedTransports |= eSSU2V4; (*m_Addresses)[eSSU2V4Idx] = addr; - } - if (addr->IsV6 ()) - { + } + if (addr->IsV6 ()) + { m_SupportedTransports |= eSSU2V6; (*m_Addresses)[eSSU2V6Idx] = addr; } @@ -747,13 +747,13 @@ namespace data if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 ()) (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eNTCP2V6Idx].reset (); - } + } if ((*m_Addresses)[eSSU2V6Idx]) { if ((*m_Addresses)[eSSU2V6Idx]->IsV4 ()) (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eSSU2V6Idx].reset (); - } + } UpdateSupportedTransports (); } } @@ -767,13 +767,13 @@ namespace data if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 ()) (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eNTCP2V4Idx].reset (); - } + } if ((*m_Addresses)[eSSU2V4Idx]) { if ((*m_Addresses)[eSSU2V4Idx]->IsV6 ()) (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eSSU2V4Idx].reset (); - } + } UpdateSupportedTransports (); } } @@ -829,8 +829,8 @@ namespace data #else return m_Addresses; #endif - } - + } + template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { @@ -862,7 +862,7 @@ namespace data auto addr = (*GetAddresses ())[isV6 ? eSSU2V6Idx : eSSU2V4Idx]; if (addr && !memcmp (addr->s, key, 32)) return addr; - return nullptr; + return nullptr; } std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const @@ -1037,7 +1037,7 @@ namespace data { auto addresses = GetAddresses (); if (!addresses) return; - + uint64_t ts = htobe64 (GetTimestamp ()); s.write ((const char *)&ts, sizeof (ts)); // addresses @@ -1049,7 +1049,7 @@ namespace data if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue; if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue; numAddresses++; - } + } s.write ((char *)&numAddresses, sizeof (numAddresses)); for (size_t idx = 0; idx < addresses->size(); idx++) { @@ -1154,7 +1154,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { - WriteString ("ih" + boost::lexical_cast(i), properties); + WriteString ("ih" + boost::lexical_cast(i), properties); properties << '='; char value[64]; size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64); @@ -1174,7 +1174,7 @@ namespace data } } } - + if (address.transportStyle == eTransportSSU2) { // write mtu diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index bd293d40..5008b5b1 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -71,7 +71,7 @@ namespace data }; #define TransportBit(tr) e##tr = (1 << e##tr##Idx) - + enum SupportedTransports { TransportBit(NTCP2V4), // 0x01 diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index dba228fd..351a8853 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -173,7 +173,7 @@ namespace transport mtu = i2p::util::net::GetMTU (localAddress); if (mtu > maxMTU) mtu = maxMTU; } - else + else if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; i2p::context.SetMTU (mtu, false); @@ -876,7 +876,7 @@ namespace transport { // token expired m_OutgoingTokens.erase (it); - return 0; + return 0; } return it->second.first; } @@ -1210,9 +1210,9 @@ namespace transport { if (!m_ProxyEndpoint) return; m_UDPAssociateSocket.reset (new boost::asio::ip::tcp::socket (m_ReceiveService.GetService ())); - m_UDPAssociateSocket->async_connect (*m_ProxyEndpoint, + m_UDPAssociateSocket->async_connect (*m_ProxyEndpoint, [this] (const boost::system::error_code& ecode) - { + { if (ecode) { LogPrint (eLogError, "SSU2: Can't connect to proxy ", *m_ProxyEndpoint, " ", ecode.message ()); @@ -1227,7 +1227,7 @@ namespace transport void SSU2Server::HandshakeWithProxy () { if (!m_UDPAssociateSocket) return; - m_UDPRequestHeader[0] = SOCKS5_VER; + m_UDPRequestHeader[0] = SOCKS5_VER; m_UDPRequestHeader[1] = 1; // 1 method m_UDPRequestHeader[2] = 0; // no authentication boost::asio::async_write (*m_UDPAssociateSocket, boost::asio::buffer (m_UDPRequestHeader, 3), boost::asio::transfer_all(), @@ -1274,8 +1274,8 @@ namespace transport void SSU2Server::SendUDPAssociateRequest () { if (!m_UDPAssociateSocket) return; - m_UDPRequestHeader[0] = SOCKS5_VER; - m_UDPRequestHeader[1] = SOCKS5_CMD_UDP_ASSOCIATE; + m_UDPRequestHeader[0] = SOCKS5_VER; + m_UDPRequestHeader[1] = SOCKS5_CMD_UDP_ASSOCIATE; m_UDPRequestHeader[2] = 0; // RSV m_UDPRequestHeader[3] = SOCKS5_ATYP_IPV4; // TODO: implement ipv6 proxy memset (m_UDPRequestHeader + 4, 0, 6); // address and port all zeros @@ -1374,7 +1374,7 @@ namespace transport LogPrint(eLogInfo, "SSU2: Reconnecting to proxy"); ConnectToProxy (); } - }); + }); } bool SSU2Server::SetProxy (const std::string& address, uint16_t port) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 13607c29..97372c17 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -30,7 +30,7 @@ namespace transport const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds - + class SSU2Server: private i2p::util::RunnableServiceWithWork { struct Packet @@ -132,7 +132,7 @@ namespace transport void SendUDPAssociateRequest (); void ReadUDPAssociateReply (); void ReadUDPAssociateSocket (); // handle if closed by peer - + private: ReceiveService m_ReceiveService; @@ -160,7 +160,7 @@ namespace transport std::unique_ptr m_UDPAssociateSocket; std::unique_ptr m_ProxyRelayEndpoint; std::unique_ptr m_ProxyConnectRetryTimer; - + public: // for HTTP/I2PControl diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 3843df2a..cf2eafde 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -96,7 +96,7 @@ namespace transport // timeout expired if (m_State == eSSU2SessionStateIntroduced) // WaitForIntroducer LogPrint (eLogWarning, "SSU2: Session was not introduced after ", SSU2_CONNECT_TIMEOUT, " seconds"); - else + else LogPrint (eLogWarning, "SSU2: Session with ", m_RemoteEndpoint, " was not established after ", SSU2_CONNECT_TIMEOUT, " seconds"); Terminate (); } @@ -530,7 +530,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: PeerTest message too short ", len); break; - } + } const uint8_t nonce[12] = {0}; uint64_t headerX[2]; i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); @@ -618,7 +618,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: SessionRequest message too short ", len); return; - } + } const uint8_t nonce[12] = {0}; uint8_t headerX[48]; i2p::crypto::ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX); @@ -889,7 +889,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: SessionConfirmed fragment too short ", len); if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); return false; - } + } if (!(header.h.flags[0] & 0xF0)) { // first fragment @@ -942,7 +942,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: SessionConfirmed message too short ", len); if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); return false; - } + } // KDF for Session Confirmed part 1 m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header) // decrypt part1 @@ -1155,7 +1155,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Retry message too short ", len); return false; - } + } uint8_t nonce[12] = {0}; uint64_t headerX[2]; // sourceConnID, token i2p::crypto::ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX); @@ -1244,7 +1244,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: HolePunch 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); @@ -1320,7 +1320,7 @@ namespace transport { 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); @@ -1392,7 +1392,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Data message too short ", len); return; - } + } uint8_t payload[SSU2_MAX_PACKET_SIZE]; size_t payloadSize = len - 32; uint32_t packetNum = be32toh (header.h.packetNum); @@ -1465,19 +1465,19 @@ namespace transport m_IsDataReceived = true; break; case eSSU2BlkTermination: - { - uint8_t rsn = buf[11]; // reason + { + uint8_t rsn = buf[11]; // reason LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) RequestTermination (eSSU2TerminationReasonTerminationReceived); - else if (m_State != eSSU2SessionStateTerminated) + else if (m_State != eSSU2SessionStateTerminated) { - if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) + if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) m_State = eSSU2SessionStateClosingConfirmed; Done (); - } + } break; - } + } case eSSU2BlkRelayRequest: LogPrint (eLogDebug, "SSU2: RelayRequest"); HandleRelayRequest (buf + offset, size); @@ -1667,13 +1667,13 @@ namespace transport LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4)); if (isV4) { - if (i2p::context.GetStatus () == eRouterStatusTesting || + if (i2p::context.GetStatus () == eRouterStatusTesting || m_State == eSSU2SessionStatePeerTest) - { + { i2p::context.SetStatus (eRouterStatusFirewalled); i2p::context.SetError (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimer (); - } + } } else { @@ -1683,7 +1683,7 @@ namespace transport i2p::context.SetStatusV6 (eRouterStatusFirewalled); i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimerV6 (); - } + } } } else @@ -1691,20 +1691,20 @@ namespace transport if (isV4) { if (i2p::context.GetError () == eRouterErrorSymmetricNAT) - { + { if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetStatus (eRouterStatusOK); i2p::context.SetError (eRouterErrorNone); - } + } } else { if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT) - { + { if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetStatusV6 (eRouterStatusOK); i2p::context.SetErrorV6 (eRouterErrorNone); - } + } } } } @@ -1913,10 +1913,10 @@ namespace transport { LogPrint (eLogDebug, "SSU2: RelayIntro attempt ", attempts + 1); s->HandleRelayIntro (vec->data (), vec->size (), attempts + 1); - }); + }); return; - } - else + } + else { LogPrint (eLogWarning, "SSU2: RelayIntro unknown router to introduce"); code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 0c584e2f..62c4acc7 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -495,27 +495,27 @@ namespace stream timeout); if (!done) { std::unique_lock l(newDataReceivedMutex); - if (!done && newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) + if (!done && newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout) ret = 0; - } + } if (!done) { // make sure that AsycReceive complete auto s = shared_from_this(); m_Service.post ([s]() - { + { s->m_ReceiveTimer.cancel (); }); int i = 0; while (!done && i < 100) // 1 sec - { + { std::this_thread::sleep_for (std::chrono::milliseconds(10)); i++; - } - } + } + } return ret; - } - + } + size_t Stream::Send (const uint8_t * buf, size_t len) { AsyncSend (buf, len, nullptr); @@ -1396,11 +1396,11 @@ namespace stream }); if (timeout) streamAccept.wait_for (l, std::chrono::seconds (timeout)); - else + else streamAccept.wait (l); return stream; - } - + } + void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 105977e8..0e1f7e88 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -186,7 +186,7 @@ namespace stream void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0); size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); }; size_t Receive (uint8_t * buf, size_t len, int timeout); - + void AsyncClose() { m_Service.post(std::bind(&Stream::Close, shared_from_this())); }; /** only call close from destination thread, use Stream::AsyncClose for other threads */ @@ -280,7 +280,7 @@ namespace stream void AcceptOnce (const Acceptor& acceptor); void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); std::shared_ptr AcceptStream (int timeout = 0); // sync - + std::shared_ptr GetOwner () const { return m_Owner; }; void SetOwner (std::shared_ptr owner) { m_Owner = owner; }; uint16_t GetLocalPort () const { return m_LocalPort; }; diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index 7b9a2021..6c2c52a7 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -33,7 +33,7 @@ namespace tunnel { m_Encryption.reset (new i2p::crypto::TunnelEncryption); m_Encryption->SetKeys (m_LayerKey, m_IVKey); - } + } m_Encryption->Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE); } diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 15bffe11..56f6b9bc 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -116,7 +116,7 @@ namespace transport virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; virtual bool IsEstablished () const = 0; - + protected: std::shared_ptr m_RemoteIdentity; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 00076f53..4f4dd929 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -823,8 +823,8 @@ namespace transport std::unique_lock l(m_PeersMutex); auto it = m_Peers.begin (); std::advance (it, rand () % m_Peers.size ()); - if (it == m_Peers.end () || it->second.router || it->second.sessions.empty () || - it->second.sessions.front ()->GetSendQueueSize () > PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE) + if (it == m_Peers.end () || it->second.router || it->second.sessions.empty () || + it->second.sessions.front ()->GetSendQueueSize () > PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE) return nullptr; // not connected or overloaded ident = it->first; } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 6032d35f..af813c81 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -44,7 +44,7 @@ namespace tunnel const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index ef52bf6d..ee115b7e 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -284,12 +284,12 @@ namespace tunnel } num = m_NumOutboundTunnels - num; if (num > 0) - { + { if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS; for (int i = 0; i < num; i++) CreateOutboundTunnel (); - } - + } + num = 0; { std::unique_lock l(m_InboundTunnelsMutex); @@ -307,12 +307,12 @@ namespace tunnel } num = m_NumInboundTunnels - num; if (num > 0) - { + { if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS; for (int i = 0; i < num; i++) CreateInboundTunnel (); } - + if (num < m_NumInboundTunnels && m_NumInboundHops <= 0 && m_LocalDestination) // zero hops IB m_LocalDestination->SetLeaseSetUpdated (); // update LeaseSet immediately } diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 07f91d2e..652dfb8d 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -833,7 +833,7 @@ namespace client } else m_Ident = addr->identHash; - // save url parts for later use + // save url parts for later use std::string dest_host = url.host; int dest_port = url.port ? url.port : 80; // try to create stream to addressbook site @@ -842,13 +842,13 @@ namespace client { LogPrint (eLogError, "Addressbook: LeaseSet for address ", url.host, " not found"); return false; - } - if (m_Etag.empty() && m_LastModified.empty()) + } + if (m_Etag.empty() && m_LastModified.empty()) { m_Book.GetEtag (m_Ident, m_Etag, m_LastModified); LogPrint (eLogDebug, "Addressbook: Loaded for ", url.host, ": ETag: ", m_Etag, ", Last-Modified: ", m_LastModified); } - // create http request & send it + // create http request & send it i2p::http::HTTPReq req; req.AddHeader("Host", dest_host); req.AddHeader("User-Agent", "Wget/1.11.4"); @@ -859,7 +859,7 @@ namespace client req.AddHeader("If-None-Match", m_Etag); if (!m_LastModified.empty()) req.AddHeader("If-Modified-Since", m_LastModified); - // convert url to relative + // convert url to relative url.schema = ""; url.host = ""; req.uri = url.to_string(); @@ -878,7 +878,7 @@ namespace client { response.append ((char *)recv_buf, received); if (!stream->IsOpen ()) end = true; - } + } else if (!stream->IsOpen ()) end = true; else @@ -886,12 +886,12 @@ namespace client LogPrint (eLogError, "Addressbook: Subscriptions request timeout expired"); numAttempts++; if (numAttempts > 5) end = true; - } + } } // process remaining buffer while (size_t len = stream->ReadSome (recv_buf, sizeof(recv_buf))) response.append ((char *)recv_buf, len); - // parse response + // parse response i2p::http::HTTPRes res; int res_head_len = res.parse(response); if (res_head_len < 0) @@ -904,7 +904,7 @@ namespace client LogPrint(eLogError, "Addressbook: Incomplete http response from ", dest_host, ", interrupted by timeout"); return false; } - // assert: res_head_len > 0 + // assert: res_head_len > 0 response.erase(0, res_head_len); if (res.code == 304) { @@ -927,7 +927,7 @@ namespace client LogPrint(eLogError, "Addressbook: Response size mismatch, expected: ", len, ", got: ", response.length(), "bytes"); return false; } - // assert: res.code == 200 + // assert: res.code == 200 auto it = res.headers.find("ETag"); if (it != res.headers.end()) m_Etag = it->second; it = res.headers.find("Last-Modified"); diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 9495ddde..1e4b3d7c 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -372,6 +372,6 @@ namespace client else LogPrint (eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort); } - + } } diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 749ec4d3..862ce216 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -180,7 +180,7 @@ namespace client bool isUpdated; // transient, used during reload only }; - + } } From 5f8d45154d12e4fe4a5d7e1d124ecdea3c6603db Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 3 Jan 2023 18:34:49 +0000 Subject: [PATCH 048/179] [docs] update transit limit description in config file Signed-off-by: R4SAS --- contrib/i2pd.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index b3048ff5..e265643f 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -237,8 +237,8 @@ verify = true # subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt [limits] -## Maximum active transit sessions (default:2500) -# transittunnels = 2500 +## Maximum active transit sessions (default: 5000) +# transittunnels = 5000 ## Limit number of open file descriptors (0 - use system limit) # openfiles = 0 ## Maximum size of corefile in Kb (0 - use system limit) From 321c7cb7cf5a8d879c2b38b28a49b74edb27d2e5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 3 Jan 2023 21:42:41 +0300 Subject: [PATCH 049/179] [docs] note about doubled transit tunnels limit for floodfill mode Signed-off-by: R4SAS --- ChangeLog | 1 + contrib/i2pd.conf | 1 + 2 files changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 964c1c20..6f9aba34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ - Removed SSU support - Reduced bandwidth calculation interval from 60 to 15 seconds - Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill +- Transit tunnels limit is doubled if floodfill mode is enabled - NTCP2 and SSU2 timestamps are rounded to seconds - Drop RouterInfos and LeaseSets with timestamp from future - Don't delete unreachable routers if tunnel creation success rate is too low diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index e265643f..c65d2bee 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -238,6 +238,7 @@ verify = true [limits] ## Maximum active transit sessions (default: 5000) +## This value is doubled if floodfill mode is enabled! # transittunnels = 5000 ## Limit number of open file descriptors (0 - use system limit) # openfiles = 0 From a1c16e129d8957ad80b5f203d339d21d3e350f90 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 4 Jan 2023 16:28:04 +0300 Subject: [PATCH 050/179] [rpm] fix date Signed-off-by: R4SAS --- contrib/rpm/i2pd-git.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index e3d487e2..e1697130 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -158,7 +158,7 @@ getent passwd i2pd >/dev/null || \ %changelog -* Mon Tue 3 2023 orignal - 2.45.0 +* Tue Jan 3 2023 orignal - 2.45.0 - update to 2.45.0 * Sun Nov 20 2022 orignal - 2.44.0 From 55be5c74f0c37f7a064eb4cd542bb02ee7e5333a Mon Sep 17 00:00:00 2001 From: kleenex Date: Wed, 4 Jan 2023 22:41:54 +0900 Subject: [PATCH 051/179] Fix segfault when UPnP is enabled Added null check. Signed-off-by: kleenex --- daemon/UPnP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index b7182055..dbaf864a 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -163,7 +163,7 @@ namespace transport if (!a) return; for (const auto& address : *a) { - if (!address->host.is_v6 () && address->port) + if (address && !address->host.is_v6 () && address->port) TryPortMapping (address); } m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes @@ -215,7 +215,7 @@ namespace transport if (!a) return; for (const auto& address : *a) { - if (!address->host.is_v6 () && address->port) + if (address && !address->host.is_v6 () && address->port) CloseMapping (address); } } From 06fae976b3de009f01420d07c6b50cf50723f027 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 4 Jan 2023 17:10:06 +0300 Subject: [PATCH 052/179] [style] update editorconfig Signed-off-by: R4SAS --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.editorconfig b/.editorconfig index 97acf820..ed3973c5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,6 +13,11 @@ insert_final_newline = true indent_style = tab indent_size = 4 +[*.cmd] +indent_style = space +indent_size = 2 +end_of_line = crlf + [*.{h,cpp}] indent_style = tab indent_size = 4 From 0d3ede56cb278f10d1516057a68a2e0ad61dd751 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Jan 2023 11:59:47 -0500 Subject: [PATCH 053/179] reject duplicated trnsit tunnel --- libi2pd/I2NPProtocol.cpp | 8 +++++--- libi2pd/Tunnel.cpp | 8 ++++++-- libi2pd/Tunnel.h | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index b8acbcbe..4d1ab6d4 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -392,7 +392,8 @@ namespace i2p clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); - i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); + if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel)) + retCode = 30; } else retCode = 30; // always reject with bandwidth reason (30) @@ -590,7 +591,8 @@ namespace i2p layerKey, ivKey, clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); - i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); + if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel)) + retCode = 30; } // encrypt reply diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index f3b7152d..611b0ec0 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -433,12 +433,16 @@ namespace tunnel } } - void Tunnels::AddTransitTunnel (std::shared_ptr tunnel) + bool Tunnels::AddTransitTunnel (std::shared_ptr tunnel) { if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) m_TransitTunnels.push_back (tunnel); else + { LogPrint (eLogError, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " already exists"); + return false; + } + return true; } void Tunnels::Start () diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index af813c81..d4fc7d5b 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -210,7 +210,7 @@ namespace tunnel std::shared_ptr GetExploratoryPool () const { return m_ExploratoryPool; }; std::shared_ptr GetTunnel (uint32_t tunnelID); int GetTransitTunnelsExpirationTimeout (); - void AddTransitTunnel (std::shared_ptr tunnel); + bool AddTransitTunnel (std::shared_ptr tunnel); void AddOutboundTunnel (std::shared_ptr newTunnel); void AddInboundTunnel (std::shared_ptr newTunnel); std::shared_ptr CreateInboundTunnel (std::shared_ptr config, std::shared_ptr pool, std::shared_ptr outboundTunnel); From 55704ece3aa477ef0b4c1e647dfe0ebd910d8acc Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Jan 2023 15:33:41 -0500 Subject: [PATCH 054/179] drop duplicated I2NP messages --- libi2pd/SSU2Session.cpp | 42 +++++++++++++++++++++++++++++++++++++---- libi2pd/SSU2Session.h | 11 ++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index cf2eafde..38d52012 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -221,6 +221,7 @@ namespace transport m_IncompleteMessages.clear (); m_RelaySessions.clear (); m_PeerTests.clear (); + m_ReceivedI2NPMsgIDs.clear (); m_Server.RemoveSession (m_SourceConnID); transports.PeerDisconnected (shared_from_this ()); LogPrint (eLogDebug, "SSU2: Session terminated"); @@ -1450,7 +1451,7 @@ namespace transport nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header memcpy (nextMsg->GetNTCP2Header (), buf + offset, size); nextMsg->FromNTCP2 (); // SSU2 has the same format as NTCP2 - m_Handler.PutNextMessage (std::move (nextMsg)); + HandleI2NPMsg (std::move (nextMsg)); m_IsDataReceived = true; break; } @@ -1738,7 +1739,7 @@ namespace transport { // we have all follow-on fragments already m->msg->FromNTCP2 (); - m_Handler.PutNextMessage (std::move (m->msg)); + HandleI2NPMsg (std::move (m->msg)); m_IncompleteMessages.erase (it); } } @@ -1760,14 +1761,14 @@ namespace transport if (isLast) { it->second->msg->FromNTCP2 (); - m_Handler.PutNextMessage (std::move (it->second->msg)); + HandleI2NPMsg (std::move (it->second->msg)); m_IncompleteMessages.erase (it); } else { if (ConcatOutOfSequenceFragments (it->second)) { - m_Handler.PutNextMessage (std::move (it->second->msg)); + HandleI2NPMsg (std::move (it->second->msg)); m_IncompleteMessages.erase (it); } else @@ -2268,6 +2269,25 @@ namespace transport } } + void SSU2Session::HandleI2NPMsg (std::shared_ptr&& msg) + { + if (!msg) return; + int32_t msgID = msg->GetMsgID (); + if (!m_ReceivedI2NPMsgIDs.count (msgID)) + { + if (!msg->IsExpired ()) + { + // m_LastActivityTimestamp is updated in ProcessData before + m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp); + m_Handler.PutNextMessage (std::move (msg)); + } + else + LogPrint (eLogDebug, "SSU2: Message ", msgID, " expired"); + } + else + LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); + } + bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep) { if (size < 2) return false; @@ -2790,6 +2810,20 @@ namespace transport else ++it; } + if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > m_LastActivityTimestamp + SSU2_DECAY_INTERVAL) + // decay + m_ReceivedI2NPMsgIDs.clear (); + else + { + // delete old received msgIDs + for (auto it = m_ReceivedI2NPMsgIDs.begin (); it != m_ReceivedI2NPMsgIDs.end ();) + { + if (ts > it->second + SSU2_RECEIVED_I2NP_MSGIDS_CLEANUP_TIMEOUT) + it = m_ReceivedI2NPMsgIDs.erase (it); + else + ++it; + } + } if (!m_OutOfSequencePackets.empty ()) { if (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index aab02127..b1cc234f 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -39,6 +39,9 @@ namespace transport const int SSU2_RESEND_INTERVAL = 300; // in milliseconds const int SSU2_MAX_NUM_RESENDS = 5; const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds + const int SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS = 5000; // how many msgID we store for duplicates check + const int SSU2_RECEIVED_I2NP_MSGIDS_CLEANUP_TIMEOUT = 10; // in seconds + const int SSU2_DECAY_INTERVAL = 20; // in seconds const size_t SSU2_MIN_WINDOW_SIZE = 16; // in packets const size_t SSU2_MAX_WINDOW_SIZE = 256; // in packets const size_t SSU2_MIN_RTO = 100; // in milliseconds @@ -47,7 +50,7 @@ namespace transport const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500; // in messages const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; - + // flags const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; @@ -308,7 +311,8 @@ namespace transport 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); - + 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 CreateAckBlock (uint8_t * buf, size_t len); @@ -351,6 +355,7 @@ namespace transport SSU2TerminationReason m_TerminationReason; size_t m_MaxPayloadSize; std::unique_ptr m_PathChallenge; + std::unordered_map m_ReceivedI2NPMsgIDs; // msgID -> timestamp in seconds }; inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) From acd6af709ee6371b3d0340d2c92cb86f6f4bcb97 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Jan 2023 18:16:36 -0500 Subject: [PATCH 055/179] don't use netdb memory pool for local RouterInfo --- libi2pd/RouterInfo.cpp | 26 +++++++++++++++++++++++--- libi2pd/RouterInfo.h | 6 +++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 4667be98..1aa0259b 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -206,13 +206,13 @@ namespace data s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses - auto addresses = netdb.NewRouterInfoAddresses (); + auto addresses = NewAddresses (); uint8_t numAddresses; s.read ((char *)&numAddresses, sizeof (numAddresses)); for (int i = 0; i < numAddresses; i++) { uint8_t supportedTransports = 0; - auto address = netdb.NewRouterInfoAddress (); + auto address = NewAddress (); uint8_t cost; // ignore s.read ((char *)&cost, sizeof (cost)); s.read ((char *)&address->date, sizeof (address->date)); @@ -974,6 +974,16 @@ namespace data return netdb.NewRouterInfoBuffer (); } + std::shared_ptr RouterInfo::NewAddress () const + { + return netdb.NewRouterInfoAddress (); + } + + boost::shared_ptr RouterInfo::NewAddresses () const + { + return netdb.NewRouterInfoAddresses (); + } + void RouterInfo::RefreshTimestamp () { m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); @@ -1255,6 +1265,16 @@ namespace data return std::make_shared (); } + std::shared_ptr LocalRouterInfo::NewAddress () const + { + return std::make_shared
(); + } + + boost::shared_ptr LocalRouterInfo::NewAddresses () const + { + return boost::make_shared (); + } + bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4) { auto addresses = GetAddresses (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 5008b5b1..4e54d615 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -285,6 +285,8 @@ namespace data template 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; private: @@ -324,6 +326,8 @@ namespace data void UpdateCapsProperty (); 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; private: From 4011502f5f9a9bf18597308bc45ef20a4c4e7d85 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 6 Jan 2023 03:58:34 +0300 Subject: [PATCH 056/179] [docker] put config in correct place Signed-off-by: R4SAS --- contrib/docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 129c5ff3..ead21f10 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -60,8 +60,8 @@ RUN apk update \ RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl miniupnpc musl-utils libstdc++ # 3. Copy preconfigured config file and entrypoint -COPY i2pd-docker.conf "$I2PD_HOME/i2pd.conf" -RUN chown i2pd:nobody "$I2PD_HOME/i2pd.conf" +COPY i2pd-docker.conf "$DATA_DIR/i2pd.conf" +RUN chown i2pd:nobody "$DATA_DIR/i2pd.conf" COPY entrypoint.sh /entrypoint.sh RUN chmod a+x /entrypoint.sh From a6f9a56e40a40f5a9d153e701a067c5251669ac4 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Jan 2023 14:08:39 -0500 Subject: [PATCH 057/179] support C++20 --- Makefile.linux | 5 ++++- libi2pd/SSU2Session.cpp | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index 28334082..a02419b7 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -20,9 +20,12 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9 else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 NEEDED_CXXFLAGS += -std=c++11 LDLIBS = -latomic -else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7 +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 - 19 + NEEDED_CXXFLAGS += -std=c++20 + LDLIBS = -latomic else # not supported $(error Compiler too old) endif diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 38d52012..cef67ea1 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2273,7 +2273,11 @@ namespace transport { if (!msg) return; int32_t msgID = msg->GetMsgID (); +#if __cplusplus >= 202002L // C++ 20 or higher + if (!m_ReceivedI2NPMsgIDs.contains (msgID)) +#else if (!m_ReceivedI2NPMsgIDs.count (msgID)) +#endif { if (!msg->IsExpired ()) { From e59ca8420eab18f1e536e951c50004e5bb55e86e Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Jan 2023 18:20:26 -0500 Subject: [PATCH 058/179] temporary change back to C++17 --- Makefile.linux | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index a02419b7..9a3fdda3 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -24,7 +24,8 @@ 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 - 19 - NEEDED_CXXFLAGS += -std=c++20 +# NEEDED_CXXFLAGS += -std=c++20 + NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic else # not supported $(error Compiler too old) From c18e8f6c7879798951894ced468096b6733df1bb Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jan 2023 10:54:49 -0500 Subject: [PATCH 059/179] drop too long LeaseSet without processing --- libi2pd/NetDb.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9eafd586..c46adff1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -807,6 +807,11 @@ namespace data uint8_t storeType = buf[DATABASE_STORE_TYPE_OFFSET]; if (storeType) // LeaseSet or LeaseSet2 { + if (len > MAX_LS_BUFFER_SIZE + offset) + { + LogPrint (eLogError, "NetDb: Database store message is too long ", len); + return; + } if (!m->from) // unsolicited LS must be received directly { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 From 1cc68ea402c26d41d84d1227288a65be224fdf48 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jan 2023 12:06:26 -0500 Subject: [PATCH 060/179] differentiate symmetric and full cone NAT --- daemon/HTTPServer.cpp | 3 +++ libi2pd/SSU2Session.cpp | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 281d3d53..dcd4f7f7 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -245,6 +245,9 @@ namespace http { case eRouterErrorSymmetricNAT: s << " - " << tr("Symmetric NAT"); break; + case eRouterErrorFullConeNAT: + s << " - " << tr("Full cone NAT"); + break; case eRouterErrorNoDescriptors: s << " - " << tr("No Descriptors"); break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index cef67ea1..d10c694c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1668,23 +1668,25 @@ namespace transport LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4)); if (isV4) { - if (i2p::context.GetStatus () == eRouterStatusTesting || - m_State == eSSU2SessionStatePeerTest) + if (i2p::context.GetStatus () == eRouterStatusTesting) { i2p::context.SetStatus (eRouterStatusFirewalled); i2p::context.SetError (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimer (); } + else if (m_State == eSSU2SessionStatePeerTest) + i2p::context.SetError (eRouterErrorFullConeNAT); } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting || - m_State == eSSU2SessionStatePeerTest) + if (i2p::context.GetStatusV6 () == eRouterStatusTesting) { i2p::context.SetStatusV6 (eRouterStatusFirewalled); i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); m_Server.RescheduleIntroducersUpdateTimerV6 (); } + else if (m_State == eSSU2SessionStatePeerTest) + i2p::context.SetErrorV6 (eRouterErrorFullConeNAT); } } else @@ -1697,6 +1699,8 @@ namespace transport i2p::context.SetStatus (eRouterStatusOK); i2p::context.SetError (eRouterErrorNone); } + else if (i2p::context.GetError () == eRouterErrorFullConeNAT) + i2p::context.SetError (eRouterErrorNone); } else { @@ -1706,6 +1710,8 @@ namespace transport i2p::context.SetStatusV6 (eRouterStatusOK); i2p::context.SetErrorV6 (eRouterErrorNone); } + else if (i2p::context.GetErrorV6 () == eRouterErrorFullConeNAT) + i2p::context.SetErrorV6 (eRouterErrorNone); } } } From 2921eaa055546d6e529537245f442dd78c481d5c Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jan 2023 12:11:51 -0500 Subject: [PATCH 061/179] differentiate symmetric and full cone NAT --- libi2pd/RouterContext.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index dd7f0272..d3638b15 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -48,7 +48,8 @@ namespace garlic eRouterErrorClockSkew = 1, eRouterErrorOffline = 2, eRouterErrorSymmetricNAT = 3, - eRouterErrorNoDescriptors = 4 + eRouterErrorFullConeNAT = 4, + eRouterErrorNoDescriptors = 5 }; class RouterContext: public i2p::garlic::GarlicDestination From a3c305032a5490a1815f3f60a0f21c4ddeed7c10 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Jan 2023 08:25:23 -0500 Subject: [PATCH 062/179] don't set Firewalled upon SessionCreated if ports mismatch --- libi2pd/RouterContext.cpp | 10 +++++++--- libi2pd/SSU2Session.cpp | 8 -------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b1ebdec7..eb65d2ca 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -240,7 +240,6 @@ namespace i2p if (status != m_Status) { m_Status = status; - m_Error = eRouterErrorNone; switch (m_Status) { case eRouterStatusOK: @@ -249,6 +248,9 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (true, false); // ipv4 break; + case eRouterStatusTesting: + m_Error = eRouterErrorNone; + break; default: ; } @@ -260,7 +262,6 @@ namespace i2p if (status != m_StatusV6) { m_StatusV6 = status; - m_ErrorV6 = eRouterErrorNone; switch (m_StatusV6) { case eRouterStatusOK: @@ -269,6 +270,9 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (false, true); // ipv6 break; + case eRouterStatusTesting: + m_ErrorV6 = eRouterErrorNone; + break; default: ; } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index d10c694c..01675f80 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1669,22 +1669,14 @@ namespace transport if (isV4) { if (i2p::context.GetStatus () == eRouterStatusTesting) - { - i2p::context.SetStatus (eRouterStatusFirewalled); i2p::context.SetError (eRouterErrorSymmetricNAT); - m_Server.RescheduleIntroducersUpdateTimer (); - } else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetError (eRouterErrorFullConeNAT); } else { if (i2p::context.GetStatusV6 () == eRouterStatusTesting) - { - i2p::context.SetStatusV6 (eRouterStatusFirewalled); i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); - m_Server.RescheduleIntroducersUpdateTimerV6 (); - } else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetErrorV6 (eRouterErrorFullConeNAT); } From f34abe60fac01aba30d24035e893d86018389a80 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Jan 2023 13:52:20 -0500 Subject: [PATCH 063/179] 2.45.1 --- ChangeLog | 11 +++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 2 +- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6f9aba34..16cb6d6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,17 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.45.1] - 2023-01-11 +### Added +- Full Cone NAT status error +### Changed +- Drop duplicated I2NP messages in SSU2 +- Set rejection code 30 if tunnel with id already exists +- Network status is always OK if peer test msg 5 received +### Fixed +- UPnP crash if SSU2 or NTCP2 is disabled +- Crash on termination for some platforms + ## [2.45.0] - 2023-01-03 ### Added - Test for Symmetric NAT with peer test msgs 6 and 7 diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index e1697130..79d591ac 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.45.0 +Version: 2.45.1 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Jan 11 2023 orignal - 2.45.1 +- update to 2.45.1 + * Tue Jan 3 2023 orignal - 2.45.0 - update to 2.45.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5a56989f..07ecfbcc 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.45.0 +Version: 2.45.1 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Jan 11 2023 orignal - 2.45.1 +- update to 2.45.1 + * Tue Jan 3 2023 orignal - 2.45.0 - update to 2.45.0 diff --git a/debian/changelog b/debian/changelog index 10ca4082..77b174c5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.45.1-1) unstable; urgency=medium + + * updated to version 2.45.1/0.9.57 + +-- orignal Wed, 11 Jan 2023 19:00:00 +0000 + i2pd (2.45.0-1) unstable; urgency=high * updated to version 2.45.0/0.9.57 diff --git a/libi2pd/version.h b/libi2pd/version.h index 26f855be..65ca1fc4 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -17,7 +17,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 45 -#define I2PD_VERSION_MICRO 0 +#define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION GITVER From f79900653b2f687f6a004377c6ff634f19822487 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 12 Jan 2023 15:49:02 +0300 Subject: [PATCH 064/179] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6f2d23ec..d0481ed9 100644 --- a/README.md +++ b/README.md @@ -69,12 +69,12 @@ Build instructions: **Supported systems:** -* GNU/Linux - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml) - * CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) - * Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc. +* GNU/Linux (Debian, Ubuntu, etc) - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml) +* CentOS, Fedora, Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) +* Alpine, ArchLinux, openSUSE, Gentoo, etc. * Windows - [![Build on Windows](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml) -* Mac OS X - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml) -* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/) [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml) +* Mac OS - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml) +* Docker image - [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml) * Snap - [![i2pd](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![i2pd](https://snapcraft.io/i2pd/trending.svg?name=0)](https://snapcraft.io/i2pd) * FreeBSD - [![Build on FreeBSD](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml) * Android - [![Android CI](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml/badge.svg)](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml) From 7146a4dbaee7df1a165a18869593ce29089dde2b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jan 2023 15:41:57 -0500 Subject: [PATCH 065/179] check if session socket was closed before tunnels were built --- libi2pd_client/SAM.cpp | 23 ++++++++++++++--------- libi2pd_client/SAM.h | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 8b991802..93df59fb 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -440,18 +440,23 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) { - auto session = m_Owner.FindSession(m_ID); - if(session) + if (m_Socket.is_open ()) { - if (session->GetLocalDestination ()->IsReady ()) - SendSessionCreateReplyOk (); - else + auto session = m_Owner.FindSession(m_ID); + if(session) { - m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); - m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, - shared_from_this (), std::placeholders::_1)); + if (session->GetLocalDestination ()->IsReady ()) + SendSessionCreateReplyOk (); + else + { + m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); + m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, + shared_from_this (), std::placeholders::_1)); + } } } + else + Terminate ("SAM: session socket closed"); } } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 88990d7c..b6ac23a6 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -30,7 +30,7 @@ namespace client { const size_t SAM_SOCKET_BUFFER_SIZE = 8192; const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds - const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds + const int SAM_SESSION_READINESS_CHECK_INTERVAL = 3; // in seconds const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n"; From d530269e4fbf6f3a92a0c1f1a1ba66d3cb0ba9e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 13 Jan 2023 19:23:26 -0500 Subject: [PATCH 066/179] try to insert received msgid instead lookup --- libi2pd/SSU2Session.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 01675f80..f414baeb 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2271,23 +2271,16 @@ namespace transport { if (!msg) return; int32_t msgID = msg->GetMsgID (); -#if __cplusplus >= 202002L // C++ 20 or higher - if (!m_ReceivedI2NPMsgIDs.contains (msgID)) -#else - if (!m_ReceivedI2NPMsgIDs.count (msgID)) -#endif - { - if (!msg->IsExpired ()) - { - // m_LastActivityTimestamp is updated in ProcessData before - m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp); + if (!msg->IsExpired ()) + { + // m_LastActivityTimestamp is updated in ProcessData before + if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second) m_Handler.PutNextMessage (std::move (msg)); - } else - LogPrint (eLogDebug, "SSU2: Message ", msgID, " expired"); - } + LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); + } else - LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); + LogPrint (eLogDebug, "SSU2: Message ", msgID, " expired"); } bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep) From 324ace103b9ea48554894d07fb1a30aae8f3a28d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 14 Jan 2023 17:05:09 -0500 Subject: [PATCH 067/179] memoery pool for fragments --- libi2pd/SSU2.cpp | 33 ++++++++++++++++++++++++++------- libi2pd/SSU2.h | 14 ++++++++++---- libi2pd/SSU2Session.cpp | 2 +- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 351a8853..d2cb1a26 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -22,7 +22,7 @@ namespace transport RunnableServiceWithWork ("SSU2"), m_ReceiveService ("SSU2r"), m_SocketV4 (m_ReceiveService.GetService ()), m_SocketV6 (m_ReceiveService.GetService ()), m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()), - m_TerminationTimer (GetService ()), m_ResendTimer (GetService ()), + m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), m_IsPublished (true), m_IsSyncClockFromPeers (true), m_IsThroughProxy (false) { @@ -109,6 +109,7 @@ namespace transport m_ReceiveService.Start (); } ScheduleTermination (); + ScheduleCleanup (); ScheduleResend (false); } } @@ -118,6 +119,7 @@ namespace transport if (IsRunning ()) { m_TerminationTimer.cancel (); + m_CleanupTimer.cancel (); m_ResendTimer.cancel (); m_IntroducersUpdateTimer.cancel (); m_IntroducersUpdateTimerV6.cancel (); @@ -807,6 +809,22 @@ namespace transport it++; } + ScheduleTermination (); + } + } + + void SSU2Server::ScheduleCleanup () + { + m_CleanupTimer.expires_from_now (boost::posix_time::seconds(SSU2_CLEANUP_INTERVAL)); + m_CleanupTimer.async_wait (std::bind (&SSU2Server::HandleCleanupTimer, + this, std::placeholders::_1)); + } + + void SSU2Server::HandleCleanupTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_Relays.begin (); it != m_Relays.begin ();) { if (it->second && it->second->GetState () == eSSU2SessionStateTerminated) @@ -830,13 +848,14 @@ namespace transport else it++; } - + m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); - ScheduleTermination (); - } - } - + m_FragmentsPool.CleanUp (); + ScheduleCleanup (); + } + } + void SSU2Server::ScheduleResend (bool more) { m_ResendTimer.expires_from_now (boost::posix_time::milliseconds (more ? SSU2_RESEND_CHECK_MORE_TIMEOUT : diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 97372c17..68d507ca 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -18,7 +18,8 @@ namespace i2p { namespace transport { - const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // in seconds + const int SSU2_TERMINATION_CHECK_TIMEOUT = 25; // in seconds + const int SSU2_CLEANUP_INTERVAL = 72; // in seconds const int SSU2_RESEND_CHECK_TIMEOUT = 400; // in milliseconds const int SSU2_RESEND_CHECK_TIMEOUT_VARIANCE = 100; // in milliseconds const int SSU2_RESEND_CHECK_MORE_TIMEOUT = 10; // in milliseconds @@ -97,7 +98,8 @@ namespace transport void RescheduleIntroducersUpdateTimerV6 (); i2p::util::MemoryPool& GetSentPacketsPool () { return m_SentPacketsPool; }; - + i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -111,6 +113,9 @@ namespace transport void ScheduleTermination (); void HandleTerminationTimer (const boost::system::error_code& ecode); + void ScheduleCleanup (); + void HandleCleanupTimer (const boost::system::error_code& ecode); + void ScheduleResend (bool more); void HandleResendTimer (const boost::system::error_code& ecode); @@ -147,7 +152,8 @@ namespace transport std::list m_Introducers, m_IntroducersV6; // introducers we are connected to i2p::util::MemoryPoolMt m_PacketsPool; i2p::util::MemoryPool m_SentPacketsPool; - boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer, + i2p::util::MemoryPool m_FragmentsPool; + boost::asio::deadline_timer m_TerminationTimer, m_CleanupTimer, m_ResendTimer, m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6; std::shared_ptr m_LastSession; bool m_IsPublished; // if we maintain introducers diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index f414baeb..79e736fe 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1788,7 +1788,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: Fragment number ", fragmentNum, " exceeds ", SSU2_MAX_NUM_FRAGMENTS); return; } - auto fragment = std::make_shared (); + auto fragment = m_Server.GetFragmentsPool ().AcquireShared (); memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; fragment->isLast = isLast; From 993dc72ce664612496e4e2c441b37d4bd704db30 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 15 Jan 2023 22:50:54 -0500 Subject: [PATCH 068/179] use separate pointer to second fragment of incomplete message --- libi2pd/SSU2Session.cpp | 71 +++++++++++++++++++++++++++++------------ libi2pd/SSU2Session.h | 6 ++-- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 79e736fe..b3c539bc 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -32,7 +32,55 @@ namespace transport nextFragmentNum++; } + bool SSU2IncompleteMessage::ConcatOutOfSequenceFragments () + { + bool isLast = false; + if (nextFragmentNum == 1) + { + if (secondFragment) + { + AttachNextFragment (secondFragment->buf, secondFragment->len); + isLast = secondFragment->isLast; + secondFragment = nullptr; + } + else + return false; + if (isLast) return true; + } + // might be more + if (outOfSequenceFragments) + { + for (auto it = outOfSequenceFragments->begin (); it != outOfSequenceFragments->end ();) + if (it->first == nextFragmentNum) + { + AttachNextFragment (it->second->buf, it->second->len); + isLast = it->second->isLast; + it = outOfSequenceFragments->erase (it); + } + else + break; + } + return isLast; + } + void SSU2IncompleteMessage::AddOutOfSequenceFragment (int fragmentNum, + std::shared_ptr fragment) + { + if (!fragmentNum || !fragment) return; // fragment 0 nun allowed + if (fragmentNum < nextFragmentNum) return; // already processed + if (fragmentNum == 1) + { + if (!secondFragment) secondFragment = fragment; + } + else + { + if (!outOfSequenceFragments) + outOfSequenceFragments.reset (new std::map >()); + outOfSequenceFragments->emplace (fragmentNum, fragment); + } + lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); + } + SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter, std::shared_ptr addr): TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), @@ -1733,7 +1781,7 @@ namespace transport m->msg = msg; m->nextFragmentNum = 1; m->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); - if (found && ConcatOutOfSequenceFragments (m)) + if (found && m->ConcatOutOfSequenceFragments ()) { // we have all follow-on fragments already m->msg->FromNTCP2 (); @@ -1764,7 +1812,7 @@ namespace transport } else { - if (ConcatOutOfSequenceFragments (it->second)) + if (it->second->ConcatOutOfSequenceFragments ()) { HandleI2NPMsg (std::move (it->second->msg)); m_IncompleteMessages.erase (it); @@ -1792,24 +1840,7 @@ namespace transport memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; fragment->isLast = isLast; - it->second->outOfSequenceFragments.emplace (fragmentNum, fragment); - it->second->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); - } - - bool SSU2Session::ConcatOutOfSequenceFragments (std::shared_ptr m) - { - if (!m) return false; - bool isLast = false; - for (auto it = m->outOfSequenceFragments.begin (); it != m->outOfSequenceFragments.end ();) - if (it->first == m->nextFragmentNum) - { - m->AttachNextFragment (it->second->buf, it->second->len); - isLast = it->second->isLast; - it = m->outOfSequenceFragments.erase (it); - } - else - break; - return isLast; + it->second->AddOutOfSequenceFragment (fragmentNum, fragment); } void SSU2Session::HandleRelayRequest (const uint8_t * buf, size_t len) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index b1cc234f..97469ed4 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -177,9 +177,12 @@ namespace transport std::shared_ptr msg; int nextFragmentNum; uint32_t lastFragmentInsertTime; // in seconds - std::map > outOfSequenceFragments; + std::shared_ptr secondFragment; // fragment #1 + std::unique_ptr > > outOfSequenceFragments; // fragments #2 and more void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); + bool ConcatOutOfSequenceFragments (); // true if message complete + void AddOutOfSequenceFragment (int fragmentNum, std::shared_ptr fragment); }; struct SSU2SentPacket @@ -306,7 +309,6 @@ namespace transport 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); - bool ConcatOutOfSequenceFragments (std::shared_ptr m); // true if message complete 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); From 10030a4e0d43038d26690504785cbba808582d15 Mon Sep 17 00:00:00 2001 From: acetone Date: Mon, 16 Jan 2023 13:31:13 +0300 Subject: [PATCH 069/179] Addresshelper updating: referer check --- libi2pd_client/HTTPProxy.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index b9d4d48c..28928836 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -333,6 +333,30 @@ namespace proxy { } else if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm) { + if (m_Confirm) + { + // Referer check to prevent forced overwriting by link with "&update=true" from harmful URL + const std::string referer_raw = m_ClientRequest.GetHeader("Referer"); + i2p::http::URL referer_url; + if (!referer_raw.empty ()) + { + referer_url.parse (referer_raw); + } + if (m_RequestURL.host != referer_url.host) + { + LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful"); + std::string full_url = m_RequestURL.to_string(); + std::stringstream ss; + ss << tr("Host") << " " << m_RequestURL.host << " " << tr("already in router's addressbook") << ". "; + ss << "" << tr("Be careful: source of this URL may be harmful") << "! "; + ss << tr(/* tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. */ "Click here to update record:" ); + ss << " " << tr("Continue") << "."; + GenericProxyInfo(tr("Addresshelper forced update rejected"), ss.str()); + return true; /* request processed */ + } + } + i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, jump); LogPrint (eLogInfo, "HTTPProxy: Added address from addresshelper for ", m_RequestURL.host); std::string full_url = m_RequestURL.to_string(); From d8b6f5438c558b13d047f1b1e8d81e5a339c0017 Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Mon, 16 Jan 2023 13:56:36 +0300 Subject: [PATCH 070/179] log typo --- libi2pd_client/HTTPProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 28928836..67d34e97 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -344,7 +344,7 @@ namespace proxy { } if (m_RequestURL.host != referer_url.host) { - LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful"); + LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful", ")"); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; ss << tr("Host") << " " << m_RequestURL.host << " " << tr("already in router's addressbook") << ". "; From 9af5a907575cc85b390f170ff32d2a1658accaac Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Mon, 16 Jan 2023 13:57:15 +0300 Subject: [PATCH 071/179] Copyright year updated --- libi2pd_client/HTTPProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 67d34e97..8c3a341e 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * From 013d5ff74f546f94fc3e21f457c128ba4c6ef0e1 Mon Sep 17 00:00:00 2001 From: acetone Date: Mon, 16 Jan 2023 16:16:16 +0300 Subject: [PATCH 072/179] Addresshelper request validation by Refer-header --- libi2pd_client/HTTPProxy.cpp | 37 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 8c3a341e..a41320be 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -333,28 +333,39 @@ namespace proxy { } else if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm) { - if (m_Confirm) + // Referer check to prevent forced overwriting by link with "&update=true" from harmful URL + const std::string referer_raw = m_ClientRequest.GetHeader("Referer"); + i2p::http::URL referer_url; + if (!referer_raw.empty ()) { - // Referer check to prevent forced overwriting by link with "&update=true" from harmful URL - const std::string referer_raw = m_ClientRequest.GetHeader("Referer"); - i2p::http::URL referer_url; - if (!referer_raw.empty ()) - { - referer_url.parse (referer_raw); - } - if (m_RequestURL.host != referer_url.host) + referer_url.parse (referer_raw); + } + if (m_RequestURL.host != referer_url.host) + { + if (m_Confirm) { LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful", ")"); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; ss << tr("Host") << " " << m_RequestURL.host << " " << tr("already in router's addressbook") << ". "; - ss << "" << tr("Be careful: source of this URL may be harmful") << "! "; + ss << "" << tr( /* Trying to overwrite an existing domain in the address book by direct link with "&update=true" is seems like an attack */ "Be careful: source of this URL may be harmful") << "! "; ss << tr(/* tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. */ "Click here to update record:" ); ss << " " << tr("Continue") << "."; GenericProxyInfo(tr("Addresshelper forced update rejected"), ss.str()); - return true; /* request processed */ } + else + { + LogPrint (eLogDebug, "HTTPProxy: Adding address from addresshelper for ", m_RequestURL.host, " (generate refer-base page)"); + std::string full_url = m_RequestURL.to_string(); + std::stringstream ss; + ss << tr("To add host") << " " << m_RequestURL.host << " " << tr("in router's addressbook") << ", "; + ss << tr("click here") << ":"; + ss << " " << tr("Continue") << "."; + GenericProxyInfo(tr("Addresshelper request"), ss.str()); + } + return true; /* request processed */ } i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, jump); @@ -363,7 +374,7 @@ namespace proxy { std::stringstream ss; ss << tr("Host") <<" " << m_RequestURL.host << " " << tr("added to router's addressbook from helper") << ". "; ss << tr("Click here to proceed:") << " " << tr("Continue") << "."; - GenericProxyInfo(tr("Addresshelper found"), ss.str()); + GenericProxyInfo(tr("Addresshelper adding"), ss.str()); return true; /* request processed */ } else @@ -374,7 +385,7 @@ namespace proxy { ss << tr(/* tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. */ "Click here to update record:" ); ss << " " << tr("Continue") << "."; - GenericProxyInfo(tr("Addresshelper found"), ss.str()); + GenericProxyInfo(tr("Addresshelper update"), ss.str()); return true; /* request processed */ } } From 6ca6591c4365d62873eeac6328e5b1932862a614 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 17 Jan 2023 01:28:50 +0300 Subject: [PATCH 073/179] [make] set PREFIX from DESTDIR if it present Signed-off-by: R4SAS --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index d792360a..35ee08a9 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,10 @@ else LD_DEBUG = -s endif +ifneq (, $(DESTDIR)) + PREFIX = $(DESTDIR) +endif + ifneq (, $(findstring darwin, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp ifeq ($(HOMEBREW),1) From bc888167a7c5483f2acc4d20d80fe9e1601c53f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Jan 2023 21:40:23 -0500 Subject: [PATCH 074/179] use linked list for out of sequence fragments --- libi2pd/SSU2Session.cpp | 64 ++++++++++++++++++++--------------------- libi2pd/SSU2Session.h | 7 +++-- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index b3c539bc..0f53bf7b 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -35,48 +35,45 @@ namespace transport bool SSU2IncompleteMessage::ConcatOutOfSequenceFragments () { bool isLast = false; - if (nextFragmentNum == 1) - { - if (secondFragment) + while (outOfSequenceFragments) + { + if (outOfSequenceFragments->fragmentNum == nextFragmentNum) { - AttachNextFragment (secondFragment->buf, secondFragment->len); - isLast = secondFragment->isLast; - secondFragment = nullptr; + AttachNextFragment (outOfSequenceFragments->buf, outOfSequenceFragments->len); + isLast = outOfSequenceFragments->isLast; + if (isLast) + outOfSequenceFragments = nullptr; + else + outOfSequenceFragments = outOfSequenceFragments->next; } else - return false; - if (isLast) return true; - } - // might be more - if (outOfSequenceFragments) - { - for (auto it = outOfSequenceFragments->begin (); it != outOfSequenceFragments->end ();) - if (it->first == nextFragmentNum) - { - AttachNextFragment (it->second->buf, it->second->len); - isLast = it->second->isLast; - it = outOfSequenceFragments->erase (it); - } - else - break; + break; } return isLast; } - void SSU2IncompleteMessage::AddOutOfSequenceFragment (int fragmentNum, - std::shared_ptr fragment) + void SSU2IncompleteMessage::AddOutOfSequenceFragment (std::shared_ptr fragment) { - if (!fragmentNum || !fragment) return; // fragment 0 nun allowed - if (fragmentNum < nextFragmentNum) return; // already processed - if (fragmentNum == 1) - { - if (!secondFragment) secondFragment = fragment; - } + if (!fragment || !fragment->fragmentNum) return; // fragment 0 not allowed + if (fragment->fragmentNum < nextFragmentNum) return; // already processed + if (!outOfSequenceFragments) + outOfSequenceFragments = fragment; else { - if (!outOfSequenceFragments) - outOfSequenceFragments.reset (new std::map >()); - outOfSequenceFragments->emplace (fragmentNum, fragment); + auto frag = outOfSequenceFragments; + std::shared_ptr prev; + do + { + if (fragment->fragmentNum < frag->fragmentNum) break; // found + if (fragment->fragmentNum == frag->fragmentNum) return; // duplicate + prev = frag; frag = frag->next; + } + while (frag); + fragment->next = frag; + if (prev) + prev->next = fragment; + else + outOfSequenceFragments = fragment; } lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); } @@ -1839,8 +1836,9 @@ namespace transport auto fragment = m_Server.GetFragmentsPool ().AcquireShared (); memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; + fragment->fragmentNum = fragmentNum; fragment->isLast = isLast; - it->second->AddOutOfSequenceFragment (fragmentNum, fragment); + it->second->AddOutOfSequenceFragment (fragment); } void SSU2Session::HandleRelayRequest (const uint8_t * buf, size_t len) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 97469ed4..08a4b7cf 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -171,18 +171,19 @@ namespace transport { uint8_t buf[SSU2_MAX_PACKET_SIZE]; size_t len; + int fragmentNum; bool isLast; + std::shared_ptr next; }; std::shared_ptr msg; int nextFragmentNum; uint32_t lastFragmentInsertTime; // in seconds - std::shared_ptr secondFragment; // fragment #1 - std::unique_ptr > > outOfSequenceFragments; // fragments #2 and more + std::shared_ptr outOfSequenceFragments; // #1 and more void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); bool ConcatOutOfSequenceFragments (); // true if message complete - void AddOutOfSequenceFragment (int fragmentNum, std::shared_ptr fragment); + void AddOutOfSequenceFragment (std::shared_ptr fragment); }; struct SSU2SentPacket From d105ab11af00297a164abab2ab29e8f80f642a13 Mon Sep 17 00:00:00 2001 From: acetone Date: Tue, 17 Jan 2023 08:45:18 +0300 Subject: [PATCH 075/179] Joining two strings to one and correct comments --- 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 a41320be..cecda2bb 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -333,7 +333,6 @@ namespace proxy { } else if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm) { - // Referer check to prevent forced overwriting by link with "&update=true" from harmful URL const std::string referer_raw = m_ClientRequest.GetHeader("Referer"); i2p::http::URL referer_url; if (!referer_raw.empty ()) @@ -342,6 +341,7 @@ namespace proxy { } if (m_RequestURL.host != referer_url.host) { + // Attempt to forced overwriting by link with "&update=true" from harmful URL if (m_Confirm) { LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful", ")"); @@ -354,13 +354,13 @@ namespace proxy { ss << jump << "&update=true\">" << tr("Continue") << "."; GenericProxyInfo(tr("Addresshelper forced update rejected"), ss.str()); } + // Preventing unauthorized additions to the address book else { LogPrint (eLogDebug, "HTTPProxy: Adding address from addresshelper for ", m_RequestURL.host, " (generate refer-base page)"); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("To add host") << " " << m_RequestURL.host << " " << tr("in router's addressbook") << ", "; - ss << tr("click here") << ":"; + ss << tr("To add host" /*... in router's addressbook, click here */ ) << " " << m_RequestURL.host << " " << tr( /* To add host SOMESHORT.i2p ... */ "in router's addressbook, click here") << ":"; ss << " " << tr("Continue") << "."; GenericProxyInfo(tr("Addresshelper request"), ss.str()); From b290ee1aa04f2f5f4b7b418b6a78df924b197c6a Mon Sep 17 00:00:00 2001 From: acetone Date: Tue, 17 Jan 2023 09:00:11 +0300 Subject: [PATCH 076/179] Cfg example: verbose comments for Web Console auth and addresshelper for public proxy --- contrib/i2pd.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index c65d2bee..c8baa046 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -122,6 +122,8 @@ port = 7070 ## Path to web console, default "/" # webroot = / ## Uncomment following lines to enable Web Console authentication +## You should not use Web Console via public networks without additional encryption. +## HTTP authentication is not encryption layer! # auth = true # user = i2pd # pass = changeme @@ -139,6 +141,8 @@ port = 4444 ## Optional keys file for proxy local destination # keys = http-proxy-keys.dat ## Enable address helper for adding .i2p domains with "jump URLs" (default: true) +## You should disable this feature if your i2pd HTTP Proxy is public, +## because anyone could spoof the short domain via addresshelper and forward other users to phishing links # addresshelper = true ## Address of a proxy server inside I2P, which is used to visit regular Internet # outproxy = http://false.i2p From e8be39af176628b5e0ef04c8bde5d8292ef6584e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Jan 2023 21:32:36 -0500 Subject: [PATCH 077/179] memrory pool for SSU2IncompleteMessage --- libi2pd/SSU2.cpp | 1 + libi2pd/SSU2.h | 4 +++- libi2pd/SSU2Session.cpp | 15 ++++++++------- libi2pd/SSU2Session.h | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index d2cb1a26..5bb27a40 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -851,6 +851,7 @@ namespace transport m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); + m_IncompleteMessagesPool.CleanUp (); m_FragmentsPool.CleanUp (); ScheduleCleanup (); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 68d507ca..8b755f60 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -98,8 +98,9 @@ namespace transport void RescheduleIntroducersUpdateTimerV6 (); i2p::util::MemoryPool& GetSentPacketsPool () { return m_SentPacketsPool; }; + i2p::util::MemoryPool& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; }; i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; - + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -152,6 +153,7 @@ namespace transport 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; i2p::util::MemoryPool m_FragmentsPool; boost::asio::deadline_timer m_TerminationTimer, m_CleanupTimer, m_ResendTimer, m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 0f53bf7b..5e97b461 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1772,7 +1772,7 @@ namespace transport } else { - m = std::make_shared(); + m = m_Server.GetIncompleteMessagesPool ().AcquireShared (); m_IncompleteMessages.emplace (msgID, m); } m->msg = msg; @@ -1791,11 +1791,17 @@ namespace transport { if (len < 5) return; uint8_t fragmentNum = buf[0] >> 1; + if (!fragmentNum || fragmentNum >= SSU2_MAX_NUM_FRAGMENTS) + { + LogPrint (eLogWarning, "SSU2: Invalid follow-on fragment num ", fragmentNum); + return; + } bool isLast = buf[0] & 0x01; uint32_t msgID; memcpy (&msgID, buf + 1, 4); auto it = m_IncompleteMessages.find (msgID); if (it != m_IncompleteMessages.end ()) { + if (fragmentNum < it->second->nextFragmentNum) return; // duplicate if (it->second->nextFragmentNum == fragmentNum && fragmentNum < SSU2_MAX_NUM_FRAGMENTS && it->second->msg) { @@ -1823,16 +1829,11 @@ namespace transport else { // follow-on fragment before first fragment - auto msg = std::make_shared (); + auto msg = m_Server.GetIncompleteMessagesPool ().AcquireShared (); msg->nextFragmentNum = 0; it = m_IncompleteMessages.emplace (msgID, msg).first; } // insert out of sequence fragment - if (fragmentNum >= SSU2_MAX_NUM_FRAGMENTS) - { - LogPrint (eLogWarning, "SSU2: Fragment number ", fragmentNum, " exceeds ", SSU2_MAX_NUM_FRAGMENTS); - return; - } auto fragment = m_Server.GetFragmentsPool ().AcquireShared (); memcpy (fragment->buf, buf + 5, len -5); fragment->len = len - 5; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 08a4b7cf..ef9ab573 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -345,7 +345,7 @@ namespace transport uint32_t m_SendPacketNum, m_ReceivePacketNum; std::set m_OutOfSequencePackets; // packet nums > receive packet num std::map > m_SentPackets; // packetNum -> packet - std::map > m_IncompleteMessages; // I2NP + 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::list > m_SendQueue; From e8ace998ba20f11c6eb204c1e254926e3927b21f Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 18 Jan 2023 07:21:36 +0300 Subject: [PATCH 078/179] [i18n] add support of string formatting Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 51 ++++++++++++++++++++--------------- i18n/Afrikaans.cpp | 8 +++--- i18n/Armenian.cpp | 18 ++++++------- i18n/Chinese.cpp | 18 ++++++------- i18n/Czech.cpp | 18 ++++++------- i18n/French.cpp | 18 ++++++------- i18n/German.cpp | 18 ++++++------- i18n/I18N.h | 62 ++++++++++++++++++++++++++++++++++++++++--- i18n/Italian.cpp | 18 ++++++------- i18n/Russian.cpp | 18 ++++++------- i18n/Spanish.cpp | 18 ++++++------- i18n/Turkmen.cpp | 18 ++++++------- i18n/Ukrainian.cpp | 18 ++++++------- i18n/Uzbek.cpp | 18 ++++++------- 14 files changed, 190 insertions(+), 129 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index dcd4f7f7..74e7df64 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -103,18 +103,18 @@ namespace http { int num; if ((num = seconds / 86400) > 0) { - s << num << " " << tr("day", "days", num) << ", "; + s << ntr("%d day", "%d days", num, num) << ", "; seconds -= num * 86400; } if ((num = seconds / 3600) > 0) { - s << num << " " << tr("hour", "hours", num) << ", "; + s << ntr("%d hour", "%d hours", num, num) << ", "; seconds -= num * 3600; } if ((num = seconds / 60) > 0) { - s << num << " " << tr("minute", "minutes", num) << ", "; + s << ntr("%d minute", "%d minutes", num, num) << ", "; seconds -= num * 60; } - s << seconds << " " << tr("second", "seconds", seconds); + s << ntr("%d second", "%d seconds", seconds, seconds); } static void ShowTraffic (std::stringstream& s, uint64_t bytes) @@ -122,11 +122,11 @@ namespace http { s << std::fixed << std::setprecision(2); auto numKBytes = (double) bytes / 1024; if (numKBytes < 1024) - s << numKBytes << " " << tr(/* tr: Kibibit */ "KiB"); + s << tr(/* tr: Kibibyte */ "%.2f KiB", numKBytes); else if (numKBytes < 1024 * 1024) - s << numKBytes / 1024 << " " << tr(/* tr: Mebibit */ "MiB"); + s << tr(/* tr: Mebibyte */ "%.2f MiB", numKBytes / 1024); else - s << numKBytes / 1024 / 1024 << " " << tr(/* tr: Gibibit */ "GiB"); + s << tr(/* tr: Gibibyte */ "%.2f GiB", numKBytes / 1024 / 1024); } static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) @@ -150,7 +150,7 @@ namespace http { else stateText = tr("unknown"); s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; - s << " " << (int) (bytes / 1024) << " " << tr(/* tr: Kibibit */ "KiB") << "\r\n"; + s << " " << tr(/* tr: Kibibit */ "%.2f KiB", (double) bytes / 1024) << "\r\n"; } static void SetLogLevel (const std::string& level) @@ -247,7 +247,7 @@ namespace http { break; case eRouterErrorFullConeNAT: s << " - " << tr("Full cone NAT"); - break; + break; case eRouterErrorNoDescriptors: s << " - " << tr("No Descriptors"); break; @@ -290,13 +290,13 @@ namespace http { s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; s << "" << tr("Received") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); - s << " (" << (double) i2p::transport::transports.GetInBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; + s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Sent") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ()); - s << " (" << (double) i2p::transport::transports.GetOutBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; + s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Transit") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ()); - s << " (" << (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; + s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Data path") << ": " << i2p::fs::GetUTF8DataDir() << "
\r\n"; s << "
"; if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { @@ -338,7 +338,7 @@ namespace http { s << "" << address->host.to_string() << ":" << address->port << "\r\n"; else { - s << "" << tr("supported"); + s << "" << tr(/* tr: Shown when router doesn't publish itself and have "Firewalled" state */ "supported"); if (address->port) s << " :" << address->port; s << "\r\n"; @@ -466,7 +466,7 @@ namespace http { } s << "⇒ " << it->GetTunnelID () << ":me"; if (it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )"; + s << " ( " << tr(/* tr: Milliseconds */ "%dms", it->GetMeanLatency()) << " )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ()); s << "
\r\n"; } @@ -486,22 +486,26 @@ namespace http { ); } if (it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr("ms") << " )"; + s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ()); s << "\r\n"; } } s << "
\r\n"; - s << "" << tr("Tags") << "
\r\n" << tr("Incoming") << ": " << dest->GetNumIncomingTags () << "
\r\n"; + s << "" << tr("Tags") << "
\r\n" + << tr("Incoming") << ": " << dest->GetNumIncomingTags () << "
\r\n"; if (!dest->GetSessions ().empty ()) { std::stringstream tmp_s; uint32_t out_tags = 0; for (const auto& it: dest->GetSessions ()) { tmp_s << "" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "" << it.second->GetNumOutgoingTags () << "\r\n"; out_tags += it.second->GetNumOutgoingTags (); } - s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
" << tr("Destination") << "" << tr("Amount") << "
\r\n
\r\n
\r\n"; + s << "
\r\n" + << "\r\n" + << "
\r\n" + << "\r\n\r\n" + << "\r\n" << tmp_s.str () << "
" << tr("Destination") << "" << tr("Amount") << "
\r\n
\r\n
\r\n"; } else s << tr("Outgoing") << ": 0
\r\n"; s << "
\r\n"; @@ -516,8 +520,11 @@ namespace http { tmp_s << "" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "" << it.second->GetState () << "\r\n"; ecies_sessions++; } - s << "
\r\n\r\n" - << "
\r\n\r\n\r\n\r\n" << tmp_s.str () << "
" << tr("Destination") << "" << tr("Status") << "
\r\n
\r\n
\r\n"; + s << "
\r\n" + << "\r\n" + << "
\r\n\r\n" + << "\r\n" + << "\r\n" << tmp_s.str () << "
" << tr("Destination") << "" << tr("Status") << "
\r\n
\r\n
\r\n"; } else s << tr("Tags sessions") << ": 0
\r\n"; s << "
\r\n"; @@ -671,7 +678,7 @@ namespace http { } s << "⇒ " << it->GetTunnelID () << ":me"; if (it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr("ms") << " )"; + s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ()); s << "\r\n"; } @@ -691,7 +698,7 @@ namespace http { ); } if (it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr("ms") << " )"; + s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ()); s << "\r\n"; } diff --git a/i18n/Afrikaans.cpp b/i18n/Afrikaans.cpp index 5860facf..b582a06a 100644 --- a/i18n/Afrikaans.cpp +++ b/i18n/Afrikaans.cpp @@ -64,10 +64,10 @@ namespace afrikaans // language namespace static std::map> plurals { - {"days", {"dag", "dae"}}, - {"hours", {"uur", "ure"}}, - {"minutes", {"minuut", "minute"}}, - {"seconds", {"seconde", "sekondes"}}, + {"%d days", {"%d dag", "%d dae"}}, + {"%d hours", {"%d uur", "%d ure"}}, + {"%d minutes", {"%d minuut", "%d minute"}}, + {"%d seconds", {"%d seconde", "%d sekondes"}}, {"", {"", ""}}, }; diff --git a/i18n/Armenian.cpp b/i18n/Armenian.cpp index 586e7579..a18d35fc 100644 --- a/i18n/Armenian.cpp +++ b/i18n/Armenian.cpp @@ -31,9 +31,9 @@ namespace armenian // language namespace static std::map strings { - {"KiB", "ԿիԲ"}, - {"MiB", "ՄիԲ"}, - {"GiB", "ԳիԲ"}, + {"%.2f KiB", "%.2f ԿիԲ"}, + {"%.2f MiB", "%.2f ՄիԲ"}, + {"%.2f GiB", "%.2f ԳիԲ"}, {"building", "կառուցվում է"}, {"failed", "Անհաջող"}, {"expiring", "Լրանում է"}, @@ -68,7 +68,7 @@ namespace armenian // language namespace {"Family", "Խմբատեսակ"}, {"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"}, {"Received", "Ստացվել է"}, - {"KiB/s", "ԿիԲ/վ"}, + {"%.2f KiB/s", "%.2f ԿիԲ/վ"}, {"Sent", "Ուղարկվել է"}, {"Transit", "Տարանցում"}, {"Data path", "Տվյալների ուղին"}, @@ -94,7 +94,7 @@ namespace armenian // language namespace {"Type", "Տեսակը"}, {"EncType", "Գաղտնագրի տեսակը"}, {"Inbound tunnels", "Մուտքային թունելներ"}, - {"ms", "մլվ"}, + {"%dms", "%dմլվ"}, {"Outbound tunnels", "Ելքային թունելներ"}, {"Tags", "Թեգեր"}, {"Incoming", "Մուտքային"}, @@ -198,10 +198,10 @@ namespace armenian // language namespace static std::map> plurals { - {"days", {"օր", "օր"}}, - {"hours", {"ժամ", "ժամ"}}, - {"minutes", {"րոպե", "րոպե"}}, - {"seconds", {"վարկյան", "վարկյան"}}, + {"%d days", {"%d օր", "%d օր"}}, + {"%d hours", {"%d ժամ", "%d ժամ"}}, + {"%d minutes", {"%d րոպե", "%d րոպե"}}, + {"%d seconds", {"%d վարկյան", "%d վարկյան"}}, {"", {"", ""}}, }; diff --git a/i18n/Chinese.cpp b/i18n/Chinese.cpp index 2f6c14e2..8a554a11 100644 --- a/i18n/Chinese.cpp +++ b/i18n/Chinese.cpp @@ -32,9 +32,9 @@ namespace chinese // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "正在构建"}, {"failed", "连接失败"}, {"expiring", "即将过期"}, @@ -70,7 +70,7 @@ namespace chinese // language namespace {"Family", "家族"}, {"Tunnel creation success rate", "隧道创建成功率"}, {"Received", "已接收"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "已发送"}, {"Transit", "中转"}, {"Data path", "数据文件路径"}, @@ -96,7 +96,7 @@ namespace chinese // language namespace {"Type", "类型"}, {"EncType", "加密类型"}, {"Inbound tunnels", "入站隧道"}, - {"ms", "毫秒"}, + {"%dms", "%d毫秒"}, {"Outbound tunnels", "出站隧道"}, {"Tags", "标签"}, {"Incoming", "传入"}, @@ -200,10 +200,10 @@ namespace chinese // language namespace static std::map> plurals { - {"days", {"日"}}, - {"hours", {"时"}}, - {"minutes", {"分"}}, - {"seconds", {"秒"}}, + {"%d days", {"%d 日"}}, + {"%d hours", {"%d 时"}}, + {"%d minutes", {"%d 分"}}, + {"%d seconds", {"%d 秒"}}, {"", {""}}, }; diff --git a/i18n/Czech.cpp b/i18n/Czech.cpp index f6ac7188..93862053 100644 --- a/i18n/Czech.cpp +++ b/i18n/Czech.cpp @@ -31,9 +31,9 @@ namespace czech // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "vytváří se"}, {"failed", "selhalo"}, {"expiring", "končící"}, @@ -69,7 +69,7 @@ namespace czech // language namespace {"Family", "Rodina"}, {"Tunnel creation success rate", "Úspěšnost vytváření tunelů"}, {"Received", "Přijato"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Odesláno"}, {"Transit", "Tranzit"}, {"Data path", "Cesta k data souborům"}, @@ -95,7 +95,7 @@ namespace czech // language namespace {"Type", "Typ"}, {"EncType", "EncType"}, {"Inbound tunnels", "Příchozí tunely"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Odchozí tunely"}, {"Tags", "Štítky"}, {"Incoming", "Příchozí"}, @@ -199,10 +199,10 @@ namespace czech // language namespace static std::map> plurals { - {"days", {"den", "dny", "dní", "dní"}}, - {"hours", {"hodina", "hodiny", "hodin", "hodin"}}, - {"minutes", {"minuta", "minuty", "minut", "minut"}}, - {"seconds", {"vteřina", "vteřiny", "vteřin", "vteřin"}}, + {"%d days", {"%d den", "%d dny", "%d dní", "%d dní"}}, + {"%d hours", {"%d hodina", "%d hodiny", "%d hodin", "%d hodin"}}, + {"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}}, + {"%d seconds", {"%d vteřina", "%d vteřiny", "%d vteřin", "%d vteřin"}}, {"", {"", "", "", ""}}, }; diff --git a/i18n/French.cpp b/i18n/French.cpp index 1a49ddfc..0d32c5c2 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -31,9 +31,9 @@ namespace french // language namespace static std::map strings { - {"KiB", "Kio"}, - {"MiB", "Mio"}, - {"GiB", "Gio"}, + {"%.2f KiB", "%.2f Kio"}, + {"%.2f MiB", "%.2f Mio"}, + {"%.2f GiB", "%.2f Gio"}, {"building", "En construction"}, {"failed", "échoué"}, {"expiring", "expiré"}, @@ -69,7 +69,7 @@ namespace french // language namespace {"Family", "Famille"}, {"Tunnel creation success rate", "Taux de succès de création de tunnels"}, {"Received", "Reçu"}, - {"KiB/s", "kio/s"}, + {"%.2f KiB/s", "%.2f kio/s"}, {"Sent", "Envoyé"}, {"Transit", "Transité"}, {"Data path", "Emplacement des données"}, @@ -93,7 +93,7 @@ namespace french // language namespace {"Address", "Adresse"}, {"Type", "Type"}, {"Inbound tunnels", "Tunnels entrants"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, {"Tags", "Balises"}, {"Incoming", "Entrant"}, @@ -194,10 +194,10 @@ namespace french // language namespace static std::map> plurals { - {"days", {"jour", "jours"}}, - {"hours", {"heure", "heures"}}, - {"minutes", {"minute", "minutes"}}, - {"seconds", {"seconde", "secondes"}}, + {"%d days", {"%d jour", "%d jours"}}, + {"%d hours", {"%d heure", "%d heures"}}, + {"%d minutes", {"%d minute", "%d minutes"}}, + {"%d seconds", {"%d seconde", "%d secondes"}}, {"", {"", ""}}, }; diff --git a/i18n/German.cpp b/i18n/German.cpp index 489a93a7..ca669436 100644 --- a/i18n/German.cpp +++ b/i18n/German.cpp @@ -31,9 +31,9 @@ namespace german // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "In Bau"}, {"failed", "fehlgeschlagen"}, {"expiring", "läuft ab"}, @@ -69,7 +69,7 @@ namespace german // language namespace {"Family", "Familie"}, {"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"}, {"Received", "Eingegangen"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Gesendet"}, {"Transit", "Transit"}, {"Data path", "Datenpfad"}, @@ -95,7 +95,7 @@ namespace german // language namespace {"Type", "Typ"}, {"EncType", "Verschlüsselungstyp"}, {"Inbound tunnels", "Eingehende Tunnel"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Ausgehende Tunnel"}, {"Tags", "Tags"}, {"Incoming", "Eingehend"}, @@ -199,10 +199,10 @@ namespace german // language namespace static std::map> plurals { - {"days", {"Tag", "Tage"}}, - {"hours", {"Stunde", "Stunden"}}, - {"minutes", {"Minute", "Minuten"}}, - {"seconds", {"Sekunde", "Sekunden"}}, + {"%d days", {"%d Tag", "%d Tage"}}, + {"%d hours", {"%d Stunde", "%d Stunden"}}, + {"%d minutes", {"%d Minute", "%d Minuten"}}, + {"%d seconds", {"%d Sekunde", "%d Sekunden"}}, {"", {"", ""}}, }; diff --git a/i18n/I18N.h b/i18n/I18N.h index 27e043b9..2489ddcf 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -67,17 +67,71 @@ namespace i18n const std::map> m_Plurals; std::function m_Formula; }; - + void SetLanguage(const std::string &lang); std::string translate (const std::string& arg); std::string translate (const std::string& arg, const std::string& arg2, const int& n); } // i18n } // i2p -template -std::string tr (TArgs&&... args) +/** + * @brief Get translation of string + * @param arg String with message + */ +template +std::string tr (TValue&& arg) { - return i2p::i18n::translate(std::forward(args)...); + return i2p::i18n::translate(std::forward(arg)); +} + +/** + * @brief Get translation of string and format it + * @param arg String with message + * @param args Array of arguments for string formatting +*/ +template +std::string tr (TValue&& arg, TArgs&&... args) +{ + std::string tr_str = i2p::i18n::translate(std::forward(arg)); + + size_t size = snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); + size = size + 1; + std::string str(size, 0); + snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + + return str; +} + +/** + * @brief Get translation of string with plural forms + * @param arg String with message in singular form + * @param arg2 String with message in plural form + * @param n Integer, used for selection of form + */ +template +std::string ntr (TValue&& arg, TValue2&& arg2, int& n) +{ + return i2p::i18n::translate(std::forward(arg), std::forward(arg2), std::forward(n)); +} + +/** + * @brief Get translation of string with plural forms and format it + * @param arg String with message in singular form + * @param arg2 String with message in plural form + * @param n Integer, used for selection of form + * @param args Array of arguments for string formatting + */ +template +std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args) +{ + std::string tr_str = i2p::i18n::translate(std::forward(arg), std::forward(arg2), std::forward(n)); + + size_t size = snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); + size = size + 1; + std::string str(size, 0); + snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + + return str; } #endif // __I18N_H__ diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index ef2e26d0..07e436d7 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -31,9 +31,9 @@ namespace italian // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "in costruzione"}, {"failed", "fallito"}, {"expiring", "in scadenza"}, @@ -69,7 +69,7 @@ namespace italian // language namespace {"Family", "Famiglia"}, {"Tunnel creation success rate", "Percentuale di tunnel creati con successo"}, {"Received", "Ricevuti"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Inviati"}, {"Transit", "Transitati"}, {"Data path", "Percorso dati"}, @@ -95,7 +95,7 @@ namespace italian // language namespace {"Type", "Tipologia"}, {"EncType", "Tipo di crittografia"}, {"Inbound tunnels", "Tunnel in entrata"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Tunnel in uscita"}, {"Tags", "Tag"}, {"Incoming", "In entrata"}, @@ -199,10 +199,10 @@ namespace italian // language namespace static std::map> plurals { - {"days", {"giorno", "giorni"}}, - {"hours", {"ora", "ore"}}, - {"minutes", {"minuto", "minuti"}}, - {"seconds", {"secondo", "secondi"}}, + {"%d days", {"%d giorno", "%d giorni"}}, + {"%d hours", {"%d ora", "%d ore"}}, + {"%d minutes", {"%d minuto", "%d minuti"}}, + {"%d seconds", {"%d secondo", "%d secondi"}}, {"", {"", ""}}, }; diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index d7616e9e..7d875f01 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -31,9 +31,9 @@ namespace russian // language namespace static std::map strings { - {"KiB", "КиБ"}, - {"MiB", "МиБ"}, - {"GiB", "ГиБ"}, + {"%.2f KiB", "%.2f КиБ"}, + {"%.2f MiB", "%.2f МиБ"}, + {"%.2f GiB", "%.2f ГиБ"}, {"building", "строится"}, {"failed", "неудачный"}, {"expiring", "истекает"}, @@ -68,7 +68,7 @@ namespace russian // language namespace {"Family", "Семейство"}, {"Tunnel creation success rate", "Успешно построенных туннелей"}, {"Received", "Получено"}, - {"KiB/s", "КиБ/с"}, + {"%.2f KiB/s", "%.2f КиБ/с"}, {"Sent", "Отправлено"}, {"Transit", "Транзит"}, {"Data path", "Путь к данным"}, @@ -94,7 +94,7 @@ namespace russian // language namespace {"Type", "Тип"}, {"EncType", "ТипШифр"}, {"Inbound tunnels", "Входящие туннели"}, - {"ms", "мс"}, + {"%dms", "%dмс"}, {"Outbound tunnels", "Исходящие туннели"}, {"Tags", "Теги"}, {"Incoming", "Входящие"}, @@ -198,10 +198,10 @@ namespace russian // language namespace static std::map> plurals { - {"days", {"день", "дня", "дней"}}, - {"hours", {"час", "часа", "часов"}}, - {"minutes", {"минуту", "минуты", "минут"}}, - {"seconds", {"секунду", "секунды", "секунд"}}, + {"%d days", {"%d день", "%d дня", "%d дней"}}, + {"%d hours", {"%d час", "%d часа", "%d часов"}}, + {"%d minutes", {"%d минуту", "%d минуты", "%d минут"}}, + {"%d seconds", {"%d секунду", "%d секунды", "%d секунд"}}, {"", {"", "", ""}}, }; diff --git a/i18n/Spanish.cpp b/i18n/Spanish.cpp index a2f53927..8b0e927a 100644 --- a/i18n/Spanish.cpp +++ b/i18n/Spanish.cpp @@ -31,9 +31,9 @@ namespace spanish // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "pendiente"}, {"failed", "fallido"}, {"expiring", "expiró"}, @@ -69,7 +69,7 @@ namespace spanish // language namespace {"Family", "Familia"}, {"Tunnel creation success rate", "Tasa de éxito de creación de túneles"}, {"Received", "Recibido"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Enviado"}, {"Transit", "Tránsito"}, {"Data path", "Ruta de datos"}, @@ -95,7 +95,7 @@ namespace spanish // language namespace {"Type", "Tipo"}, {"EncType", "TipoEncrip"}, {"Inbound tunnels", "Túneles entrantes"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Túneles salientes"}, {"Tags", "Etiquetas"}, {"Incoming", "Entrante"}, @@ -199,10 +199,10 @@ namespace spanish // language namespace static std::map> plurals { - {"days", {"día", "días"}}, - {"hours", {"hora", "horas"}}, - {"minutes", {"minuto", "minutos"}}, - {"seconds", {"segundo", "segundos"}}, + {"%d days", {"%d día", "%d días"}}, + {"%d hours", {"%d hora", "%d horas"}}, + {"%d minutes", {"%d minuto", "%d minutos"}}, + {"%d seconds", {"%d segundo", "%d segundos"}}, {"", {"", ""}}, }; diff --git a/i18n/Turkmen.cpp b/i18n/Turkmen.cpp index 356ada85..7e7a24f0 100644 --- a/i18n/Turkmen.cpp +++ b/i18n/Turkmen.cpp @@ -31,9 +31,9 @@ namespace turkmen // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "bina"}, {"failed", "şowsuz"}, {"expiring", "möhleti gutarýar"}, @@ -68,7 +68,7 @@ namespace turkmen // language namespace {"Family", "Maşgala"}, {"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"}, {"Received", "Alnan"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Ýerleşdirildi"}, {"Transit", "Tranzit"}, {"Data path", "Maglumat ýoly"}, @@ -94,7 +94,7 @@ namespace turkmen // language namespace {"Type", "Görnüş"}, {"EncType", "Şifrlemek görnüşi"}, {"Inbound tunnels", "Gelýän tuneller"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Çykýan tuneller"}, {"Tags", "Bellikler"}, {"Incoming", "Gelýän"}, @@ -198,10 +198,10 @@ namespace turkmen // language namespace static std::map> plurals { - {"days", {"gün", "gün"}}, - {"hours", {"sagat", "sagat"}}, - {"minutes", {"minut", "minut"}}, - {"seconds", {"sekunt", "sekunt"}}, + {"%d days", {"%d gün", "%d gün"}}, + {"%d hours", {"%d sagat", "%d sagat"}}, + {"%d minutes", {"%d minut", "%d minut"}}, + {"%d seconds", {"%d sekunt", "%d sekunt"}}, {"", {"", ""}}, }; diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index abbe8f81..991f46ab 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -31,9 +31,9 @@ namespace ukrainian // language namespace static std::map strings { - {"KiB", "КіБ"}, - {"MiB", "МіБ"}, - {"GiB", "ГіБ"}, + {"%.2f KiB", "%.2f КіБ"}, + {"%.2f MiB", "%.2f МіБ"}, + {"%.2f GiB", "%.2f ГіБ"}, {"building", "будується"}, {"failed", "невдалий"}, {"expiring", "завершується"}, @@ -68,7 +68,7 @@ namespace ukrainian // language namespace {"Family", "Сімейство"}, {"Tunnel creation success rate", "Успішно побудованих тунелів"}, {"Received", "Отримано"}, - {"KiB/s", "КіБ/с"}, + {"%.2f KiB/s", "%.2f КіБ/с"}, {"Sent", "Відправлено"}, {"Transit", "Транзит"}, {"Data path", "Шлях до даних"}, @@ -94,7 +94,7 @@ namespace ukrainian // language namespace {"Type", "Тип"}, {"EncType", "ТипШифр"}, {"Inbound tunnels", "Вхідні тунелі"}, - {"ms", "мс"}, + {"%dms", "%dмс"}, {"Outbound tunnels", "Вихідні тунелі"}, {"Tags", "Теги"}, {"Incoming", "Вхідні"}, @@ -198,10 +198,10 @@ namespace ukrainian // language namespace static std::map> plurals { - {"days", {"день", "дня", "днів"}}, - {"hours", {"годину", "години", "годин"}}, - {"minutes", {"хвилину", "хвилини", "хвилин"}}, - {"seconds", {"секунду", "секунди", "секунд"}}, + {"%d days", {"%d день", "%d дня", "%d днів"}}, + {"%d hours", {"%d годину", "%d години", "%d годин"}}, + {"%d minutes", {"%d хвилину", "%d хвилини", "%d хвилин"}}, + {"%d seconds", {"%d секунду", "%d секунди", "%d секунд"}}, {"", {"", "", ""}}, }; diff --git a/i18n/Uzbek.cpp b/i18n/Uzbek.cpp index e750918f..7355471b 100644 --- a/i18n/Uzbek.cpp +++ b/i18n/Uzbek.cpp @@ -31,9 +31,9 @@ namespace uzbek // language namespace static std::map strings { - {"KiB", "KiB"}, - {"MiB", "MiB"}, - {"GiB", "GiB"}, + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, {"building", "yaratilmoqda"}, {"failed", "muvaffaqiyatsiz"}, {"expiring", "muddati tugaydi"}, @@ -68,7 +68,7 @@ namespace uzbek // language namespace {"Family", "Oila"}, {"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"}, {"Received", "Qabul qilindi"}, - {"KiB/s", "KiB/s"}, + {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Yuborilgan"}, {"Transit", "Tranzit"}, {"Data path", "Ma'lumotlar joylanishi"}, @@ -94,7 +94,7 @@ namespace uzbek // language namespace {"Type", "Turi"}, {"EncType", "ShifrlashTuri"}, {"Inbound tunnels", "Kirish tunnellari"}, - {"ms", "ms"}, + {"%dms", "%dms"}, {"Outbound tunnels", "Chiquvchi tunnellar"}, {"Tags", "Teglar"}, {"Incoming", "Kiruvchi"}, @@ -198,10 +198,10 @@ namespace uzbek // language namespace static std::map> plurals { - {"days", {"kun", "kun"}}, - {"hours", {"soat", "soat"}}, - {"minutes", {"daqiqa", "daqiqa"}}, - {"seconds", {"soniya", "soniya"}}, + {"%d days", {"%d kun", "%d kun"}}, + {"%d hours", {"%d soat", "%d soat"}}, + {"%d minutes", {"%d daqiqa", "%d daqiqa"}}, + {"%d seconds", {"%d soniya", "%d soniya"}}, {"", {"", ""}}, }; From d68c7f8ea7d7f49d241d890111be44524097d56c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 18 Jan 2023 08:19:45 +0300 Subject: [PATCH 079/179] [i18n] fix build on macos Signed-off-by: R4SAS --- i18n/I18N.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/I18N.h b/i18n/I18N.h index 2489ddcf..4217a384 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -94,10 +94,10 @@ std::string tr (TValue&& arg, TArgs&&... args) { std::string tr_str = i2p::i18n::translate(std::forward(arg)); - size_t size = snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); + size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); size = size + 1; std::string str(size, 0); - snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); return str; } @@ -126,10 +126,10 @@ std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args) { std::string tr_str = i2p::i18n::translate(std::forward(arg), std::forward(arg2), std::forward(n)); - size_t size = snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); + size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); size = size + 1; std::string str(size, 0); - snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); return str; } From 88dfe3ca4ea3273917badf4b5e28cd93b1348bc5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 18 Jan 2023 18:56:21 +0300 Subject: [PATCH 080/179] [i18n] fix build on macos Signed-off-by: R4SAS --- i18n/I18N.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/I18N.h b/i18n/I18N.h index 4217a384..9b413222 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -97,7 +97,7 @@ std::string tr (TValue&& arg, TArgs&&... args) size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); size = size + 1; std::string str(size, 0); - std::snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(&str.front(), size, tr_str.c_str(), std::forward(args)...); return str; } @@ -129,7 +129,7 @@ std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args) size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); size = size + 1; std::string str(size, 0); - std::snprintf(str.data(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(&str.front(), size, tr_str.c_str(), std::forward(args)...); return str; } From a57ae4dc5693bc97d57fd16717d369bd376b723f Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Jan 2023 05:53:29 +0300 Subject: [PATCH 081/179] [i18n] add sweedish translation Translation author: corona@mail.i2p Signed-off-by: R4SAS --- Win32/DaemonWin32.cpp | 6 +- i18n/I18N.h | 2 +- i18n/I18N_langs.h | 2 + i18n/Swedish.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 4 deletions(-) create mode 100644 i18n/Swedish.cpp diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index 0badf802..affc301a 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -29,7 +29,7 @@ namespace util setlocale(LC_CTYPE, ""); SetConsoleCP(1251); SetConsoleOutputCP(1251); - setlocale(LC_ALL, "Russian"); + //setlocale(LC_ALL, "Russian"); setlocale(LC_TIME, "C"); i2p::log::SetThrowFunction ([](const std::string& s) @@ -61,7 +61,7 @@ namespace util setlocale(LC_CTYPE, ""); SetConsoleCP(1251); SetConsoleOutputCP(1251); - setlocale(LC_ALL, "Russian"); + //setlocale(LC_ALL, "Russian"); setlocale(LC_TIME, "C"); #ifdef WIN32_APP if (!i2p::win32::StartWin32App ()) return false; diff --git a/i18n/I18N.h b/i18n/I18N.h index 9b413222..395c18eb 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 9a236d7a..51e23b19 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -33,6 +33,7 @@ namespace i18n namespace italian { std::shared_ptr GetLocale (); } namespace russian { std::shared_ptr GetLocale (); } namespace spanish { std::shared_ptr GetLocale (); } + namespace swedish { std::shared_ptr GetLocale (); } namespace turkmen { std::shared_ptr GetLocale (); } namespace ukrainian { std::shared_ptr GetLocale (); } namespace uzbek { std::shared_ptr GetLocale (); } @@ -52,6 +53,7 @@ namespace i18n { "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} }, { "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} }, { "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} }, + { "swedish", {"Svenska", "sv", i2p::i18n::swedish::GetLocale} }, { "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} }, { "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} }, { "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} }, diff --git a/i18n/Swedish.cpp b/i18n/Swedish.cpp new file mode 100644 index 00000000..180f74aa --- /dev/null +++ b/i18n/Swedish.cpp @@ -0,0 +1,217 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Swedish localization file + +namespace i2p +{ +namespace i18n +{ +namespace swedish // language namespace +{ + // language name in lowercase + static std::string language = "swedish"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return n != 1 ? 1 : 0; + } + + static std::map strings + { + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, + {"building", "bygger"}, + {"failed", "misslyckad"}, + {"expiring", "utgår"}, + {"established", "upprättad"}, + {"unknown", "okänt"}, + {"exploratory", "utforskande"}, + {"Purple I2P Webconsole", "Purple I2P Webbkonsoll"}, + {"i2pd webbkonsoll", "i2pd-Webbkonsoll"}, + {"Main page", "Huvudsida"}, + {"Router commands", "Routerkommandon"}, + {"Local Destinations", "Lokala Platser"}, + {"LeaseSets", "Hyresuppsättningar"}, + {"Tunnels", "Tunnlar"}, + {"Transit Tunnels", "Förmedlande Tunnlar"}, + {"Transports", "Transporter"}, + {"I2P tunnels", "I2P-tunnlar"}, + {"SAM sessions", "SAM-perioder"}, + {"ERROR", "FEL"}, + {"OK", "OK"}, + {"Testing", "Prövar"}, + {"Firewalled", "Bakom Brandvägg"}, + {"Unknown", "Okänt"}, + {"Proxy", "Proxy"}, + {"Mesh", "Mesh"}, + {"Error", "Fel"}, + {"Clock skew", "Tidsförskjutning"}, + {"Offline", "Nedkopplad"}, + {"Symmetric NAT", "Symmetrisk NAT"}, + {"Uptime", "Upptid"}, + {"Network status", "Nätverkstillstånd"}, + {"Network status v6", "Nätverkstillstånd v6"}, + {"Stopping in", "Avstängd om"}, + {"Family", "Familj"}, + {"Tunnel creation success rate", "Andel framgångsrika tunnlar"}, + {"Received", "Mottaget"}, + {"%.2f KiB/s", "%.2f KiB/s"}, + {"Sent", "Skickat"}, + {"Transit", "Förmedlat"}, + {"Data path", "Sökväg"}, + {"Hidden content. Press on text to see.", "Dolt innehåll. Tryck för att visa."}, + {"Router Ident", "Routeridentitet"}, + {"Router Family", "Routerfamilj"}, + {"Router Caps", "Routerbegränsningar"}, + {"Version", "Version"}, + {"Our external address", "Vår externa adress"}, + {"supported", "stöds"}, + {"Routers", "Routrar"}, + {"Floodfills", "Översvämningsfyllare"}, + {"Client Tunnels", "Klienttunnlar"}, + {"Services", "Tjänster"}, + {"Enabled", "Påslaget"}, + {"Disabled", "Avslaget"}, + {"Encrypted B33 address", "Krypterad B33-Adress"}, + {"Address registration line", "Adressregistreringsrad"}, + {"Domain", "Domän"}, + {"Generate", "Skapa"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Uppmärksamma: den resulterande strängen kan enbart användas för att registrera 2LD-domäner (exempel.i2p). För att registrera underdomäner, vänligen använd i2pd-tools."}, + {"Address", "Adress"}, + {"Type", "Typ"}, + {"EncType", "EncTyp"}, + {"Inbound tunnels", "Ingående Tunnlar"}, + {"%dms", "%dms"}, + {"Outbound tunnels", "Utgående Tunnlar"}, + {"Tags", "Taggar"}, + {"Incoming", "Ingående"}, + {"Outgoing", "Utgående"}, + {"Destination", "Plats"}, + {"Amount", "Mängd"}, + {"Incoming Tags", "Ingående Taggar"}, + {"Tags sessions", "Tagg-perioder"}, + {"Status", "Tillstånd"}, + {"Local Destination", "Lokal Plats"}, + {"Streams", "Strömmar"}, + {"Close stream", "Stäng strömmen"}, + {"I2CP session not found", "I2CP-period hittades inte"}, + {"I2CP is not enabled", "I2CP är inte påslaget"}, + {"Invalid", "Ogiltig"}, + {"Store type", "Lagringstyp"}, + {"Expires", "Utgångsdatum"}, + {"Non Expired Leases", "Ickeutgångna Hyresuppsättningar"}, + {"Gateway", "Gateway"}, + {"TunnelID", "TunnelID"}, + {"EndDate", "EndDate"}, + {"not floodfill", "inte Översvämningsfyllare"}, + {"Queue size", "Köstorlek"}, + {"Run peer test", "Utför utsiktstest"}, + {"Decline transit tunnels", "Avvisa förmedlande tunnlar"}, + {"Accept transit tunnels", "Tillåt förmedlande tunnlar"}, + {"Cancel graceful shutdown", "Avbryt välvillig avstängning"}, + {"Start graceful shutdown", "Påbörja välvillig avstängning"}, + {"Force shutdown", "Tvingad avstängning"}, + {"Reload external CSS styles", "Ladda om externa CSS-stilar"}, + {"Note: any action done here are not persistent and not changes your config files.", "Uppmärksamma: inga ändringar här är beständiga eller påverkar dina inställningsfiler."}, + {"Logging level", "Protokollförningsnivå"}, + {"Transit tunnels limit", "Begränsa förmedlande tunnlar"}, + {"Change", "Ändra"}, + {"Change language", "Ändra språk"}, + {"no transit tunnels currently built", "inga förmedlande tunnlar har byggts"}, + {"SAM disabled", "SAM avslaget"}, + {"no sessions currently running", "inga perioder igång"}, + {"SAM session not found", "SAM-perioder hittades ej"}, + {"SAM Session", "SAM-period"}, + {"Server Tunnels", "Värdtunnlar"}, + {"Client Forwards", "Klientförpassningar"}, + {"Server Forwards", "Värdförpassningar"}, + {"Unknown page", "Okänd sida"}, + {"Invalid token", "Ogiltig polett"}, + {"SUCCESS", "FRAMGÅNG"}, + {"Stream closed", "Ström stängd"}, + {"Stream not found or already was closed", "Strömmen hittades inte eller var redan avslutad"}, + {"Destination not found", "Plats hittades ej"}, + {"StreamID can't be null", "Ström-ID kan inte vara null"}, + {"Return to destination page", "Återvänd till platssidan"}, + {"You will be redirected in 5 seconds", "Du omdirigeras inom fem sekunder"}, + {"Transit tunnels count must not exceed 65535", "Förmedlande tunnlar får inte överstiga 65535"}, + {"Back to commands list", "Tillbaka till kommandolistan"}, + {"Register at reg.i2p", "Registrera vid reg.i2p"}, + {"Description", "Beskrivning"}, + {"A bit information about service on domain", "Ett stycke information om domänens tjänst"}, + {"Submit", "Skicka"}, + {"Domain can't end with .b32.i2p", "Domänen får inte sluta med .b32.i2p"}, + {"Domain must end with .i2p", "Domänen måste sluta med .i2p"}, + {"Such destination is not found", "En sådan plats hittas ej"}, + {"Unknown command", "Okänt kommando"}, + {"Command accepted", "Kommando accepterades"}, + {"Proxy error", "Proxyfel"}, + {"Proxy info", "Proxyinfo"}, + {"Proxy error: Host not found", "Proxyfel: Värden hittades ej"}, + {"Remote host not found in router's addressbook", "Främmande värd hittades inte i routerns adressbok"}, + {"You may try to find this host on jump services below", "Du kan försöka att hitta värden genom hopptjänsterna nedan"}, + {"Invalid request", "Ogiltig förfrågan"}, + {"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"}, + {"addresshelper is not supported", "adresshjälparen stöds ej"}, + {"Host", "Värd"}, + {"added to router's addressbook from helper", "tillagd i routerns adressbok från adresshjälparen"}, + {"Click here to proceed:", "Tryck här för att fortsätta:"}, + {"Continue", "Fortsätt"}, + {"Addresshelper found", "Adresshjälpare hittad"}, + {"already in router's addressbook", "finns redan i routerns adressbok"}, + {"Click here to update record:", "Tryck här för att uppdatera:"}, + {"invalid request uri", "ogiltig förfrågnings-URI"}, + {"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"}, + {"Outproxy failure", "Utproxyfel"}, + {"bad outproxy settings", "ogiltig utproxyinställning"}, + {"not inside I2P network, but outproxy is not enabled", "adressen är inte inom I2P-näverket, men utproxy är inte påslaget"}, + {"unknown outproxy url", "okänt Utproxy-URL"}, + {"cannot resolve upstream proxy", "hittar inte uppströmsproxyt"}, + {"hostname too long", "värdnamnet är för långt"}, + {"cannot connect to upstream socks proxy", "kan inte ansluta till uppströmsproxyt"}, + {"Cannot negotiate with socks proxy", "Kan inte förhandla med socksproxyt"}, + {"CONNECT error", "CONNECT-fel"}, + {"Failed to Connect", "Anslutningen misslyckades"}, + {"socks proxy error", "Socksproxyfel"}, + {"failed to send request to upstream", "förfrågan uppströms kunde ej skickas"}, + {"No Reply From socks proxy", "Fick inget svar från socksproxyt"}, + {"cannot connect", "kan inte ansluta"}, + {"http out proxy not implemented", "HTTP-Utproxy ej implementerat"}, + {"cannot connect to upstream http proxy", "Kan inte ansluta till uppströms HTTP-proxy"}, + {"Host is down", "Värden är nere"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Kan inte ansluta till värden, den kan vara nere. Vänligen försök senare."}, + {"", ""}, + }; + + static std::map> plurals + { + {"%d days", {"%d Dag", "%d Dagar"}}, + {"%d hours", {"%d Timme", "%d Timmar"}}, + {"%d minutes", {"%d Minut", "%d Minuter"}}, + {"%d seconds", {"%d Sekund", "%d Sekunder"}}, + {"", {"", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p + From 533c8a8a55665acd4e71b792d5c4db4c45296407 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Jan 2023 06:40:32 +0300 Subject: [PATCH 082/179] [i18n] set decimal point based on language Signed-off-by: R4SAS --- i18n/I18N.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/i18n/I18N.cpp b/i18n/I18N.cpp index fe04bcb6..cf4873eb 100644 --- a/i18n/I18N.cpp +++ b/i18n/I18N.cpp @@ -1,11 +1,12 @@ /* -* Copyright (c) 2021-2022, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * * See full license text in LICENSE file at top of project tree */ +#include #include "ClientContext.h" #include "I18N_langs.h" #include "I18N.h" @@ -18,9 +19,15 @@ namespace i18n { const auto it = i2p::i18n::languages.find(lang); if (it == i2p::i18n::languages.end()) // fallback + { i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale()); + setlocale(LC_NUMERIC, "english"); + } else + { i2p::client::context.SetLanguage (it->second.LocaleFunc()); + setlocale(LC_NUMERIC, lang.c_str()); // set decimal point based on language + } } std::string translate (const std::string& arg) From a0e71c41732cd4af06f3aae219653c301fd6282d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Jan 2023 07:46:54 +0300 Subject: [PATCH 083/179] [i18n] update strings and translation file Signed-off-by: R4SAS --- contrib/i18n/English.po | 542 +++++++++++++++++++---------------- daemon/HTTPServer.cpp | 28 +- daemon/HTTPServer.h | 2 + libi2pd_client/HTTPProxy.cpp | 59 ++-- 4 files changed, 330 insertions(+), 301 deletions(-) diff --git a/contrib/i18n/English.po b/contrib/i18n/English.po index c9ded966..22010680 100644 --- a/contrib/i18n/English.po +++ b/contrib/i18n/English.po @@ -1,13 +1,13 @@ # i2pd -# Copyright (C) 2021-2022 PurpleI2P team +# Copyright (C) 2021-2023 PurpleI2P team # This file is distributed under the same license as the i2pd package. -# R4SAS , 2021-2022. +# R4SAS , 2021-2023. # msgid "" msgstr "" "Project-Id-Version: i2pd\n" "Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n" -"POT-Creation-Date: 2022-07-26 21:22\n" +"POT-Creation-Date: 2023-01-19 04:18\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -18,712 +18,748 @@ msgstr "" "X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n" "X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n" -#: daemon/HTTPServer.cpp:108 -msgid "day" -msgid_plural "days" +#: daemon/HTTPServer.cpp:106 +#, c-format +msgid "%d day" +msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:112 -msgid "hour" -msgid_plural "hours" +#: daemon/HTTPServer.cpp:110 +#, c-format +msgid "%d hour" +msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:116 -msgid "minute" -msgid_plural "minutes" +#: daemon/HTTPServer.cpp:114 +#, c-format +msgid "%d minute" +msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:119 -msgid "second" -msgid_plural "seconds" +#: daemon/HTTPServer.cpp:117 +#, c-format +msgid "%d second" +msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" -#. tr: Kibibit -#: daemon/HTTPServer.cpp:127 daemon/HTTPServer.cpp:155 -msgid "KiB" +#. tr: Kibibyte +#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153 +#, c-format +msgid "%.2f KiB" msgstr "" -#. tr: Mebibit +#. tr: Mebibyte +#: daemon/HTTPServer.cpp:127 +#, c-format +msgid "%.2f MiB" +msgstr "" + +#. tr: Gibibyte #: daemon/HTTPServer.cpp:129 -msgid "MiB" +#, c-format +msgid "%.2f GiB" msgstr "" -#. tr: Gibibit -#: daemon/HTTPServer.cpp:131 -msgid "GiB" -msgstr "" - -#: daemon/HTTPServer.cpp:148 +#: daemon/HTTPServer.cpp:146 msgid "building" msgstr "" -#: daemon/HTTPServer.cpp:149 +#: daemon/HTTPServer.cpp:147 msgid "failed" msgstr "" -#: daemon/HTTPServer.cpp:150 +#: daemon/HTTPServer.cpp:148 msgid "expiring" msgstr "" -#: daemon/HTTPServer.cpp:151 +#: daemon/HTTPServer.cpp:149 msgid "established" msgstr "" -#: daemon/HTTPServer.cpp:152 +#: daemon/HTTPServer.cpp:150 msgid "unknown" msgstr "" -#: daemon/HTTPServer.cpp:154 +#: daemon/HTTPServer.cpp:152 msgid "exploratory" msgstr "" #. tr: Webconsole page title -#: daemon/HTTPServer.cpp:185 +#: daemon/HTTPServer.cpp:183 msgid "Purple I2P Webconsole" msgstr "" -#: daemon/HTTPServer.cpp:190 +#: daemon/HTTPServer.cpp:188 msgid "i2pd webconsole" msgstr "" -#: daemon/HTTPServer.cpp:193 +#: daemon/HTTPServer.cpp:191 msgid "Main page" msgstr "" -#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:700 +#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712 msgid "Router commands" msgstr "" -#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:382 -#: daemon/HTTPServer.cpp:394 +#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387 +#: daemon/HTTPServer.cpp:399 msgid "Local Destinations" msgstr "" -#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:352 -#: daemon/HTTPServer.cpp:438 daemon/HTTPServer.cpp:444 -#: daemon/HTTPServer.cpp:597 daemon/HTTPServer.cpp:640 -#: daemon/HTTPServer.cpp:644 +#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:357 +#: daemon/HTTPServer.cpp:443 daemon/HTTPServer.cpp:449 +#: daemon/HTTPServer.cpp:609 daemon/HTTPServer.cpp:652 +#: daemon/HTTPServer.cpp:656 msgid "LeaseSets" msgstr "" -#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:650 +#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662 msgid "Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:359 -#: daemon/HTTPServer.cpp:770 daemon/HTTPServer.cpp:786 +#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364 +#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797 msgid "Transit Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:839 +#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855 msgid "Transports" msgstr "" -#: daemon/HTTPServer.cpp:204 +#: daemon/HTTPServer.cpp:202 msgid "I2P tunnels" msgstr "" -#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:908 -#: daemon/HTTPServer.cpp:918 +#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884 +#: daemon/HTTPServer.cpp:894 msgid "SAM sessions" msgstr "" -#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1302 -#: daemon/HTTPServer.cpp:1305 daemon/HTTPServer.cpp:1308 -#: daemon/HTTPServer.cpp:1322 daemon/HTTPServer.cpp:1367 -#: daemon/HTTPServer.cpp:1370 daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:220 daemon/HTTPServer.cpp:1278 +#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1284 +#: daemon/HTTPServer.cpp:1298 daemon/HTTPServer.cpp:1343 +#: daemon/HTTPServer.cpp:1346 daemon/HTTPServer.cpp:1349 msgid "ERROR" msgstr "" -#: daemon/HTTPServer.cpp:229 +#: daemon/HTTPServer.cpp:227 msgid "OK" msgstr "" -#: daemon/HTTPServer.cpp:230 +#: daemon/HTTPServer.cpp:228 msgid "Testing" msgstr "" -#: daemon/HTTPServer.cpp:231 +#: daemon/HTTPServer.cpp:229 msgid "Firewalled" msgstr "" -#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:253 -#: daemon/HTTPServer.cpp:325 +#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233 +#: daemon/HTTPServer.cpp:329 msgid "Unknown" msgstr "" -#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:369 -#: daemon/HTTPServer.cpp:370 daemon/HTTPServer.cpp:976 -#: daemon/HTTPServer.cpp:985 +#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374 +#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952 +#: daemon/HTTPServer.cpp:961 msgid "Proxy" msgstr "" -#: daemon/HTTPServer.cpp:234 +#: daemon/HTTPServer.cpp:232 msgid "Mesh" msgstr "" -#: daemon/HTTPServer.cpp:237 -msgid "Error" -msgstr "" - -#: daemon/HTTPServer.cpp:241 +#: daemon/HTTPServer.cpp:240 msgid "Clock skew" msgstr "" -#: daemon/HTTPServer.cpp:244 +#: daemon/HTTPServer.cpp:243 msgid "Offline" msgstr "" -#: daemon/HTTPServer.cpp:247 +#: daemon/HTTPServer.cpp:246 msgid "Symmetric NAT" msgstr "" -#: daemon/HTTPServer.cpp:259 +#: daemon/HTTPServer.cpp:249 +msgid "Full cone NAT" +msgstr "" + +#: daemon/HTTPServer.cpp:252 +msgid "No Descriptors" +msgstr "" + +#: daemon/HTTPServer.cpp:261 msgid "Uptime" msgstr "" -#: daemon/HTTPServer.cpp:262 +#: daemon/HTTPServer.cpp:264 msgid "Network status" msgstr "" -#: daemon/HTTPServer.cpp:267 +#: daemon/HTTPServer.cpp:269 msgid "Network status v6" msgstr "" -#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:280 +#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282 msgid "Stopping in" msgstr "" -#: daemon/HTTPServer.cpp:287 +#: daemon/HTTPServer.cpp:289 msgid "Family" msgstr "" -#: daemon/HTTPServer.cpp:288 +#: daemon/HTTPServer.cpp:290 msgid "Tunnel creation success rate" msgstr "" -#: daemon/HTTPServer.cpp:289 +#: daemon/HTTPServer.cpp:291 msgid "Received" msgstr "" -#. tr: Kibibit/s -#: daemon/HTTPServer.cpp:291 daemon/HTTPServer.cpp:294 -#: daemon/HTTPServer.cpp:297 -msgid "KiB/s" +#. tr: Kibibyte/s +#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296 +#: daemon/HTTPServer.cpp:299 +#, c-format +msgid "%.2f KiB/s" msgstr "" -#: daemon/HTTPServer.cpp:292 +#: daemon/HTTPServer.cpp:294 msgid "Sent" msgstr "" -#: daemon/HTTPServer.cpp:295 +#: daemon/HTTPServer.cpp:297 msgid "Transit" msgstr "" -#: daemon/HTTPServer.cpp:298 +#: daemon/HTTPServer.cpp:300 msgid "Data path" msgstr "" -#: daemon/HTTPServer.cpp:301 +#: daemon/HTTPServer.cpp:303 msgid "Hidden content. Press on text to see." msgstr "" -#: daemon/HTTPServer.cpp:304 +#: daemon/HTTPServer.cpp:307 msgid "Router Ident" msgstr "" -#: daemon/HTTPServer.cpp:306 +#: daemon/HTTPServer.cpp:309 msgid "Router Family" msgstr "" -#: daemon/HTTPServer.cpp:307 +#: daemon/HTTPServer.cpp:310 msgid "Router Caps" msgstr "" -#: daemon/HTTPServer.cpp:308 +#: daemon/HTTPServer.cpp:311 msgid "Version" msgstr "" -#: daemon/HTTPServer.cpp:309 +#: daemon/HTTPServer.cpp:312 msgid "Our external address" msgstr "" -#: daemon/HTTPServer.cpp:337 +#. tr: Shown when router doesn't publish itself and have "Firewalled" state +#: daemon/HTTPServer.cpp:341 msgid "supported" msgstr "" -#: daemon/HTTPServer.cpp:350 +#: daemon/HTTPServer.cpp:355 msgid "Routers" msgstr "" -#: daemon/HTTPServer.cpp:351 +#: daemon/HTTPServer.cpp:356 msgid "Floodfills" msgstr "" -#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:962 +#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938 msgid "Client Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:368 +#: daemon/HTTPServer.cpp:373 msgid "Services" msgstr "" -#: daemon/HTTPServer.cpp:369 daemon/HTTPServer.cpp:370 -#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372 -#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374 +#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 +#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 +#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 msgid "Enabled" msgstr "" -#: daemon/HTTPServer.cpp:369 daemon/HTTPServer.cpp:370 -#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372 -#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374 +#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 +#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 +#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 msgid "Disabled" msgstr "" -#: daemon/HTTPServer.cpp:417 +#: daemon/HTTPServer.cpp:422 msgid "Encrypted B33 address" msgstr "" -#: daemon/HTTPServer.cpp:426 +#: daemon/HTTPServer.cpp:431 msgid "Address registration line" msgstr "" -#: daemon/HTTPServer.cpp:431 +#: daemon/HTTPServer.cpp:436 msgid "Domain" msgstr "" -#: daemon/HTTPServer.cpp:432 +#: daemon/HTTPServer.cpp:437 msgid "Generate" msgstr "" -#: daemon/HTTPServer.cpp:433 +#: daemon/HTTPServer.cpp:438 msgid "" "Note: result string can be used only for registering 2LD domains " "(example.i2p). For registering subdomains please use i2pd-tools." msgstr "" -#: daemon/HTTPServer.cpp:439 +#: daemon/HTTPServer.cpp:444 msgid "Address" msgstr "" -#: daemon/HTTPServer.cpp:439 +#: daemon/HTTPServer.cpp:444 msgid "Type" msgstr "" -#: daemon/HTTPServer.cpp:439 +#: daemon/HTTPServer.cpp:444 msgid "EncType" msgstr "" -#: daemon/HTTPServer.cpp:449 daemon/HTTPServer.cpp:655 +#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667 msgid "Inbound tunnels" msgstr "" #. tr: Milliseconds -#: daemon/HTTPServer.cpp:464 daemon/HTTPServer.cpp:484 -#: daemon/HTTPServer.cpp:669 daemon/HTTPServer.cpp:689 -msgid "ms" +#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489 +#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701 +#, c-format +msgid "%dms" msgstr "" -#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:674 +#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686 msgid "Outbound tunnels" msgstr "" -#: daemon/HTTPServer.cpp:491 +#: daemon/HTTPServer.cpp:496 msgid "Tags" msgstr "" -#: daemon/HTTPServer.cpp:491 +#: daemon/HTTPServer.cpp:497 msgid "Incoming" msgstr "" -#: daemon/HTTPServer.cpp:498 daemon/HTTPServer.cpp:501 +#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510 msgid "Outgoing" msgstr "" -#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:515 +#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526 msgid "Destination" msgstr "" -#: daemon/HTTPServer.cpp:499 +#: daemon/HTTPServer.cpp:507 msgid "Amount" msgstr "" -#: daemon/HTTPServer.cpp:506 +#: daemon/HTTPServer.cpp:515 msgid "Incoming Tags" msgstr "" -#: daemon/HTTPServer.cpp:514 daemon/HTTPServer.cpp:517 +#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529 msgid "Tags sessions" msgstr "" -#: daemon/HTTPServer.cpp:515 +#: daemon/HTTPServer.cpp:526 msgid "Status" msgstr "" -#: daemon/HTTPServer.cpp:524 daemon/HTTPServer.cpp:582 +#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594 msgid "Local Destination" msgstr "" -#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:941 +#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917 msgid "Streams" msgstr "" -#: daemon/HTTPServer.cpp:558 +#: daemon/HTTPServer.cpp:570 msgid "Close stream" msgstr "" -#: daemon/HTTPServer.cpp:587 +#: daemon/HTTPServer.cpp:599 msgid "I2CP session not found" msgstr "" -#: daemon/HTTPServer.cpp:590 +#: daemon/HTTPServer.cpp:602 msgid "I2CP is not enabled" msgstr "" -#: daemon/HTTPServer.cpp:616 +#: daemon/HTTPServer.cpp:628 msgid "Invalid" msgstr "" -#: daemon/HTTPServer.cpp:619 +#: daemon/HTTPServer.cpp:631 msgid "Store type" msgstr "" -#: daemon/HTTPServer.cpp:620 +#: daemon/HTTPServer.cpp:632 msgid "Expires" msgstr "" -#: daemon/HTTPServer.cpp:625 +#: daemon/HTTPServer.cpp:637 msgid "Non Expired Leases" msgstr "" -#: daemon/HTTPServer.cpp:628 +#: daemon/HTTPServer.cpp:640 msgid "Gateway" msgstr "" -#: daemon/HTTPServer.cpp:629 +#: daemon/HTTPServer.cpp:641 msgid "TunnelID" msgstr "" -#: daemon/HTTPServer.cpp:630 +#: daemon/HTTPServer.cpp:642 msgid "EndDate" msgstr "" -#: daemon/HTTPServer.cpp:640 -msgid "not floodfill" +#: daemon/HTTPServer.cpp:652 +msgid "floodfill mode is disabled" msgstr "" -#: daemon/HTTPServer.cpp:651 +#: daemon/HTTPServer.cpp:663 msgid "Queue size" msgstr "" -#: daemon/HTTPServer.cpp:701 +#: daemon/HTTPServer.cpp:713 msgid "Run peer test" msgstr "" -#: daemon/HTTPServer.cpp:706 +#: daemon/HTTPServer.cpp:714 +msgid "Reload tunnels configuration" +msgstr "" + +#: daemon/HTTPServer.cpp:717 msgid "Decline transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:708 +#: daemon/HTTPServer.cpp:719 msgid "Accept transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:712 daemon/HTTPServer.cpp:717 +#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728 msgid "Cancel graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:714 daemon/HTTPServer.cpp:719 +#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730 msgid "Start graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:722 +#: daemon/HTTPServer.cpp:733 msgid "Force shutdown" msgstr "" -#: daemon/HTTPServer.cpp:723 +#: daemon/HTTPServer.cpp:734 msgid "Reload external CSS styles" msgstr "" -#: daemon/HTTPServer.cpp:726 +#: daemon/HTTPServer.cpp:737 msgid "" "Note: any action done here are not persistent and not changes your " "config files." msgstr "" -#: daemon/HTTPServer.cpp:728 +#: daemon/HTTPServer.cpp:739 msgid "Logging level" msgstr "" -#: daemon/HTTPServer.cpp:736 +#: daemon/HTTPServer.cpp:747 msgid "Transit tunnels limit" msgstr "" -#: daemon/HTTPServer.cpp:741 daemon/HTTPServer.cpp:760 +#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771 msgid "Change" msgstr "" -#: daemon/HTTPServer.cpp:748 +#: daemon/HTTPServer.cpp:759 msgid "Change language" msgstr "" -#: daemon/HTTPServer.cpp:786 +#: daemon/HTTPServer.cpp:797 msgid "no transit tunnels currently built" msgstr "" -#: daemon/HTTPServer.cpp:902 daemon/HTTPServer.cpp:925 +#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901 msgid "SAM disabled" msgstr "" -#: daemon/HTTPServer.cpp:918 +#: daemon/HTTPServer.cpp:894 msgid "no sessions currently running" msgstr "" -#: daemon/HTTPServer.cpp:931 +#: daemon/HTTPServer.cpp:907 msgid "SAM session not found" msgstr "" -#: daemon/HTTPServer.cpp:936 +#: daemon/HTTPServer.cpp:912 msgid "SAM Session" msgstr "" -#: daemon/HTTPServer.cpp:993 +#: daemon/HTTPServer.cpp:969 msgid "Server Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:1009 +#: daemon/HTTPServer.cpp:985 msgid "Client Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1023 +#: daemon/HTTPServer.cpp:999 msgid "Server Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1223 +#: daemon/HTTPServer.cpp:1199 msgid "Unknown page" msgstr "" -#: daemon/HTTPServer.cpp:1242 +#: daemon/HTTPServer.cpp:1218 msgid "Invalid token" msgstr "" -#: daemon/HTTPServer.cpp:1300 daemon/HTTPServer.cpp:1357 -#: daemon/HTTPServer.cpp:1397 +#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333 +#: daemon/HTTPServer.cpp:1373 msgid "SUCCESS" msgstr "" -#: daemon/HTTPServer.cpp:1300 +#: daemon/HTTPServer.cpp:1276 msgid "Stream closed" msgstr "" -#: daemon/HTTPServer.cpp:1302 +#: daemon/HTTPServer.cpp:1278 msgid "Stream not found or already was closed" msgstr "" -#: daemon/HTTPServer.cpp:1305 +#: daemon/HTTPServer.cpp:1281 msgid "Destination not found" msgstr "" -#: daemon/HTTPServer.cpp:1308 +#: daemon/HTTPServer.cpp:1284 msgid "StreamID can't be null" msgstr "" -#: daemon/HTTPServer.cpp:1310 daemon/HTTPServer.cpp:1375 +#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351 msgid "Return to destination page" msgstr "" -#: daemon/HTTPServer.cpp:1311 daemon/HTTPServer.cpp:1324 -#: daemon/HTTPServer.cpp:1399 -msgid "You will be redirected in 5 seconds" +#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300 +#: daemon/HTTPServer.cpp:1375 +#, c-format +msgid "You will be redirected in %d seconds" msgstr "" -#: daemon/HTTPServer.cpp:1322 -msgid "Transit tunnels count must not exceed 65535" +#: daemon/HTTPServer.cpp:1298 +#, c-format +msgid "Transit tunnels count must not exceed %d" msgstr "" -#: daemon/HTTPServer.cpp:1323 daemon/HTTPServer.cpp:1398 +#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374 msgid "Back to commands list" msgstr "" -#: daemon/HTTPServer.cpp:1359 +#: daemon/HTTPServer.cpp:1335 msgid "Register at reg.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1360 +#: daemon/HTTPServer.cpp:1336 msgid "Description" msgstr "" -#: daemon/HTTPServer.cpp:1360 +#: daemon/HTTPServer.cpp:1336 msgid "A bit information about service on domain" msgstr "" -#: daemon/HTTPServer.cpp:1361 +#: daemon/HTTPServer.cpp:1337 msgid "Submit" msgstr "" -#: daemon/HTTPServer.cpp:1367 +#: daemon/HTTPServer.cpp:1343 msgid "Domain can't end with .b32.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1370 +#: daemon/HTTPServer.cpp:1346 msgid "Domain must end with .i2p" msgstr "" -#: daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:1349 msgid "Such destination is not found" msgstr "" -#: daemon/HTTPServer.cpp:1393 +#: daemon/HTTPServer.cpp:1369 msgid "Unknown command" msgstr "" -#: daemon/HTTPServer.cpp:1397 +#: daemon/HTTPServer.cpp:1373 msgid "Command accepted" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:163 +#: libi2pd_client/HTTPProxy.cpp:166 msgid "Proxy error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:171 +#: libi2pd_client/HTTPProxy.cpp:174 msgid "Proxy info" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:179 +#: libi2pd_client/HTTPProxy.cpp:182 msgid "Proxy error: Host not found" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:180 +#: libi2pd_client/HTTPProxy.cpp:183 msgid "Remote host not found in router's addressbook" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:181 +#: libi2pd_client/HTTPProxy.cpp:184 msgid "You may try to find this host on jump services below" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:282 libi2pd_client/HTTPProxy.cpp:297 -#: libi2pd_client/HTTPProxy.cpp:331 libi2pd_client/HTTPProxy.cpp:372 +#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324 +#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435 msgid "Invalid request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:282 +#: libi2pd_client/HTTPProxy.cpp:309 msgid "Proxy unable to parse your request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:297 -msgid "addresshelper is not supported" +#: libi2pd_client/HTTPProxy.cpp:324 +msgid "Addresshelper is not supported" +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:349 +#, c-format +msgid "" +"Host %s is already in router's addressbook. Be " +"careful: source of this URL may be harmful! Click here to update record: " +"Continue." +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:351 +msgid "Addresshelper forced update rejected" +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:358 +#, c-format +msgid "" +"To add host %s in router's addressbook, click here: Continue." +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:360 +msgid "Addresshelper request" +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:369 +#, c-format +msgid "" +"Host %s added to router's addressbook from helper. Click here to proceed: Continue." +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:370 +msgid "Addresshelper adding" +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:377 +#, c-format +msgid "" +"Host %s is already in router's addressbook. Click " +"here to update record: Continue." +msgstr "" + +#: libi2pd_client/HTTPProxy.cpp:379 +msgid "Addresshelper update" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:306 libi2pd_client/HTTPProxy.cpp:315 #: libi2pd_client/HTTPProxy.cpp:392 -msgid "Host" +msgid "Invalid request URI" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:306 -msgid "added to router's addressbook from helper" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:307 -msgid "Click here to proceed:" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:307 libi2pd_client/HTTPProxy.cpp:317 -msgid "Continue" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:308 libi2pd_client/HTTPProxy.cpp:318 -msgid "Addresshelper found" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:315 -msgid "already in router's addressbook" -msgstr "" - -#. tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. -#: libi2pd_client/HTTPProxy.cpp:316 -msgid "Click here to update record:" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:331 -msgid "invalid request uri" -msgstr "" - -#: libi2pd_client/HTTPProxy.cpp:372 +#: libi2pd_client/HTTPProxy.cpp:435 msgid "Can't detect destination host from request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:389 libi2pd_client/HTTPProxy.cpp:393 +#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456 msgid "Outproxy failure" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:389 -msgid "bad outproxy settings" +#: libi2pd_client/HTTPProxy.cpp:452 +msgid "Bad outproxy settings" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:392 -msgid "not inside I2P network, but outproxy is not enabled" +#: libi2pd_client/HTTPProxy.cpp:455 +#, c-format +msgid "Host %s is not inside I2P network, but outproxy is not enabled" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:482 -msgid "unknown outproxy url" +#: libi2pd_client/HTTPProxy.cpp:544 +msgid "Unknown outproxy URL" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:490 -msgid "cannot resolve upstream proxy" +#: libi2pd_client/HTTPProxy.cpp:550 +msgid "Cannot resolve upstream proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:498 -msgid "hostname too long" +#: libi2pd_client/HTTPProxy.cpp:558 +msgid "Hostname is too long" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:525 -msgid "cannot connect to upstream socks proxy" +#: libi2pd_client/HTTPProxy.cpp:585 +msgid "Cannot connect to upstream SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:531 -msgid "Cannot negotiate with socks proxy" +#: libi2pd_client/HTTPProxy.cpp:591 +msgid "Cannot negotiate with SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:573 +#: libi2pd_client/HTTPProxy.cpp:633 msgid "CONNECT error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:573 -msgid "Failed to Connect" +#: libi2pd_client/HTTPProxy.cpp:633 +msgid "Failed to connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:584 libi2pd_client/HTTPProxy.cpp:610 -msgid "socks proxy error" +#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670 +msgid "SOCKS proxy error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:592 -msgid "failed to send request to upstream" +#: libi2pd_client/HTTPProxy.cpp:652 +msgid "Failed to send request to upstream" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:613 -msgid "No Reply From socks proxy" +#: libi2pd_client/HTTPProxy.cpp:673 +msgid "No reply from SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:620 -msgid "cannot connect" +#: libi2pd_client/HTTPProxy.cpp:680 +msgid "Cannot connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:620 -msgid "http out proxy not implemented" +#: libi2pd_client/HTTPProxy.cpp:680 +msgid "HTTP out proxy not implemented" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:621 -msgid "cannot connect to upstream http proxy" +#: libi2pd_client/HTTPProxy.cpp:681 +msgid "Cannot connect to upstream HTTP proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:654 +#: libi2pd_client/HTTPProxy.cpp:714 msgid "Host is down" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:654 +#: libi2pd_client/HTTPProxy.cpp:714 msgid "" "Can't create connection to requested host, it may be down. Please try again " "later." diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 74e7df64..e18ce053 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -150,7 +150,7 @@ namespace http { else stateText = tr("unknown"); s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; - s << " " << tr(/* tr: Kibibit */ "%.2f KiB", (double) bytes / 1024) << "\r\n"; + s << " " << tr(/* tr: Kibibyte */ "%.2f KiB", (double) bytes / 1024) << "\r\n"; } static void SetLogLevel (const std::string& level) @@ -290,13 +290,13 @@ namespace http { s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; s << "" << tr("Received") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); - s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")
\r\n"; + s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Sent") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ()); - s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")
\r\n"; + s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Transit") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ()); - s << " (" << tr(/* tr: Kibibit/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")
\r\n"; + s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")
\r\n"; s << "" << tr("Data path") << ": " << i2p::fs::GetUTF8DataDir() << "
\r\n"; s << "
"; if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { @@ -649,7 +649,7 @@ namespace http { } else if (!i2p::context.IsFloodfill ()) { - s << "" << tr("LeaseSets") << ": " << tr("not floodfill") << ".
\r\n"; + s << "" << tr("LeaseSets") << ": " << tr(/* Message on LeaseSets page */ "floodfill mode is disabled") << ".
\r\n"; } else { @@ -794,7 +794,7 @@ namespace http { } else { - s << "" << tr("Transit Tunnels") << ": " << tr("no transit tunnels currently built") << ".
\r\n"; + s << "" << tr("Transit Tunnels") << ": " << tr(/* Message on transit tunnels page */ "no transit tunnels currently built") << ".
\r\n"; } } @@ -891,7 +891,7 @@ namespace http { s << "
\r\n"; } else - s << "" << tr("SAM sessions") << ": " << tr("no sessions currently running") << ".
\r\n"; + s << "" << tr("SAM sessions") << ": " << tr(/* Message on SAM sessions page */ "no sessions currently running") << ".
\r\n"; } void ShowSAMSession (std::stringstream& s, const std::string& id) @@ -1210,7 +1210,7 @@ namespace http { url.parse_query(params); std::string webroot; i2p::config::GetOption("http.webroot", webroot); - std::string redirect = "5; url=" + webroot + "?page=commands"; + std::string redirect = COMMAND_REDIRECT_TIMEOUT + "; url=" + webroot + "?page=commands"; std::string token = params["token"]; if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) @@ -1284,20 +1284,20 @@ namespace http { s << "" << tr("ERROR") << ": " << tr("StreamID can't be null") << "
\r\n
\r\n"; s << "" << tr("Return to destination page") << "
\r\n"; - s << "

" << tr("You will be redirected in 5 seconds") << ""; - redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32; + s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; + redirect = COMMAND_REDIRECT_TIMEOUT + "; url=" + webroot + "?page=local_destination&b32=" + b32; res.add_header("Refresh", redirect.c_str()); return; } else if (cmd == HTTP_COMMAND_LIMITTRANSIT) { uint32_t limit = std::stoul(params["limit"], nullptr); - if (limit > 0 && limit <= 65535) + if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT) SetMaxNumTransitTunnels (limit); else { - s << "" << tr("ERROR") << ": " << tr("Transit tunnels count must not exceed 65535") << "\r\n
\r\n
\r\n"; + s << "" << tr("ERROR") << ": " << tr("Transit tunnels count must not exceed %d", TRANSIT_TUNNELS_LIMIT) << "\r\n
\r\n
\r\n"; s << "" << tr("Back to commands list") << "\r\n
\r\n"; - s << "

" << tr("You will be redirected in 5 seconds") << ""; + s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; res.add_header("Refresh", redirect.c_str()); return; } @@ -1372,7 +1372,7 @@ namespace http { s << "" << tr("SUCCESS") << ": " << tr("Command accepted") << "

\r\n"; s << "" << tr("Back to commands list") << "
\r\n"; - s << "

" << tr("You will be redirected in 5 seconds") << ""; + s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; res.add_header("Refresh", redirect.c_str()); } diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index 8646253f..603bc25e 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -24,6 +24,8 @@ namespace http { const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds + const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds + const int TRANSIT_TUNNELS_LIMIT = 65535; class HTTPConnection: public std::enable_shared_from_this { diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index cecda2bb..6b015f2b 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -321,7 +321,7 @@ namespace proxy { if (!m_Addresshelper) { LogPrint(eLogWarning, "HTTPProxy: Addresshelper request rejected"); - GenericProxyError(tr("Invalid request"), tr("addresshelper is not supported")); + GenericProxyError(tr("Invalid request"), tr("Addresshelper is not supported")); return true; } @@ -341,28 +341,22 @@ namespace proxy { } if (m_RequestURL.host != referer_url.host) { - // Attempt to forced overwriting by link with "&update=true" from harmful URL - if (m_Confirm) + if (m_Confirm) // Attempt to forced overwriting by link with "&update=true" from harmful URL { LogPrint (eLogWarning, "HTTPProxy: Address update from addresshelper rejected for ", m_RequestURL.host, " (referer is ", m_RequestURL.host.empty() ? "empty" : "harmful", ")"); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("Host") << " " << m_RequestURL.host << " " << tr("already in router's addressbook") << ". "; - ss << "" << tr( /* Trying to overwrite an existing domain in the address book by direct link with "&update=true" is seems like an attack */ "Be careful: source of this URL may be harmful") << "! "; - ss << tr(/* tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. */ "Click here to update record:" ); - ss << " " << tr("Continue") << "."; + ss << tr("Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", + m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); GenericProxyInfo(tr("Addresshelper forced update rejected"), ss.str()); } - // Preventing unauthorized additions to the address book - else + else // Preventing unauthorized additions to the address book { LogPrint (eLogDebug, "HTTPProxy: Adding address from addresshelper for ", m_RequestURL.host, " (generate refer-base page)"); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("To add host" /*... in router's addressbook, click here */ ) << " " << m_RequestURL.host << " " << tr( /* To add host SOMESHORT.i2p ... */ "in router's addressbook, click here") << ":"; - ss << " " << tr("Continue") << "."; + ss << tr("To add host %s in router's addressbook, click here: Continue.", + m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); GenericProxyInfo(tr("Addresshelper request"), ss.str()); } return true; /* request processed */ @@ -372,8 +366,7 @@ namespace proxy { LogPrint (eLogInfo, "HTTPProxy: Added address from addresshelper for ", m_RequestURL.host); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("Host") <<" " << m_RequestURL.host << " " << tr("added to router's addressbook from helper") << ". "; - ss << tr("Click here to proceed:") << " " << tr("Continue") << "."; + ss << tr("Host %s added to router's addressbook from helper. Click here to proceed: Continue.", m_RequestURL.host, full_url); GenericProxyInfo(tr("Addresshelper adding"), ss.str()); return true; /* request processed */ } @@ -381,10 +374,8 @@ namespace proxy { { std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("Host") << " " << m_RequestURL.host << " " << tr("already in router's addressbook") << ". "; - ss << tr(/* tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it. */ "Click here to update record:" ); - ss << " " << tr("Continue") << "."; + ss << tr("Host %s is already in router's addressbook. Click here to update record: Continue.", + m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); GenericProxyInfo(tr("Addresshelper update"), ss.str()); return true; /* request processed */ } @@ -398,7 +389,7 @@ namespace proxy { auto pos = uri.find(":"); if(pos == std::string::npos || pos == uri.size() - 1) { - GenericProxyError(tr("Invalid request"), tr("invalid request uri")); + GenericProxyError(tr("Invalid request"), tr("Invalid request URI")); return true; } else @@ -458,10 +449,10 @@ namespace proxy { if(m_ProxyURL.parse(m_OutproxyUrl)) ForwardToUpstreamProxy(); else - GenericProxyError(tr("Outproxy failure"), tr("bad outproxy settings")); + GenericProxyError(tr("Outproxy failure"), tr("Bad outproxy settings")); } else { LogPrint (eLogWarning, "HTTPProxy: Outproxy failure for ", dest_host, ": no outproxy enabled"); - std::stringstream ss; ss << tr("Host") << " " << dest_host << " " << tr("not inside I2P network, but outproxy is not enabled"); + std::stringstream ss; ss << tr("Host %s is not inside I2P network, but outproxy is not enabled", dest_host); GenericProxyError(tr("Outproxy failure"), ss.str()); } return true; @@ -550,13 +541,13 @@ namespace proxy { else { /* unknown type, complain */ - GenericProxyError(tr("unknown outproxy url"), m_ProxyURL.to_string()); + GenericProxyError(tr("Unknown outproxy URL"), m_ProxyURL.to_string()); } } void HTTPReqHandler::HandleUpstreamProxyResolved(const boost::system::error_code & ec, boost::asio::ip::tcp::resolver::iterator it, ProxyResolvedHandler handler) { - if(ec) GenericProxyError(tr("cannot resolve upstream proxy"), ec.message()); + if(ec) GenericProxyError(tr("Cannot resolve upstream proxy"), ec.message()); else handler(*it); } @@ -564,7 +555,7 @@ namespace proxy { { if(!ec) { if(m_RequestURL.host.size() > 255) { - GenericProxyError(tr("hostname too long"), m_RequestURL.host); + GenericProxyError(tr("Hostname is too long"), m_RequestURL.host); return; } uint16_t port = m_RequestURL.port; @@ -591,13 +582,13 @@ namespace proxy { reqsize += host.size(); m_socks_buf[++reqsize] = 0; boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2)); - } else GenericProxyError(tr("cannot connect to upstream socks proxy"), ec.message()); + } else GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message()); } void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred) { LogPrint(eLogDebug, "HTTPProxy: Upstream SOCKS handshake sent"); - if(ec) GenericProxyError(tr("Cannot negotiate with socks proxy"), ec.message()); + if(ec) GenericProxyError(tr("Cannot negotiate with SOCKS proxy"), ec.message()); else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2)); } @@ -639,7 +630,7 @@ namespace proxy { } else { - GenericProxyError(tr("CONNECT error"), tr("Failed to Connect")); + GenericProxyError(tr("CONNECT error"), tr("Failed to connect")); } } @@ -650,7 +641,7 @@ namespace proxy { m_send_buf = m_ClientResponse.to_string(); boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) { - if(ec) GenericProxyError(tr("socks proxy error"), ec.message()); + if(ec) GenericProxyError(tr("SOCKS proxy error"), ec.message()); else HandoverToUpstreamProxy(); }); } else { @@ -658,7 +649,7 @@ namespace proxy { LogPrint(eLogDebug, "HTTPProxy: Send ", m_send_buf.size(), " bytes"); boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) { - if(ec) GenericProxyError(tr("failed to send request to upstream"), ec.message()); + if(ec) GenericProxyError(tr("Failed to send request to upstream"), ec.message()); else HandoverToUpstreamProxy(); }); } @@ -676,18 +667,18 @@ namespace proxy { ss << "error code: "; ss << (int) m_socks_buf[1]; std::string msg = ss.str(); - GenericProxyError(tr("socks proxy error"), msg); + GenericProxyError(tr("SOCKS proxy error"), msg); } } - else GenericProxyError(tr("No Reply From socks proxy"), ec.message()); + else GenericProxyError(tr("No reply from SOCKS proxy"), ec.message()); } void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec) { if(!ec) { LogPrint(eLogDebug, "HTTPProxy: Connected to http upstream"); - GenericProxyError(tr("cannot connect"), tr("http out proxy not implemented")); - } else GenericProxyError(tr("cannot connect to upstream http proxy"), ec.message()); + GenericProxyError(tr("Cannot connect"), tr("HTTP out proxy not implemented")); + } else GenericProxyError(tr("Cannot connect to upstream HTTP proxy"), ec.message()); } /* will be called after some data received from client */ From 84d4e074ceeadb7d6dda39d87a70ced6ec75fe80 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Jan 2023 08:33:03 +0300 Subject: [PATCH 084/179] add loglevel checker, fix fields passing to translated string formatter Signed-off-by: R4SAS --- contrib/webconsole/style.css | 586 +++++++++++++++++------------------ daemon/HTTPServer.cpp | 15 +- daemon/HTTPServer.h | 2 +- daemon/HTTPServerResources.h | 4 +- libi2pd/Log.cpp | 2 +- libi2pd_client/HTTPProxy.cpp | 11 +- 6 files changed, 311 insertions(+), 309 deletions(-) diff --git a/contrib/webconsole/style.css b/contrib/webconsole/style.css index 5d63d1a7..89021539 100644 --- a/contrib/webconsole/style.css +++ b/contrib/webconsole/style.css @@ -1,293 +1,293 @@ -/* - * Copyright (c) 2021-2022, The PurpleI2P Project - * - * This file is part of Purple i2pd project and licensed under BSD3 - * - * See full license text in LICENSE file at top of project tree - * - ****************************************************************** - * - * This is style sheet for webconsole, with @media selectors for adaptive - * view on desktop and mobile devices, respecting preferred user's color - * scheme used in system/browser. - * - * Minified copy of that style sheet is bundled inside i2pd sources. -*/ - -:root { - --main-bg-color: #fafafa; - --main-text-color: #103456; - --main-link-color: #894c84; - --main-link-hover-color: #fafafa; -} - -@media (prefers-color-scheme: dark) { - :root { - --main-bg-color: #242424; - --main-text-color: #17ab5c; - --main-link-color: #bf64b7; - --main-link-hover-color: #000000; - } -} - -body { - font: 100%/1.5em sans-serif; - margin: 0; - padding: 1.5em; - background: var(--main-bg-color); - color: var(--main-text-color); -} - -a, .slide label { - text-decoration: none; - color: var(--main-link-color); -} - -a:hover, .slide label:hover, button[type=submit]:hover { - color: var(--main-link-hover-color); - background: var(--main-link-color); -} - -a.button { - appearance: button; - text-decoration: none; - padding: 0 5px; - border: 1px solid var(--main-link-color); -} - -.header { - font-size: 2.5em; - text-align: center; - margin: 1em 0; - color: var(--main-link-color); -} - -.wrapper { - margin: 0 auto; - padding: 1em; - max-width: 64em; -} - -.menu { - display: block; - float: left; - overflow: hidden; - padding: 4px; - max-width: 12em; - white-space: nowrap; - text-overflow: ellipsis; -} - -.listitem { - display: block; - font-family: monospace; - font-size: 1.2em; - white-space: nowrap; -} - -.tableitem { - font-family: monospace; - font-size: 1.2em; - white-space: nowrap; -} - -.content { - float: left; - font-size: 1em; - margin-left: 2em; - padding: 4px; - max-width: 50em; - overflow: auto; -} - -.tunnel.established { - color: #56B734; -} - -.tunnel.expiring { - color: #D3AE3F; -} - -.tunnel.failed { - color: #D33F3F; -} - -.tunnel.building { - color: #434343; -} - -caption { - font-size: 1.5em; - text-align: center; - color: var(--main-link-color); -} - -table { - display: table; - border-collapse: collapse; - text-align: center; -} - -table.extaddr { - text-align: left; -} - -table.services { - width: 100%; -} - -textarea { - background-color: var(--main-bg-color); - color: var(--main-text-color); - word-break: break-all; -} - -.streamdest { - width: 120px; - max-width: 240px; - overflow: hidden; - text-overflow: ellipsis; -} - -.slide div.slidecontent, .slide [type="checkbox"] { - display: none; -} - -.slide [type="checkbox"]:checked ~ div.slidecontent { - display: block; - margin-top: 0; - padding: 0; -} - -.disabled { - color: #D33F3F; -} - -.enabled { - color: #56B734; -} - -button[type=submit] { - background-color: transparent; - color: var(--main-link-color); - text-decoration: none; - padding: 5px; - border: 1px solid var(--main-link-color); - font-size: 14px; -} - -input, select, select option { - background-color: var(--main-bg-color); - color: var(--main-link-color); - padding: 5px; - border: 1px solid var(--main-link-color); - font-size: 14px; -} - -input:focus, select:focus, select option:focus { - outline: none; -} - -input[type=number]::-webkit-inner-spin-button { - -webkit-appearance: none; -} - -@media screen and (max-width: 1150px) { /* adaptive style */ - .wrapper { - max-width: 58em; - } - - .content { - max-width: 40em; - } -} - -@media screen and (max-width: 980px) { - body { - font: 100%/1.2em sans-serif; - padding: 1.2em 0 0 0; - } - - .menu { - width: 100%; - max-width: unset; - display: block; - float: none; - position: unset; - font-size: 16px; - text-align: center; - } - - .menu a, .commands a { - display: inline-block; - padding: 4px; - } - - .content { - float: none; - margin-left: unset; - margin-top: 16px; - max-width: 100%; - width: 100%; - text-align: center; - } - - a, .slide label { - display: block; - } - - .header { - margin: unset; - font-size: 1.5em; - } - - small { - display: block - } - - a.button { - appearance: button; - text-decoration: none; - margin-top: 10px; - padding: 6px; - border: 2px solid var(--main-link-color); - border-radius: 5px; - width: -webkit-fill-available; - } - - input, select { - width: 35%; - text-align: center; - padding: 5px; - border: 2px solid var(--main-link-color); - border-radius: 5px; - font-size: 18px; - } - - table.extaddr { - margin: auto; - text-align: unset; - } - - textarea { - width: -webkit-fill-available; - height: auto; - padding: 5px; - border: 2px solid var(--main-link-color); - border-radius: 5px; - font-size: 12px; - } - - button[type=submit] { - padding: 5px 15px; - background: transparent; - border: 2px solid var(--main-link-color); - cursor: pointer; - -webkit-border-radius: 5px; - border-radius: 5px; - position: relative; - height: 36px; - display: -webkit-inline-box; - margin-top: 10px; - } -} \ No newline at end of file +/* + * Copyright (c) 2021-2023, The PurpleI2P Project + * + * This file is part of Purple i2pd project and licensed under BSD3 + * + * See full license text in LICENSE file at top of project tree + * + ****************************************************************** + * + * This is style sheet for webconsole, with @media selectors for adaptive + * view on desktop and mobile devices, respecting preferred user's color + * scheme used in system/browser. + * + * Minified copy of that style sheet is bundled inside i2pd sources. +*/ + +:root { + --main-bg-color: #fafafa; + --main-text-color: #103456; + --main-link-color: #894c84; + --main-link-hover-color: #fafafa; +} + +@media (prefers-color-scheme: dark) { + :root { + --main-bg-color: #242424; + --main-text-color: #17ab5c; + --main-link-color: #bf64b7; + --main-link-hover-color: #000000; + } +} + +body { + font: 100%/1.5em sans-serif; + margin: 0; + padding: 1.5em; + background: var(--main-bg-color); + color: var(--main-text-color); +} + +a, .slide label { + text-decoration: none; + color: var(--main-link-color); +} + +a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { + color: var(--main-link-hover-color); + background: var(--main-link-color); +} + +a.button { + appearance: button; + text-decoration: none; + padding: 0 5px; + border: 1px solid var(--main-link-color); +} + +.header { + font-size: 2.5em; + text-align: center; + margin: 1em 0; + color: var(--main-link-color); +} + +.wrapper { + margin: 0 auto; + padding: 1em; + max-width: 64em; +} + +.menu { + display: block; + float: left; + overflow: hidden; + padding: 4px; + max-width: 12em; + white-space: nowrap; + text-overflow: ellipsis; +} + +.listitem { + display: block; + font-family: monospace; + font-size: 1.2em; + white-space: nowrap; +} + +.tableitem { + font-family: monospace; + font-size: 1.2em; + white-space: nowrap; +} + +.content { + float: left; + font-size: 1em; + margin-left: 2em; + padding: 4px; + max-width: 50em; + overflow: auto; +} + +.tunnel.established { + color: #56B734; +} + +.tunnel.expiring { + color: #D3AE3F; +} + +.tunnel.failed { + color: #D33F3F; +} + +.tunnel.building { + color: #434343; +} + +caption { + font-size: 1.5em; + text-align: center; + color: var(--main-link-color); +} + +table { + display: table; + border-collapse: collapse; + text-align: center; +} + +table.extaddr { + text-align: left; +} + +table.services { + width: 100%; +} + +textarea { + background-color: var(--main-bg-color); + color: var(--main-text-color); + word-break: break-all; +} + +.streamdest { + width: 120px; + max-width: 240px; + overflow: hidden; + text-overflow: ellipsis; +} + +.slide div.slidecontent, .slide [type="checkbox"] { + display: none; +} + +.slide [type="checkbox"]:checked ~ div.slidecontent { + display: block; + margin-top: 0; + padding: 0; +} + +.disabled { + color: #D33F3F; +} + +.enabled { + color: #56B734; +} + +button[type=submit] { + background-color: transparent; + color: var(--main-link-color); + text-decoration: none; + padding: 5px; + border: 1px solid var(--main-link-color); + font-size: 14px; +} + +input, select, select option { + background-color: var(--main-bg-color); + color: var(--main-link-color); + padding: 5px; + border: 1px solid var(--main-link-color); + font-size: 14px; +} + +input:focus, select:focus, select option:focus { + outline: none; +} + +input[type=number]::-webkit-inner-spin-button { + -webkit-appearance: none; +} + +@media screen and (max-width: 1150px) { /* adaptive style */ + .wrapper { + max-width: 58em; + } + + .content { + max-width: 40em; + } +} + +@media screen and (max-width: 980px) { + body { + font: 100%/1.2em sans-serif; + padding: 1.2em 0 0 0; + } + + .menu { + width: 100%; + max-width: unset; + display: block; + float: none; + position: unset; + font-size: 16px; + text-align: center; + } + + .menu a, .commands a { + display: inline-block; + padding: 4px; + } + + .content { + float: none; + margin-left: unset; + margin-top: 16px; + max-width: 100%; + width: 100%; + text-align: center; + } + + a, .slide label { + display: block; + } + + .header { + margin: unset; + font-size: 1.5em; + } + + small { + display: block + } + + a.button { + appearance: button; + text-decoration: none; + margin-top: 10px; + padding: 6px; + border: 2px solid var(--main-link-color); + border-radius: 5px; + width: -webkit-fill-available; + } + + input, select { + width: 35%; + text-align: center; + padding: 5px; + border: 2px solid var(--main-link-color); + border-radius: 5px; + font-size: 18px; + } + + table.extaddr { + margin: auto; + text-align: unset; + } + + textarea { + width: -webkit-fill-available; + height: auto; + padding: 5px; + border: 2px solid var(--main-link-color); + border-radius: 5px; + font-size: 12px; + } + + button[type=submit] { + padding: 5px 15px; + background: transparent; + border: 2px solid var(--main-link-color); + cursor: pointer; + -webkit-border-radius: 5px; + border-radius: 5px; + position: relative; + height: 36px; + display: -webkit-inline-box; + margin-top: 10px; + } +} diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index e18ce053..2bf92df3 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -198,7 +198,7 @@ namespace http { if (i2p::context.AcceptsTunnels () || i2p::tunnel::tunnels.CountTransitTunnels()) s << " " << tr("Transit Tunnels") << "
\r\n"; s << - " " << tr ("Transports") << "
\r\n" + " " << tr("Transports") << "
\r\n" " " << tr("I2P tunnels") << "
\r\n"; if (i2p::client::context.GetSAMBridge ()) s << " " << tr("SAM sessions") << "
\r\n"; @@ -736,19 +736,20 @@ namespace http { s << "
\r\n" << tr("Note: any action done here are not persistent and not changes your config files.") << "\r\n
\r\n"; + auto loglevel = i2p::log::Logger().GetLogLevel(); s << "" << tr("Logging level") << "
\r\n"; - s << " none \r\n"; - s << " error \r\n"; - s << " warn \r\n"; - s << " info \r\n"; - s << " debug
\r\n
\r\n"; + s << " none \r\n"; + s << " error \r\n"; + s << " warn \r\n"; + s << " info \r\n"; + s << " debug
\r\n
\r\n"; uint16_t maxTunnels = GetMaxNumTransitTunnels (); s << "" << tr("Transit tunnels limit") << "
\r\n"; s << "

\r\n"; s << " \r\n"; s << " \r\n"; - s << " \r\n"; + s << " \r\n"; s << " \r\n"; s << "
\r\n
\r\n"; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index 603bc25e..f41d925d 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/daemon/HTTPServerResources.h b/daemon/HTTPServerResources.h index 0acbe8d1..1e5b6f75 100644 --- a/daemon/HTTPServerResources.h +++ b/daemon/HTTPServerResources.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -38,7 +38,7 @@ namespace http "@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n" "body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n" "a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n" - "a:hover, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n" + "a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n" "a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n" ".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n" ".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n" diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index 94e65691..65b00e10 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -126,7 +126,7 @@ namespace log { if (level == "none") { m_MinLevel = eLogNone; } else if (level == "error") { m_MinLevel = eLogError; } else if (level == "warn") { m_MinLevel = eLogWarning; } - else if (level == "info") { m_MinLevel = eLogInfo; } + else if (level == "info") { m_MinLevel = eLogInfo; } else if (level == "debug") { m_MinLevel = eLogDebug; } else { LogPrint(eLogError, "Log: Unknown loglevel: ", level); diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 6b015f2b..b8ecd199 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -347,7 +347,7 @@ namespace proxy { std::string full_url = m_RequestURL.to_string(); std::stringstream ss; ss << tr("Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", - m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); + m_RequestURL.host.c_str(), full_url.c_str(), (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump.c_str()); GenericProxyInfo(tr("Addresshelper forced update rejected"), ss.str()); } else // Preventing unauthorized additions to the address book @@ -356,7 +356,7 @@ namespace proxy { std::string full_url = m_RequestURL.to_string(); std::stringstream ss; ss << tr("To add host %s in router's addressbook, click here: Continue.", - m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); + m_RequestURL.host.c_str(), full_url.c_str(), (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump.c_str()); GenericProxyInfo(tr("Addresshelper request"), ss.str()); } return true; /* request processed */ @@ -366,7 +366,8 @@ namespace proxy { LogPrint (eLogInfo, "HTTPProxy: Added address from addresshelper for ", m_RequestURL.host); std::string full_url = m_RequestURL.to_string(); std::stringstream ss; - ss << tr("Host %s added to router's addressbook from helper. Click here to proceed: Continue.", m_RequestURL.host, full_url); + ss << tr("Host %s added to router's addressbook from helper. Click here to proceed: Continue.", + m_RequestURL.host.c_str(), full_url.c_str()); GenericProxyInfo(tr("Addresshelper adding"), ss.str()); return true; /* request processed */ } @@ -375,7 +376,7 @@ namespace proxy { std::string full_url = m_RequestURL.to_string(); std::stringstream ss; ss << tr("Host %s is already in router's addressbook. Click here to update record: Continue.", - m_RequestURL.host, full_url, (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump); + m_RequestURL.host.c_str(), full_url.c_str(), (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper="), jump.c_str()); GenericProxyInfo(tr("Addresshelper update"), ss.str()); return true; /* request processed */ } @@ -452,7 +453,7 @@ namespace proxy { GenericProxyError(tr("Outproxy failure"), tr("Bad outproxy settings")); } else { LogPrint (eLogWarning, "HTTPProxy: Outproxy failure for ", dest_host, ": no outproxy enabled"); - std::stringstream ss; ss << tr("Host %s is not inside I2P network, but outproxy is not enabled", dest_host); + std::stringstream ss; ss << tr("Host %s is not inside I2P network, but outproxy is not enabled", dest_host.c_str()); GenericProxyError(tr("Outproxy failure"), ss.str()); } return true; From cd6d86c8c30a8c3250da2857a8a36722d185334e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Jan 2023 13:40:12 -0500 Subject: [PATCH 085/179] make sure that async CreateStream complete --- libi2pd/Destination.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 4a2cc4ae..7523b939 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1138,19 +1138,25 @@ namespace client template std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, int port) { + volatile bool done = false; std::shared_ptr stream; std::condition_variable streamRequestComplete; std::mutex streamRequestCompleteMutex; - std::unique_lock l(streamRequestCompleteMutex); CreateStream ( - [&streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr s) + [&done, &streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr s) { stream = s; std::unique_lock l(streamRequestCompleteMutex); streamRequestComplete.notify_all (); + done = true; }, dest, port); - streamRequestComplete.wait (l); + while (!done) + { + std::unique_lock l(streamRequestCompleteMutex); + if (!done) + streamRequestComplete.wait (l); + } return stream; } From 47eb49c34e0da0a8db18cd70cd96e734f89e7c66 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 20 Jan 2023 18:52:56 +0200 Subject: [PATCH 086/179] use correct style for Server Forwards section --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 2bf92df3..7a5175ce 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1001,7 +1001,7 @@ namespace http { for (auto& it: serverForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << "
"; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; From d4426118c5f030f3b8a127922426c7a9b9f599dc Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 20 Jan 2023 15:34:40 -0500 Subject: [PATCH 087/179] exclude router from tunnel build for 2.5 minutes if declined --- libi2pd/Profiling.cpp | 20 +++++++++++++++++++- libi2pd/Profiling.h | 7 +++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 55b95831..06b1ec17 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -12,6 +12,7 @@ #include "Base.h" #include "FS.h" #include "Log.h" +#include "Timestamp.h" #include "Profiling.h" namespace i2p @@ -22,6 +23,7 @@ namespace data RouterProfile::RouterProfile (): m_LastUpdateTime (boost::posix_time::second_clock::local_time()), + m_LastDeclineTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), m_NumTimesTaken (0), m_NumTimesRejected (0) { @@ -131,9 +133,15 @@ namespace data { UpdateTime (); if (ret > 0) + { m_NumTunnelsDeclined++; + m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); + } else + { m_NumTunnelsAgreed++; + m_LastDeclineTime = 0; + } } void RouterProfile::TunnelNonReplied () @@ -153,8 +161,18 @@ namespace data return m_NumTunnelsNonReplied > 10*(total + 1); } + bool RouterProfile::IsDeclinedRecently () + { + if (!m_LastDeclineTime) return false; + auto ts = i2p::util::GetSecondsSinceEpoch (); + if (ts > m_LastDeclineTime + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL) + m_LastDeclineTime = 0; + return m_LastDeclineTime; + } + bool RouterProfile::IsBad () { + if (IsDeclinedRecently ()) return true; auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/; if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) { diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 49e362ca..1c523a22 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -31,6 +31,7 @@ namespace data const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days) const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day) const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours) + const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) class RouterProfile { @@ -55,10 +56,12 @@ namespace data bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; }; bool IsLowPartcipationRate () const; bool IsLowReplyRate () const; + bool IsDeclinedRecently (); private: - boost::posix_time::ptime m_LastUpdateTime; + boost::posix_time::ptime m_LastUpdateTime; // TODO: use std::chrono + uint64_t m_LastDeclineTime; // in seconds // participation uint32_t m_NumTunnelsAgreed; uint32_t m_NumTunnelsDeclined; From e1ec79daf239cf5f1945ef14ba875943b05b2b66 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 21 Jan 2023 00:50:53 +0300 Subject: [PATCH 088/179] [webconsole] format transit tunnels with table Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 7a5175ce..6166c97c 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -779,19 +779,20 @@ namespace http { { if (i2p::tunnel::tunnels.CountTransitTunnels()) { - s << "" << tr("Transit Tunnels") << ":
\r\n
\r\n"; + s << "" << tr("Transit Tunnels") << ":
\r\n"; + s << ""; for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) { - s << "
\r\n"; if (std::dynamic_pointer_cast(it)) - s << it->GetTunnelID () << " ⇒ "; + s << "
\r\n"; } - s << "\r\n"; + s << "
ID" << tr("Amount") << "
" << it->GetTunnelID () << ""; else if (std::dynamic_pointer_cast(it)) - s << " ⇒ " << it->GetTunnelID (); + s << "
" << it->GetTunnelID () << ""; else - s << " ⇒ " << it->GetTunnelID () << " ⇒ "; - s << " " << it->GetNumTransmittedBytes () << "\r\n"; + s << "
" << it->GetTunnelID () << ""; + ShowTraffic(s, it->GetNumTransmittedBytes ()); + s << "
\r\n"; } else { From 8baf62eb2ccad24678e22edae5785ada434aa82d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 21 Jan 2023 01:55:43 +0300 Subject: [PATCH 089/179] [websonsole] fix int concatenation with char strings Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 6166c97c..02b689a6 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1212,7 +1212,7 @@ namespace http { url.parse_query(params); std::string webroot; i2p::config::GetOption("http.webroot", webroot); - std::string redirect = COMMAND_REDIRECT_TIMEOUT + "; url=" + webroot + "?page=commands"; + std::string redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=commands"; std::string token = params["token"]; if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) @@ -1287,7 +1287,7 @@ namespace http { s << "" << tr("Return to destination page") << "
\r\n"; s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; - redirect = COMMAND_REDIRECT_TIMEOUT + "; url=" + webroot + "?page=local_destination&b32=" + b32; + redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32; res.add_header("Refresh", redirect.c_str()); return; } From ac287a896c289bebb9d0c69c711de53aeac449dc Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 20 Jan 2023 23:03:00 +0000 Subject: [PATCH 090/179] [websonsole] use a function to format the amount of tunnel traffic Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 02b689a6..0b99c047 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -150,7 +150,8 @@ namespace http { else stateText = tr("unknown"); s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; - s << " " << tr(/* tr: Kibibyte */ "%.2f KiB", (double) bytes / 1024) << "\r\n"; + ShowTraffic(s, bytes); + s << "\r\n"; } static void SetLogLevel (const std::string& level) From 067fb45a252fa87ecba8ed2fe781f953fa14cc56 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Jan 2023 19:40:43 -0500 Subject: [PATCH 091/179] exclude router from tunnel build for 2.5 minutes if doesn't reply too often --- libi2pd/Profiling.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 06b1ec17..f826bf43 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -148,6 +148,8 @@ namespace data { m_NumTunnelsNonReplied++; UpdateTime (); + if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3) + m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } bool RouterProfile::IsLowPartcipationRate () const From 1f23584c24747dda91a67c17a38f23212489775a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Jan 2023 21:24:01 -0500 Subject: [PATCH 092/179] update all SSU2 addresses --- libi2pd/RouterContext.cpp | 76 ++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index eb65d2ca..4713bb8a 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -397,41 +397,59 @@ namespace i2p { auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; - bool found = false, updated = false; - for (auto& it : *addresses) - { - if (it && it->IsSSU2 ()) - { - found = true; - if (enable) - { - it->s = m_SSU2Keys->staticPublicKey; - it->i = m_SSU2Keys->intro; - } - else - it.reset (); - updated = true; - } - } - if (enable && !found) + bool updated = false; + if (enable) { bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv6; i2p::config::GetOption("ipv6", ipv6); - bool published; i2p::config::GetOption("ntcp2.published", published); - if (published) + if (ipv4 && (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]) { - if (ipv4) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV4); - if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6); - } - else + (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]->s = m_SSU2Keys->staticPublicKey; + (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]->i = m_SSU2Keys->intro; + ipv4 = false; + } + if (ipv6 && (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]) { - uint8_t addressCaps = 0; - if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; - if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps); + (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]->s = m_SSU2Keys->staticPublicKey; + (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]->i = m_SSU2Keys->intro; + ipv6 = false; } - updated = true; - } + if (ipv4 && ipv6) + { + bool published; i2p::config::GetOption("ssu2.published", published); + if (!published) + { + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, + i2p::data::RouterInfo::AddressCaps::eV4 | i2p::data::RouterInfo::AddressCaps::eV6); + ipv4 = false; ipv6 = false; + updated = true; + } + } + if (ipv4) + { + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV4); + updated = true; + } + if (ipv6) + { + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6); + updated= true; + } + } + else + { + if ((*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]) + { + (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx] = nullptr; + updated = true; + } + if ((*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]) + { + (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx] = nullptr; + updated = true; + } + } + if (updated) UpdateRouterInfo (); } From 5479ddd03ce58b00a9bdd3f51667c0883f8f50df Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Jan 2023 14:07:22 -0500 Subject: [PATCH 093/179] publish NTCP2 addreses by index --- libi2pd/RouterContext.cpp | 81 +++++++++++++++++++++------------------ libi2pd/RouterContext.h | 5 ++- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 4713bb8a..6d529863 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -296,34 +296,50 @@ namespace i2p UpdateRouterInfo (); } + void RouterContext::PublishNTCP2Address (std::shared_ptr address, + int port, bool publish) const + { + if (!address) return; + if (!port && !address->port) port = SelectRandomPort (); + if (port) address->port = port; + address->published = publish; + memcpy (address->i, m_NTCP2Keys->iv, 16); + } + void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg) { if (!m_NTCP2Keys) return; auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; bool updated = false; - for (auto& address : *addresses) + if (v4) { - if (address && address->IsNTCP2 () && (address->port != port || address->published != publish)) + auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx]; + if (addr) { - bool isAddr = v4 && address->IsV4 (); - if (!isAddr && (v6 || ygg)) - { - if (i2p::util::net::IsYggdrasilAddress (address->host)) - isAddr = ygg; - else - isAddr = v6 && address->IsV6 (); - } - if (isAddr) - { - if (!port && !address->port) port = SelectRandomPort (); - if (port) address->port = port; - address->published = publish; - memcpy (address->i, m_NTCP2Keys->iv, 16); - updated = true; - } - } + PublishNTCP2Address (addr, port, publish); + updated = true; + } + } + if (v6) + { + auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx]; + if (addr) + { + PublishNTCP2Address (addr, port, publish); + updated = true; + } } + if (ygg) + { + auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]; + if (addr) + { + PublishNTCP2Address (addr, port, publish); + updated = true; + } + } + if (updated) UpdateRouterInfo (); } @@ -916,29 +932,18 @@ namespace i2p void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host) { - bool isYgg = i2p::util::net::IsYggdrasilAddress (host); - bool updated = false; auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; - for (auto& addr: *addresses) + std::shared_ptr addr; + if (i2p::util::net::IsYggdrasilAddress (host)) // yggdrasil + addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]; + else if (host.is_v6 ()) + addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx]; + if (addr && addr->IsPublishedNTCP2 () && addr->host != host) { - if (addr && addr->IsPublishedNTCP2 ()) - { - bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host); - if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1))) - { - if (addr->host != host) - { - addr->host = host; - updated = true; - } - break; - } - } - } - - if (updated) + addr->host = host; UpdateRouterInfo (); + } } void RouterContext::UpdateStats () diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index d3638b15..a2fd268f 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -181,7 +181,8 @@ namespace garlic bool Load (); void SaveKeys (); uint16_t SelectRandomPort () const; - + void PublishNTCP2Address (std::shared_ptr address, int port, bool publish) const; + bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize); private: From 4fae7b8d651ab759df03bd15dcb84dad17cc08f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Jan 2023 18:20:16 -0500 Subject: [PATCH 094/179] don't update local RouterInfo addresses in Load but in InitTransports only --- libi2pd/RouterContext.cpp | 64 +++++++++++++++------------------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 6d529863..62f4f3de 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -315,7 +315,7 @@ namespace i2p if (v4) { auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V4Idx]; - if (addr) + if (addr && (addr->port != port || addr->published != publish)) { PublishNTCP2Address (addr, port, publish); updated = true; @@ -324,7 +324,7 @@ namespace i2p if (v6) { auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx]; - if (addr) + if (addr && (addr->port != port || addr->published != publish)) { PublishNTCP2Address (addr, port, publish); updated = true; @@ -333,7 +333,7 @@ namespace i2p if (ygg) { auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6MeshIdx]; - if (addr) + if (addr && (addr->port != port || addr->published != publish)) { PublishNTCP2Address (addr, port, publish); updated = true; @@ -1011,6 +1011,27 @@ namespace i2p } n2k.close (); } + // create new NTCP2 keys if required + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); + if ((ntcp2 || ygg) && !m_NTCP2Keys) NewNTCP2Keys (); + // read SSU2 keys if available + std::ifstream s2k (i2p::fs::DataDirPath (SSU2_KEYS), std::ifstream::in | std::ifstream::binary); + if (s2k) + { + s2k.seekg (0, std::ios::end); + size_t len = s2k.tellg(); + s2k.seekg (0, std::ios::beg); + if (len == sizeof (SSU2PrivateKeys)) + { + m_SSU2Keys.reset (new SSU2PrivateKeys ()); + s2k.read ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); + } + s2k.close (); + } + // create new SSU2 keys if required + bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); + if (ssu2 && !m_SSU2Keys) NewSSU2Keys (); // read RouterInfo m_RouterInfo.SetRouterIdentity (oldIdentity ? oldIdentity : GetIdentity ()); i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO)); @@ -1030,42 +1051,6 @@ namespace i2p if (IsUnreachable ()) SetReachable (true, true); // we assume reachable until we discover firewall through peer tests - - // read NTCP2 - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); - if (ntcp2 || ygg) - { - if (!m_NTCP2Keys) NewNTCP2Keys (); - UpdateNTCP2Address (true); // enable NTCP2 - } - else - UpdateNTCP2Address (false); // disable NTCP2 - - // read SSU2 - bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - if (ssu2) - { - // read SSU2 keys if available - std::ifstream s2k (i2p::fs::DataDirPath (SSU2_KEYS), std::ifstream::in | std::ifstream::binary); - if (s2k) - { - s2k.seekg (0, std::ios::end); - size_t len = s2k.tellg(); - s2k.seekg (0, std::ios::beg); - if (len == sizeof (SSU2PrivateKeys)) - { - m_SSU2Keys.reset (new SSU2PrivateKeys ()); - s2k.read ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); - } - s2k.close (); - } - if (!m_SSU2Keys) NewSSU2Keys (); - UpdateSSU2Address (true); // enable SSU2 - } - else - UpdateSSU2Address (false); // disable SSU2 - return true; } @@ -1098,7 +1083,6 @@ namespace i2p return true; } - void RouterContext::ProcessGarlicMessage (std::shared_ptr msg) { std::unique_lock l(m_GarlicMutex); From b31f52e332cdae586f02e39228c4e229d07bc4ea Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 25 Jan 2023 08:54:45 +0000 Subject: [PATCH 095/179] [http] keep query even if it was empty (closes #1844) Signed-off-by: R4SAS --- libi2pd/HTTP.cpp | 5 ++++- libi2pd/HTTP.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 8791eadb..b8d7e8c3 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -160,6 +160,7 @@ namespace http return true; } else if (url.at(pos_c) == '?') { /* found query part */ + hasquery = true; path = url.substr(pos_p, pos_c - pos_p); pos_p = pos_c + 1; pos_c = url.find('#', pos_p); @@ -218,8 +219,10 @@ namespace http } } out += path; + if (hasquery) // add query even if it was empty + out += "?"; if (query != "") - out += "?" + query; + out += query; if (frag != "") out += "#" + frag; return out; diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 9445a01a..046eebb9 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -33,6 +33,7 @@ namespace http std::string host; unsigned short int port; std::string path; + bool hasquery; std::string query; std::string frag; From 273aa31b1e5253cb7795e6e7c8b38762d6c4dd4d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Jan 2023 12:43:46 -0500 Subject: [PATCH 096/179] try another floodfill if it's incompatible with tunnels --- libi2pd/Destination.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 7523b939..17bce5c4 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -763,9 +763,17 @@ namespace client request->requestTime = ts; if (!SendLeaseSetRequest (dest, floodfill, request)) { - // request failed - m_LeaseSetRequests.erase (ret.first); - if (requestComplete) requestComplete (nullptr); + // try another + LogPrint (eLogWarning, "Destination: Couldn't send LeaseSet request to ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another"); + request->excluded.insert (floodfill->GetIdentHash ()); + floodfill = i2p::data::netdb.GetClosestFloodfill (dest, request->excluded); + if (!SendLeaseSetRequest (dest, floodfill, request)) + { + // request failed + LogPrint (eLogWarning, "Destination: LeaseSet request for ", dest.ToBase32 (), " was not sent"); + m_LeaseSetRequests.erase (ret.first); + if (requestComplete) requestComplete (nullptr); + } } } else // duplicate @@ -792,11 +800,11 @@ namespace client std::shared_ptr nextFloodfill, std::shared_ptr request) { if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) - request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true)); - if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found"); + request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false)); // outbound from floodfill + if (!request->replyTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible inbound tunnels found"); if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ()) - request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false)); - if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found"); + request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true)); // inbound from floodfill + if (!request->outboundTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible outbound tunnels found"); if (request->replyTunnel && request->outboundTunnel) { From 4de6201b84dc8927fb46941495f3ee5872c7d642 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Jan 2023 13:23:46 -0500 Subject: [PATCH 097/179] update RouuterInfo if NTCP2 or SSU2 keys were recreated --- libi2pd/RouterContext.cpp | 117 ++++++++++++-------------------------- libi2pd/RouterContext.h | 7 +-- 2 files changed, 39 insertions(+), 85 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 62f4f3de..4188fa47 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -344,35 +344,21 @@ namespace i2p UpdateRouterInfo (); } - void RouterContext::UpdateNTCP2Address (bool enable) + void RouterContext::UpdateNTCP2Keys () { + if (!m_NTCP2Keys) return; auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; - bool found = false, updated = false; for (auto& it: *addresses) { if (it && it->IsNTCP2 ()) { - found = true; - if (enable) - { - it->s = m_NTCP2Keys->staticPublicKey; - memcpy (it->i, m_NTCP2Keys->iv, 16); - } - else - it.reset (); - updated = true; + it->s = m_NTCP2Keys->staticPublicKey; + memcpy (it->i, m_NTCP2Keys->iv, 16); } } - if (enable && !found) - { - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); - updated = true; - } - if (updated) - UpdateRouterInfo (); - } - + } + void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6) { if (!m_SSU2Keys) return; @@ -409,67 +395,21 @@ namespace i2p UpdateRouterInfo (); } - void RouterContext::UpdateSSU2Address (bool enable) + void RouterContext::UpdateSSU2Keys () { + if (!m_SSU2Keys) return; auto addresses = m_RouterInfo.GetAddresses (); if (!addresses) return; - bool updated = false; - if (enable) + for (auto& it: *addresses) { - bool ipv4; i2p::config::GetOption("ipv4", ipv4); - bool ipv6; i2p::config::GetOption("ipv6", ipv6); - if (ipv4 && (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]) + if (it && it->IsSSU2 ()) { - (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]->s = m_SSU2Keys->staticPublicKey; - (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]->i = m_SSU2Keys->intro; - ipv4 = false; - } - if (ipv6 && (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]) - { - (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]->s = m_SSU2Keys->staticPublicKey; - (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]->i = m_SSU2Keys->intro; - ipv6 = false; + it->s = m_SSU2Keys->staticPublicKey; + it->i = m_SSU2Keys->intro; } - if (ipv4 && ipv6) - { - bool published; i2p::config::GetOption("ssu2.published", published); - if (!published) - { - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, - i2p::data::RouterInfo::AddressCaps::eV4 | i2p::data::RouterInfo::AddressCaps::eV6); - ipv4 = false; ipv6 = false; - updated = true; - } - } - if (ipv4) - { - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV4); - updated = true; - } - if (ipv6) - { - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6); - updated= true; - } - } - else - { - if ((*addresses)[i2p::data::RouterInfo::eSSU2V4Idx]) - { - (*addresses)[i2p::data::RouterInfo::eSSU2V4Idx] = nullptr; - updated = true; - } - if ((*addresses)[i2p::data::RouterInfo::eSSU2V6Idx]) - { - (*addresses)[i2p::data::RouterInfo::eSSU2V6Idx] = nullptr; - updated = true; - } - } + } + } - if (updated) - UpdateRouterInfo (); - } - void RouterContext::UpdateAddress (const boost::asio::ip::address& host) { auto addresses = m_RouterInfo.GetAddresses (); @@ -1011,10 +951,6 @@ namespace i2p } n2k.close (); } - // create new NTCP2 keys if required - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); - if ((ntcp2 || ygg) && !m_NTCP2Keys) NewNTCP2Keys (); // read SSU2 keys if available std::ifstream s2k (i2p::fs::DataDirPath (SSU2_KEYS), std::ifstream::in | std::ifstream::binary); if (s2k) @@ -1029,9 +965,6 @@ namespace i2p } s2k.close (); } - // create new SSU2 keys if required - bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - if (ssu2 && !m_SSU2Keys) NewSSU2Keys (); // read RouterInfo m_RouterInfo.SetRouterIdentity (oldIdentity ? oldIdentity : GetIdentity ()); i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO)); @@ -1051,6 +984,28 @@ namespace i2p if (IsUnreachable ()) SetReachable (true, true); // we assume reachable until we discover firewall through peer tests + + bool updated = false; + // create new NTCP2 keys if required + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); + if ((ntcp2 || ygg) && !m_NTCP2Keys) + { + NewNTCP2Keys (); + UpdateNTCP2Keys (); + updated = true; + } + // create new SSU2 keys if required + bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); + if (ssu2 && !m_SSU2Keys) + { + NewSSU2Keys (); + UpdateSSU2Keys (); + updated = true; + } + if (updated) + UpdateRouterInfo (); + return true; } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index a2fd268f..22359ded 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -116,11 +116,9 @@ namespace garlic bool DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data); void UpdatePort (int port); // called from Daemon - void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon + void UpdateAddress (const boost::asio::ip::address& host); // called from SSU2 or Daemon void PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg); - void UpdateNTCP2Address (bool enable); void PublishSSU2Address (int port, bool publish, bool v4, bool v6); - void UpdateSSU2Address (bool enable); bool AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4); void RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4); void ClearSSU2Introducers (bool v4); @@ -177,7 +175,8 @@ namespace garlic void UpdateRouterInfo (); void NewNTCP2Keys (); void NewSSU2Keys (); - bool IsSSU2Only () const; // SSU2 and no SSU + void UpdateNTCP2Keys (); + void UpdateSSU2Keys (); bool Load (); void SaveKeys (); uint16_t SelectRandomPort () const; From 8ee461f60aa70a70ecc75c9c64dd1ecdbee4fa3e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Jan 2023 18:11:26 -0500 Subject: [PATCH 098/179] enable all ipv4 adresses even if one is already enabled --- libi2pd/RouterContext.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 4188fa47..54817b2e 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -749,10 +749,6 @@ namespace i2p void RouterContext::SetSupportsV4 (bool supportsV4) { - // check if updates - if (supportsV4 && SupportsV4 ()) return; - if (!supportsV4 && !SupportsV4 ()) return; - // update if (supportsV4) { bool foundNTCP2 = false, foundSSU2 = false; From e91d0bbec8310f77d5ca4f7b54dec5dfe8dfc3ad Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Jan 2023 11:21:08 -0500 Subject: [PATCH 099/179] delete address if corresponding transport is disabled --- libi2pd/RouterContext.cpp | 40 +++++++++++++++++++------------ libi2pd/RouterInfo.cpp | 50 ++++++++++++++++++++++++++++++++------- libi2pd/RouterInfo.h | 2 ++ 3 files changed, 69 insertions(+), 23 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 54817b2e..1c2e5be6 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -702,12 +702,12 @@ namespace i2p if (!port) port = SelectRandomPort (); } // NTCP2 - if (!foundNTCP2) + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + if (ntcp2) { - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); - if (ntcp2) + if (!foundNTCP2) { + bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); if (ntcp2Published) { std::string ntcp2Host; @@ -723,11 +723,13 @@ namespace i2p m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV6); } } + else + m_RouterInfo.RemoveNTCP2Address (false); // SSU2 - if (!foundSSU2) + bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); + if (ssu2) { - bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - if (ssu2) + if (!foundSSU2) { bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published); if (ssu2Published) @@ -740,7 +742,10 @@ namespace i2p m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6); } } - m_RouterInfo.EnableV6 (); + else + m_RouterInfo.RemoveSSU2Address (false); + if (ntcp2 || ssu2) + m_RouterInfo.EnableV6 (); } else m_RouterInfo.DisableV6 (); @@ -781,10 +786,10 @@ namespace i2p if (!port) port = SelectRandomPort (); } // NTCP2 - if (!foundNTCP2) + bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); + if (ntcp2) { - bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); - if (ntcp2) + if (!foundNTCP2) { bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); if (ntcp2Published) @@ -797,11 +802,13 @@ namespace i2p m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV4); } } + else + m_RouterInfo.RemoveNTCP2Address (false); // SSU2 - if (!foundSSU2) + bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); + if (ssu2) { - bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - if (ssu2) + if (!foundSSU2) { bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published); if (ssu2Published) @@ -814,7 +821,10 @@ namespace i2p m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV4); } } - m_RouterInfo.EnableV4 (); + else + m_RouterInfo.RemoveSSU2Address (false); + if (ntcp2 || ssu2) + m_RouterInfo.EnableV4 (); } else m_RouterInfo.DisableV4 (); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 1aa0259b..9e4701d3 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -655,6 +655,23 @@ namespace data } } + void RouterInfo::RemoveNTCP2Address (bool v4) + { + if (v4) + { + if ((*m_Addresses)[eNTCP2V6Idx]) + (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; + (*m_Addresses)[eNTCP2V4Idx].reset (); + } + else + { + if ((*m_Addresses)[eNTCP2V4Idx]) + (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; + (*m_Addresses)[eNTCP2V6Idx].reset (); + } + UpdateSupportedTransports (); + } + void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps) { auto addr = std::make_shared

(); @@ -706,6 +723,23 @@ namespace data } } + void RouterInfo::RemoveSSU2Address (bool v4) + { + if (v4) + { + if ((*m_Addresses)[eSSU2V6Idx]) + (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; + (*m_Addresses)[eSSU2V4Idx].reset (); + } + else + { + if ((*m_Addresses)[eSSU2V4Idx]) + (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; + (*m_Addresses)[eSSU2V6Idx].reset (); + } + UpdateSupportedTransports (); + } + bool RouterInfo::IsNTCP2 (bool v4only) const { if (v4only) @@ -744,14 +778,14 @@ namespace data { if ((*m_Addresses)[eNTCP2V6Idx]) { - if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 ()) - (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV6; + if ((*m_Addresses)[eNTCP2V6Idx]->IsV4 () && (*m_Addresses)[eNTCP2V4Idx]) + (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eNTCP2V6Idx].reset (); } if ((*m_Addresses)[eSSU2V6Idx]) { - if ((*m_Addresses)[eSSU2V6Idx]->IsV4 ()) - (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV6; + if ((*m_Addresses)[eSSU2V6Idx]->IsV4 () && (*m_Addresses)[eSSU2V4Idx]) + (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eSSU2V6Idx].reset (); } UpdateSupportedTransports (); @@ -764,14 +798,14 @@ namespace data { if ((*m_Addresses)[eNTCP2V4Idx]) { - if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 ()) - (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV4; + if ((*m_Addresses)[eNTCP2V4Idx]->IsV6 () && (*m_Addresses)[eNTCP2V6Idx]) + (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eNTCP2V4Idx].reset (); } if ((*m_Addresses)[eSSU2V4Idx]) { - if ((*m_Addresses)[eSSU2V4Idx]->IsV6 ()) - (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV4; + if ((*m_Addresses)[eSSU2V4Idx]->IsV6 () && (*m_Addresses)[eSSU2V6Idx]) + (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eSSU2V4Idx].reset (); } UpdateSupportedTransports (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 4e54d615..10405a0a 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -200,9 +200,11 @@ namespace data void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0); + void RemoveNTCP2Address (bool v4); void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps = 0); // non published void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, const boost::asio::ip::address& host, int port); // published + void RemoveSSU2Address (bool v4); void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps void UpdateSupportedTransports (); bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; }; From ad5540c9f379d5ca6f3c31c81356c9395da020ad Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Jan 2023 11:32:59 -0500 Subject: [PATCH 100/179] delete address if corresponding transport is disabled --- libi2pd/RouterContext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 1c2e5be6..86a0e915 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -803,7 +803,7 @@ namespace i2p } } else - m_RouterInfo.RemoveNTCP2Address (false); + m_RouterInfo.RemoveNTCP2Address (true); // SSU2 bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); if (ssu2) @@ -822,7 +822,7 @@ namespace i2p } } else - m_RouterInfo.RemoveSSU2Address (false); + m_RouterInfo.RemoveSSU2Address (true); if (ntcp2 || ssu2) m_RouterInfo.EnableV4 (); } From 126ca0209bb084942805c05aedf9f684c97b6e81 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 27 Jan 2023 20:11:05 +0000 Subject: [PATCH 101/179] [gha] update docker build workflow Signed-off-by: R4SAS --- .github/workflows/docker.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 899a7eec..262ab51c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -57,6 +57,7 @@ jobs: tags: | purplei2p/i2pd:latest-${{ matrix.archname }} ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }} + provenance: false push: runs-on: ubuntu-latest @@ -92,15 +93,15 @@ jobs: - name: Create and push latest manifest image to Docker Hub uses: Noelware/docker-manifest-action@master with: - base-image: purplei2p/i2pd:latest - extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + images: purplei2p/i2pd:latest + inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push latest manifest image to GHCR uses: Noelware/docker-manifest-action@master with: - base-image: ghcr.io/purplei2p/i2pd:latest - extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + images: ghcr.io/purplei2p/i2pd:latest + inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true - name: Store release version to env @@ -111,30 +112,30 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - base-image: purplei2p/i2pd:latest-release - extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + images: purplei2p/i2pd:latest-release + inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push release manifest image to GHCR if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - base-image: ghcr.io/purplei2p/i2pd:latest-release - extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + images: ghcr.io/purplei2p/i2pd:latest-release + inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true - name: Create and push versioned manifest image to Docker Hub if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - base-image: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + images: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push versioned manifest image to GHCR if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - base-image: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + images: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true From f9331897b881338f108ae4479bbbe14491480066 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 27 Jan 2023 21:11:26 +0000 Subject: [PATCH 102/179] [gha] fix docker manifest merging Signed-off-by: R4SAS --- .github/workflows/docker.yml | 38 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 262ab51c..1f3142e4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -91,51 +91,37 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Create and push latest manifest image to Docker Hub + if: ${{ !startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - images: purplei2p/i2pd:latest - inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + inputs: purplei2p/i2pd:latest + images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push latest manifest image to GHCR + if: ${{ !startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - images: ghcr.io/purplei2p/i2pd:latest - inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + inputs: ghcr.io/purplei2p/i2pd:latest + images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true - name: Store release version to env if: ${{ startsWith(github.ref, 'refs/tags/') }} run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV - - name: Create and push release manifest image to Docker Hub + - name: Create and push release manifest to Docker Hub if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - images: purplei2p/i2pd:latest-release - inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - - name: Create and push release manifest image to GHCR + - name: Create and push release manifest to GHCR if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: Noelware/docker-manifest-action@master with: - images: ghcr.io/purplei2p/i2pd:latest-release - inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 - push: true - - - name: Create and push versioned manifest image to Docker Hub - if: ${{ startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - images: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - inputs: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 - push: true - - - name: Create and push versioned manifest image to GHCR - if: ${{ startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - images: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - inputs: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true From 8a106eb09e421eb99e6cbb6c93df6e48a51bf2e0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 28 Jan 2023 17:18:54 -0500 Subject: [PATCH 103/179] fixed test-http-req --- libi2pd/HTTP.cpp | 10 +++++++++- libi2pd/HTTP.h | 4 +++- tests/test-http-req.cpp | 30 +++++++++++++++--------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index b8d7e8c3..8b61c7e5 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -350,6 +350,14 @@ namespace http return ""; } + size_t HTTPReq::GetNumHeaders (const std::string& name) const + { + size_t num = 0; + for (auto& it : headers) + if (it.first == name) num++; + return num; + } + bool HTTPRes::is_chunked() const { auto it = headers.find("Transfer-Encoding"); diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 046eebb9..9b8788ec 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -102,6 +102,8 @@ namespace http void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); }; std::string GetHeader (const std::string& name) const; + size_t GetNumHeaders (const std::string& name) const; + size_t GetNumHeaders () const { return headers.size (); }; }; struct HTTPRes : HTTPMsg { diff --git a/tests/test-http-req.cpp b/tests/test-http-req.cpp index 6deb66b0..db973a2e 100644 --- a/tests/test-http-req.cpp +++ b/tests/test-http-req.cpp @@ -22,13 +22,13 @@ int main() { assert(req->version == "HTTP/1.0"); assert(req->method == "GET"); assert(req->uri == "/"); - assert(req->headers.size() == 3); - assert(req->headers.count("Host") == 1); - assert(req->headers.count("Accept") == 1); - assert(req->headers.count("User-Agent") == 1); - assert(req->headers.find("Host")->second == "inr.i2p"); - assert(req->headers.find("Accept")->second == "*/*"); - assert(req->headers.find("User-Agent")->second == "curl/7.26.0"); + assert(req->GetNumHeaders () == 3); + assert(req->GetNumHeaders("Host") == 1); + assert(req->GetNumHeaders("Accept") == 1); + assert(req->GetNumHeaders("User-Agent") == 1); + assert(req->GetHeader("Host") == "inr.i2p"); + assert(req->GetHeader("Accept") == "*/*"); + assert(req->GetHeader("User-Agent") == "curl/7.26.0"); delete req; /* test: parsing request without body */ @@ -41,7 +41,7 @@ int main() { assert(req->version == "HTTP/1.0"); assert(req->method == "GET"); assert(req->uri == "/"); - assert(req->headers.size() == 0); + assert(req->GetNumHeaders () == 0); delete req; /* test: parsing request without body */ @@ -74,13 +74,13 @@ int main() { assert((ret = req->parse(buf, len)) == len); /* no host header */ assert(req->method == "GET"); assert(req->uri == "http://inr.i2p"); - assert(req->headers.size() == 3); - assert(req->headers.count("Host") == 1); - assert(req->headers.count("Accept") == 1); - assert(req->headers.count("Accept-Encoding") == 1); - assert(req->headers["Host"] == "stats.i2p"); - assert(req->headers["Accept"] == "*/*"); - assert(req->headers["Accept-Encoding"] == ""); + assert(req->GetNumHeaders () == 3); + assert(req->GetNumHeaders("Host") == 1); + assert(req->GetNumHeaders("Accept") == 1); + assert(req->GetNumHeaders("Accept-Encoding") == 1); + assert(req->GetHeader("Host") == "stats.i2p"); + assert(req->GetHeader("Accept") == "*/*"); + assert(req->GetHeader("Accept-Encoding") == ""); delete req; return 0; From 70fec2bc99612d7d7085ae69a4a42dfb46ab91b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 28 Jan 2023 22:33:44 -0500 Subject: [PATCH 104/179] don't publish localhost addresses in RouterInfo --- libi2pd/Config.cpp | 4 +- libi2pd/RouterContext.cpp | 208 +++++++++++++++++++++++++------------- libi2pd/RouterInfo.cpp | 38 +++++-- libi2pd/RouterInfo.h | 5 +- 4 files changed, 170 insertions(+), 85 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 556b226b..07ab2f20 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -45,7 +45,7 @@ namespace config { ("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)") ("family", value()->default_value(""), "Specify a family, router belongs to") ("datadir", value()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") - ("host", value()->default_value("0.0.0.0"), "External IP") + ("host", value()->default_value(""), "External IP") ("ifname", value()->default_value(""), "Network interface to bind to") ("ifname4", value()->default_value(""), "Network interface to bind to for ipv4") ("ifname6", value()->default_value(""), "Network interface to bind to for ipv6") diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 86a0e915..d37bd440 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -88,92 +88,115 @@ namespace i2p uint8_t caps = 0, addressCaps = 0; if (ipv4) { - std::string host = "127.0.0.1"; - if (!i2p::config::IsDefault("host")) - i2p::config::GetOption("host", host); - else if (!nat) - { + std::string host; + if (!nat) // we have no NAT so set external address from local address - std::string address4; i2p::config::GetOption("address4", address4); - if (!address4.empty ()) host = address4; - } + i2p::config::GetOption("address4", host); + if (host.empty ()) i2p::config::GetOption("host", host); if (ntcp2) { - if (ntcp2Published) - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v4::from_string (host), port); - else // add non-published NTCP2 address + uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); + if (!ntcp2Port) ntcp2Port = port; + bool added = false; + if (ntcp2Published && ntcp2Port) + { + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v4 ()) + { + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); + added = true; + } + } + } + if (!added) { + // add non-published NTCP2 address addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::AddressCaps::eV4); } } if (ssu2) { - if (ssu2Published) - { - uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); - if (!ssu2Port) ssu2Port = port; - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port); - } - else + uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); + if (!ssu2Port) ssu2Port = port; + bool added = false; + if (ssu2Published && ssu2Port) + { + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v4 ()) + { + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); + added = true; + } + } + } + if (!added) { addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro); + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::AddressCaps::eV4); } } } if (ipv6) { - std::string host; - if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only - i2p::config::GetOption("host", host); - else - { - std::string address6; i2p::config::GetOption("address6", address6); - if (!address6.empty ()) host = address6; - } + std::string host; i2p::config::GetOption("address6", host); + if (host.empty () && !ipv4) i2p::config::GetOption("host", host); // use host for ipv6 only if ipv4 is not presented if (ntcp2) { + uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); + if (!ntcp2Port) ntcp2Port = port; bool added = false; - if (ntcp2Published) + if (ntcp2Published && ntcp2Port) { std::string ntcp2Host; if (!i2p::config::IsDefault ("ntcp2.addressv6")) i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); else ntcp2Host = host; - if (!ntcp2Host.empty () && port) + if (!ntcp2Host.empty ()) { - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port); - added = true; + auto addr = boost::asio::ip::address::from_string (ntcp2Host); + if (addr.is_v6 ()) + { + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); + added = true; + } } } if (!added) { if (!ipv4) // no other ntcp2 addresses yet - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::AddressCaps::eV6); addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; } } if (ssu2) { + uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); + if (!ssu2Port) ssu2Port = port; bool added = false; - if (ssu2Published) + if (ssu2Published && ssu2Port) { - uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); - if (!ssu2Port) ssu2Port = port; - if (!host.empty () && ssu2Port) - { - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port); - added = true; - } + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v6 ()) + { + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); + added = true; + } + } } if (!added) { if (!ipv4) // no other ssu2 addresses yet - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro); + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::AddressCaps::eV6); addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; } } @@ -286,7 +309,7 @@ namespace i2p bool updated = false; for (auto& address : *addresses) { - if (address && address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) + if (address && address->port != port) { address->port = port; updated = true; @@ -707,6 +730,9 @@ namespace i2p { if (!foundNTCP2) { + uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); + if (!ntcp2Port) ntcp2Port = port; + bool added = false; bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); if (ntcp2Published) { @@ -714,13 +740,19 @@ namespace i2p if (!i2p::config::IsDefault ("ntcp2.addressv6")) i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); else - ntcp2Host = "::1"; - uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); - if (!ntcp2Port) ntcp2Port = port; - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port); + i2p::config::GetOption("host", ntcp2Host); + if (!ntcp2Host.empty () && ntcp2Port) + { + auto addr = boost::asio::ip::address::from_string (ntcp2Host); + if (addr.is_v6 ()) + { + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); + added = true; + } + } } - else - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV6); + if (!added) + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV6); } } else @@ -731,15 +763,25 @@ namespace i2p { if (!foundSSU2) { + uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); + if (!ssu2Port) ssu2Port = port; + bool added = false; bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published); - if (ssu2Published) + if (ssu2Published && ssu2Port) { - uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); - if (!ssu2Port) ssu2Port = port; - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("::1"), ssu2Port); - } - else - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6); + std::string host; i2p::config::GetOption("host", host); + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v6 ()) + { + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); + added = true; + } + } + } + if (!added) + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV6); } } else @@ -757,7 +799,6 @@ namespace i2p if (supportsV4) { bool foundNTCP2 = false, foundSSU2 = false; - std::string host = "127.0.0.1"; uint16_t port = 0; auto addresses = m_RouterInfo.GetAddresses (); if (addresses) @@ -791,15 +832,25 @@ namespace i2p { if (!foundNTCP2) { + uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); + if (!ntcp2Port) ntcp2Port = port; + bool added = false; bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); - if (ntcp2Published) - { - uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); - if (!ntcp2Port) ntcp2Port = port; - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (host), ntcp2Port); - } - else - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV4); + if (ntcp2Published && ntcp2Port) + { + std::string host; i2p::config::GetOption("host", host); + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v4 ()) + { + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); + added = true; + } + } + } + if (!added) + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV4); } } else @@ -810,15 +861,26 @@ namespace i2p { if (!foundSSU2) { + uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); + if (!ssu2Port) ssu2Port = port; + bool added = false; bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published); - if (ssu2Published) - { - uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); - if (!ssu2Port) ssu2Port = port; - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("127.0.0.1"), ssu2Port); - } - else - m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV4); + std::string host; i2p::config::GetOption("host", host); + if (ssu2Published && ssu2Port) + { + std::string host; i2p::config::GetOption("host", host); + if (!host.empty ()) + { + auto addr = boost::asio::ip::address::from_string (host); + if (addr.is_v4 ()) + { + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); + added = true; + } + } + } + if (!added) + m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV4); } } else diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 9e4701d3..ff86fb51 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -620,22 +620,44 @@ namespace data return l+1; } - void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, - const boost::asio::ip::address& host, int port, uint8_t caps) + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps) { auto addr = std::make_shared
(); - addr->host = host; addr->port = port; addr->transportStyle = eTransportNTCP2; addr->caps = caps; addr->date = 0; - if (port) addr->published = true; + addr->published = false; memcpy (addr->s, staticKey, 32); memcpy (addr->i, iv, 16); if (addr->IsV4 ()) { m_SupportedTransports |= eNTCP2V4; - if (addr->published) m_ReachableTransports |= eNTCP2V4; + (*m_Addresses)[eNTCP2V4Idx] = addr; + } + if (addr->IsV6 ()) + { + m_SupportedTransports |= eNTCP2V6; + (*m_Addresses)[eNTCP2V6Idx] = addr; + } + } + + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, + const boost::asio::ip::address& host, int port) + { + auto addr = std::make_shared
(); + addr->host = host; + addr->port = port; + addr->transportStyle = eTransportNTCP2; + addr->caps = 0; + addr->date = 0; + addr->published = true; + memcpy (addr->s, staticKey, 32); + memcpy (addr->i, iv, 16); + if (addr->IsV4 ()) + { + m_SupportedTransports |= eNTCP2V4; + m_ReachableTransports |= eNTCP2V4; (*m_Addresses)[eNTCP2V4Idx] = addr; } if (addr->IsV6 ()) @@ -649,7 +671,7 @@ namespace data else { m_SupportedTransports |= eNTCP2V6; - if (addr->published) m_ReachableTransports |= eNTCP2V6; + m_ReachableTransports |= eNTCP2V6; (*m_Addresses)[eNTCP2V6Idx] = addr; } } @@ -672,11 +694,11 @@ namespace data UpdateSupportedTransports (); } - void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps) + void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, int port, uint8_t caps) { auto addr = std::make_shared
(); addr->transportStyle = eTransportSSU2; - addr->port = 0; + addr->port = port; addr->caps = caps; addr->date = 0; addr->ssu.reset (new SSUExt ()); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 10405a0a..7d004a33 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -198,10 +198,11 @@ namespace data std::shared_ptr GetSSU2V6Address () const; std::shared_ptr GetSSU2Address (bool v4) const; + void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps); // non published void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, - const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0); + const boost::asio::ip::address& host, int port); // published void RemoveNTCP2Address (bool v4); - void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps = 0); // non published + void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, int port, uint8_t caps); // non published void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, const boost::asio::ip::address& host, int port); // published void RemoveSSU2Address (bool v4); From 86dbfdb53686906e46ddcbce6d013d37872ffd5a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Jan 2023 09:19:12 -0500 Subject: [PATCH 105/179] mutex for encrypted LeaseSet update --- libi2pd/Destination.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 17bce5c4..d202af96 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -467,12 +467,15 @@ namespace client { auto ls2 = std::make_shared (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ()); - if (ls2->IsValid ()) + if (ls2->IsValid () && !ls2->IsExpired ()) { + leaseSet = ls2; + std::lock_guard lock(m_RemoteLeaseSetsMutex); m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup - leaseSet = ls2; } + else + LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed"); } else LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2"); From 3cee8bfcb28a66ea832464ff31d722602c646416 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 30 Jan 2023 01:17:49 +0000 Subject: [PATCH 106/179] Update tests and corresponding makefiles (#1862) --- Makefile | 4 +-- Makefile.linux | 4 +-- build/.gitignore | 3 ++ libi2pd/HTTP.cpp | 4 +-- tests/.gitignore | 12 +++++++ tests/CMakeLists.txt | 48 ++++++++------------------ tests/Makefile | 52 ++++++++++++++++++----------- tests/test-aeadchacha20poly1305.cpp | 12 +++---- tests/test-blinding.cpp | 14 ++++---- tests/test-elligator.cpp | 12 +++---- tests/test-x25519.cpp | 7 ++-- 11 files changed, 89 insertions(+), 83 deletions(-) create mode 100644 tests/.gitignore diff --git a/Makefile b/Makefile index 35ee08a9..520a56ba 100644 --- a/Makefile +++ b/Makefile @@ -118,9 +118,9 @@ obj/%.o: %.cpp | mk_obj_dir $(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) -$(SHLIB): $(LIB_OBJS) $(SHLIB_LANG) +$(SHLIB): $(LIB_OBJS) ifneq ($(USE_STATIC),yes) - $(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB_LANG) + $(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) endif $(SHLIB_CLIENT): $(LIB_CLIENT_OBJS) $(SHLIB) $(SHLIB_LANG) diff --git a/Makefile.linux b/Makefile.linux index 9a3fdda3..d01f2b73 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -20,10 +20,10 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9 else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 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} "[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 - 19 +else ifeq ($(shell expr match ${CXXVER} "1[0-9]"),2) # gcc 10+ # NEEDED_CXXFLAGS += -std=c++20 NEEDED_CXXFLAGS += -std=c++17 LDLIBS = -latomic diff --git a/build/.gitignore b/build/.gitignore index 872332c5..7689cc88 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -1,5 +1,7 @@ # Various generated files /CMakeFiles/ +/Testing/ +/tests/ /i2pd /libi2pd.a /libi2pdclient.a @@ -8,6 +10,7 @@ /CMakeCache.txt /CPackConfig.cmake /CPackSourceConfig.cmake +/CTestTestfile.cmake /install_manifest.txt /arch.c # windows build script diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 8b61c7e5..7cc87df8 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -356,8 +356,8 @@ namespace http for (auto& it : headers) if (it.first == name) num++; return num; - } - + } + bool HTTPRes::is_chunked() const { auto it = headers.find("Transfer-Encoding"); diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..90457c23 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,12 @@ +/test-http-merge_chunked +/test-http-req +/test-http-res +/test-http-url +/test-http-url_decode +/test-gost +/test-gost-sig +/test-base-64 +/test-x25519 +/test-aeadchacha20poly1305 +/test-blinding +/test-elligator diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c6eec047..21daadd9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,9 +4,9 @@ include_directories(${CHECK_INCLUDE_DIRS}) # Compiler flags: if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -Wl,-undefined,dynamic_lookup") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -Wl,-undefined,dynamic_lookup") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -D_GLIBCXX_USE_NANOSLEEP=1 -Wl,--unresolved-symbols=ignore-in-object-files") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -Wl,--unresolved-symbols=ignore-in-object-files") endif() set(TEST_PATH ${CMAKE_CURRENT_BINARY_DIR}) @@ -18,80 +18,50 @@ include_directories( ) set(test-http-merge_chunked_SRCS - ../libi2pd/HTTP.cpp test-http-merge_chunked.cpp ) set(test-http-req_SRCS - ../libi2pd/HTTP.cpp test-http-req.cpp ) set(test-http-res_SRCS - ../libi2pd/HTTP.cpp test-http-res.cpp ) set(test-http-url_decode_SRCS - ../libi2pd/HTTP.cpp test-http-url_decode.cpp ) set(test-http-url_SRCS - ../libi2pd/HTTP.cpp test-http-url.cpp ) set(test-base-64_SRCS - ../libi2pd/Base.cpp test-base-64.cpp ) set(test-gost_SRCS - ../libi2pd/Gost.cpp - ../libi2pd/I2PEndian.cpp test-gost.cpp ) set(test-gost-sig_SRCS - ../libi2pd/Gost.cpp - ../libi2pd/I2PEndian.cpp - ../libi2pd/Crypto.cpp - ../libi2pd/Log.cpp test-gost-sig.cpp ) set(test-x25519_SRCS - ../libi2pd/Ed25519.cpp - ../libi2pd/I2PEndian.cpp - ../libi2pd/Log.cpp - ../libi2pd/Crypto.cpp test-x25519.cpp ) set(test-aeadchacha20poly1305_SRCS - ../libi2pd/Crypto.cpp - ../libi2pd/ChaCha20.cpp - ../libi2pd/Poly1305.cpp test-aeadchacha20poly1305.cpp ) set(test-blinding_SRCS - ../libi2pd/Crypto.cpp - ../libi2pd/Blinding.cpp - ../libi2pd/Ed25519.cpp - ../libi2pd/I2PEndian.cpp - ../libi2pd/Log.cpp - ../libi2pd/util.cpp - ../libi2pd/Identity.cpp - ../libi2pd/Signature.cpp - ../libi2pd/Timestamp.cpp test-blinding.cpp ) SET(test-elligator_SRCS - ../libi2pd/Elligator.cpp - ../libi2pd/Crypto.cpp test-elligator.cpp ) @@ -109,15 +79,23 @@ add_executable(test-blinding ${test-blinding_SRCS}) add_executable(test-elligator ${test-elligator_SRCS}) set(LIBS + libi2pd ${Boost_LIBRARIES} - ${CHECK_LDFLAGS} - ${CMAKE_REQUIRED_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto + ZLIB::ZLIB Threads::Threads + ${CHECK_LDFLAGS} + ${CMAKE_REQUIRED_LIBRARIES} ) -target_link_libraries(test-gost OpenSSL::Crypto Threads::Threads) +target_link_libraries(test-http-merge_chunked ${LIBS}) +target_link_libraries(test-http-req ${LIBS}) +target_link_libraries(test-http-res ${LIBS}) +target_link_libraries(test-http-url_decode ${LIBS}) +target_link_libraries(test-http-url ${LIBS}) +target_link_libraries(test-base-64 ${LIBS}) +target_link_libraries(test-gost ${LIBS}) target_link_libraries(test-gost-sig ${LIBS}) target_link_libraries(test-x25519 ${LIBS}) target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) diff --git a/tests/Makefile b/tests/Makefile index f8f6cf77..db71a06e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,36 +1,50 @@ -CXXFLAGS += -Wall -Wno-unused-parameter -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -pthread -Wl,--unresolved-symbols=ignore-in-object-files +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 INCFLAGS += -I../libi2pd -TESTS = test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding test-elligator +LIBI2PD = ../libi2pd.a + +TESTS = \ + test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \ + test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding test-elligator + +LDLIBS = \ + -lcrypto \ + -lssl \ + -lboost_filesystem \ + -lboost_program_options \ + -lpthread all: $(TESTS) run -test-http-%: ../libi2pd/HTTP.cpp test-http-%.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ +$(LIBI2PD): + @echo "Building libi2pd.a ..." && cd .. && $(MAKE) libi2pd.a -test-base-%: ../libi2pd/Base.cpp test-base-%.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ +test-http-%: test-http-%.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-gost: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp test-gost.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto +test-base-%: test-base-%.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-gost-sig: ../libi2pd/Gost.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Crypto.cpp ../libi2pd/Log.cpp test-gost-sig.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-gost: test-gost.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-x25519: ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/Crypto.cpp test-x25519.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-gost-sig: test-gost-sig.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-aeadchacha20poly1305: ../libi2pd/Crypto.cpp ../libi2pd/ChaCha20.cpp ../libi2pd/Poly1305.cpp test-aeadchacha20poly1305.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-x25519: test-x25519.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-blinding: ../libi2pd/Crypto.cpp ../libi2pd/Blinding.cpp ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/util.cpp ../libi2pd/Identity.cpp ../libi2pd/Signature.cpp ../libi2pd/Timestamp.cpp test-blinding.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-aeadchacha20poly1305: test-aeadchacha20poly1305.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) -test-elligator: ../libi2pd/Elligator.cpp ../libi2pd/Crypto.cpp test-elligator.cpp - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-blinding: test-blinding.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + +test-elligator: test-elligator.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) run: $(TESTS) - @for TEST in $(TESTS); do ./$$TEST ; done + @for TEST in $(TESTS); do echo Running $$TEST; ./$$TEST ; done clean: rm -f $(TESTS) diff --git a/tests/test-aeadchacha20poly1305.cpp b/tests/test-aeadchacha20poly1305.cpp index de9f1db2..64a0f358 100644 --- a/tests/test-aeadchacha20poly1305.cpp +++ b/tests/test-aeadchacha20poly1305.cpp @@ -7,28 +7,28 @@ char text[] = "Ladies and Gentlemen of the class of '99: If I could offer you " "only one tip for the future, sunscreen would be it."; // 114 bytes -uint8_t key[32] = +uint8_t key[32] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }; -uint8_t ad[12] = +uint8_t ad[12] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; -uint8_t nonce[12] = +uint8_t nonce[12] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; -uint8_t tag[16] = +uint8_t tag[16] = { 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 }; -uint8_t encrypted[114] = +uint8_t encrypted[114] = { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, @@ -53,7 +53,7 @@ int main () assert (memcmp (buf1, text, 114) == 0); // test encryption of multiple buffers memcpy (buf, text, 114); - std::vector > bufs{ std::make_pair (buf, 20), std::make_pair (buf + 20, 10), std::make_pair (buf + 30, 70), std::make_pair (buf + 100, 14) }; + std::vector > bufs{ std::make_pair (buf, 20), std::make_pair (buf + 20, 10), std::make_pair (buf + 30, 70), std::make_pair (buf + 100, 14) }; i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114); i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false); assert (memcmp (buf1, text, 114) == 0); diff --git a/tests/test-blinding.cpp b/tests/test-blinding.cpp index d7c41809..10b72e4f 100644 --- a/tests/test-blinding.cpp +++ b/tests/test-blinding.cpp @@ -13,12 +13,12 @@ void BlindTest (SigningKeyType sigType) { auto keys = PrivateKeys::CreateRandomKeys (sigType); BlindedPublicKey blindedKey (keys.GetPublic ()); - auto timestamp = GetSecondsSinceEpoch (); + auto timestamp = GetSecondsSinceEpoch (); char date[9]; GetDateString (timestamp, date); - uint8_t blindedPriv[32], blindedPub[32]; + uint8_t blindedPriv[32], blindedPub[32]; auto publicKeyLen = blindedKey.BlindPrivateKey (keys.GetSigningPrivateKey (), date, blindedPriv, blindedPub); - uint8_t blindedPub1[32]; + uint8_t blindedPub1[32]; blindedKey.GetBlindedKey (date, blindedPub1); // check if public key produced from private blinded key matches blided public key assert (!memcmp (blindedPub, blindedPub1, publicKeyLen)); @@ -26,16 +26,16 @@ void BlindTest (SigningKeyType sigType) std::unique_ptr blindedSigner (PrivateKeys::CreateSigner (blindedKey.GetBlindedSigType (), blindedPriv)); uint8_t buf[100], signature[64]; memset (buf, 1, 100); - blindedSigner->Sign (buf, 100, signature); + blindedSigner->Sign (buf, 100, signature); std::unique_ptr blindedVerifier (IdentityEx::CreateVerifier (blindedKey.GetBlindedSigType ())); blindedVerifier->SetPublicKey (blindedPub); - assert (blindedVerifier->Verify (buf, 100, signature)); + assert (blindedVerifier->Verify (buf, 100, signature)); } int main () { - // EdDSA test + // EdDSA test BlindTest (SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); - // RedDSA test + // RedDSA test BlindTest (SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519); } diff --git a/tests/test-elligator.cpp b/tests/test-elligator.cpp index 48c9e31a..359c71c5 100644 --- a/tests/test-elligator.cpp +++ b/tests/test-elligator.cpp @@ -4,19 +4,19 @@ #include "Elligator.h" -const uint8_t key[32] = +const uint8_t key[32] = { 0x33, 0x95, 0x19, 0x64, 0x00, 0x3c, 0x94, 0x08, 0x78, 0x06, 0x3c, 0xcf, 0xd0, 0x34, 0x8a, 0xf4, 0x21, 0x50, 0xca, 0x16, 0xd2, 0x64, 0x6f, 0x2c, 0x58, 0x56, 0xe8, 0x33, 0x83, 0x77, 0xd8, 0x80 }; -const uint8_t encoded_key[32] = +const uint8_t encoded_key[32] = { 0x28, 0x20, 0xb6, 0xb2, 0x41, 0xe0, 0xf6, 0x8a, 0x6c, 0x4a, 0x7f, 0xee, 0x3d, 0x97, 0x82, 0x28, 0xef, 0x3a, 0xe4, 0x55, 0x33, 0xcd, 0x41, 0x0a, 0xa9, 0x1a, 0x41, 0x53, 0x31, 0xd8, 0x61, 0x2d }; -const uint8_t encoded_key_high_y[32] = +const uint8_t encoded_key_high_y[32] = { 0x3c, 0xfb, 0x87, 0xc4, 0x6c, 0x0b, 0x45, 0x75, 0xca, 0x81, 0x75, 0xe0, 0xed, 0x1c, 0x0a, 0xe9, 0xda, 0xe7, 0x9d, 0xb7, 0x8d, 0xf8, 0x69, 0x97, 0xc4, 0x84, 0x7b, 0x9f, 0x20, 0xb2, 0x77, 0x18 @@ -28,7 +28,7 @@ const uint8_t encoded1[32] = 0x14, 0x50, 0x95, 0x89, 0x28, 0x84, 0x57, 0x99, 0x5a, 0x2b, 0x4c, 0xa3, 0x49, 0x0a, 0xa2, 0x07 }; -const uint8_t key1[32] = +const uint8_t key1[32] = { 0x1e, 0x8a, 0xff, 0xfe, 0xd6, 0xbf, 0x53, 0xfe, 0x27, 0x1a, 0xd5, 0x72, 0x47, 0x32, 0x62, 0xde, 0xd8, 0xfa, 0xec, 0x68, 0xe5, 0xe6, 0x7e, 0xf4, 0x5e, 0xbb, 0x82, 0xee, 0xba, 0x52, 0x60, 0x4f @@ -40,7 +40,7 @@ const uint8_t encoded2[32] = 0xd9, 0x03, 0x65, 0xf2, 0x4a, 0x38, 0xaa, 0x7a, 0xef, 0x1b, 0x97, 0xe2, 0x39, 0x54, 0x10, 0x1b }; -const uint8_t key2[32] = +const uint8_t key2[32] = { 0x79, 0x4f, 0x05, 0xba, 0x3e, 0x3a, 0x72, 0x95, 0x80, 0x22, 0x46, 0x8c, 0x88, 0x98, 0x1e, 0x0b, 0xe5, 0x78, 0x2b, 0xe1, 0xe1, 0x14, 0x5c, 0xe2, 0xc3, 0xc6, 0xfd, 0xe1, 0x6d, 0xed, 0x53, 0x63 @@ -52,7 +52,7 @@ const uint8_t encoded3[32] = 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f }; -const uint8_t key3[32] = +const uint8_t key3[32] = { 0x9c, 0xdb, 0x52, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 diff --git a/tests/test-x25519.cpp b/tests/test-x25519.cpp index 2ab8ad6a..a1f3f424 100644 --- a/tests/test-x25519.cpp +++ b/tests/test-x25519.cpp @@ -4,21 +4,21 @@ #include "Ed25519.h" -const uint8_t k[32] = +const uint8_t k[32] = { 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4 }; -const uint8_t u[32] = +const uint8_t u[32] = { 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c }; -uint8_t p[32] = +uint8_t p[32] = { 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, @@ -36,4 +36,3 @@ int main () assert(memcmp (buf, p, 32) == 0); #endif } - From 2a6883e305d5258bf049258696d88584aaf214d5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 30 Jan 2023 20:57:08 +0300 Subject: [PATCH 107/179] [debian] add missing space in changelog (closes #1863) --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 77b174c5..d4464668 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,7 +2,7 @@ i2pd (2.45.1-1) unstable; urgency=medium * updated to version 2.45.1/0.9.57 --- orignal Wed, 11 Jan 2023 19:00:00 +0000 + -- orignal Wed, 11 Jan 2023 19:00:00 +0000 i2pd (2.45.0-1) unstable; urgency=high From fafdb0c59009ffa9525486965fd4ef7acc44f6e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Jan 2023 15:06:40 -0500 Subject: [PATCH 108/179] drop too long or too short LeaseSet --- libi2pd/Destination.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d202af96..9be0c06e 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -399,6 +399,11 @@ namespace client void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) { + if (len < DATABASE_STORE_HEADER_SIZE) + { + LogPrint (eLogError, "Destination: Database store msg is too short ", len); + return; + } uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; if (replyToken) @@ -406,6 +411,11 @@ namespace client LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); offset += 36; } + if (offset > len || len > i2p::data::MAX_LS_BUFFER_SIZE + offset) + { + LogPrint (eLogError, "Destination: Database store message is too long ", len); + return; + } i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET); std::shared_ptr leaseSet; switch (buf[DATABASE_STORE_TYPE_OFFSET]) From 2ed281472f20cd01043351e8debb44bab30fcf0b Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 1 Feb 2023 00:25:41 +0200 Subject: [PATCH 109/179] enclose IPv6 address in square brackets --- daemon/HTTPServer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 0b99c047..d9daeb5e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -329,14 +329,15 @@ namespace http { default: s << tr("Unknown"); } - if (address->IsV6 ()) + bool v6 = address->IsV6 (); + if (v6) { if (address->IsV4 ()) s << "v4"; s << "v6"; } s << "\r\n"; if (address->published) - s << "" << address->host.to_string() << ":" << address->port << "\r\n"; + s << "" << (v6 ? "[" : "") << address->host.to_string() << (v6 ? "]:" : ":") << address->port << "\r\n"; else { s << "" << tr(/* tr: Shown when router doesn't publish itself and have "Firewalled" state */ "supported"); From 22b1066b0a880083d447ca9101aa600018a58c37 Mon Sep 17 00:00:00 2001 From: weko Date: Wed, 1 Feb 2023 14:06:28 +0300 Subject: [PATCH 110/179] Add parameter for show TCSR with old algorithm and it's realization --- daemon/HTTPServer.cpp | 5 +++++ libi2pd/Config.cpp | 1 + libi2pd/Tunnel.cpp | 6 +++++- libi2pd/Tunnel.h | 9 ++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index d9daeb5e..5095bcd7 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -289,6 +289,11 @@ namespace http { if (family.length () > 0) s << ""<< tr("Family") << ": " << family << "
\r\n"; s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; + bool isOldTCSR; + i2p::config::GetOption("http.old_tcsr", isOldTCSR); + if (isOldTCSR) { + s << "" << tr("Tunnel creation success rate (old algorithm)") << ": " << i2p::tunnel::tunnels.OldGetTunnelCreationSuccessRate() << "%
\r\n"; + } s << "" << tr("Received") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")
\r\n"; diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 07ab2f20..9181e28e 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -95,6 +95,7 @@ namespace config { ("http.hostname", value()->default_value("localhost"), "Expected hostname for WebUI") ("http.webroot", value()->default_value("/"), "WebUI root path (default: / )") ("http.lang", value()->default_value("english"), "WebUI language (default: english )") + ("http.old_tcsr", value()->default_value(false), "Show TCSR with old algorithm (default: false)") ; options_description httpproxy("HTTP Proxy options"); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 4d205544..d19649d6 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -332,7 +332,8 @@ namespace tunnel Tunnels tunnels; Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), - m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) { + m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0), + m_OldNumSuccesiveTunnelCreations (0), m_OldNumFailedTunnelCreations (0) { } Tunnels::~Tunnels () @@ -634,6 +635,7 @@ namespace tunnel // delete it = pendingTunnels.erase (it); FailedTunnelCreation(); + m_OldNumFailedTunnelCreations++; } else ++it; @@ -642,6 +644,7 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " failed, deleted"); it = pendingTunnels.erase (it); FailedTunnelCreation(); + m_OldNumFailedTunnelCreations++; break; case eTunnelStateBuildReplyReceived: // intermediate state, will be either established of build failed @@ -651,6 +654,7 @@ namespace tunnel // success it = pendingTunnels.erase (it); SuccesiveTunnelCreation(); + m_OldNumSuccesiveTunnelCreations++; } } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 7fa1eb54..a997502a 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -269,7 +269,9 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - + // some old stats + int m_OldNumSuccesiveTunnelCreations, m_OldNumFailedTunnelCreations; + // Calculating of tunnel creation success rate // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity void SuccesiveTunnelCreation() { @@ -297,6 +299,11 @@ namespace tunnel int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents + int OldGetTunnelCreationSuccessRate () const // in percents + { + int totalNum = m_OldNumSuccesiveTunnelCreations + m_OldNumFailedTunnelCreations; + return totalNum ? m_OldNumSuccesiveTunnelCreations*100/totalNum : 0; + } }; extern Tunnels tunnels; From 7df2ed611470f105669a5daf668fc5ce08f9a116 Mon Sep 17 00:00:00 2001 From: weko Date: Wed, 1 Feb 2023 19:14:56 +0300 Subject: [PATCH 111/179] rename and refactor --- daemon/HTTPServer.cpp | 8 ++++---- libi2pd/Config.cpp | 2 +- libi2pd/Tunnel.cpp | 5 +---- libi2pd/Tunnel.h | 16 ++++++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 5095bcd7..8706f786 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -289,10 +289,10 @@ namespace http { if (family.length () > 0) s << ""<< tr("Family") << ": " << family << "
\r\n"; s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; - bool isOldTCSR; - i2p::config::GetOption("http.old_tcsr", isOldTCSR); - if (isOldTCSR) { - s << "" << tr("Tunnel creation success rate (old algorithm)") << ": " << i2p::tunnel::tunnels.OldGetTunnelCreationSuccessRate() << "%
\r\n"; + bool isTotalTCSR; + i2p::config::GetOption("http.showTotalTCSR", isTotalTCSR); + if (isTotalTCSR) { + s << "" << tr("Total tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTotalTunnelCreationSuccessRate() << "%
\r\n"; } s << "" << tr("Received") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 9181e28e..971b1273 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -95,7 +95,7 @@ namespace config { ("http.hostname", value()->default_value("localhost"), "Expected hostname for WebUI") ("http.webroot", value()->default_value("/"), "WebUI root path (default: / )") ("http.lang", value()->default_value("english"), "WebUI language (default: english )") - ("http.old_tcsr", value()->default_value(false), "Show TCSR with old algorithm (default: false)") + ("http.showTotalTCSR", value()->default_value(false), "Show additional value with total TCSR since router's start (default: false)") ; options_description httpproxy("HTTP Proxy options"); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index d19649d6..a0e36978 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -333,7 +333,7 @@ namespace tunnel Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0), - m_OldNumSuccesiveTunnelCreations (0), m_OldNumFailedTunnelCreations (0) { + m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0) { // for normal avarage } Tunnels::~Tunnels () @@ -635,7 +635,6 @@ namespace tunnel // delete it = pendingTunnels.erase (it); FailedTunnelCreation(); - m_OldNumFailedTunnelCreations++; } else ++it; @@ -644,7 +643,6 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " failed, deleted"); it = pendingTunnels.erase (it); FailedTunnelCreation(); - m_OldNumFailedTunnelCreations++; break; case eTunnelStateBuildReplyReceived: // intermediate state, will be either established of build failed @@ -654,7 +652,6 @@ namespace tunnel // success it = pendingTunnels.erase (it); SuccesiveTunnelCreation(); - m_OldNumSuccesiveTunnelCreations++; } } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index a997502a..03693206 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -269,17 +269,21 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - // some old stats - int m_OldNumSuccesiveTunnelCreations, m_OldNumFailedTunnelCreations; + // count of tunnels for total TCSR algorithm + int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; // Calculating of tunnel creation success rate - // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity void SuccesiveTunnelCreation() { + // total TCSR + m_TotalNumSuccesiveTunnelCreations++; + // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; m_TunnelCreationSuccessRate = alpha * 1 + (1 - alpha) * m_TunnelCreationSuccessRate; }; void FailedTunnelCreation() { + m_TotalNumFailedTunnelCreations++; + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; m_TunnelCreationSuccessRate = alpha * 0 + (1 - alpha) * m_TunnelCreationSuccessRate; }; @@ -299,10 +303,10 @@ namespace tunnel int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents - int OldGetTunnelCreationSuccessRate () const // in percents + int GetTotalTunnelCreationSuccessRate () const // in percents { - int totalNum = m_OldNumSuccesiveTunnelCreations + m_OldNumFailedTunnelCreations; - return totalNum ? m_OldNumSuccesiveTunnelCreations*100/totalNum : 0; + int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations; + return totalNum ? m_TotalNumSuccesiveTunnelCreations*100/totalNum : 0; } }; From bf8eecf407cd2a5bebf66b1c5641870929362687 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Feb 2023 16:04:09 -0500 Subject: [PATCH 112/179] more attempts to find good peer --- libi2pd/Transports.cpp | 98 ++++++++++++++++++++++++++++++++++++++---- libi2pd/Transports.h | 3 ++ 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 4f4dd929..05776dc4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -815,20 +815,100 @@ namespace transport } } - std::shared_ptr Transports::GetRandomPeer () const + template + std::shared_ptr Transports::GetRandomPeer (Filter filter) const { - if (m_Peers.empty ()) return nullptr; + if (m_Peers.empty()) return nullptr; + bool found = false; i2p::data::IdentHash ident; { + uint16_t inds[3]; + RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::unique_lock l(m_PeersMutex); + inds[0] %= m_Peers.size (); auto it = m_Peers.begin (); - std::advance (it, rand () % m_Peers.size ()); - if (it == m_Peers.end () || it->second.router || it->second.sessions.empty () || - it->second.sessions.front ()->GetSendQueueSize () > PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE) - return nullptr; // not connected or overloaded - ident = it->first; - } - return i2p::data::netdb.FindRouter (ident); + std::advance (it, inds[0]); + // try random peer + if (it != m_Peers.end () && filter (it->second)) + { + ident = it->first; + found = true; + } + else + { + // try some peers around + auto it1 = m_Peers.begin (); + if (inds[0]) + { + // before + inds[1] %= inds[0]; + std::advance (it1, (inds[1] + inds[0])/2); + } + else + it1 = it; + auto it2 = it; + if (inds[0] < m_Peers.size () - 1) + { + // after + inds[2] %= (m_Peers.size () - 1 - inds[0]); inds[2] /= 2; + std::advance (it2, inds[2]); + } + // it1 - from, it2 - to + it = it1; + while (it != it2 && it != m_Peers.end ()) + { + if (filter (it->second)) + { + ident = it->first; + found = true; + break; + } + it++; + } + if (!found) + { + // still not found, try from the beginning + it = m_Peers.begin (); + while (it != it1 && it != m_Peers.end ()) + { + if (filter (it->second)) + { + ident = it->first; + found = true; + break; + } + it++; + } + if (!found) + { + // still not found, try to the beginning + it = it2; + while (it != m_Peers.end ()) + { + if (filter (it->second)) + { + ident = it->first; + found = true; + break; + } + it++; + } + } + } + } + } + return found ? i2p::data::netdb.FindRouter (ident) : nullptr; + } + + std::shared_ptr Transports::GetRandomPeer () const + { + return GetRandomPeer ( + [](const Peer& peer)->bool + { + // connected and not overloaded + return !peer.router && !peer.sessions.empty () && + peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE; + }); } void Transports::RestrictRoutesToFamilies(const std::set& families) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index bbe98bf3..76b6a089 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -163,6 +163,9 @@ namespace transport void DetectExternalIP (); + template + std::shared_ptr GetRandomPeer (Filter filter) const; + private: volatile bool m_IsOnline; From 4960587f466d54e378f00fa2bb899adbc5d1f3c5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Feb 2023 18:37:31 -0500 Subject: [PATCH 113/179] cleanup out-of-sequnce list more aggressivly --- libi2pd/SSU2Session.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 5e97b461..4a934ab2 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2851,7 +2851,8 @@ namespace transport } if (!m_OutOfSequencePackets.empty ()) { - if (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || + int ranges = 0; + while (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8) { uint32_t packet = *m_OutOfSequencePackets.begin (); @@ -2861,9 +2862,14 @@ namespace transport packet--; m_ReceivePacketNum = packet - 1; UpdateReceivePacketNum (packet); + ranges++; + if (ranges > SSU2_MAX_NUM_ACK_RANGES) break; } else + { LogPrint (eLogError, "SSU2: Out of sequence packet ", packet, " is less than last received ", m_ReceivePacketNum); + break; + } } if (m_OutOfSequencePackets.size () > 255*4) { From e9f0ed64733677cd9dd98fdbe91cc842325df7d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Feb 2023 19:05:04 -0500 Subject: [PATCH 114/179] cleanup out-of-sequnce list more aggressivly --- libi2pd/SSU2Session.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4a934ab2..bf6ac61e 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2852,8 +2852,9 @@ namespace transport if (!m_OutOfSequencePackets.empty ()) { int ranges = 0; - while (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || - *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8) + while (ranges < SSU2_MAX_NUM_ACK_RANGES && !m_OutOfSequencePackets.empty () && + (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || + *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8)) { uint32_t packet = *m_OutOfSequencePackets.begin (); if (packet > m_ReceivePacketNum + 1) @@ -2863,7 +2864,6 @@ namespace transport m_ReceivePacketNum = packet - 1; UpdateReceivePacketNum (packet); ranges++; - if (ranges > SSU2_MAX_NUM_ACK_RANGES) break; } else { From f7101cc260cfead45a5046638d25fbfbf771cfc7 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Feb 2023 21:28:05 -0500 Subject: [PATCH 115/179] fixed warning --- libi2pd/Tunnel.cpp | 5 +++-- libi2pd/Tunnel.h | 36 +++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index a0e36978..065befbe 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -332,8 +332,9 @@ namespace tunnel Tunnels tunnels; Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), - m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0), - m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0) { // for normal avarage + m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal avarage + m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) + { } Tunnels::~Tunnels () diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 03693206..36dee936 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -253,6 +253,24 @@ namespace tunnel std::shared_ptr CreateZeroHopsInboundTunnel (std::shared_ptr pool); std::shared_ptr CreateZeroHopsOutboundTunnel (std::shared_ptr pool); + // Calculating of tunnel creation success rate + void SuccesiveTunnelCreation() + { + // total TCSR + m_TotalNumSuccesiveTunnelCreations++; + // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; + m_TunnelCreationSuccessRate = alpha * 1 + (1 - alpha) * m_TunnelCreationSuccessRate; + + } + void FailedTunnelCreation() + { + m_TotalNumFailedTunnelCreations++; + + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; + m_TunnelCreationSuccessRate = alpha * 0 + (1 - alpha) * m_TunnelCreationSuccessRate; + } + private: bool m_IsRunning; @@ -270,23 +288,7 @@ namespace tunnel i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; // count of tunnels for total TCSR algorithm - int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; - - // Calculating of tunnel creation success rate - void SuccesiveTunnelCreation() { - // total TCSR - m_TotalNumSuccesiveTunnelCreations++; - // A modified version of the EWMA algorithm, where alpha is increased at the beginning to accelerate similarity - double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; - m_TunnelCreationSuccessRate = alpha * 1 + (1 - alpha) * m_TunnelCreationSuccessRate; - - }; - void FailedTunnelCreation() { - m_TotalNumFailedTunnelCreations++; - - double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; - m_TunnelCreationSuccessRate = alpha * 0 + (1 - alpha) * m_TunnelCreationSuccessRate; - }; + int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; int m_TunnelCreationAttemptsNum; From 02e7f6b0c369eb3d67ac9bef800267addacfd8cd Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 Feb 2023 13:52:48 -0500 Subject: [PATCH 116/179] cleanup out of sequence packet nums in one call --- libi2pd/SSU2Session.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bf6ac61e..c9bd45ef 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2757,15 +2757,25 @@ namespace transport if (packetNum <= m_ReceivePacketNum) return false; // duplicate if (packetNum == m_ReceivePacketNum + 1) { - for (auto it = m_OutOfSequencePackets.begin (); it != m_OutOfSequencePackets.end ();) + if (!m_OutOfSequencePackets.empty ()) { + auto it = m_OutOfSequencePackets.begin (); if (*it == packetNum + 1) { - packetNum++; - it = m_OutOfSequencePackets.erase (it); - } - else - break; + // first out of sequence packet is in sequence now + packetNum++; it++; + while (it != m_OutOfSequencePackets.end ()) + { + if (*it == packetNum + 1) + { + packetNum++; + it++; + } + else // next out of sequence + break; + } + m_OutOfSequencePackets.erase (m_OutOfSequencePackets.begin (), it); + } } m_ReceivePacketNum = packetNum; } @@ -2852,7 +2862,7 @@ namespace transport if (!m_OutOfSequencePackets.empty ()) { int ranges = 0; - while (ranges < SSU2_MAX_NUM_ACK_RANGES && !m_OutOfSequencePackets.empty () && + while (ranges < 8 && !m_OutOfSequencePackets.empty () && (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8)) { From 9bc3b11b96e66558b62bb8671cba28e9c0184563 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 3 Feb 2023 00:05:58 +0200 Subject: [PATCH 117/179] Sort transports by IP:port pairs --- daemon/HTTPServer.cpp | 51 +++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 8706f786..2f846257 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -810,37 +810,46 @@ namespace http { template static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name) { - std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0; - for (const auto& it: sessions ) + auto comp = [](typename Sessions::mapped_type a, typename Sessions::mapped_type b) + { return a->GetRemoteEndpoint() < b->GetRemoteEndpoint(); }; + std::set sortedSessions(comp); + for (const auto& it : sessions) { - auto endpoint = it.second->GetRemoteEndpoint (); - if (it.second && it.second->IsEstablished () && endpoint.address ().is_v4 ()) + auto ret = sortedSessions.insert(it.second); + if (!ret.second) + LogPrint(eLogError, "HTTPServer: Duplicate remote endpoint detected: ", (*ret.first)->GetRemoteEndpoint()); + } + std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0; + for (const auto& it: sortedSessions) + { + auto endpoint = it->GetRemoteEndpoint (); + if (it && it->IsEstablished () && endpoint.address ().is_v4 ()) { tmp_s << "
\r\n"; - if (it.second->IsOutgoing ()) tmp_s << " ⇒ "; - tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " + if (it->IsOutgoing ()) tmp_s << " ⇒ "; + tmp_s << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": " << endpoint.address ().to_string () << ":" << endpoint.port (); - if (!it.second->IsOutgoing ()) tmp_s << " ⇒ "; - tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - if (it.second->GetRelayTag ()) - tmp_s << " [itag:" << it.second->GetRelayTag () << "]"; - if (it.second->GetSendQueueSize () > 0) - tmp_s << " [queue:" << it.second->GetSendQueueSize () << "]"; + if (!it->IsOutgoing ()) tmp_s << " ⇒ "; + tmp_s << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]"; + if (it->GetRelayTag ()) + tmp_s << " [itag:" << it->GetRelayTag () << "]"; + if (it->GetSendQueueSize () > 0) + tmp_s << " [queue:" << it->GetSendQueueSize () << "]"; tmp_s << "
\r\n" << std::endl; cnt++; } - if (it.second && it.second->IsEstablished () && endpoint.address ().is_v6 ()) + if (it && it->IsEstablished () && endpoint.address ().is_v6 ()) { tmp_s6 << "
\r\n"; - if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ "; - tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " + if (it->IsOutgoing ()) tmp_s6 << " ⇒ "; + tmp_s6 << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": " << "[" << endpoint.address ().to_string () << "]:" << endpoint.port (); - if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ "; - tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; - if (it.second->GetRelayTag ()) - tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]"; - if (it.second->GetSendQueueSize () > 0) - tmp_s6 << " [queue:" << it.second->GetSendQueueSize () << "]"; + if (!it->IsOutgoing ()) tmp_s6 << " ⇒ "; + tmp_s6 << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]"; + if (it->GetRelayTag ()) + tmp_s6 << " [itag:" << it->GetRelayTag () << "]"; + if (it->GetSendQueueSize () > 0) + tmp_s6 << " [queue:" << it->GetSendQueueSize () << "]"; tmp_s6 << "
\r\n" << std::endl; cnt6++; } From 21542e81504155279cc459ce422a8489d7609cb0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Feb 2023 15:59:56 -0500 Subject: [PATCH 118/179] select first hop from high bandwidth peer for client tunnels --- libi2pd/Transports.cpp | 11 ++++++----- libi2pd/Transports.h | 15 +++++++++++++-- libi2pd/TunnelPool.cpp | 8 ++++---- libi2pd/TunnelPool.h | 10 ++++------ libi2pd_client/MatchedDestination.cpp | 4 ++-- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 05776dc4..7a2fb431 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -476,7 +476,7 @@ namespace transport bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer) { if (!peer.router) // reconnect - peer.router = netdb.FindRouter (ident); // try to get new one from netdb + peer.SetRouter (netdb.FindRouter (ident)); // try to get new one from netdb if (peer.router) // we have RI already { if (peer.priority.empty ()) @@ -598,7 +598,7 @@ namespace transport if (r) { LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect"); - it->second.router = r; + it->second.SetRouter (r); ConnectToPeer (ident, it->second); } else @@ -900,14 +900,15 @@ namespace transport return found ? i2p::data::netdb.FindRouter (ident) : nullptr; } - std::shared_ptr Transports::GetRandomPeer () const + std::shared_ptr Transports::GetRandomPeer (bool isHighBandwidth) const { return GetRandomPeer ( - [](const Peer& peer)->bool + [isHighBandwidth](const Peer& peer)->bool { // connected and not overloaded return !peer.router && !peer.sessions.empty () && - peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE; + peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && + (!isHighBandwidth || peer.isHighBandwidth); }); } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 76b6a089..ebb6261e 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -72,11 +72,15 @@ namespace transport uint64_t creationTime, nextRouterInfoUpdateTime; std::vector > delayedMessages; std::vector priority; + bool isHighBandwidth; Peer (std::shared_ptr r, uint64_t ts): numAttempts (0), router (r), creationTime (ts), - nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL) + nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL), + isHighBandwidth (false) { + if (router) + isHighBandwidth = router->IsHighBandwidth (); } void Done () @@ -84,6 +88,13 @@ namespace transport for (auto& it: sessions) it->Done (); } + + void SetRouter (std::shared_ptr r) + { + router = r; + if (router) + isHighBandwidth = router->IsHighBandwidth (); + } }; const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds @@ -131,7 +142,7 @@ namespace transport bool IsBandwidthExceeded () const; bool IsTransitBandwidthExceeded () const; size_t GetNumPeers () const { return m_Peers.size (); }; - std::shared_ptr GetRandomPeer () const; + std::shared_ptr GetRandomPeer (bool isHighBandwidth) const; /** get a trusted first hop for restricted routes */ std::shared_ptr GetRestrictedPeer() const; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index ee115b7e..a9592efd 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -480,7 +480,7 @@ namespace tunnel return hop; } - bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop) + bool TunnelPool::StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop) { int start = 0; std::shared_ptr prevHop = i2p::context.GetSharedRouterInfo (); @@ -496,7 +496,7 @@ namespace tunnel else if (i2p::transport::transports.GetNumPeers () > 100 || (inbound && i2p::transport::transports.GetNumPeers () > 25)) { - auto r = i2p::transport::transports.GetRandomPeer (); + auto r = i2p::transport::transports.GetRandomPeer (IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable { @@ -512,7 +512,7 @@ namespace tunnel if (!hop && !i) // if no suitable peer found for first hop, try already connected { LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); - hop = i2p::transport::transports.GetRandomPeer (); + hop = i2p::transport::transports.GetRandomPeer (false); if (hop && !hop->IsECIES ()) hop = nullptr; } if (!hop) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index aed29eaf..6936d3ad 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -54,12 +54,9 @@ namespace tunnel virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0; }; - - typedef std::function(std::shared_ptr, bool)> SelectHopFunc; - bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); - class TunnelPool: public std::enable_shared_from_this // per local destination { + typedef std::function(std::shared_ptr, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -116,7 +113,8 @@ namespace tunnel // for overriding tunnel peer selection std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; - + bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); + private: void TestTunnels (); diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index ce800ecc..1e2e8275 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -72,7 +72,7 @@ namespace client bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) { auto pool = GetTunnelPool(); - if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, + if(!pool || !pool->StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) return false; // more here for outbound tunnels From 5a6b50ae51d3906acf514fa5449a811acfe714a0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Feb 2023 17:32:43 -0500 Subject: [PATCH 119/179] fixed typo --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a9592efd..bafc1c2d 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -496,7 +496,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 (!IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable { From 54fb234424aa9a7875d51698d66e9e5e6ce3375b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Feb 2023 19:17:46 -0500 Subject: [PATCH 120/179] limit number of acked packets to 510 --- libi2pd/SSU2Session.cpp | 52 ++++++++++++++++++++++++----------------- libi2pd/SSU2Session.h | 2 ++ 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index c9bd45ef..2f814b4c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2455,21 +2455,24 @@ namespace transport if (ackThrough) { if (m_OutOfSequencePackets.empty ()) - acnt = std::min ((int)ackThrough, 255); // no gaps + acnt = std::min ((int)ackThrough, SSU2_MAX_NUM_ACNT); // no gaps else { auto it = m_OutOfSequencePackets.rbegin (); it++; // prev packet num while (it != m_OutOfSequencePackets.rend () && *it == ackThrough - acnt - 1) { acnt++; - it++; + if (acnt >= SSU2_MAX_NUM_ACK_PACKETS) + break; + else + it++; } // ranges uint32_t lastNum = ackThrough - acnt; - if (acnt > 255) + if (acnt > SSU2_MAX_NUM_ACNT) { - auto d = std::div (acnt - 255, 255); - acnt = 255; + auto d = std::div (acnt - SSU2_MAX_NUM_ACNT, SSU2_MAX_NUM_ACNT); + acnt = SSU2_MAX_NUM_ACNT; if (d.quot > maxNumRanges) { d.quot = maxNumRanges; @@ -2478,7 +2481,7 @@ namespace transport // Acks only ranges for acnt for (int i = 0; i < d.quot; i++) { - buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = 255; // NACKs 0, Acks 255 + buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // NACKs 0, Acks 255 numRanges++; } if (d.rem > 0) @@ -2487,21 +2490,25 @@ namespace transport numRanges++; } } - while (it != m_OutOfSequencePackets.rend () && numRanges < maxNumRanges) + int numPackets = acnt + numRanges*SSU2_MAX_NUM_ACNT; + while (it != m_OutOfSequencePackets.rend () && + numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS) { - if (lastNum - (*it) > 255) + if (lastNum - (*it) > SSU2_MAX_NUM_ACNT) { // NACKs only ranges - if (lastNum > (*it) + 255*(maxNumRanges - numRanges)) break; // too many NACKs - while (lastNum - (*it) > 255) + if (lastNum > (*it) + SSU2_MAX_NUM_ACNT*(maxNumRanges - numRanges)) break; // too many NACKs + while (lastNum - (*it) > SSU2_MAX_NUM_ACNT) { - buf[8 + numRanges*2] = 255; buf[8 + numRanges*2 + 1] = 0; // NACKs 255, Acks 0 - lastNum -= 255; + buf[8 + numRanges*2] = SSU2_MAX_NUM_ACNT; buf[8 + numRanges*2 + 1] = 0; // NACKs 255, Acks 0 + lastNum -= SSU2_MAX_NUM_ACNT; numRanges++; + numPackets += SSU2_MAX_NUM_ACNT; } } // NACKs and Acks ranges buf[8 + numRanges*2] = lastNum - (*it) - 1; // NACKs + numPackets += buf[8 + numRanges*2]; lastNum = *it; it++; int numAcks = 1; while (it != m_OutOfSequencePackets.rend () && lastNum > 0 && *it == lastNum - 1) @@ -2509,28 +2516,31 @@ namespace transport numAcks++; lastNum--; it++; } - while (numAcks > 255) + while (numAcks > SSU2_MAX_NUM_ACNT) { // Acks only ranges - buf[8 + numRanges*2 + 1] = 255; // Acks 255 - numAcks -= 255; + buf[8 + numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // Acks 255 + numAcks -= SSU2_MAX_NUM_ACNT; numRanges++; + numPackets += SSU2_MAX_NUM_ACNT; buf[8 + numRanges*2] = 0; // NACKs 0 - if (numRanges >= maxNumRanges) break; + if (numRanges >= maxNumRanges || numPackets >= SSU2_MAX_NUM_ACK_PACKETS) break; } - if (numAcks > 255) numAcks = 255; + if (numAcks > SSU2_MAX_NUM_ACNT) numAcks = SSU2_MAX_NUM_ACNT; buf[8 + numRanges*2 + 1] = (uint8_t)numAcks; // Acks + numPackets += numAcks; numRanges++; } - if (numRanges < maxNumRanges && it == m_OutOfSequencePackets.rend ()) + if (it == m_OutOfSequencePackets.rend () && + numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS) { // add range between out-of-sequence and received int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1; if (nacks > 0) { - if (nacks > 255) nacks = 255; + if (nacks > SSU2_MAX_NUM_ACNT) nacks = SSU2_MAX_NUM_ACNT; buf[8 + numRanges*2] = nacks; - buf[8 + numRanges*2 + 1] = std::min ((int)m_ReceivePacketNum + 1, 255); + buf[8 + numRanges*2 + 1] = std::min ((int)m_ReceivePacketNum + 1, SSU2_MAX_NUM_ACNT); numRanges++; } } @@ -2864,7 +2874,7 @@ namespace transport int ranges = 0; while (ranges < 8 && !m_OutOfSequencePackets.empty () && (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || - *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + 255*8)) + *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + SSU2_MAX_NUM_ACK_PACKETS)) { uint32_t packet = *m_OutOfSequencePackets.begin (); if (packet > m_ReceivePacketNum + 1) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index ef9ab573..03395d0f 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -48,6 +48,8 @@ namespace transport const size_t SSU2_MAX_RTO = 2500; // in milliseconds const float SSU2_kAPPA = 1.8; const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500; // in messages + const int SSU2_MAX_NUM_ACNT = 255; // acnt, acks or nacks + const int SSU2_MAX_NUM_ACK_PACKETS = 510; // 2*255 ack + nack const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; From 212a1156a1607c41f1e8d75bfd0e9172e6f831da Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Feb 2023 11:00:00 -0500 Subject: [PATCH 121/179] filter our addresses with invalid hosts --- libi2pd/RouterInfo.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index ff86fb51..49cfd72d 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -252,7 +252,15 @@ namespace data { boost::system::error_code ecode; address->host = boost::asio::ip::address::from_string (value, ecode); - if (!ecode && !address->host.is_unspecified ()) isHost = true; + if (!ecode && !address->host.is_unspecified ()) + { + if (!i2p::util::net::IsInReservedRange (address->host) || + i2p::util::net::IsYggdrasilAddress (address->host)) + isHost = true; + else + // we consider such address as invalid + address->transportStyle = eTransportUnknown; + } } else if (!strcmp (key, "port")) { @@ -390,7 +398,7 @@ namespace data { if (address->IsV4 ()) supportedTransports |= eSSU2V4; if (address->IsV6 ()) supportedTransports |= eSSU2V6; - if (address->port) + if (isHost && address->port) { if (address->host.is_v4 ()) m_ReachableTransports |= eSSU2V4; if (address->host.is_v6 ()) m_ReachableTransports |= eSSU2V6; From f1415c22346452a69a0a935ce49a3c135cc0139f Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Feb 2023 15:42:46 -0500 Subject: [PATCH 122/179] compare published address and actual endpoint --- libi2pd/SSU2Session.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 2f814b4c..8ef1058c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1047,6 +1047,12 @@ namespace transport LogPrint (eLogError, "SSU2: No SSU2 address with static key found in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } + if (m_Address->published && m_RemoteEndpoint.address () != m_Address->host) + { + LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, + " and actual enpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); + return false; + } // update RouterInfo in netdb ri = i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); // ri points to one from netdb now if (!ri) From 21123e2afaa28d6ca7cac24427061518c907d431 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Feb 2023 18:26:09 -0500 Subject: [PATCH 123/179] compare published address and actual endpoint --- libi2pd/NTCP2.cpp | 13 ++++++++++--- libi2pd/RouterInfo.cpp | 19 +++++-------------- libi2pd/RouterInfo.h | 4 ++-- libi2pd/SSU2Session.cpp | 8 ++++---- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index e5199bdc..dadd2075 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -693,13 +693,20 @@ namespace transport SendTerminationAndTerminate (eNTCP2Message3Error); return; } - auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey); - if (!addr) + auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () : + (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ()); + if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32)) { - LogPrint (eLogError, "NTCP2: No NTCP2 address with static key found in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: Wrong static key in SessionConfirmed"); Terminate (); return; } + if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host) + { + 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 diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 49cfd72d..28959fe9 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -910,25 +910,16 @@ namespace data return nullptr; } - std::shared_ptr RouterInfo::GetNTCP2AddressWithStaticKey (const uint8_t * key) const + std::shared_ptr RouterInfo::GetNTCP2V4Address () const { - if (!key) return nullptr; - return GetAddress ( - [key](std::shared_ptr address)->bool - { - return address->IsNTCP2 () && !memcmp (address->s, key, 32); - }); + return (*GetAddresses ())[eNTCP2V4Idx]; } - std::shared_ptr RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const + std::shared_ptr RouterInfo::GetNTCP2V6Address () const { - if (!key) return nullptr; - auto addr = (*GetAddresses ())[isV6 ? eSSU2V6Idx : eSSU2V4Idx]; - if (addr && !memcmp (addr->s, key, 32)) - return addr; - return nullptr; + return (*GetAddresses ())[eNTCP2V6Idx]; } - + std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const { auto addr = (*GetAddresses ())[eNTCP2V4Idx]; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 7d004a33..ea0abf41 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -189,8 +189,8 @@ namespace data 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 - std::shared_ptr GetNTCP2AddressWithStaticKey (const uint8_t * key) const; - std::shared_ptr GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const; + std::shared_ptr GetNTCP2V4Address () const; + std::shared_ptr GetNTCP2V6Address () const; std::shared_ptr GetPublishedNTCP2V4Address () const; std::shared_ptr GetPublishedNTCP2V6Address () const; std::shared_ptr GetYggdrasilAddress () const; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 8ef1058c..4c359454 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1041,16 +1041,16 @@ namespace transport LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block"); return false; } - m_Address = ri->GetSSU2AddressWithStaticKey (S, m_RemoteEndpoint.address ().is_v6 ()); - if (!m_Address) + m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); + if (!m_Address || memcmp (S, m_Address->s, 32)) { - LogPrint (eLogError, "SSU2: No SSU2 address with static key found in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); + LogPrint (eLogError, "SSU2: Wrong static key in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } if (m_Address->published && m_RemoteEndpoint.address () != m_Address->host) { LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, - " and actual enpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); + " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } // update RouterInfo in netdb From 3c02cade5849371e26b63416304647a3732fba16 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Feb 2023 19:19:20 -0500 Subject: [PATCH 124/179] compare only first 8 bytes for temporary addreses --- libi2pd/NTCP2.cpp | 4 +++- libi2pd/SSU2Session.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index dadd2075..bc532a52 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -701,7 +701,9 @@ namespace transport Terminate (); return; } - if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host) + if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host && + (!m_RemoteEndpoint.address ().is_v6 () || + 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 ()); Terminate (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4c359454..121e93be 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1047,7 +1047,9 @@ namespace transport LogPrint (eLogError, "SSU2: Wrong static key in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } - if (m_Address->published && m_RemoteEndpoint.address () != m_Address->host) + if (m_Address->published && m_RemoteEndpoint.address () != m_Address->host && + (!m_RemoteEndpoint.address ().is_v6 () || + memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address { LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); From 80a55c5b75dd2a7d4891e331394bc92432474e19 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Feb 2023 13:19:41 -0500 Subject: [PATCH 125/179] store unrechable in profile --- libi2pd/NetDb.cpp | 14 ++++++++++++-- libi2pd/Profiling.cpp | 23 ++++++++++++++++++++--- libi2pd/Profiling.h | 11 ++++++++--- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index c46adff1..02e1c058 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -427,7 +427,15 @@ namespace data { auto it = m_RouterInfos.find (ident); if (it != m_RouterInfos.end ()) - return it->second->SetUnreachable (unreachable); + { + it->second->SetUnreachable (unreachable); + if (unreachable) + { + auto profile = it->second->GetProfile (); + if (profile) + profile->Unreachable (); + } + } } void NetDb::Reseed () @@ -626,6 +634,8 @@ namespace data updatedCount++; continue; } + if (it.second->GetProfile ()->IsUnreachable ()) + it.second->SetUnreachable (true); // make router reachable back if too few routers or floodfills if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate || (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) @@ -1334,7 +1344,7 @@ namespace data std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) { - if (!it->IsUnreachable ()) + if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ()) { XORMetric m = destKey ^ it->GetIdentHash (); if (m < minMetric && !excluded.count (it->GetIdentHash ())) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index f826bf43..6f805193 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -23,7 +23,7 @@ namespace data RouterProfile::RouterProfile (): m_LastUpdateTime (boost::posix_time::second_clock::local_time()), - m_LastDeclineTime (0), + m_LastDeclineTime (0), m_LastUnreachableTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), m_NumTimesTaken (0), m_NumTimesRejected (0) { @@ -52,6 +52,8 @@ namespace data // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); + if (m_LastUnreachableTime) + pt.put (PEER_PROFILE_LAST_UNREACHABLE_TIME, m_LastUnreachableTime); pt.put_child (PEER_PROFILE_SECTION_PARTICIPATION, participation); pt.put_child (PEER_PROFILE_SECTION_USAGE, usage); @@ -96,6 +98,7 @@ namespace data m_LastUpdateTime = boost::posix_time::time_from_string (t); if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT) { + m_LastUnreachableTime = pt.get (PEER_PROFILE_LAST_UNREACHABLE_TIME, 0); try { // read participations @@ -152,6 +155,11 @@ namespace data m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } + void RouterProfile::Unreachable () + { + m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate @@ -169,12 +177,12 @@ namespace data auto ts = i2p::util::GetSecondsSinceEpoch (); if (ts > m_LastDeclineTime + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL) m_LastDeclineTime = 0; - return m_LastDeclineTime; + return (bool)m_LastDeclineTime; } bool RouterProfile::IsBad () { - if (IsDeclinedRecently ()) return true; + if (IsDeclinedRecently () || IsUnreachable ()) return true; auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/; if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) { @@ -188,6 +196,15 @@ namespace data return isBad; } + bool RouterProfile::IsUnreachable () + { + if (!m_LastUnreachableTime) return false; + auto ts = i2p::util::GetSecondsSinceEpoch (); + if (ts > m_LastUnreachableTime + PEER_PROFILE_UNREACHABLE_INTERVAL) + m_LastUnreachableTime = 0; + return (bool)m_LastUnreachableTime; + } + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { auto profile = std::make_shared (); diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 1c523a22..58b5e2ea 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -22,6 +22,7 @@ namespace data const char PEER_PROFILE_SECTION_USAGE[] = "usage"; // params const char PEER_PROFILE_LAST_UPDATE_TIME[] = "lastupdatetime"; + const char PEER_PROFILE_LAST_UNREACHABLE_TIME[] = "lastunreachabletime"; const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed"; const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined"; const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; @@ -32,7 +33,8 @@ namespace data const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day) const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) - + const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + class RouterProfile { public: @@ -44,10 +46,13 @@ namespace data void Load (const IdentHash& identHash); bool IsBad (); - + bool IsUnreachable (); + void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); + void Unreachable (); + private: boost::posix_time::ptime GetTime () const; @@ -61,7 +66,7 @@ namespace data private: boost::posix_time::ptime m_LastUpdateTime; // TODO: use std::chrono - uint64_t m_LastDeclineTime; // in seconds + uint64_t m_LastDeclineTime, m_LastUnreachableTime; // in seconds // participation uint32_t m_NumTunnelsAgreed; uint32_t m_NumTunnelsDeclined; From d30d1e8a7de213dbe93ae686e7aa7a523e526103 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Feb 2023 14:18:15 -0500 Subject: [PATCH 126/179] don't set unrechable for routers without published addresses --- libi2pd/Transports.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 7a2fb431..bfd1b190 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -539,7 +539,8 @@ namespace transport } LogPrint (eLogInfo, "Transports: No compatible addresses available"); - i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed + if (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); m_Peers.erase (ident); From 4930157e93093f8b38e260c2124ccb9e8df5e45f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Feb 2023 16:18:16 -0500 Subject: [PATCH 127/179] don't innsert back unreachable router --- libi2pd/NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 02e1c058..2bf3ab08 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -295,7 +295,7 @@ namespace data else { r = std::make_shared (buf, len); - if (!r->IsUnreachable () && r->HasValidAddresses () && + if (!r->IsUnreachable () && r->HasValidAddresses () && !r->GetProfile ()->IsUnreachable () && i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) { bool inserted = false; From d1c98c58b9860346d1a953c6782adfc20499eeda Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Feb 2023 19:31:31 -0500 Subject: [PATCH 128/179] update status before deleting session --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 121e93be..ac570b84 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2296,9 +2296,9 @@ namespace transport m_Server.RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); break; case 7: // Alice from Charlie 2 - m_Server.RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); 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]); From f29ef2c057d3b81853e015b87be78af35f8e00b6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Feb 2023 15:28:33 -0500 Subject: [PATCH 129/179] don't compare first byte for yggdrasil addresses --- libi2pd/NTCP2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index bc532a52..ccc0086b 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -702,7 +702,8 @@ namespace transport return; } if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host && - (!m_RemoteEndpoint.address ().is_v6 () || + (!m_RemoteEndpoint.address ().is_v6 () || i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? + 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 ()); From 2baaa8bb8f0f0499f56420319ecda3c99c32906d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Feb 2023 18:01:24 -0500 Subject: [PATCH 130/179] fixed typo --- libi2pd/NTCP2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index ccc0086b..47b8081f 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -702,9 +702,9 @@ namespace transport return; } if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host && - (!m_RemoteEndpoint.address ().is_v6 () || i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? + (!m_RemoteEndpoint.address ().is_v6 () || (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? 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 + 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 ()); Terminate (); From aac9a8d18f8d14c5b16b24502429918cb6896c74 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Feb 2023 18:32:18 -0500 Subject: [PATCH 131/179] check if clock was adjusted backwards --- libi2pd/NetDb.cpp | 15 +++-- libi2pd/Tunnel.cpp | 144 ++++++++++++++++++++++----------------------- libi2pd/Tunnel.h | 12 ++-- 3 files changed, 86 insertions(+), 85 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 2bf3ab08..0ffdb3ef 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -153,13 +153,13 @@ namespace data if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastManageRequest >= 15) // manage requests every 15 seconds + if (ts - lastManageRequest >= 15 || ts + 15 < lastManageRequest) // manage requests every 15 seconds { m_Requests.ManageRequests (); lastManageRequest = ts; } - if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute + if (ts - lastSave >= 60 || ts + 60 < lastSave) // save routers, manage leasesets and validate subscriptions every minute { if (lastSave) { @@ -169,13 +169,15 @@ namespace data lastSave = ts; } - if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) + if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT || + ts + i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT < lastDestinationCleanup) { i2p::context.CleanupDestination (); lastDestinationCleanup = ts; } - if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance)) + if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || + ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { DeleteObsoleteProfiles (); lastProfilesCleanup = ts; @@ -192,7 +194,8 @@ namespace data if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true; } else if (i2p::context.GetLastUpdateTime () > lastPublish || - ts - lastPublish >= NETDB_PUBLISH_INTERVAL) + ts - lastPublish >= NETDB_PUBLISH_INTERVAL || + ts + NETDB_PUBLISH_INTERVAL < lastPublish) { // new publish m_PublishExcluded.clear (); @@ -208,7 +211,7 @@ namespace data } } - if (ts - lastExploratory >= 30) // exploratory every 30 seconds + if (ts - lastExploratory >= 30 || ts + 30 < lastExploratory) // exploratory every 30 seconds { auto numRouters = m_RouterInfos.size (); if (!numRouters) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 065befbe..12fa7771 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -537,17 +537,20 @@ namespace tunnel if (i2p::transport::transports.IsOnline()) { uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL) // manage tunnels every 15 seconds + if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL || // manage tunnels every 15 seconds + ts + TUNNEL_MANAGE_INTERVAL < lastTs) { - ManageTunnels (); + ManageTunnels (ts); lastTs = ts; } - if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL) // manage pools every 5 seconds + if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL || // manage pools every 5 secondsts + ts + TUNNEL_POOLS_MANAGE_INTERVAL < lastPoolsTs) { ManageTunnelPools (ts); lastPoolsTs = ts; } - if (ts - lastMemoryPoolTs >= TUNNEL_MEMORY_POOL_MANAGE_INTERVAL) // manage memory pool every 2 minutes + if (ts - lastMemoryPoolTs >= TUNNEL_MEMORY_POOL_MANAGE_INTERVAL || + ts + TUNNEL_MEMORY_POOL_MANAGE_INTERVAL < lastMemoryPoolTs) // manage memory pool every 2 minutes { m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt (); m_I2NPTunnelMessagesMemoryPool.CleanUpMt (); @@ -589,32 +592,32 @@ namespace tunnel tunnel->SendTunnelDataMsg (msg); } - void Tunnels::ManageTunnels () + void Tunnels::ManageTunnels (uint64_t ts) { - ManagePendingTunnels (); - ManageInboundTunnels (); - ManageOutboundTunnels (); - ManageTransitTunnels (); + ManagePendingTunnels (ts); + ManageInboundTunnels (ts); + ManageOutboundTunnels (ts); + ManageTransitTunnels (ts); } - void Tunnels::ManagePendingTunnels () + void Tunnels::ManagePendingTunnels (uint64_t ts) { - ManagePendingTunnels (m_PendingInboundTunnels); - ManagePendingTunnels (m_PendingOutboundTunnels); + ManagePendingTunnels (m_PendingInboundTunnels, ts); + ManagePendingTunnels (m_PendingOutboundTunnels, ts); } template - void Tunnels::ManagePendingTunnels (PendingTunnels& pendingTunnels) + void Tunnels::ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts) { // check pending tunnel. delete failed or timeout - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();) { auto tunnel = it->second; switch (tunnel->GetState ()) { case eTunnelStatePending: - if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT) + if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT || + ts + TUNNEL_CREATION_TIMEOUT < tunnel->GetCreationTime ()) { LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " timeout, deleted"); // update stats @@ -657,41 +660,38 @@ namespace tunnel } } - void Tunnels::ManageOutboundTunnels () + void Tunnels::ManageOutboundTunnels (uint64_t ts) { - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();) { - for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();) + auto tunnel = *it; + if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + auto pool = tunnel->GetTunnelPool (); + if (pool) + pool->TunnelExpired (tunnel); + // we don't have outbound tunnels in m_Tunnels + it = m_OutboundTunnels.erase (it); + } + else + { + if (tunnel->IsEstablished ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); - auto pool = tunnel->GetTunnelPool (); - if (pool) - pool->TunnelExpired (tunnel); - // we don't have outbound tunnels in m_Tunnels - it = m_OutboundTunnels.erase (it); - } - else - { - if (tunnel->IsEstablished ()) + if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + auto pool = tunnel->GetTunnelPool (); + // let it die if the tunnel pool has been reconfigured and this is old + if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops()) { - auto pool = tunnel->GetTunnelPool (); - // let it die if the tunnel pool has been reconfigured and this is old - if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops()) - { - tunnel->SetRecreated (true); - pool->RecreateOutboundTunnel (tunnel); - } + tunnel->SetRecreated (true); + pool->RecreateOutboundTunnel (tunnel); } - if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) - tunnel->SetState (eTunnelStateExpiring); } - ++it; + if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + tunnel->SetState (eTunnelStateExpiring); } + ++it; } } @@ -711,44 +711,42 @@ namespace tunnel } } - void Tunnels::ManageInboundTunnels () + void Tunnels::ManageInboundTunnels (uint64_t ts) { - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) { - for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) + auto tunnel = *it; + if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { - auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + auto pool = tunnel->GetTunnelPool (); + if (pool) + pool->TunnelExpired (tunnel); + m_Tunnels.erase (tunnel->GetTunnelID ()); + it = m_InboundTunnels.erase (it); + } + else + { + if (tunnel->IsEstablished ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); - auto pool = tunnel->GetTunnelPool (); - if (pool) - pool->TunnelExpired (tunnel); - m_Tunnels.erase (tunnel->GetTunnelID ()); - it = m_InboundTunnels.erase (it); - } - else - { - if (tunnel->IsEstablished ()) + if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + auto pool = tunnel->GetTunnelPool (); + // let it die if the tunnel pool was reconfigured and has different number of hops + if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops()) { - auto pool = tunnel->GetTunnelPool (); - // let it die if the tunnel pool was reconfigured and has different number of hops - if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops()) - { - tunnel->SetRecreated (true); - pool->RecreateInboundTunnel (tunnel); - } + tunnel->SetRecreated (true); + pool->RecreateInboundTunnel (tunnel); } - - if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) - tunnel->SetState (eTunnelStateExpiring); - else // we don't need to cleanup expiring tunnels - tunnel->Cleanup (); } - it++; + + if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + tunnel->SetState (eTunnelStateExpiring); + else // we don't need to cleanup expiring tunnels + tunnel->Cleanup (); } + it++; } } @@ -787,13 +785,13 @@ namespace tunnel } } - void Tunnels::ManageTransitTunnels () + void Tunnels::ManageTransitTunnels (uint64_t ts) { - uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_TransitTunnels.begin (); it != m_TransitTunnels.end ();) { auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired"); m_Tunnels.erase (tunnel->GetTunnelID ()); diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 36dee936..a603ff92 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -241,13 +241,13 @@ namespace tunnel void HandleTunnelGatewayMsg (std::shared_ptr tunnel, std::shared_ptr msg); void Run (); - void ManageTunnels (); - void ManageOutboundTunnels (); - void ManageInboundTunnels (); - void ManageTransitTunnels (); - void ManagePendingTunnels (); + void ManageTunnels (uint64_t ts); + void ManageOutboundTunnels (uint64_t ts); + void ManageInboundTunnels (uint64_t ts); + void ManageTransitTunnels (uint64_t ts); + void ManagePendingTunnels (uint64_t ts); template - void ManagePendingTunnels (PendingTunnels& pendingTunnels); + void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts); void ManageTunnelPools (uint64_t ts); std::shared_ptr CreateZeroHopsInboundTunnel (std::shared_ptr pool); From 993900aa7738eb2f69b743dcb18d5c0221fb93df Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Feb 2023 18:49:35 -0500 Subject: [PATCH 132/179] terminate sessions if clock was adjusted backwards too much --- libi2pd/Profiling.cpp | 6 ++++-- libi2pd/TransportSession.h | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 6f805193..6909e209 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -175,7 +175,8 @@ namespace data { if (!m_LastDeclineTime) return false; auto ts = i2p::util::GetSecondsSinceEpoch (); - if (ts > m_LastDeclineTime + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL) + if (ts > m_LastDeclineTime + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL || + ts + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL < m_LastDeclineTime) m_LastDeclineTime = 0; return (bool)m_LastDeclineTime; } @@ -200,7 +201,8 @@ namespace data { if (!m_LastUnreachableTime) return false; auto ts = i2p::util::GetSecondsSinceEpoch (); - if (ts > m_LastUnreachableTime + PEER_PROFILE_UNREACHABLE_INTERVAL) + if (ts > m_LastUnreachableTime + PEER_PROFILE_UNREACHABLE_INTERVAL || + ts + PEER_PROFILE_UNREACHABLE_INTERVAL < m_LastUnreachableTime) m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; } diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 56f6b9bc..03ade393 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -107,7 +107,10 @@ namespace transport int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; bool IsTerminationTimeoutExpired (uint64_t ts) const - { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; + { + return ts >= m_LastActivityTimestamp + GetTerminationTimeout () || + ts + GetTerminationTimeout () < m_LastActivityTimestamp; + }; uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers From 0829b186b7179210cc784318d76b6ad02b7fe423 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 10 Feb 2023 01:57:43 +0200 Subject: [PATCH 133/179] Fix debug log output --- libi2pd/NetDb.cpp | 2 +- libi2pd/SSU2Session.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0ffdb3ef..4a6fed70 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -834,7 +834,7 @@ namespace data } else // all others are considered as LeaseSet2 { - LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32()); + LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", int(storeType), " for ", ident.ToBase32()); updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index ac570b84..76dce891 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2308,7 +2308,7 @@ namespace transport void SSU2Session::HandleI2NPMsg (std::shared_ptr&& msg) { if (!msg) return; - int32_t msgID = msg->GetMsgID (); + uint32_t msgID = msg->GetMsgID (); if (!msg->IsExpired ()) { // m_LastActivityTimestamp is updated in ProcessData before From cb44a35fde728c6d4afb8128297b810131b49d26 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 10 Feb 2023 16:58:42 +0200 Subject: [PATCH 134/179] Fix description for nettime.enabled option --- libi2pd/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 971b1273..1bb3717c 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -285,7 +285,7 @@ namespace config { options_description nettime("Time sync options"); nettime.add_options() - ("nettime.enabled", value()->default_value(false), "Disable time sync (default: disabled)") + ("nettime.enabled", value()->default_value(false), "Enable NTP time sync (default: disabled)") ("nettime.ntpservers", value()->default_value( "0.pool.ntp.org," "1.pool.ntp.org," From ac94341203b90e1553a9860fcd8b360311f638bd Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Feb 2023 11:48:11 -0500 Subject: [PATCH 135/179] disconnect established session if clock skew detected --- libi2pd/NTCP2.cpp | 14 +++++++++++++- libi2pd/SSU2Session.cpp | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 47b8081f..b659ba78 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -884,8 +884,20 @@ namespace transport switch (blk) { case eNTCP2BlkDateTime: + { LogPrint (eLogDebug, "NTCP2: Datetime"); - break; + if (m_IsEstablished) + { + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + uint64_t tsA = bufbe32toh (frame + offset); + if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW) + { + LogPrint (eLogWarning, "NTCP2: Established session time difference ", (int)(ts - tsA), " exceeds clock skew"); + SendTerminationAndTerminate (eNTCP2ClockSkew); + } + } + break; + } case eNTCP2BlkOptions: LogPrint (eLogDebug, "NTCP2: Options"); break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 76dce891..a36536a8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1617,6 +1617,7 @@ namespace transport { case eSSU2SessionStateSessionRequestReceived: case eSSU2SessionStateTokenRequestReceived: + case eSSU2SessionStateEstablished: if (std::abs (offset) > SSU2_CLOCK_SKEW) m_TerminationReason = eSSU2TerminationReasonClockSkew; break; From 1c4cc02c234bd8ca1bf0c7c87aee318e9fc49f43 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Feb 2023 18:21:12 -0500 Subject: [PATCH 136/179] drop garlic message in garlic clove --- libi2pd/RouterContext.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index d37bd440..b6c7a5d9 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1100,6 +1100,12 @@ namespace i2p bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) { + if (typeID == eI2NPGarlic) + { + // TODO: implement + LogPrint (eLogWarning, "Router: garlic message in garlic clove. Dropped"); + return false; + } auto msg = CreateI2NPMessage (typeID, payload, len, msgID); if (!msg) return false; i2p::HandleI2NPMessage (msg); From 97b7ea0da5184caeaeef3a706c88af6d0f20d115 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Feb 2023 22:04:42 -0500 Subject: [PATCH 137/179] create separate new ipv4 and ipv6 published addresses --- libi2pd/RouterContext.cpp | 80 +++++++++++++++------------------------ 1 file changed, 31 insertions(+), 49 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b6c7a5d9..91bfadbc 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -85,7 +85,7 @@ namespace i2p bool ssu2Published = false; if (ssu2) i2p::config::GetOption("ssu2.published", ssu2Published); - uint8_t caps = 0, addressCaps = 0; + uint8_t caps = 0; if (ipv4) { std::string host; @@ -98,47 +98,41 @@ namespace i2p { uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); if (!ntcp2Port) ntcp2Port = port; - bool added = false; if (ntcp2Published && ntcp2Port) { + boost::asio::ip::address addr; if (!host.empty ()) - { - auto addr = boost::asio::ip::address::from_string (host); - if (addr.is_v4 ()) - { - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); - added = true; - } - } + addr = boost::asio::ip::address::from_string (host); + if (!addr.is_v4()) + addr = boost::asio::ip::address_v4 (); + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); } - if (!added) + else { // add non-published NTCP2 address - addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::AddressCaps::eV4); + uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; + if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, addressCaps); } } if (ssu2) { uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = port; - bool added = false; if (ssu2Published && ssu2Port) { + boost::asio::ip::address addr; if (!host.empty ()) - { - auto addr = boost::asio::ip::address::from_string (host); - if (addr.is_v4 ()) - { - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); - added = true; - } - } + addr = boost::asio::ip::address::from_string (host); + if (!addr.is_v4()) + addr = boost::asio::ip::address_v4 (); + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); } - if (!added) + else { - addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4; - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::AddressCaps::eV4); + uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; + if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, addressCaps); } } } @@ -151,7 +145,6 @@ namespace i2p { uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); if (!ntcp2Port) ntcp2Port = port; - bool added = false; if (ntcp2Published && ntcp2Port) { std::string ntcp2Host; @@ -159,45 +152,36 @@ namespace i2p i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); else ntcp2Host = host; + boost::asio::ip::address addr; if (!ntcp2Host.empty ()) - { - auto addr = boost::asio::ip::address::from_string (ntcp2Host); - if (addr.is_v6 ()) - { - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); - added = true; - } - } + addr = boost::asio::ip::address::from_string (ntcp2Host); + if (!addr.is_v6()) + addr = boost::asio::ip::address_v6 (); + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); } - if (!added) + else { if (!ipv4) // no other ntcp2 addresses yet routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::AddressCaps::eV6); - addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; } } if (ssu2) { uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = port; - bool added = false; if (ssu2Published && ssu2Port) { + boost::asio::ip::address addr; if (!host.empty ()) - { - auto addr = boost::asio::ip::address::from_string (host); - if (addr.is_v6 ()) - { - routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); - added = true; - } - } + addr = boost::asio::ip::address::from_string (host); + if (!addr.is_v6()) + addr = boost::asio::ip::address_v6 (); + routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); } - if (!added) + else { if (!ipv4) // no other ssu2 addresses yet routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::AddressCaps::eV6); - addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; } } } @@ -208,8 +192,6 @@ namespace i2p routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port); } - if (addressCaps) - routerInfo.SetUnreachableAddressesTransportCaps (addressCaps); routerInfo.UpdateCaps (caps); // caps + L routerInfo.SetProperty ("netId", std::to_string (m_NetID)); routerInfo.SetProperty ("router.version", I2P_VERSION); From 3c65012a63a0015db8ab871204e814fb88284fdd Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 11 Feb 2023 06:29:37 +0000 Subject: [PATCH 138/179] [ssu2] close socket if it was opened on OpenSocket Signed-off-by: R4SAS --- libi2pd/SSU2.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5bb27a40..3773f03d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -212,6 +212,8 @@ namespace transport boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4; try { + if (socket.is_open ()) + socket.close (); socket.open (localEndpoint.protocol ()); if (localEndpoint.address ().is_v6 ()) socket.set_option (boost::asio::ip::v6_only (true)); @@ -819,7 +821,7 @@ namespace transport m_CleanupTimer.async_wait (std::bind (&SSU2Server::HandleCleanupTimer, this, std::placeholders::_1)); } - + void SSU2Server::HandleCleanupTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) @@ -848,15 +850,15 @@ namespace transport else it++; } - + m_PacketsPool.CleanUpMt (); m_SentPacketsPool.CleanUp (); m_IncompleteMessagesPool.CleanUp (); m_FragmentsPool.CleanUp (); ScheduleCleanup (); - } - } - + } + } + void SSU2Server::ScheduleResend (bool more) { m_ResendTimer.expires_from_now (boost::posix_time::milliseconds (more ? SSU2_RESEND_CHECK_MORE_TIMEOUT : From 86fc12e3959e105032e73b28bdf6c8f62407c3d7 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 11 Feb 2023 09:41:51 +0300 Subject: [PATCH 139/179] [style] clean code Signed-off-by: R4SAS --- libi2pd/Config.cpp | 2 +- libi2pd/Destination.cpp | 8 ++-- libi2pd/NTCP2.cpp | 14 +++--- libi2pd/NetDb.cpp | 10 ++-- libi2pd/Profiling.cpp | 20 ++++---- libi2pd/Profiling.h | 8 ++-- libi2pd/RouterContext.cpp | 98 +++++++++++++++++++------------------- libi2pd/RouterContext.h | 2 +- libi2pd/RouterInfo.cpp | 54 ++++++++++----------- libi2pd/SSU2.h | 4 +- libi2pd/SSU2Session.cpp | 58 +++++++++++----------- libi2pd/SSU2Session.h | 4 +- libi2pd/TransportSession.h | 4 +- libi2pd/Transports.cpp | 32 ++++++------- libi2pd/Transports.h | 4 +- libi2pd/Tunnel.cpp | 14 +++--- libi2pd/Tunnel.h | 10 ++-- libi2pd/TunnelPool.h | 4 +- 18 files changed, 175 insertions(+), 175 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 1bb3717c..8df08118 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -45,7 +45,7 @@ namespace config { ("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)") ("family", value()->default_value(""), "Specify a family, router belongs to") ("datadir", value()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") - ("host", value()->default_value(""), "External IP") + ("host", value()->default_value(""), "External IP") ("ifname", value()->default_value(""), "Network interface to bind to") ("ifname4", value()->default_value(""), "Network interface to bind to for ipv4") ("ifname6", value()->default_value(""), "Network interface to bind to for ipv6") diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9be0c06e..5d6b71b9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -415,7 +415,7 @@ namespace client { LogPrint (eLogError, "Destination: Database store message is too long ", len); return; - } + } i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET); std::shared_ptr leaseSet; switch (buf[DATABASE_STORE_TYPE_OFFSET]) @@ -786,7 +786,7 @@ namespace client LogPrint (eLogWarning, "Destination: LeaseSet request for ", dest.ToBase32 (), " was not sent"); m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); - } + } } } else // duplicate @@ -1173,11 +1173,11 @@ namespace client }, dest, port); while (!done) - { + { std::unique_lock l(streamRequestCompleteMutex); if (!done) streamRequestComplete.wait (l); - } + } return stream; } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index b659ba78..68ed7353 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -693,8 +693,8 @@ 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 ()); + auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () : + (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ()); if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32)) { LogPrint (eLogError, "NTCP2: Wrong static key in SessionConfirmed"); @@ -703,13 +703,13 @@ namespace transport } if (addr->IsPublishedNTCP2 () && m_RemoteEndpoint.address () != addr->host && (!m_RemoteEndpoint.address ().is_v6 () || (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? - 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 () + 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 ()); Terminate (); return; - } + } i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options @@ -884,7 +884,7 @@ namespace transport switch (blk) { case eNTCP2BlkDateTime: - { + { LogPrint (eLogDebug, "NTCP2: Datetime"); if (m_IsEstablished) { @@ -894,8 +894,8 @@ namespace transport { LogPrint (eLogWarning, "NTCP2: Established session time difference ", (int)(ts - tsA), " exceeds clock skew"); SendTerminationAndTerminate (eNTCP2ClockSkew); - } - } + } + } break; } case eNTCP2BlkOptions: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 4a6fed70..d28b0bb3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -430,15 +430,15 @@ namespace data { auto it = m_RouterInfos.find (ident); if (it != m_RouterInfos.end ()) - { + { it->second->SetUnreachable (unreachable); if (unreachable) - { + { auto profile = it->second->GetProfile (); if (profile) profile->Unreachable (); - } - } + } + } } void NetDb::Reseed () @@ -824,7 +824,7 @@ namespace data { LogPrint (eLogError, "NetDb: Database store message is too long ", len); return; - } + } if (!m->from) // unsolicited LS must be received directly { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 6909e209..a127ce81 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -136,15 +136,15 @@ namespace data { UpdateTime (); if (ret > 0) - { + { m_NumTunnelsDeclined++; m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); - } + } else - { + { m_NumTunnelsAgreed++; m_LastDeclineTime = 0; - } + } } void RouterProfile::TunnelNonReplied () @@ -158,8 +158,8 @@ namespace data void RouterProfile::Unreachable () { m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); - } - + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate @@ -179,8 +179,8 @@ namespace data ts + PEER_PROFILE_DECLINED_RECENTLY_INTERVAL < m_LastDeclineTime) m_LastDeclineTime = 0; return (bool)m_LastDeclineTime; - } - + } + bool RouterProfile::IsBad () { if (IsDeclinedRecently () || IsUnreachable ()) return true; @@ -205,8 +205,8 @@ namespace data ts + PEER_PROFILE_UNREACHABLE_INTERVAL < m_LastUnreachableTime) m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; - } - + } + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { auto profile = std::make_shared (); diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 58b5e2ea..bccf19de 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -33,8 +33,8 @@ namespace data const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day) const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) - const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) - + const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + class RouterProfile { public: @@ -47,12 +47,12 @@ namespace data bool IsBad (); bool IsUnreachable (); - + void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); void Unreachable (); - + private: boost::posix_time::ptime GetTime () const; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 91bfadbc..a91b9217 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -88,7 +88,7 @@ namespace i2p uint8_t caps = 0; if (ipv4) { - std::string host; + std::string host; if (!nat) // we have no NAT so set external address from local address i2p::config::GetOption("address4", host); @@ -99,15 +99,15 @@ namespace i2p uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); if (!ntcp2Port) ntcp2Port = port; if (ntcp2Published && ntcp2Port) - { + { boost::asio::ip::address addr; if (!host.empty ()) addr = boost::asio::ip::address::from_string (host); if (!addr.is_v4()) addr = boost::asio::ip::address_v4 (); - routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); - } - else + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); + } + else { // add non-published NTCP2 address uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; @@ -120,14 +120,14 @@ namespace i2p uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port); if (!ssu2Port) ssu2Port = port; if (ssu2Published && ssu2Port) - { + { boost::asio::ip::address addr; if (!host.empty ()) addr = boost::asio::ip::address::from_string (host); if (!addr.is_v4()) addr = boost::asio::ip::address_v4 (); routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); - } + } else { uint8_t addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; @@ -138,7 +138,7 @@ namespace i2p } if (ipv6) { - std::string host; i2p::config::GetOption("address6", host); + std::string host; i2p::config::GetOption("address6", host); if (host.empty () && !ipv4) i2p::config::GetOption("host", host); // use host for ipv6 only if ipv4 is not presented if (ntcp2) @@ -255,7 +255,7 @@ namespace i2p break; case eRouterStatusTesting: m_Error = eRouterErrorNone; - break; + break; default: ; } @@ -277,7 +277,7 @@ namespace i2p break; case eRouterStatusTesting: m_ErrorV6 = eRouterErrorNone; - break; + break; default: ; } @@ -309,8 +309,8 @@ namespace i2p if (port) address->port = port; address->published = publish; memcpy (address->i, m_NTCP2Keys->iv, 16); - } - + } + void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg) { if (!m_NTCP2Keys) return; @@ -324,8 +324,8 @@ namespace i2p { PublishNTCP2Address (addr, port, publish); updated = true; - } - } + } + } if (v6) { auto addr = (*addresses)[i2p::data::RouterInfo::eNTCP2V6Idx]; @@ -333,7 +333,7 @@ namespace i2p { PublishNTCP2Address (addr, port, publish); updated = true; - } + } } if (ygg) { @@ -342,9 +342,9 @@ namespace i2p { PublishNTCP2Address (addr, port, publish); updated = true; - } + } } - + if (updated) UpdateRouterInfo (); } @@ -362,8 +362,8 @@ namespace i2p memcpy (it->i, m_NTCP2Keys->iv, 16); } } - } - + } + void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6) { if (!m_SSU2Keys) return; @@ -413,8 +413,8 @@ namespace i2p it->i = m_SSU2Keys->intro; } } - } - + } + void RouterContext::UpdateAddress (const boost::asio::ip::address& host) { auto addresses = m_RouterInfo.GetAddresses (); @@ -727,11 +727,11 @@ namespace i2p { auto addr = boost::asio::ip::address::from_string (ntcp2Host); if (addr.is_v6 ()) - { + { m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); added = true; - } - } + } + } } if (!added) m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV6); @@ -753,15 +753,15 @@ namespace i2p { std::string host; i2p::config::GetOption("host", host); if (!host.empty ()) - { + { auto addr = boost::asio::ip::address::from_string (host); if (addr.is_v6 ()) - { + { m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); added = true; } - } - } + } + } if (!added) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV6); } @@ -819,18 +819,18 @@ namespace i2p bool added = false; bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); if (ntcp2Published && ntcp2Port) - { + { std::string host; i2p::config::GetOption("host", host); if (!host.empty ()) - { + { auto addr = boost::asio::ip::address::from_string (host); if (addr.is_v4 ()) - { + { m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, addr, ntcp2Port); added = true; - } - } - } + } + } + } if (!added) m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, ntcp2Port, i2p::data::RouterInfo::eV4); } @@ -849,18 +849,18 @@ namespace i2p bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published); std::string host; i2p::config::GetOption("host", host); if (ssu2Published && ssu2Port) - { + { std::string host; i2p::config::GetOption("host", host); if (!host.empty ()) - { + { auto addr = boost::asio::ip::address::from_string (host); if (addr.is_v4 ()) - { + { m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addr, ssu2Port); added = true; } - } - } + } + } if (!added) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, ssu2Port, i2p::data::RouterInfo::eV4); } @@ -933,7 +933,7 @@ namespace i2p { addr->host = host; UpdateRouterInfo (); - } + } } void RouterContext::UpdateStats () @@ -1034,28 +1034,28 @@ namespace i2p if (IsUnreachable ()) SetReachable (true, true); // we assume reachable until we discover firewall through peer tests - + bool updated = false; // create new NTCP2 keys if required bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); - if ((ntcp2 || ygg) && !m_NTCP2Keys) - { + if ((ntcp2 || ygg) && !m_NTCP2Keys) + { NewNTCP2Keys (); UpdateNTCP2Keys (); updated = true; - } + } // create new SSU2 keys if required bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - if (ssu2 && !m_SSU2Keys) - { + if (ssu2 && !m_SSU2Keys) + { NewSSU2Keys (); UpdateSSU2Keys (); updated = true; - } + } if (updated) UpdateRouterInfo (); - + return true; } @@ -1087,7 +1087,7 @@ namespace i2p // TODO: implement LogPrint (eLogWarning, "Router: garlic message in garlic clove. Dropped"); return false; - } + } auto msg = CreateI2NPMessage (typeID, payload, len, msgID); if (!msg) return false; i2p::HandleI2NPMessage (msg); diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 22359ded..9fbbb178 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -181,7 +181,7 @@ namespace garlic void SaveKeys (); uint16_t SelectRandomPort () const; void PublishNTCP2Address (std::shared_ptr address, int port, bool publish) const; - + bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize); private: diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 28959fe9..32b01217 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -252,15 +252,15 @@ namespace data { boost::system::error_code ecode; address->host = boost::asio::ip::address::from_string (value, ecode); - if (!ecode && !address->host.is_unspecified ()) + if (!ecode && !address->host.is_unspecified ()) { - if (!i2p::util::net::IsInReservedRange (address->host) || + if (!i2p::util::net::IsInReservedRange (address->host) || i2p::util::net::IsYggdrasilAddress (address->host)) isHost = true; else - // we consider such address as invalid - address->transportStyle = eTransportUnknown; - } + // we consider such address as invalid + address->transportStyle = eTransportUnknown; + } } else if (!strcmp (key, "port")) { @@ -648,8 +648,8 @@ namespace data m_SupportedTransports |= eNTCP2V6; (*m_Addresses)[eNTCP2V6Idx] = addr; } - } - + } + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port) { @@ -688,20 +688,20 @@ namespace data void RouterInfo::RemoveNTCP2Address (bool v4) { if (v4) - { + { if ((*m_Addresses)[eNTCP2V6Idx]) (*m_Addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eNTCP2V4Idx].reset (); - } + } else - { + { if ((*m_Addresses)[eNTCP2V4Idx]) (*m_Addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eNTCP2V6Idx].reset (); - } + } UpdateSupportedTransports (); - } - + } + void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, int port, uint8_t caps) { auto addr = std::make_shared
(); @@ -756,20 +756,20 @@ namespace data void RouterInfo::RemoveSSU2Address (bool v4) { if (v4) - { + { if ((*m_Addresses)[eSSU2V6Idx]) (*m_Addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; (*m_Addresses)[eSSU2V4Idx].reset (); - } + } else - { + { if ((*m_Addresses)[eSSU2V4Idx]) (*m_Addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; (*m_Addresses)[eSSU2V6Idx].reset (); - } + } UpdateSupportedTransports (); - } - + } + bool RouterInfo::IsNTCP2 (bool v4only) const { if (v4only) @@ -919,7 +919,7 @@ namespace data { return (*GetAddresses ())[eNTCP2V6Idx]; } - + std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const { auto addr = (*GetAddresses ())[eNTCP2V4Idx]; @@ -1032,13 +1032,13 @@ namespace data std::shared_ptr RouterInfo::NewAddress () const { return netdb.NewRouterInfoAddress (); - } - + } + boost::shared_ptr RouterInfo::NewAddresses () const { return netdb.NewRouterInfoAddresses (); - } - + } + void RouterInfo::RefreshTimestamp () { m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); @@ -1324,12 +1324,12 @@ namespace data { return std::make_shared
(); } - + boost::shared_ptr LocalRouterInfo::NewAddresses () const { return boost::make_shared (); - } - + } + bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4) { auto addresses = GetAddresses (); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 8b755f60..2e652786 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -100,7 +100,7 @@ namespace transport i2p::util::MemoryPool& GetSentPacketsPool () { return m_SentPacketsPool; }; i2p::util::MemoryPool& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; }; i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; - + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -116,7 +116,7 @@ namespace transport void ScheduleCleanup (); void HandleCleanupTimer (const boost::system::error_code& ecode); - + void ScheduleResend (bool more); void HandleResendTimer (const boost::system::error_code& ecode); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index a36536a8..b713f02d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -36,34 +36,34 @@ namespace transport { bool isLast = false; while (outOfSequenceFragments) - { + { if (outOfSequenceFragments->fragmentNum == nextFragmentNum) { AttachNextFragment (outOfSequenceFragments->buf, outOfSequenceFragments->len); isLast = outOfSequenceFragments->isLast; if (isLast) outOfSequenceFragments = nullptr; - else + else outOfSequenceFragments = outOfSequenceFragments->next; - } + } else break; - } + } return isLast; - } + } void SSU2IncompleteMessage::AddOutOfSequenceFragment (std::shared_ptr fragment) - { + { if (!fragment || !fragment->fragmentNum) return; // fragment 0 not allowed if (fragment->fragmentNum < nextFragmentNum) return; // already processed - if (!outOfSequenceFragments) + if (!outOfSequenceFragments) outOfSequenceFragments = fragment; else { auto frag = outOfSequenceFragments; std::shared_ptr prev; do - { + { if (fragment->fragmentNum < frag->fragmentNum) break; // found if (fragment->fragmentNum == frag->fragmentNum) return; // duplicate prev = frag; frag = frag->next; @@ -71,13 +71,13 @@ namespace transport while (frag); fragment->next = frag; if (prev) - prev->next = fragment; + prev->next = fragment; else outOfSequenceFragments = fragment; - } + } lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); } - + SSU2Session::SSU2Session (SSU2Server& server, std::shared_ptr in_RemoteRouter, std::shared_ptr addr): TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), @@ -1041,20 +1041,20 @@ namespace transport LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block"); return false; } - m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); + m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); if (!m_Address || memcmp (S, m_Address->s, 32)) { LogPrint (eLogError, "SSU2: Wrong static key in SessionConfirmed from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; } if (m_Address->published && m_RemoteEndpoint.address () != m_Address->host && - (!m_RemoteEndpoint.address ().is_v6 () || + (!m_RemoteEndpoint.address ().is_v6 () || memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address { - LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, + LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); return false; - } + } // update RouterInfo in netdb ri = i2p::data::netdb.AddRouterInfo (ri->GetBuffer (), ri->GetBufferLen ()); // ri points to one from netdb now if (!ri) @@ -1617,7 +1617,7 @@ namespace transport { case eSSU2SessionStateSessionRequestReceived: case eSSU2SessionStateTokenRequestReceived: - case eSSU2SessionStateEstablished: + case eSSU2SessionStateEstablished: if (std::abs (offset) > SSU2_CLOCK_SKEW) m_TerminationReason = eSSU2TerminationReasonClockSkew; break; @@ -1804,7 +1804,7 @@ namespace transport { LogPrint (eLogWarning, "SSU2: Invalid follow-on fragment num ", fragmentNum); return; - } + } bool isLast = buf[0] & 0x01; uint32_t msgID; memcpy (&msgID, buf + 1, 4); auto it = m_IncompleteMessages.find (msgID); @@ -2307,21 +2307,21 @@ namespace transport } void SSU2Session::HandleI2NPMsg (std::shared_ptr&& msg) - { + { if (!msg) return; uint32_t msgID = msg->GetMsgID (); if (!msg->IsExpired ()) { // m_LastActivityTimestamp is updated in ProcessData before if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second) - m_Handler.PutNextMessage (std::move (msg)); + m_Handler.PutNextMessage (std::move (msg)); else LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); } else LogPrint (eLogDebug, "SSU2: Message ", msgID, " expired"); - } - + } + bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep) { if (size < 2) return false; @@ -2473,7 +2473,7 @@ namespace transport acnt++; if (acnt >= SSU2_MAX_NUM_ACK_PACKETS) break; - else + else it++; } // ranges @@ -2499,8 +2499,8 @@ namespace transport numRanges++; } } - int numPackets = acnt + numRanges*SSU2_MAX_NUM_ACNT; - while (it != m_OutOfSequencePackets.rend () && + int numPackets = acnt + numRanges*SSU2_MAX_NUM_ACNT; + while (it != m_OutOfSequencePackets.rend () && numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS) { if (lastNum - (*it) > SSU2_MAX_NUM_ACNT) @@ -2786,7 +2786,7 @@ namespace transport while (it != m_OutOfSequencePackets.end ()) { if (*it == packetNum + 1) - { + { packetNum++; it++; } @@ -2794,7 +2794,7 @@ namespace transport break; } m_OutOfSequencePackets.erase (m_OutOfSequencePackets.begin (), it); - } + } } m_ReceivePacketNum = packetNum; } @@ -2881,7 +2881,7 @@ namespace transport if (!m_OutOfSequencePackets.empty ()) { int ranges = 0; - while (ranges < 8 && !m_OutOfSequencePackets.empty () && + while (ranges < 8 && !m_OutOfSequencePackets.empty () && (m_OutOfSequencePackets.size () > 2*SSU2_MAX_NUM_ACK_RANGES || *m_OutOfSequencePackets.rbegin () > m_ReceivePacketNum + SSU2_MAX_NUM_ACK_PACKETS)) { @@ -2895,10 +2895,10 @@ namespace transport ranges++; } else - { + { LogPrint (eLogError, "SSU2: Out of sequence packet ", packet, " is less than last received ", m_ReceivePacketNum); break; - } + } } if (m_OutOfSequencePackets.size () > 255*4) { diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 03395d0f..151aae4d 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -52,7 +52,7 @@ namespace transport const int SSU2_MAX_NUM_ACK_PACKETS = 510; // 2*255 ack + nack const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; - + // flags const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; @@ -317,7 +317,7 @@ namespace transport void HandleRelayResponse (const uint8_t * buf, size_t len); 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 CreateAckBlock (uint8_t * buf, size_t len); diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 03ade393..83b6cacd 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -107,9 +107,9 @@ namespace transport int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; bool IsTerminationTimeoutExpired (uint64_t ts) const - { + { return ts >= m_LastActivityTimestamp + GetTerminationTimeout () || - ts + GetTerminationTimeout () < m_LastActivityTimestamp; + ts + GetTerminationTimeout () < m_LastActivityTimestamp; }; uint32_t GetCreationTime () const { return m_CreationTime; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index bfd1b190..aa326a92 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -831,12 +831,12 @@ namespace transport std::advance (it, inds[0]); // try random peer if (it != m_Peers.end () && filter (it->second)) - { + { ident = it->first; found = true; - } + } else - { + { // try some peers around auto it1 = m_Peers.begin (); if (inds[0]) @@ -859,48 +859,48 @@ namespace transport while (it != it2 && it != m_Peers.end ()) { if (filter (it->second)) - { + { ident = it->first; found = true; break; - } + } it++; } if (!found) - { + { // still not found, try from the beginning it = m_Peers.begin (); while (it != it1 && it != m_Peers.end ()) { if (filter (it->second)) - { + { ident = it->first; found = true; break; - } + } it++; } if (!found) - { + { // still not found, try to the beginning it = it2; while (it != m_Peers.end ()) { if (filter (it->second)) - { + { ident = it->first; found = true; break; - } + } it++; } - } - } - } - } + } + } + } + } return found ? i2p::data::netdb.FindRouter (ident) : nullptr; } - + std::shared_ptr Transports::GetRandomPeer (bool isHighBandwidth) const { return GetRandomPeer ( diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index ebb6261e..dc97a952 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -94,7 +94,7 @@ namespace transport router = r; if (router) isHighBandwidth = router->IsHighBandwidth (); - } + } }; const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds @@ -176,7 +176,7 @@ namespace transport template std::shared_ptr GetRandomPeer (Filter filter) const; - + private: volatile bool m_IsOnline; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 12fa7771..372c3ff9 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -334,7 +334,7 @@ namespace tunnel Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal avarage m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) - { + { } Tunnels::~Tunnels () @@ -439,11 +439,11 @@ namespace tunnel if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) m_TransitTunnels.push_back (tunnel); else - { + { LogPrint (eLogError, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " already exists"); - return false; - } - return true; + return false; + } + return true; } void Tunnels::Start () @@ -538,13 +538,13 @@ namespace tunnel { uint64_t ts = i2p::util::GetSecondsSinceEpoch (); if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL || // manage tunnels every 15 seconds - ts + TUNNEL_MANAGE_INTERVAL < lastTs) + ts + TUNNEL_MANAGE_INTERVAL < lastTs) { ManageTunnels (ts); lastTs = ts; } if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL || // manage pools every 5 secondsts - ts + TUNNEL_POOLS_MANAGE_INTERVAL < lastPoolsTs) + ts + TUNNEL_POOLS_MANAGE_INTERVAL < lastPoolsTs) { ManageTunnelPools (ts); lastPoolsTs = ts; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index a603ff92..b690d1eb 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -254,7 +254,7 @@ namespace tunnel std::shared_ptr CreateZeroHopsOutboundTunnel (std::shared_ptr pool); // Calculating of tunnel creation success rate - void SuccesiveTunnelCreation() + void SuccesiveTunnelCreation() { // total TCSR m_TotalNumSuccesiveTunnelCreations++; @@ -263,14 +263,14 @@ namespace tunnel m_TunnelCreationSuccessRate = alpha * 1 + (1 - alpha) * m_TunnelCreationSuccessRate; } - void FailedTunnelCreation() + void FailedTunnelCreation() { m_TotalNumFailedTunnelCreations++; - + double alpha = TCSR_SMOOTHING_CONSTANT + (1 - TCSR_SMOOTHING_CONSTANT)/++m_TunnelCreationAttemptsNum; m_TunnelCreationSuccessRate = alpha * 0 + (1 - alpha) * m_TunnelCreationSuccessRate; } - + private: bool m_IsRunning; @@ -288,7 +288,7 @@ namespace tunnel i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; // count of tunnels for total TCSR algorithm - int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; + int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; int m_TunnelCreationAttemptsNum; diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 6936d3ad..7d952559 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -56,7 +56,7 @@ namespace tunnel class TunnelPool: public std::enable_shared_from_this // per local destination { - typedef std::function(std::shared_ptr, bool)> SelectHopFunc; + typedef std::function(std::shared_ptr, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -114,7 +114,7 @@ namespace tunnel // for overriding tunnel peer selection std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); - + private: void TestTunnels (); From 48a3c767e58435ee448ced2bf9664f4c6a09822d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 11 Feb 2023 16:22:02 -0500 Subject: [PATCH 140/179] in-meory storage for router profiles --- libi2pd/NetDb.cpp | 16 +++++----- libi2pd/Profiling.cpp | 68 ++++++++++++++++++++++++++++++++++--------- libi2pd/Profiling.h | 14 ++++++--- libi2pd/RouterInfo.h | 2 +- 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index d28b0bb3..0d68cee3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -85,8 +85,7 @@ namespace data if (m_IsRunning) { if (m_PersistProfiles) - for (auto& it: m_RouterInfos) - it.second->SaveProfile (); + SaveProfiles (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); m_Floodfills.clear (); @@ -179,6 +178,7 @@ namespace data if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { + if (m_PersistProfiles) PersistProfiles (); DeleteObsoleteProfiles (); lastProfilesCleanup = ts; profilesCleanupVariance = (rand () % (2 * i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE) - i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE); @@ -684,12 +684,12 @@ namespace data for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { if (it->second->IsUnreachable ()) - { - if (m_PersistProfiles) it->second->SaveProfile (); it = m_RouterInfos.erase (it); - continue; - } - ++it; + else + { + it->second->DropProfile (); + it++; + } } } // clean up expired floodfills or not floodfills anymore @@ -699,7 +699,7 @@ namespace data if ((*it)->IsUnreachable () || !(*it)->IsFloodfill ()) it = m_Floodfills.erase (it); else - ++it; + it++; } } } diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index a127ce81..2dafe8ca 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include "Base.h" @@ -19,24 +20,26 @@ namespace i2p { namespace data { - i2p::fs::HashedStorage m_ProfilesStorage("peerProfiles", "p", "profile-", "txt"); + static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt"); + static std::unordered_map > g_Profiles; + static boost::posix_time::ptime GetTime () + { + return boost::posix_time::second_clock::local_time(); + } + RouterProfile::RouterProfile (): - m_LastUpdateTime (boost::posix_time::second_clock::local_time()), + m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), m_NumTimesTaken (0), m_NumTimesRejected (0) { } - boost::posix_time::ptime RouterProfile::GetTime () const - { - return boost::posix_time::second_clock::local_time(); - } - void RouterProfile::UpdateTime () { m_LastUpdateTime = GetTime (); + m_IsUpdated = true; } void RouterProfile::Save (const IdentHash& identHash) @@ -59,7 +62,7 @@ namespace data // save to file std::string ident = identHash.ToBase64 (); - std::string path = m_ProfilesStorage.Path(ident); + std::string path = g_ProfilesStorage.Path(ident); try { boost::property_tree::write_ini (path, pt); @@ -72,7 +75,7 @@ namespace data void RouterProfile::Load (const IdentHash& identHash) { std::string ident = identHash.ToBase64 (); - std::string path = m_ProfilesStorage.Path(ident); + std::string path = g_ProfilesStorage.Path(ident); boost::property_tree::ptree pt; if (!i2p::fs::Exists(path)) @@ -158,6 +161,7 @@ namespace data void RouterProfile::Unreachable () { m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); + UpdateTime (); } bool RouterProfile::IsLowPartcipationRate () const @@ -209,30 +213,68 @@ namespace data std::shared_ptr GetRouterProfile (const IdentHash& identHash) { + auto it = g_Profiles.find (identHash); + if (it != g_Profiles.end ()) + return it->second; auto profile = std::make_shared (); profile->Load (identHash); // if possible + g_Profiles.emplace (identHash, profile); return profile; } void InitProfilesStorage () { - m_ProfilesStorage.SetPlace(i2p::fs::GetDataDir()); - m_ProfilesStorage.Init(i2p::data::GetBase64SubstitutionTable(), 64); + g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir()); + g_ProfilesStorage.Init(i2p::data::GetBase64SubstitutionTable(), 64); } + void PersistProfiles () + { + auto ts = GetTime (); + for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) + { + if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) + { + if (it->second->IsUpdated ()) + it->second->Save (it->first); + it = g_Profiles.erase (it); + } + else + it++; + } + } + + void SaveProfiles () + { + auto ts = GetTime (); + for (auto it: g_Profiles) + if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + it.second->Save (it.first); + g_Profiles.clear (); + } + void DeleteObsoleteProfiles () { + auto ts = GetTime (); + for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) + { + if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + it = g_Profiles.erase (it); + else + it++; + } + struct stat st; std::time_t now = std::time(nullptr); std::vector files; - m_ProfilesStorage.Traverse(files); + g_ProfilesStorage.Traverse(files); for (const auto& path: files) { if (stat(path.c_str(), &st) != 0) { LogPrint(eLogWarning, "Profiling: Can't stat(): ", path); continue; } - if (((now - st.st_mtime) / 3600) >= PEER_PROFILE_EXPIRATION_TIMEOUT) { + if (now - st.st_mtime >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) { LogPrint(eLogDebug, "Profiling: Removing expired peer profile: ", path); i2p::fs::Remove(path); } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index bccf19de..752d6190 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -29,10 +29,11 @@ namespace data const char PEER_PROFILE_USAGE_TAKEN[] = "taken"; const char PEER_PROFILE_USAGE_REJECTED[] = "rejected"; - const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days) - const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day) - const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours) + const int PEER_PROFILE_EXPIRATION_TIMEOUT = 36; // in hours (1.5 days) + const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 6 * 3600; // in seconds (6 hours) + const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) + const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) class RouterProfile @@ -53,9 +54,11 @@ namespace data void Unreachable (); + boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; + bool IsUpdated () const { return m_IsUpdated; }; + private: - boost::posix_time::ptime GetTime () const; void UpdateTime (); bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; }; @@ -66,6 +69,7 @@ namespace data private: boost::posix_time::ptime m_LastUpdateTime; // TODO: use std::chrono + bool m_IsUpdated; uint64_t m_LastDeclineTime, m_LastUnreachableTime; // in seconds // participation uint32_t m_NumTunnelsAgreed; @@ -79,6 +83,8 @@ namespace data std::shared_ptr GetRouterProfile (const IdentHash& identHash); void InitProfilesStorage (); void DeleteObsoleteProfiles (); + void SaveProfiles (); + void PersistProfiles (); } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index ea0abf41..f31b3cc2 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -251,7 +251,7 @@ namespace data bool SaveToFile (const std::string& fullPath); std::shared_ptr GetProfile () const; - void SaveProfile () { if (m_Profile) m_Profile->Save (GetIdentHash ()); }; + void DropProfile () { m_Profile = nullptr; }; void Update (const uint8_t * buf, size_t len); void DeleteBuffer () { m_Buffer = nullptr; }; From d79bdc9f66fc687b08b2ca073f2330b4bdda25e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 11 Feb 2023 20:11:34 -0500 Subject: [PATCH 141/179] send datetime block after approximately every 250 packets --- libi2pd/SSU2Session.cpp | 17 +++++++++++++---- libi2pd/SSU2Session.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index b713f02d..e45a33a2 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -83,9 +83,9 @@ namespace transport TransportSession (in_RemoteRouter, SSU2_CONNECT_TIMEOUT), m_Server (server), m_Address (addr), m_RemoteTransports (0), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), - m_SendPacketNum (0), m_ReceivePacketNum (0), m_IsDataReceived (false), - m_WindowSize (SSU2_MIN_WINDOW_SIZE), m_RTT (SSU2_RESEND_INTERVAL), - m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0), + m_SendPacketNum (0), m_ReceivePacketNum (0), m_LastDatetimeSentPacketNum (0), + m_IsDataReceived (false), m_WindowSize (SSU2_MIN_WINDOW_SIZE), + m_RTT (SSU2_RESEND_INTERVAL), m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0), m_ConnectTimer (server.GetService ()), m_TerminationReason (eSSU2TerminationReasonNormalClose), m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32) // min size { @@ -2806,7 +2806,16 @@ namespace transport void SSU2Session::SendQuickAck () { uint8_t payload[SSU2_MAX_PACKET_SIZE]; - size_t payloadSize = CreateAckBlock (payload, m_MaxPayloadSize); + size_t payloadSize = 0; + if (m_SendPacketNum > m_LastDatetimeSentPacketNum + SSU2_SEND_DATETIME_NUM_PACKETS) + { + payload[0] = eSSU2BlkDateTime; + htobe16buf (payload + 1, 4); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); + payloadSize += 7; + m_LastDatetimeSentPacketNum = m_SendPacketNum; + } + payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 151aae4d..363cb982 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -52,6 +52,7 @@ namespace transport const int SSU2_MAX_NUM_ACK_PACKETS = 510; // 2*255 ack + nack const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; + const int SSU2_SEND_DATETIME_NUM_PACKETS = 250; // flags const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; @@ -344,7 +345,7 @@ namespace transport uint64_t m_DestConnID, m_SourceConnID; SSU2SessionState m_State; uint8_t m_KeyDataSend[64], m_KeyDataReceive[64]; - uint32_t m_SendPacketNum, m_ReceivePacketNum; + uint32_t m_SendPacketNum, m_ReceivePacketNum, m_LastDatetimeSentPacketNum; std::set m_OutOfSequencePackets; // packet nums > receive packet num std::map > m_SentPackets; // packetNum -> packet std::unordered_map > m_IncompleteMessages; // msgID -> I2NP From 88f19f551d9c11330b5e0b96f52bcfdab6ccf195 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Feb 2023 09:21:59 -0500 Subject: [PATCH 142/179] don't save RouterInfo buffer if invalid --- libi2pd/RouterInfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 32b01217..1bf1d42d 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -99,13 +99,13 @@ namespace data m_Caps = 0; // don't clean up m_Addresses, it will be replaced in ReadFromStream ClearProperties (); - // copy buffer - UpdateBuffer (buf, len); // skip identity size_t identityLen = m_RouterIdentity->GetFullLen (); // read new RI - std::stringstream str (std::string ((char *)m_Buffer->data () + identityLen, m_BufferLen - identityLen)); + std::stringstream str (std::string ((char *)buf + identityLen, len - identityLen)); ReadFromStream (str); + if (!m_IsUnreachable) + UpdateBuffer (buf, len); // save buffer // don't delete buffer until saved to the file } else From 7bde4de1f557d9c86ab9f4abc9b49046d71a7d10 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Feb 2023 15:28:06 -0500 Subject: [PATCH 143/179] don't try to save unreachable routers --- libi2pd/RouterInfo.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 1bf1d42d..65b6a0f0 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -595,14 +595,16 @@ namespace data bool RouterInfo::SaveToFile (const std::string& fullPath) { + if (m_IsUnreachable) return false; // don't save bad router if (!m_Buffer) { - LogPrint (eLogError, "RouterInfo: Can't save, m_Buffer == NULL"); + LogPrint (eLogWarning, "RouterInfo: Can't save, m_Buffer == NULL"); return false; } std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); - if (!f.is_open ()) { - LogPrint(eLogError, "RouterInfo: Can't save to ", fullPath); + if (!f.is_open ()) + { + LogPrint (eLogError, "RouterInfo: Can't save to ", fullPath); return false; } f.write ((char *)m_Buffer->data (), m_BufferLen); From d15581d95e0662a511d25903ee29e04af0b0701a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Feb 2023 18:02:16 -0500 Subject: [PATCH 144/179] delete invalid router after update --- libi2pd/NetDb.cpp | 17 ++++++++++++++++- libi2pd/RouterInfo.cpp | 16 ++++++++-------- libi2pd/RouterInfo.h | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0d68cee3..374d2d6d 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -276,7 +276,22 @@ namespace data bool wasFloodfill = r->IsFloodfill (); { std::unique_lock l(m_RouterInfosMutex); - r->Update (buf, len); + if (!r->Update (buf, len)) + { + updated = false; + return r; + } + if (r->IsUnreachable ()) + { + // delete router as invalid after update + m_RouterInfos.erase (ident); + if (wasFloodfill) + { + std::unique_lock l(m_FloodfillsMutex); + m_Floodfills.remove (r); + } + return nullptr; + } } LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 65b6a0f0..3cf79f11 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -79,13 +79,12 @@ namespace data { } - void RouterInfo::Update (const uint8_t * buf, size_t len) + bool RouterInfo::Update (const uint8_t * buf, size_t len) { if (len > MAX_RI_BUFFER_SIZE) { - LogPrint (eLogError, "RouterInfo: Buffer is too long ", len); - m_IsUnreachable = true; - return; + LogPrint (eLogWarning, "RouterInfo: Updated buffer is too long ", len, ". Not changed"); + return false; } // verify signature since we have identity already int l = len - m_RouterIdentity->GetSignatureLen (); @@ -109,10 +108,11 @@ namespace data // don't delete buffer until saved to the file } else - { - LogPrint (eLogError, "RouterInfo: Signature verification failed"); - m_IsUnreachable = true; - } + { + LogPrint (eLogWarning, "RouterInfo: Updated signature verification failed. Not changed"); + return false; + } + return true; } void RouterInfo::SetRouterIdentity (std::shared_ptr identity) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index f31b3cc2..dcdabf39 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -253,7 +253,7 @@ namespace data std::shared_ptr GetProfile () const; void DropProfile () { m_Profile = nullptr; }; - void Update (const uint8_t * buf, size_t len); + bool Update (const uint8_t * buf, size_t len); void DeleteBuffer () { m_Buffer = nullptr; }; bool IsNewer (const uint8_t * buf, size_t len) const; From c2faa5c6145dd5b5064564c52cdc4338618ef8f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Feb 2023 19:10:22 -0500 Subject: [PATCH 145/179] don't try to save RouterInfo if no buffer --- libi2pd/NetDb.cpp | 12 +++++++++--- libi2pd/RouterInfo.h | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 374d2d6d..153553a3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -279,6 +279,7 @@ namespace data if (!r->Update (buf, len)) { updated = false; + m_Requests.RequestComplete (ident, r); return r; } if (r->IsUnreachable ()) @@ -290,6 +291,7 @@ namespace data std::unique_lock l(m_FloodfillsMutex); m_Floodfills.remove (r); } + m_Requests.RequestComplete (ident, nullptr); return nullptr; } } @@ -645,10 +647,14 @@ namespace data std::string ident = it.second->GetIdentHashBase64(); if (it.second->IsUpdated ()) { - it.second->SaveToFile (m_Storage.Path(ident)); + if (it.second->GetBuffer ()) + { + // we have something to save + it.second->SaveToFile (m_Storage.Path(ident)); + it.second->SetUnreachable (false); + it.second->DeleteBuffer (); + } it.second->SetUpdated (false); - it.second->SetUnreachable (false); - it.second->DeleteBuffer (); updatedCount++; continue; } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index dcdabf39..1024cda8 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -242,7 +242,7 @@ namespace data void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; - const uint8_t * GetBuffer () const { return m_Buffer->data (); }; + const uint8_t * GetBuffer () const { return m_Buffer ? m_Buffer->data () : nullptr; }; const uint8_t * LoadBuffer (const std::string& fullPath); // load if necessary size_t GetBufferLen () const { return m_BufferLen; }; From 7b632bd03d2e28be4dbd31098697a55db7df38b0 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Feb 2023 13:25:02 -0500 Subject: [PATCH 146/179] set minimal floodfill version to 0.9.51 --- libi2pd/NetDb.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 90ebe824..599a2bff 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -48,8 +48,8 @@ namespace data const int NETDB_PUBLISH_INTERVAL = 60 * 40; const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; - const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36 - const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 38); // 0.9.38 + const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 + const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 /** function for visiting a leaseset stored in a floodfill */ From 4d0ad474919253ce7e055802fd89692b7d30deb2 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Feb 2023 13:45:06 -0500 Subject: [PATCH 147/179] GetBit for IdentHash --- libi2pd/Tag.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index d898395f..d0b0c056 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -80,6 +80,13 @@ namespace data { return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); } + uint8_t GetBit (int i) const + { + int pos = i >> 3; // /8 + if (pos >= sz) return 0; + return m_Buf[pos] & (1 << (7 - (i & 0x07))); + } + private: union // 8 bytes aligned From 4f3a416e37126ed35eb18baec3e8d3e7fa9e6e95 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Feb 2023 15:44:20 -0500 Subject: [PATCH 148/179] send DateTime together with RouterInfo --- libi2pd/NTCP2.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 68ed7353..6ccd0f80 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1142,12 +1142,17 @@ namespace transport { if (!IsEstablished ()) return; auto riLen = i2p::context.GetRouterInfo ().GetBufferLen (); - size_t payloadLen = riLen + 4; // 3 bytes block header + 1 byte RI flag + size_t payloadLen = riLen + 4 + 1 + 7; // 3 bytes block header + 1 byte RI flag + 7 bytes DateTime m_NextSendBuffer = new uint8_t[payloadLen + 16 + 2 + 64]; // up to 64 bytes padding - m_NextSendBuffer[2] = eNTCP2BlkRouterInfo; - htobe16buf (m_NextSendBuffer + 3, riLen + 1); // size - m_NextSendBuffer[5] = 0; // flag - memcpy (m_NextSendBuffer + 6, i2p::context.GetRouterInfo ().GetBuffer (), riLen); + // DateTime block + m_NextSendBuffer[2] = eNTCP2BlkDateTime; + htobe16buf (m_NextSendBuffer + 3, 4); + htobe32buf (m_NextSendBuffer + 5, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); + // RouterInfo block + m_NextSendBuffer[9] = eNTCP2BlkRouterInfo; + htobe16buf (m_NextSendBuffer + 10, riLen + 1); // size + m_NextSendBuffer[12] = 0; // flag + memcpy (m_NextSendBuffer + 13, i2p::context.GetRouterInfo ().GetBuffer (), riLen); // padding block auto paddingSize = CreatePaddingBlock (payloadLen, m_NextSendBuffer + 2 + payloadLen, 64); payloadLen += paddingSize; From 532a29b0c41f8730330a1a8aa3ff342a0c5a9fc9 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Feb 2023 19:18:02 -0500 Subject: [PATCH 149/179] don't reply with unreachable router --- libi2pd/NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 153553a3..694eb7c4 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1040,7 +1040,7 @@ namespace data lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) { auto router = FindRouter (ident); - if (router) + if (router && !router->IsUnreachable ()) { LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found"); PopulateRouterInfoBuffer (router); From 1ad38c0b95edea5c578bfe9d4b7b8bd9559ce41e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Feb 2023 19:37:11 -0500 Subject: [PATCH 150/179] fixed typo --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 6ccd0f80..813ea6d5 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1142,7 +1142,7 @@ namespace transport { if (!IsEstablished ()) return; auto riLen = i2p::context.GetRouterInfo ().GetBufferLen (); - size_t payloadLen = riLen + 4 + 1 + 7; // 3 bytes block header + 1 byte RI flag + 7 bytes DateTime + size_t payloadLen = riLen + 3 + 1 + 7; // 3 bytes block header + 1 byte RI flag + 7 bytes DateTime m_NextSendBuffer = new uint8_t[payloadLen + 16 + 2 + 64]; // up to 64 bytes padding // DateTime block m_NextSendBuffer[2] = eNTCP2BlkDateTime; From abb81c353de037fb418a04b4281cf2c82c9c0ccb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Feb 2023 09:33:10 -0500 Subject: [PATCH 151/179] fixed race condition --- libi2pd/Profiling.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 2dafe8ca..4f032326 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include "Base.h" @@ -22,6 +23,7 @@ namespace data { static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt"); static std::unordered_map > g_Profiles; + static std::mutex g_ProfilesMutex; static boost::posix_time::ptime GetTime () { @@ -213,11 +215,15 @@ namespace data std::shared_ptr GetRouterProfile (const IdentHash& identHash) { - auto it = g_Profiles.find (identHash); - if (it != g_Profiles.end ()) - return it->second; + { + std::unique_lock l(g_ProfilesMutex); + auto it = g_Profiles.find (identHash); + if (it != g_Profiles.end ()) + return it->second; + } auto profile = std::make_shared (); profile->Load (identHash); // if possible + std::unique_lock l(g_ProfilesMutex); g_Profiles.emplace (identHash, profile); return profile; } @@ -231,6 +237,7 @@ namespace data void PersistProfiles () { auto ts = GetTime (); + std::unique_lock l(g_ProfilesMutex); for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) { if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) @@ -247,6 +254,7 @@ namespace data void SaveProfiles () { auto ts = GetTime (); + std::unique_lock l(g_ProfilesMutex); for (auto it: g_Profiles) if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); @@ -255,14 +263,17 @@ namespace data void DeleteObsoleteProfiles () { - auto ts = GetTime (); - for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) - { - if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) - it = g_Profiles.erase (it); - else - it++; - } + { + auto ts = GetTime (); + std::unique_lock l(g_ProfilesMutex); + for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) + { + if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + it = g_Profiles.erase (it); + else + it++; + } + } struct stat st; std::time_t now = std::time(nullptr); From 03111ad0dff2d8873e9fc5094aa42db1d3c60f86 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Feb 2023 09:50:32 -0500 Subject: [PATCH 152/179] don't save profiles under mutex --- libi2pd/Profiling.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 4f032326..311d1c86 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -237,28 +238,37 @@ namespace data void PersistProfiles () { auto ts = GetTime (); - std::unique_lock l(g_ProfilesMutex); - for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) - { - if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) - { - if (it->second->IsUpdated ()) - it->second->Save (it->first); - it = g_Profiles.erase (it); - } - else - it++; - } + std::list > > tmp; + { + std::unique_lock l(g_ProfilesMutex); + for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) + { + if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) + { + if (it->second->IsUpdated ()) + tmp.push_back (std::make_pair (it->first, it->second)); + it = g_Profiles.erase (it); + } + else + it++; + } + } + for (auto& it: tmp) + if (it.second) it.second->Save (it.first); } void SaveProfiles () { + std::unordered_map > tmp; + { + std::unique_lock l(g_ProfilesMutex); + tmp = g_Profiles; + g_Profiles.clear (); + } auto ts = GetTime (); - std::unique_lock l(g_ProfilesMutex); - for (auto it: g_Profiles) + for (auto& it: tmp) if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); - g_Profiles.clear (); } void DeleteObsoleteProfiles () From 9e0c5d67c7c4e6b92e0fa9971f3d0afa07f549f7 Mon Sep 17 00:00:00 2001 From: weko Date: Tue, 14 Feb 2023 14:58:11 +0300 Subject: [PATCH 153/179] Don't use reversed port for choise random port. (by whothefuckami) --- libi2pd/RouterContext.cpp | 8 +++++++- libi2pd/util.cpp | 16 ++++++++++++++++ libi2pd/util.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index a91b9217..a0a0ab06 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -202,7 +202,13 @@ namespace i2p uint16_t RouterContext::SelectRandomPort () const { - uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range + uint16_t port; + do + { + port = rand () % (30777 - 9111) + 9111; // I2P network ports range + } + while(i2p::util::net::IsPortInReservedRange(port)); + if (port == 9150) port = 9151; // Tor browser return port; } diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index f0e9a7c6..48a8fab3 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "util.h" @@ -487,6 +488,21 @@ namespace net return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ()); } + bool IsPortInReservedRange (const uint16_t port) noexcept + { + static const std::unordered_set reservedPorts{ + 9119,9306,9312,9389,9418,9535,9536,9695, + 9800,9899,10000,10050,10051,10110,10212, + 10933,11001,11112,11235,11371,12222,12223, + 13075,13400,13720,13721,13724,13782,13783, + 13785,13786,15345,17224,17225,17500,18104, + 19788,19812,19813,19814,19999,20000,24465, + 24554,26000,27000,27001,27002,27003,27004, + 27005,27006,27007,27008,27009,28000}; + + return (reservedPorts.find(port) != reservedPorts.end()); + } + boost::asio::ip::address_v6 GetYggdrasilAddress () { #if defined(_WIN32) diff --git a/libi2pd/util.h b/libi2pd/util.h index 248c2bad..7ba24694 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -224,6 +224,7 @@ namespace util bool IsLocalAddress (const boost::asio::ip::address& addr); bool IsInReservedRange (const boost::asio::ip::address& host); bool IsYggdrasilAddress (const boost::asio::ip::address& addr); + bool IsPortInReservedRange (const uint16_t port) noexcept; } } } From 76d39cc7c9fe5d26ebd37d2746c622ec7c1b6b98 Mon Sep 17 00:00:00 2001 From: weko Date: Tue, 14 Feb 2023 20:03:04 +0300 Subject: [PATCH 154/179] changed to tabs, move tor port to function --- libi2pd/RouterContext.cpp | 9 ++++----- libi2pd/util.cpp | 27 ++++++++++++++------------- libi2pd/util.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index a0a0ab06..72b723ea 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -204,12 +204,11 @@ namespace i2p { uint16_t port; do - { - port = rand () % (30777 - 9111) + 9111; // I2P network ports range - } - while(i2p::util::net::IsPortInReservedRange(port)); + { + port = rand () % (30777 - 9111) + 9111; // I2P network ports range + } + while(i2p::util::net::IsPortInReservedRange(port)); - if (port == 9150) port = 9151; // Tor browser return port; } diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 48a8fab3..369f999e 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -488,20 +488,21 @@ namespace net return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ()); } - bool IsPortInReservedRange (const uint16_t port) noexcept - { - static const std::unordered_set reservedPorts{ - 9119,9306,9312,9389,9418,9535,9536,9695, - 9800,9899,10000,10050,10051,10110,10212, - 10933,11001,11112,11235,11371,12222,12223, - 13075,13400,13720,13721,13724,13782,13783, - 13785,13786,15345,17224,17225,17500,18104, - 19788,19812,19813,19814,19999,20000,24465, - 24554,26000,27000,27001,27002,27003,27004, - 27005,27006,27007,27008,27009,28000}; + bool IsPortInReservedRange (const uint16_t port) noexcept + { + // https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers (Feb. 3, 2023) + Tor browser (9150) + static const std::unordered_set reservedPorts{ + 9119,9150,9306,9312,9389,9418,9535,9536,9695, + 9800,9899,10000,10050,10051,10110,10212, + 10933,11001,11112,11235,11371,12222,12223, + 13075,13400,13720,13721,13724,13782,13783, + 13785,13786,15345,17224,17225,17500,18104, + 19788,19812,19813,19814,19999,20000,24465, + 24554,26000,27000,27001,27002,27003,27004, + 27005,27006,27007,27008,27009,28000}; - return (reservedPorts.find(port) != reservedPorts.end()); - } + return (reservedPorts.find(port) != reservedPorts.end()); + } boost::asio::ip::address_v6 GetYggdrasilAddress () { diff --git a/libi2pd/util.h b/libi2pd/util.h index 7ba24694..e2037212 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -224,7 +224,7 @@ namespace util bool IsLocalAddress (const boost::asio::ip::address& addr); bool IsInReservedRange (const boost::asio::ip::address& host); bool IsYggdrasilAddress (const boost::asio::ip::address& addr); - bool IsPortInReservedRange (const uint16_t port) noexcept; + bool IsPortInReservedRange (const uint16_t port) noexcept; } } } From 77142e59eee1058e09d65618bb2132a342721cb8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 14 Feb 2023 18:51:14 +0000 Subject: [PATCH 155/179] [http] fix query detection, addresshelper processing, update tests Signed-off-by: R4SAS --- libi2pd/HTTP.h | 2 +- libi2pd_client/HTTPProxy.cpp | 28 ++++++++++++++++++++++++++-- tests/Makefile | 34 +++++++++++++++++++++++----------- tests/test-http-url.cpp | 9 +++++++++ 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 9b8788ec..f9d5d009 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -37,7 +37,7 @@ namespace http std::string query; std::string frag; - URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), query(""), frag("") {}; + URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag("") {}; /** * @brief Tries to parse url from string diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index b8ecd199..3e5ab595 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -238,9 +238,33 @@ namespace proxy { std::string value = params["i2paddresshelper"]; len += value.length(); b64 = i2p::http::UrlDecode(value); + // if we need update exists, request formed with update param - if (params["update"] == "true") { len += std::strlen("&update=true"); confirm = true; } - if (pos != 0 && url.query[pos-1] == '&') { pos--; len++; } // if helper is not only one query option + if (params["update"] == "true") + { + len += std::strlen("&update=true"); + confirm = true; + } + + // if helper is not only one query option and it placed after user's query + if (pos != 0 && url.query[pos-1] == '&') + { + pos--; + len++; + } + // if helper is not only one query option and it placed before user's query + else if (pos == 0 && url.query.length () > len && url.query[len] == '&') + { + // we don't touch the '?' but remove the trailing '&' + len++; + } + else + { + // there is no more query options, resetting hasquery flag + url.hasquery = false; + } + + // reset hasquery flag and remove addresshelper from URL url.query.replace(pos, len, ""); return true; } diff --git a/tests/Makefile b/tests/Makefile index db71a06e..9c5711e2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,5 @@ +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 INCFLAGS += -I../libi2pd @@ -7,41 +9,51 @@ TESTS = \ test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \ test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding test-elligator +ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) + CXXFLAGS += -DWIN32_LEAN_AND_MEAN + LDFLAGS += -mwindows -static + BOOST_SUFFIX = -mt + NEEDED_LDLIBS = -lwsock32 -lws2_32 -lgdi32 -liphlpapi -lole32 +endif + LDLIBS = \ - -lcrypto \ + -lboost_filesystem$(BOOST_SUFFIX) \ + -lboost_program_options$(BOOST_SUFFIX) \ -lssl \ - -lboost_filesystem \ - -lboost_program_options \ + -lcrypto \ + -lz \ + $(NEEDED_LDLIBS) \ -lpthread + all: $(TESTS) run $(LIBI2PD): @echo "Building libi2pd.a ..." && cd .. && $(MAKE) libi2pd.a test-http-%: test-http-%.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-base-%: test-base-%.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-gost: test-gost.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-gost-sig: test-gost-sig.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-x25519: test-x25519.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-aeadchacha20poly1305: test-aeadchacha20poly1305.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-blinding: test-blinding.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test-elligator: test-elligator.cpp $(LIBI2PD) - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ $(LDLIBS) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) run: $(TESTS) @for TEST in $(TESTS); do echo Running $$TEST; ./$$TEST ; done diff --git a/tests/test-http-url.cpp b/tests/test-http-url.cpp index 1759a3a8..a5021c43 100644 --- a/tests/test-http-url.cpp +++ b/tests/test-http-url.cpp @@ -15,6 +15,7 @@ int main() { assert(url->host == "127.0.0.1"); assert(url->port == 7070); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == "12345"); assert(url->to_string() == "https://127.0.0.1:7070/asdasd?12345"); delete url; @@ -27,6 +28,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 8080); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == "123456"); delete url; @@ -38,6 +40,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 0); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == "name=value"); delete url; @@ -49,6 +52,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 0); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == "name=value1&name=value2"); delete url; @@ -60,6 +64,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 0); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == "name1=value1&name2&name3=value2"); assert(url->parse_query(params)); assert(params.size() == 3); @@ -79,6 +84,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 800); assert(url->path == "/asdasd"); + assert(url->hasquery == true); assert(url->query == ""); delete url; @@ -90,6 +96,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 17); assert(url->path == ""); + assert(url->hasquery == false); assert(url->query == ""); delete url; @@ -101,6 +108,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 0); assert(url->path == ""); + assert(url->hasquery == false); assert(url->query == ""); delete url; @@ -112,6 +120,7 @@ int main() { assert(url->host == "site.com"); assert(url->port == 84); assert(url->path == "/asdasd/@17"); + assert(url->hasquery == false); assert(url->query == ""); assert(url->frag == "frag"); delete url; From 02a36a9fa81e5734938749136f783b7075f90868 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Feb 2023 15:44:35 -0500 Subject: [PATCH 156/179] don't populate buffer of unreachable router --- libi2pd/NetDb.cpp | 10 +++++----- libi2pd/NetDb.hpp | 2 +- libi2pd/RouterInfo.cpp | 2 ++ libi2pd/SSU2Session.cpp | 11 +++++------ 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 694eb7c4..34ad5efc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1043,8 +1043,7 @@ namespace data if (router && !router->IsUnreachable ()) { LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found"); - PopulateRouterInfoBuffer (router); - if (router->GetBuffer ()) + if (PopulateRouterInfoBuffer (router)) replyMsg = CreateDatabaseStoreMsg (router); } } @@ -1481,10 +1480,11 @@ namespace data m_LeasesPool.CleanUpMt (); } - void NetDb::PopulateRouterInfoBuffer (std::shared_ptr r) + bool NetDb::PopulateRouterInfoBuffer (std::shared_ptr r) { - if (!r || r->GetBuffer ()) return; - r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ())); + if (!r) return false; + if (r->GetBuffer ()) return true; + return r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ())); } } } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 599a2bff..f0315582 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -124,7 +124,7 @@ namespace data void ClearRouterInfos () { m_RouterInfos.clear (); }; std::shared_ptr NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; - void PopulateRouterInfoBuffer (std::shared_ptr r); + bool PopulateRouterInfoBuffer (std::shared_ptr r); std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; boost::shared_ptr NewRouterInfoAddresses () { diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3cf79f11..afa8cbe0 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -589,6 +589,8 @@ namespace data { if (LoadFile (fullPath)) LogPrint (eLogDebug, "RouterInfo: Buffer for ", GetIdentHashAbbreviation (GetIdentHash ()), " loaded from file"); + else + return nullptr; } return m_Buffer->data (); } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index e45a33a2..f2b002cd 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1872,10 +1872,9 @@ namespace transport // send relay intro to Charlie auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI - if (r) - i2p::data::netdb.PopulateRouterInfoBuffer (r); - else - LogPrint (eLogWarning, "SSU2: RelayRequest Alice's router info not found"); + 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) @@ -2069,7 +2068,7 @@ namespace transport auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); // Alice's RouterInfo auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); - if (r) i2p::data::netdb.PopulateRouterInfoBuffer (r); + if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0; if (!packet->payloadSize && r) session->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); @@ -2173,7 +2172,7 @@ namespace transport uint8_t payload[SSU2_MAX_PACKET_SIZE]; // Charlie's RouterInfo auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); - if (r) i2p::data::netdb.PopulateRouterInfoBuffer (r); + 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)); From fa286a6fb3dd3c0d1621abf9282b835da9c00a48 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Feb 2023 19:49:29 -0500 Subject: [PATCH 157/179] faster GetBit --- libi2pd/Tag.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index d0b0c056..72f181a2 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -83,8 +83,8 @@ namespace data { uint8_t GetBit (int i) const { int pos = i >> 3; // /8 - if (pos >= sz) return 0; - return m_Buf[pos] & (1 << (7 - (i & 0x07))); + if (pos >= (int)sz) return 0; + return m_Buf[pos] & (0x80 >> (i & 0x07)); } private: From c6c71916823246cccfb379bece2f0912402824e7 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 15 Feb 2023 17:55:16 +0000 Subject: [PATCH 158/179] [debian] exclude parallel flag, remove conffiles Signed-off-by: R4SAS --- debian/conffiles | 2 -- debian/rules | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 debian/conffiles diff --git a/debian/conffiles b/debian/conffiles deleted file mode 100644 index 6894732c..00000000 --- a/debian/conffiles +++ /dev/null @@ -1,2 +0,0 @@ -/etc/i2pd/i2pd.conf -/etc/i2pd/tunnels.conf diff --git a/debian/rules b/debian/rules index 11791d9b..fc769066 100755 --- a/debian/rules +++ b/debian/rules @@ -8,6 +8,6 @@ export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic export DEB_LDFLAGS_MAINT_APPEND = %: - dh $@ --parallel + dh $@ override_dh_auto_install: From 359781c69881688d4a4c58e3ab60f620ebefeeba Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 15 Feb 2023 17:56:44 +0000 Subject: [PATCH 159/179] [webconsole] streams table little fix Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 2f846257..f78057b3 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -554,7 +554,7 @@ namespace http { << tr("Streams") << "\r\n\r\n" << "StreamID" - << "" // Stream closing button column + << " " // Stream closing button column << "Destination" << "Sent" << "Received" From 385e592045898191eb26fd786d23676a92851d4b Mon Sep 17 00:00:00 2001 From: barracuda156 Date: Wed, 15 Feb 2023 11:55:13 +0800 Subject: [PATCH 160/179] TargetArch.cmake: fix info re OSX arch support, update copyright year --- build/cmake_modules/TargetArch.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/cmake_modules/TargetArch.cmake b/build/cmake_modules/TargetArch.cmake index ac7275b1..d59925c8 100644 --- a/build/cmake_modules/TargetArch.cmake +++ b/build/cmake_modules/TargetArch.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2022, The PurpleI2P Project +# Copyright (c) 2017-2023, The PurpleI2P Project # This file is part of Purple i2pd project and licensed under BSD3 # See full license text in LICENSE file at top of project tree @@ -83,13 +83,13 @@ function(target_architecture output_var) # First let's normalize the order of the values # Note that it's not possible to compile PowerPC applications if you are using - # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we - # disable it by default + # the OS X SDK version 10.7 or later - you'll need 10.4/10.5/10.6 for that, so we + # disable it by default. Also, ppc64 is not supported in 10.6. # See this page for more information: # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. - # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise; 10.6 also supports ppc. foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) if("${osx_arch}" STREQUAL "ppc" AND ppc_support) @@ -133,11 +133,11 @@ function(target_architecture output_var) enable_language(C) # Detect the architecture in a rather creative way... - # This compiles a small C program which is a series of ifdefs that selects a - # particular #error preprocessor directive whose message string contains the - # target architecture. The program will always fail to compile (both because - # file is not a valid C program, and obviously because of the presence of the - # #error preprocessor directives... but by exploiting the preprocessor in this + # This compiles a small C program which is a series of ifdefs that selects + # a particular #error preprocessor directive whose message string contains + # the target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of + # the #error preprocessor directives... but by exploiting the preprocessor in this # way, we can detect the correct target architecture even when cross-compiling, # since the program itself never needs to be run (only the compiler/preprocessor) try_run( From 00c75a7afa2124cb634f7d93e2c27c0ef2ec7f94 Mon Sep 17 00:00:00 2001 From: barracuda156 Date: Wed, 15 Feb 2023 12:04:30 +0800 Subject: [PATCH 161/179] CMakeLists.txt: update comment re Boost and atomics on PPC --- build/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index d9c50e9c..f6f52001 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -178,6 +178,7 @@ 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. if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc") add_definitions(-DBOOST_SP_USE_STD_ATOMIC) endif() From 182a721674748adf23cb258d278cced6f0fb6d35 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Feb 2023 14:47:02 -0500 Subject: [PATCH 162/179] 2.46.0 --- ChangeLog | 30 ++++++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 16cb6d6b..ff3f9697 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,36 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.46.0] - 2023-02-15 +### Added +- Limit number of acked SSU2 packets to 511 +- Localization to Swedish +- Periodically send Datetime block in NTCP2 and SSU2 +- Don't select random port from reserved +- In memory table for peer profiles +- Store if router was unreachable in it's peer profile +- Show IPv6 addresses in square brackets in webconsole +### Changed +- Algorithm for tunnel creation success rate calculation +- Drop incoming NTCP2 and SSU2 connection if published IP doesn't match actual endpoint' +- Exclude actually unreachable router from netdb for 2 hours +- Select first hop from high bandwidth peers for client tunnels +- Drop too long or too short LeaseSet +- Delete router from netdb if became inavlid after update +- Terminate existing session if clock skew detected +- Close previous UDP socket if open before reopening +- Minimal version for floodfill is 0.9.51 +- Sort transports by endpoints in webconsole +### Fixed +- Deadlock druing processing I2NP block with Garlic in ECIES encrypted message to router +- Race condition with encrypted LeaseSets +- HTTP query detection +- Connection attempts to IPs from invalid ranges +- Publish "0.0.0.0" in RouterInfo +- Crash upon receiving PeerTest 7 +- Tunnels for closed SAM session socket +- Missing NTCP2 address in RouterInfo if enabled back + ## [2.45.1] - 2023-01-11 ### Added - Full Cone NAT status error diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 79d591ac..e902d1fd 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.45.1 +Version: 2.46.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Feb 15 2023 orignal - 2.46.0 +- update to 2.46.0 + * Wed Jan 11 2023 orignal - 2.45.1 - update to 2.45.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 07ecfbcc..5ddd8727 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.45.1 +Version: 2.46.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Feb 15 2023 orignal - 2.46.0 +- update to 2.46.0 + * Wed Jan 11 2023 orignal - 2.45.1 - update to 2.45.1 diff --git a/debian/changelog b/debian/changelog index d4464668..5408d4d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.46.0-1) unstable; urgency=medium + + * updated to version 2.46.0/0.9.57 + + -- orignal Wed, 15 Feb 2023 19:00:00 +0000 + i2pd (2.45.1-1) unstable; urgency=medium * updated to version 2.45.1/0.9.57 diff --git a/libi2pd/version.h b/libi2pd/version.h index 65ca1fc4..e1206d21 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -16,8 +16,8 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 45 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MINOR 46 +#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION GITVER From e53fe2d988e9158d228dbb97a08486ef134c5484 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 15 Feb 2023 20:39:18 +0000 Subject: [PATCH 163/179] 2.46.0 Signed-off-by: R4SAS --- ChangeLog | 19 ++++++++++--------- debian/changelog | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff3f9697..4606a69b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,26 +3,27 @@ ## [2.46.0] - 2023-02-15 ### Added -- Limit number of acked SSU2 packets to 511 +- Limit number of acked SSU2 packets to 511 - Localization to Swedish - Periodically send Datetime block in NTCP2 and SSU2 - Don't select random port from reserved - In memory table for peer profiles - Store if router was unreachable in it's peer profile - Show IPv6 addresses in square brackets in webconsole +- Check referer when processing Addresshelper ### Changed - Algorithm for tunnel creation success rate calculation -- Drop incoming NTCP2 and SSU2 connection if published IP doesn't match actual endpoint' +- Drop incoming NTCP2 and SSU2 connection if published IP doesn't match actual endpoint - Exclude actually unreachable router from netdb for 2 hours -- Select first hop from high bandwidth peers for client tunnels +- Select first hop from high bandwidth peers for client tunnels - Drop too long or too short LeaseSet -- Delete router from netdb if became inavlid after update +- Delete router from netdb if became invalid after update - Terminate existing session if clock skew detected -- Close previous UDP socket if open before reopening +- Close previous UDP socket if open before reopening - Minimal version for floodfill is 0.9.51 -- Sort transports by endpoints in webconsole -### Fixed -- Deadlock druing processing I2NP block with Garlic in ECIES encrypted message to router +- Sort transports by endpoints in webconsole +### Fixed +- Deadlock during processing I2NP block with Garlic in ECIES encrypted message to router - Race condition with encrypted LeaseSets - HTTP query detection - Connection attempts to IPs from invalid ranges @@ -39,7 +40,7 @@ - Set rejection code 30 if tunnel with id already exists - Network status is always OK if peer test msg 5 received ### Fixed -- UPnP crash if SSU2 or NTCP2 is disabled +- UPnP crash if SSU2 or NTCP2 is disabled - Crash on termination for some platforms ## [2.45.0] - 2023-01-03 diff --git a/debian/changelog b/debian/changelog index 5408d4d0..91d8f1dc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -i2pd (2.46.0-1) unstable; urgency=medium +i2pd (2.46.0-1) unstable; urgency=high * updated to version 2.46.0/0.9.57 From a1fb97cfad9ca63ba4cf5a3cf135da24bf1d5ac8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 16 Feb 2023 00:42:31 +0300 Subject: [PATCH 164/179] [i18n] update and add Polish, Portuguese, Turkish Signed-off-by: R4SAS --- contrib/i18n/README.md | 58 +++++------ i18n/Armenian.cpp | 53 ++++------ i18n/Chinese.cpp | 78 ++++++++------- i18n/Czech.cpp | 44 +++------ i18n/French.cpp | 64 ++++++------ i18n/German.cpp | 44 +++------ i18n/I18N_langs.h | 36 ++++--- i18n/Italian.cpp | 49 ++++----- i18n/Polish.cpp | 59 +++++++++++ i18n/Portuguese.cpp | 219 +++++++++++++++++++++++++++++++++++++++++ i18n/Russian.cpp | 60 +++++------ i18n/Spanish.cpp | 44 +++------ i18n/Swedish.cpp | 55 +++++------ i18n/Turkish.cpp | 114 +++++++++++++++++++++ i18n/Turkmen.cpp | 45 ++++----- i18n/Ukrainian.cpp | 60 +++++------ i18n/Uzbek.cpp | 60 +++++------ 17 files changed, 744 insertions(+), 398 deletions(-) create mode 100644 i18n/Polish.cpp create mode 100644 i18n/Portuguese.cpp create mode 100644 i18n/Turkish.cpp diff --git a/contrib/i18n/README.md b/contrib/i18n/README.md index 57021f60..56d76c5a 100644 --- a/contrib/i18n/README.md +++ b/contrib/i18n/README.md @@ -1,29 +1,29 @@ -`xgettext` command for extracting translation ---- - -``` -xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp -``` - -Regex for transforming gettext translations to our format: ---- - -``` -in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)? -out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n -``` - -``` -in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n -out: {"$1", "$2"},\n -``` - -``` -in: ^#[:.](.*)$\n -out: -``` - -``` -in: \n\n -out: \n -``` +`xgettext` command for extracting translation +--- + +``` +xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp +``` + +Regex for transforming gettext translations to our format: +--- + +``` +in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)? +out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n +``` + +``` +in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n +out: {"$1", "$2"},\n +``` + +``` +in: ^#[:.,](.*)$\n +out: +``` + +``` +in: \n\n +out: \n +``` diff --git a/i18n/Armenian.cpp b/i18n/Armenian.cpp index a18d35fc..b99e5032 100644 --- a/i18n/Armenian.cpp +++ b/i18n/Armenian.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,6 +40,7 @@ namespace armenian // language namespace {"established", "կարգավոյված է"}, {"unknown", "անհայտ"}, {"exploratory", "հետազոտոկան"}, + {"Purple I2P Webconsole", "Վեբ-կոնսոլ Purple I2P"}, {"i2pd webconsole", "Վեբ-կոնսոլ i2pd"}, {"Main page", "Գլխավոր էջ"}, {"Router commands", "Երթուղիչի հրահանգներ"}, @@ -57,10 +58,10 @@ namespace armenian // language namespace {"Unknown", "Անհայտ"}, {"Proxy", "Պրոկսի"}, {"Mesh", "MESH-ցանց"}, - {"Error", "Սխալ"}, {"Clock skew", "Ոչ ճշգրիտ ժամանակ"}, {"Offline", "Օֆլայն"}, {"Symmetric NAT", "Սիմետրիկ NAT"}, + {"Full cone NAT", "Full cone NAT"}, {"Uptime", "Առկայություն"}, {"Network status", "Ցանցի կարգավիճակ"}, {"Network status v6", "Ցանցի կարգավիճակ v6"}, @@ -89,7 +90,7 @@ namespace armenian // language namespace {"Address registration line", "Հասցեի գրանցման տող"}, {"Domain", "Տիրույթ"}, {"Generate", "Գեներացնել"}, - {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", " Նշում. արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել i2pd-tools գործիքակազմը"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", " Նշում. արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել i2pd-tools գործիքակազմը:"}, {"Address", "Հասցե"}, {"Type", "Տեսակը"}, {"EncType", "Գաղտնագրի տեսակը"}, @@ -112,11 +113,10 @@ namespace armenian // language namespace {"Invalid", "Անվավեր"}, {"Store type", "Պահեստավորման տեսակը"}, {"Expires", "Սպառվում է"}, - {"Non Expired Leases", "Չսպառված Lease-եր"}, + {"Non Expired Leases", "Չսպառված Lease-եր"}, {"Gateway", "Դարպաս"}, {"TunnelID", "Թունելի ID"}, {"EndDate", "Ավարտ"}, - {"not floodfill", "ոչ floodfill-ներ"}, {"Queue size", "Հերթի չափսը"}, {"Run peer test", "Գործարկել փորձարկումը"}, {"Decline transit tunnels", "Մերժել տարանցիկ թունելներ"}, @@ -146,10 +146,7 @@ namespace armenian // language namespace {"Destination not found", "Հասցեի վայրը չի գտնվել"}, {"StreamID can't be null", "StreamID-ն չի կարող լինել դատարկ"}, {"Return to destination page", "Վերադառնալ նախորդ էջի հասցե"}, - {"You will be redirected in 5 seconds", "Դուք կտեղափոխվեք 5 վայրկյանից"}, - {"Transit tunnels count must not exceed 65535", "Տարանցիկ թունելների քանակը չպետք է գերազանցի 65535-ը"}, {"Back to commands list", "Վերադառնալ հրահանգների ցուցակ"}, - {"Register at reg.i2p", "Գրանցել reg.i2p-ում"}, {"Description", "Նկարագրություն"}, {"A bit information about service on domain", "Մի փոքր տեղեկատվություն տիրոիյթում գտնվող ծառայության մասին"}, {"Submit", "Ուղարկվել"}, @@ -165,34 +162,26 @@ namespace armenian // language namespace {"You may try to find this host on jump services below", "Ստորև Դուք կարող եք գտնել այս հոսթը jump ծառայությունների միջոցով"}, {"Invalid request", "Սխալ հարցում"}, {"Proxy unable to parse your request", "Պրոկսին չի կարող հասկանալ Ձեր հարցումը"}, - {"addresshelper is not supported", "addresshelper-ը համատեղելի չէ"}, - {"Host", "Հոսթ"}, - {"added to router's addressbook from helper", "Ավելացված է երթուղիչի հասցեագրքում helper-ի միջոցով"}, - {"Click here to proceed:", "Շարունակելու համար սեղմեք այստեղ"}, - {"Continue", "Շարունակել"}, - {"Addresshelper found", "addresshelper-ը գնտված է"}, - {"already in router's addressbook", "արդեն առկա է երթուղիչի հասցեագրքում"}, - {"Click here to update record:", "Սեղմեկ այստեղ որպեսզի թարվացնեք գրառումը"}, - {"invalid request uri", "Սխալ ձևավորված URI հարցում"}, + {"Invalid request URI", "Սխալ ձևավորված URI հարցում"}, {"Can't detect destination host from request", "Չհաջողվեց հայնտաբերեկ վայրի հասցեն նշված հարցմամբ"}, {"Outproxy failure", "Սխալ արտաքին պրոքսի"}, - {"bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"}, - {"not inside I2P network, but outproxy is not enabled", "Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"}, - {"unknown outproxy url", "արտաքին պրոքսիի անհայտ URL"}, - {"cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"}, - {"hostname too long", "Հոսթի անունը չափազանց երկար է"}, - {"cannot connect to upstream socks proxy", "չհաջողվեց միանալ վերադաս socks պրոկսիին"}, - {"Cannot negotiate with socks proxy", "Չհաջողվեց պայմանավորվել վերադաս socks պրոկսիի հետ"}, + {"Bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Հոսթ %s Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"}, + {"Unknown outproxy URL", "Արտաքին պրոքսիի անհայտ URL"}, + {"Cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"}, + {"Hostname is too long", "Հոսթի անունը չափազանց երկար է"}, + {"Cannot connect to upstream SOCKS proxy", "Չհաջողվեց միանալ վերադաս SOCKS պրոկսի սերվերին"}, + {"Cannot negotiate with SOCKS proxy", "Չհաջողվեց պայմանավորվել վերադաս SOCKS պրոկսիի հետ"}, {"CONNECT error", "Սխալ CONNECT հարցում"}, - {"Failed to Connect", "Միանալ չhաջողվեց"}, - {"socks proxy error", "Սխալ SOCKS պրոկսի"}, - {"failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"}, - {"No Reply From socks proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"}, - {"cannot connect", "Հնարավոր չե միանալ"}, - {"http out proxy not implemented", "Արտաքին http պրոկսին դեռ իրականացված չէ"}, - {"cannot connect to upstream http proxy", "Չհաջողվեց միանալ վերադաս http պրոկսի սերվերին"}, + {"Failed to connect", "Միանալ չhաջողվեց"}, + {"SOCKS proxy error", "Սխալ SOCKS պրոկսի"}, + {"Failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"}, + {"No reply from SOCKS proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"}, + {"Cannot connect", "Հնարավոր չե միանալ"}, + {"HTTP out proxy not implemented", "Արտաքին HTTP պրոկսին դեռ իրականացված չէ"}, + {"Cannot connect to upstream HTTP proxy", "Չհաջողվեց միանալ վերադաս HTTP պրոկսի սերվերին"}, {"Host is down", "Հոսթն անհասանելի է"}, - {"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ:"}, {"", ""}, }; diff --git a/i18n/Chinese.cpp b/i18n/Chinese.cpp index 8a554a11..cd38fa0f 100644 --- a/i18n/Chinese.cpp +++ b/i18n/Chinese.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -13,7 +13,6 @@ #include "I18N.h" // Simplified Chinese localization file -// This is an example translation file without strings in it. namespace i2p { @@ -46,7 +45,7 @@ namespace chinese // language namespace {"Main page", "主页"}, {"Router commands", "路由命令"}, {"Local Destinations", "本地目标"}, - {"LeaseSets", "租契集"}, + {"LeaseSets", "租约集"}, {"Tunnels", "隧道"}, {"Transit Tunnels", "中转隧道"}, {"Transports", "传输"}, @@ -58,11 +57,12 @@ namespace chinese // language namespace {"Firewalled", "受到防火墙限制"}, {"Unknown", "未知"}, {"Proxy", "代理"}, - {"Mesh", "Mesh组网"}, - {"Error", "错误"}, + {"Mesh", "自组网"}, {"Clock skew", "时钟偏移"}, {"Offline", "离线"}, {"Symmetric NAT", "对称 NAT"}, + {"Full cone NAT", "全锥型NAT"}, + {"No Descriptors", "无描述符"}, {"Uptime", "运行时间"}, {"Network status", "IPv4 网络状态"}, {"Network status v6", "IPv6 网络状态"}, @@ -91,12 +91,12 @@ namespace chinese // language namespace {"Address registration line", "地址域名注册"}, {"Domain", "域名"}, {"Generate", "生成"}, - {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "注意: 结果字符串只能用于注册次级域名(例如:example.i2p)。若需注册子域名,请使用 i2pd-tools。"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "注意: 结果字符串只能用于注册二级域名(例如:example.i2p)。若需注册三级域名,请使用 i2pd-tools。"}, {"Address", "地址"}, {"Type", "类型"}, {"EncType", "加密类型"}, {"Inbound tunnels", "入站隧道"}, - {"%dms", "%d毫秒"}, + {"%dms", "%dms"}, {"Outbound tunnels", "出站隧道"}, {"Tags", "标签"}, {"Incoming", "传入"}, @@ -118,9 +118,10 @@ namespace chinese // language namespace {"Gateway", "网关"}, {"TunnelID", "隧道 ID"}, {"EndDate", "结束日期"}, - {"not floodfill", "非洪泛"}, + {"floodfill mode is disabled", "洪泛已禁用"}, {"Queue size", "队列大小"}, {"Run peer test", "运行节点测试"}, + {"Reload tunnels configuration", "重新载入隧道配置"}, {"Decline transit tunnels", "拒绝中转隧道"}, {"Accept transit tunnels", "允许中转隧道"}, {"Cancel graceful shutdown", "取消平滑关闭"}, @@ -128,7 +129,7 @@ namespace chinese // language namespace {"Force shutdown", "强制停止"}, {"Reload external CSS styles", "重载外部 CSS 样式"}, {"Note: any action done here are not persistent and not changes your config files.", "注意: 此处完成的任何操作都不是永久的,不会更改您的配置文件。"}, - {"Logging level", "日志记录级别"}, + {"Logging level", "日志级别"}, {"Transit tunnels limit", "中转隧道限制"}, {"Change", "修改"}, {"Change language", "更改语言"}, @@ -148,8 +149,8 @@ namespace chinese // language namespace {"Destination not found", "找不到目标"}, {"StreamID can't be null", "StreamID 不能为空"}, {"Return to destination page", "返回目标页面"}, - {"You will be redirected in 5 seconds", "您将在5秒内被重定向"}, - {"Transit tunnels count must not exceed 65535", "中转隧道数量不能超过 65535"}, + {"You will be redirected in %d seconds", "您将在%d秒内被重定向"}, + {"Transit tunnels count must not exceed %d", "中转隧道数量限制为 %d"}, {"Back to commands list", "返回命令列表"}, {"Register at reg.i2p", "在 reg.i2p 注册域名"}, {"Description", "描述"}, @@ -164,35 +165,36 @@ namespace chinese // language namespace {"Proxy info", "代理信息"}, {"Proxy error: Host not found", "代理错误:未找到主机"}, {"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"}, - {"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到该主机"}, + {"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到此主机"}, {"Invalid request", "无效请求"}, {"Proxy unable to parse your request", "代理无法解析您的请求"}, - {"addresshelper is not supported", "不支持地址助手"}, - {"Host", "主机"}, - {"added to router's addressbook from helper", "将此地址从地址助手添加到路由地址簿"}, - {"Click here to proceed:", "点击此处继续:"}, - {"Continue", "继续"}, - {"Addresshelper found", "已找到地址助手"}, - {"already in router's addressbook", "已在路由地址簿中"}, - {"Click here to update record:", "点击此处更新地址簿记录"}, - {"invalid request uri", "无效的 URL 请求"}, + {"Addresshelper is not supported", "不支持地址助手"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "主机 %s 已在路由地址簿中请注意:此地址的来源可能是有害的!点击此处更新记录:继续"}, + {"Addresshelper forced update rejected", "地址助手强制更新被拒绝"}, + {"To add host %s in router's addressbook, click here: Continue.", "若要在路由器地址簿中添加主机 %s 请点击这里: 继续"}, + {"Addresshelper request", "请求地址助手"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "主机 %s 已通过地址助手添加到路由地址簿中。点击此处继续:继续"}, + {"Addresshelper adding", "正在添加地址助手"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "主机 %s 已在路由地址簿中。点击此处更新记录:继续"}, + {"Addresshelper update", "更新地址助手"}, + {"Invalid request URI", "无效的 URI 请求"}, {"Can't detect destination host from request", "无法从请求中检测到目标主机"}, {"Outproxy failure", "出口代理故障"}, - {"bad outproxy settings", "错误的出口代理设置"}, - {"not inside I2P network, but outproxy is not enabled", "该地址不在 I2P 网络内,但未启用出口代理"}, - {"unknown outproxy url", "未知的出口代理地址"}, - {"cannot resolve upstream proxy", "无法解析上游代理"}, - {"hostname too long", "主机名过长"}, - {"cannot connect to upstream socks proxy", "无法连接到上游 socks 代理"}, - {"Cannot negotiate with socks proxy", "无法与 socks 代理协商"}, + {"Bad outproxy settings", "错误的出口代理设置"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "主机 %s 不在 I2P 网络内,但出口代理未启用"}, + {"Unknown outproxy URL", "未知的出口代理地址"}, + {"Cannot resolve upstream proxy", "无法解析上游代理"}, + {"Hostname is too long", "主机名过长"}, + {"Cannot connect to upstream SOCKS proxy", "无法连接到上游 SOCKS 代理"}, + {"Cannot negotiate with SOCKS proxy", "无法与 SOCKS 代理协商"}, {"CONNECT error", "连接错误"}, - {"Failed to Connect", "连接失败"}, - {"socks proxy error", "socks 代理错误"}, - {"failed to send request to upstream", "向上游发送请求失败"}, - {"No Reply From socks proxy", "没有来自 socks 代理的回复"}, - {"cannot connect", "无法连接"}, - {"http out proxy not implemented", "http 出口代理未实现"}, - {"cannot connect to upstream http proxy", "无法连接到上游 http 代理"}, + {"Failed to connect", "连接失败"}, + {"SOCKS proxy error", "SOCKS 代理错误"}, + {"Failed to send request to upstream", "向上游发送请求失败"}, + {"No reply from SOCKS proxy", "没有来自 SOCKS 代理的回复"}, + {"Cannot connect", "无法连接"}, + {"HTTP out proxy not implemented", "HTTP 出口代理未实现"}, + {"Cannot connect to upstream HTTP proxy", "无法连接到上游 HTTP 代理"}, {"Host is down", "主机已关闭"}, {"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"}, {"", ""}, @@ -200,9 +202,9 @@ namespace chinese // language namespace static std::map> plurals { - {"%d days", {"%d 日"}}, - {"%d hours", {"%d 时"}}, - {"%d minutes", {"%d 分"}}, + {"%d days", {"%d 天"}}, + {"%d hours", {"%d 小时"}}, + {"%d minutes", {"%d 分钟"}}, {"%d seconds", {"%d 秒"}}, {"", {""}}, }; diff --git a/i18n/Czech.cpp b/i18n/Czech.cpp index 93862053..09a56d50 100644 --- a/i18n/Czech.cpp +++ b/i18n/Czech.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -58,7 +58,6 @@ namespace czech // language namespace {"Unknown", "Neznámý"}, {"Proxy", "Proxy"}, {"Mesh", "Síť"}, - {"Error", "Chyba"}, {"Clock skew", "Časová nesrovnalost"}, {"Offline", "Offline"}, {"Symmetric NAT", "Symetrický NAT"}, @@ -117,7 +116,6 @@ namespace czech // language namespace {"Gateway", "Brána"}, {"TunnelID", "ID tunelu"}, {"EndDate", "Datum ukončení"}, - {"not floodfill", "není floodfill"}, {"Queue size", "Velikost fronty"}, {"Run peer test", "Spustit peer test"}, {"Decline transit tunnels", "Odmítnout tranzitní tunely"}, @@ -147,8 +145,6 @@ namespace czech // language namespace {"Destination not found", "Destinace nenalezena"}, {"StreamID can't be null", "StreamID nemůže být null"}, {"Return to destination page", "Zpět na stránku destinací"}, - {"You will be redirected in 5 seconds", "Budete přesměrováni za 5 vteřin"}, - {"Transit tunnels count must not exceed 65535", "Počet tranzitních tunelů nesmí přesáhnout 65535"}, {"Back to commands list", "Zpět na list příkazů"}, {"Register at reg.i2p", "Zaregistrovat na reg.i2p"}, {"Description", "Popis"}, @@ -166,32 +162,24 @@ namespace czech // language namespace {"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"}, {"Invalid request", "Neplatný požadavek"}, {"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"}, - {"addresshelper is not supported", "Adresshelper není podporován"}, - {"Host", "Hostitel"}, - {"added to router's addressbook from helper", "přidáno do adresáře routeru od pomocníka"}, - {"Click here to proceed:", "Pro pokračování, klikněte zde:"}, - {"Continue", "Pokračovat"}, - {"Addresshelper found", "Adresář nalezen"}, - {"already in router's addressbook", "je již v adresáři routeru"}, - {"Click here to update record:", "Pro aktualizaci záznamu, klikněte zde:"}, - {"invalid request uri", "neplatný URI požadavek"}, + {"Invalid request URI", "Neplatný URI požadavek"}, {"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"}, {"Outproxy failure", "Outproxy selhání"}, - {"bad outproxy settings", "špatné outproxy nastavení"}, - {"not inside I2P network, but outproxy is not enabled", "není uvnitř I2P sítě a outproxy není nastavena"}, - {"unknown outproxy url", "neznámá outproxy URL"}, - {"cannot resolve upstream proxy", "nelze rozluštit upstream proxy server"}, - {"hostname too long", "Název hostitele je příliš dlouhý"}, - {"cannot connect to upstream socks proxy", "nelze se připojit k upstream socks proxy serveru"}, - {"Cannot negotiate with socks proxy", "Nelze vyjednávat se socks proxy serverem"}, + {"Bad outproxy settings", "Špatné outproxy nastavení"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Hostitel %s není uvnitř I2P sítě a outproxy není nastavena"}, + {"Unknown outproxy URL", "Neznámá outproxy URL"}, + {"Cannot resolve upstream proxy", "Nelze rozluštit upstream proxy server"}, + {"Hostname is too long", "Název hostitele je příliš dlouhý"}, + {"Cannot connect to upstream SOCKS proxy", "Nelze se připojit k upstream SOCKS proxy serveru"}, + {"Cannot negotiate with SOCKS proxy", "Nelze vyjednávat se SOCKS proxy serverem"}, {"CONNECT error", "Chyba PŘIPOJENÍ"}, - {"Failed to Connect", "Připojení se nezdařilo"}, - {"socks proxy error", "chyba socks proxy serveru"}, - {"failed to send request to upstream", "odeslání žádosti upstream serveru se nezdařilo"}, - {"No Reply From socks proxy", "Žádná odpověď od socks proxy serveru"}, - {"cannot connect", "nelze se připojit"}, - {"http out proxy not implemented", "http out proxy není implementován"}, - {"cannot connect to upstream http proxy", "nelze se připojit k upstream socks proxy serveru"}, + {"Failed to connect", "Připojení se nezdařilo"}, + {"SOCKS proxy error", "Chyba SOCKS proxy serveru"}, + {"Failed to send request to upstream", "Odeslání žádosti upstream serveru se nezdařilo"}, + {"No reply from SOCKS proxy", "Žádná odpověď od SOCKS proxy serveru"}, + {"Cannot connect", "Nelze se připojit"}, + {"HTTP out proxy not implemented", "HTTP out proxy není implementován"}, + {"Cannot connect to upstream HTTP proxy", "Nelze se připojit k upstream HTTP proxy serveru"}, {"Host is down", "Hostitel je nedostupný"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."}, {"", ""}, diff --git a/i18n/French.cpp b/i18n/French.cpp index 0d32c5c2..0ce044e1 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -58,10 +58,11 @@ namespace french // language namespace {"Unknown", "Inconnu"}, {"Proxy", "Proxy"}, {"Mesh", "Maillé"}, - {"Error", "Erreur"}, {"Clock skew", "Horloge décalée"}, {"Offline", "Hors ligne"}, {"Symmetric NAT", "NAT symétrique"}, + {"Full cone NAT", "NAT à cône complet"}, + {"No Descriptors", "Aucuns Descripteurs"}, {"Uptime", "Temps de fonctionnement"}, {"Network status", "État du réseau"}, {"Network status v6", "État du réseau v6"}, @@ -69,7 +70,7 @@ namespace french // language namespace {"Family", "Famille"}, {"Tunnel creation success rate", "Taux de succès de création de tunnels"}, {"Received", "Reçu"}, - {"%.2f KiB/s", "%.2f kio/s"}, + {"%.2f KiB/s", "%.2f Kio/s"}, {"Sent", "Envoyé"}, {"Transit", "Transité"}, {"Data path", "Emplacement des données"}, @@ -81,6 +82,7 @@ namespace french // language namespace {"Our external address", "Notre adresse externe"}, {"supported", "supporté"}, {"Routers", "Routeurs"}, + {"Floodfills", "Remplisseurs"}, {"Client Tunnels", "Tunnels clients"}, {"Services", "Services"}, {"Enabled", "Activé"}, @@ -92,6 +94,7 @@ namespace french // language namespace {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Note: La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."}, {"Address", "Adresse"}, {"Type", "Type"}, + {"EncType", "EncType"}, {"Inbound tunnels", "Tunnels entrants"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, @@ -115,8 +118,10 @@ namespace french // language namespace {"Gateway", "Passerelle"}, {"TunnelID", "ID du tunnel"}, {"EndDate", "Date de fin"}, + {"floodfill mode is disabled", "le mode de remplissage est désactivé"}, {"Queue size", "Longueur de la file"}, {"Run peer test", "Lancer test des pairs"}, + {"Reload tunnels configuration", "Recharger la configuration des tunnels"}, {"Decline transit tunnels", "Refuser les tunnels transitoires"}, {"Accept transit tunnels", "Accepter les tunnels transitoires"}, {"Cancel graceful shutdown", "Annuler l'arrêt gracieux"}, @@ -134,6 +139,8 @@ namespace french // language namespace {"SAM session not found", "session SAM introuvable"}, {"SAM Session", "Session SAM"}, {"Server Tunnels", "Tunnels serveurs"}, + {"Client Forwards", "Transmission du client"}, + {"Server Forwards", "Transmission du serveur"}, {"Unknown page", "Page inconnue"}, {"Invalid token", "Jeton invalide"}, {"SUCCESS", "SUCCÈS"}, @@ -142,8 +149,8 @@ namespace french // language namespace {"Destination not found", "Destination introuvable"}, {"StreamID can't be null", "StreamID ne peut pas être vide"}, {"Return to destination page", "Retourner à la page de destination"}, - {"You will be redirected in 5 seconds", "Vous allez être redirigé dans cinq secondes"}, - {"Transit tunnels count must not exceed 65535", "Le nombre de tunnels transitoires ne doit pas dépasser 65535"}, + {"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"}, + {"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"}, {"Back to commands list", "Retour à la liste des commandes"}, {"Register at reg.i2p", "Inscription à reg.i2p"}, {"Description", "Description"}, @@ -161,32 +168,33 @@ namespace french // language namespace {"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"}, {"Invalid request", "Requête invalide"}, {"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"}, - {"addresshelper is not supported", "Assistant d'adresse non supporté"}, - {"Host", "Hôte"}, - {"added to router's addressbook from helper", "Ajouté au carnet d'adresse du routeur par l'assistant"}, - {"Click here to proceed:", "Cliquez ici pour continuer:"}, - {"Continue", "Continuer"}, - {"Addresshelper found", "Assistant d'adresse trouvé"}, - {"already in router's addressbook", "déjà dans le carnet d'adresses du routeur"}, - {"Click here to update record:", "Cliquez ici pour mettre à jour le carnet d'adresse:"}, - {"invalid request uri", "uri de la requête invalide"}, + {"Addresshelper is not supported", "Assistant d'adresse non supporté"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Attention : la source de cette URL peut être nuisible ! Cliquez ici pour mettre à jour l'enregistrement : Continuer."}, + {"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"}, + {"To add host %s in router's addressbook, click here: Continue.", "Pour ajouter l'hôte %s au carnet d'adresses du routeur, cliquez ici : Continuer."}, + {"Addresshelper request", "Demande à l'assistant d'adresse"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "L'hôte %s a été ajouté au carnet d'adresses du routeur depuis l'assistant. Cliquez ici pour continuer : Continuer."}, + {"Addresshelper adding", "Ajout de l'assistant d'adresse"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Cliquez ici pour mettre à jour le dossier : Continuer."}, + {"Addresshelper update", "Mise à jour de l'assistant d'adresse"}, + {"Invalid request URI", "URI de la requête invalide"}, {"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"}, {"Outproxy failure", "Échec de proxy de sortie"}, - {"bad outproxy settings", "Mauvaise configuration du proxy de sortie"}, - {"not inside I2P network, but outproxy is not enabled", "pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"}, - {"unknown outproxy url", "URL du proxy de sortie inconnu"}, - {"cannot resolve upstream proxy", "impossible de résoudre l'adresse du proxy en amont"}, - {"hostname too long", "nom d'hôte trop long"}, - {"cannot connect to upstream socks proxy", "impossible de se connecter au proxy socks en amont"}, - {"Cannot negotiate with socks proxy", "Impossible de négocier avec le proxy socks"}, + {"Bad outproxy settings", "Mauvaise configuration du proxy de sortie"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Hôte %s pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"}, + {"Unknown outproxy URL", "URL du proxy de sortie inconnu"}, + {"Cannot resolve upstream proxy", "Impossible de résoudre l'adresse du proxy en amont"}, + {"Hostname is too long", "Nom d'hôte trop long"}, + {"Cannot connect to upstream SOCKS proxy", "Impossible de se connecter au proxy SOCKS en amont"}, + {"Cannot negotiate with SOCKS proxy", "Impossible de négocier avec le proxy SOCKS"}, {"CONNECT error", "Erreur de connexion"}, - {"Failed to Connect", "Échec de connexion"}, - {"socks proxy error", "Erreur de proxy socks"}, - {"failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"}, - {"No Reply From socks proxy", "Pas de réponse du proxy socks"}, - {"cannot connect", "impossible de connecter"}, - {"http out proxy not implemented", "Proxy de sortie HTTP non implémenté"}, - {"cannot connect to upstream http proxy", "impossible de se connecter au proxy HTTP en amont"}, + {"Failed to connect", "Échec de connexion"}, + {"SOCKS proxy error", "Erreur de proxy SOCKS"}, + {"Failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"}, + {"No reply from SOCKS proxy", "Pas de réponse du proxy SOCKS"}, + {"Cannot connect", "Impossible de connecter"}, + {"HTTP out proxy not implemented", "Proxy de sortie HTTP non implémenté"}, + {"Cannot connect to upstream HTTP proxy", "Impossible de se connecter au proxy HTTP en amont"}, {"Host is down", "Hôte hors service"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."}, {"", ""}, diff --git a/i18n/German.cpp b/i18n/German.cpp index ca669436..0db3d6be 100644 --- a/i18n/German.cpp +++ b/i18n/German.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -58,7 +58,6 @@ namespace german // language namespace {"Unknown", "Unbekannt"}, {"Proxy", "Proxy"}, {"Mesh", "Mesh"}, - {"Error", "Fehler"}, {"Clock skew", "Zeitabweichung"}, {"Offline", "Offline"}, {"Symmetric NAT", "Symmetrisches NAT"}, @@ -117,7 +116,6 @@ namespace german // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "Enddatum"}, - {"not floodfill", "kein Floodfill"}, {"Queue size", "Größe der Warteschlange"}, {"Run peer test", "Peer-Test durchführen"}, {"Decline transit tunnels", "Transittunnel ablehnen"}, @@ -147,8 +145,6 @@ namespace german // language namespace {"Destination not found", "Ziel nicht gefunden"}, {"StreamID can't be null", "StreamID kann nicht null sein"}, {"Return to destination page", "Zurück zur Ziel-Seite"}, - {"You will be redirected in 5 seconds", "Du wirst in 5 Sekunden weitergeleitet"}, - {"Transit tunnels count must not exceed 65535", "Es darf maximal 65535 Transittunnel geben"}, {"Back to commands list", "Zurück zur Befehlsliste"}, {"Register at reg.i2p", "Auf reg.i2p registrieren"}, {"Description", "Beschreibung"}, @@ -166,32 +162,24 @@ namespace german // language namespace {"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"}, {"Invalid request", "Ungültige Anfrage"}, {"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"}, - {"addresshelper is not supported", "Addresshelfer wird nicht unterstützt"}, - {"Host", "Host"}, - {"added to router's addressbook from helper", "vom Helfer zum Router-Adressbuch hinzugefügt"}, - {"Click here to proceed:", "Klicke hier um fortzufahren:"}, - {"Continue", "Fortsetzen"}, - {"Addresshelper found", "Adresshelfer gefunden"}, - {"already in router's addressbook", "bereits im Adressbuch des Routers"}, - {"Click here to update record:", "Klicke hier, um den Eintrag zu aktualisieren:"}, - {"invalid request uri", "ungültige Anfrage-URI"}, + {"Invalid request URI", "Ungültige Anfrage-URI"}, {"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"}, {"Outproxy failure", "Outproxy-Fehler"}, - {"bad outproxy settings", "ungültige Outproxy-Einstellungen"}, - {"not inside I2P network, but outproxy is not enabled", "außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"}, - {"unknown outproxy url", "unbekannte Outproxy-URL"}, - {"cannot resolve upstream proxy", "kann den Upstream-Proxy nicht auflösen"}, - {"hostname too long", "Hostname zu lang"}, - {"cannot connect to upstream socks proxy", "Kann keine Verbindung zum Upstream-Socks-Proxy herstellen"}, - {"Cannot negotiate with socks proxy", "Kann nicht mit Socks-Proxy verhandeln"}, + {"Bad outproxy settings", "Ungültige Outproxy-Einstellungen"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"}, + {"Unknown outproxy URL", "Unbekannte Outproxy-URL"}, + {"Cannot resolve upstream proxy", "Kann den Upstream-Proxy nicht auflösen"}, + {"Hostname is too long", "Hostname zu lang"}, + {"Cannot connect to upstream SOCKS proxy", "Kann keine Verbindung zum Upstream-SOCKS-Proxy herstellen"}, + {"Cannot negotiate with SOCKS proxy", "Kann nicht mit SOCKS-Proxy verhandeln"}, {"CONNECT error", "CONNECT-Fehler"}, - {"Failed to Connect", "Verbindung konnte nicht hergestellt werden"}, - {"socks proxy error", "Socks-Proxy-Fehler"}, - {"failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"}, - {"No Reply From socks proxy", "Keine Antwort vom Socks-Proxy"}, - {"cannot connect", "kann nicht verbinden"}, - {"http out proxy not implemented", "HTTP-Outproxy nicht implementiert"}, - {"cannot connect to upstream http proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"}, + {"Failed to connect", "Verbindung konnte nicht hergestellt werden"}, + {"SOCKS proxy error", "SOCKS-Proxy-Fehler"}, + {"Failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"}, + {"No reply from SOCKS proxy", "Keine Antwort vom SOCKS-Proxy"}, + {"Cannot connect", "Kann nicht verbinden"}, + {"HTTP out proxy not implemented", "HTTP-Outproxy nicht implementiert"}, + {"Cannot connect to upstream HTTP proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"}, {"Host is down", "Host ist offline"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."}, {"", ""}, diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 51e23b19..6426e2ce 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -23,20 +23,23 @@ namespace i18n }; // Add localization here with language name as namespace - namespace afrikaans { std::shared_ptr GetLocale (); } - namespace armenian { std::shared_ptr GetLocale (); } - namespace chinese { std::shared_ptr GetLocale (); } - namespace czech { std::shared_ptr GetLocale (); } - namespace english { std::shared_ptr GetLocale (); } - namespace french { std::shared_ptr GetLocale (); } - namespace german { std::shared_ptr GetLocale (); } - namespace italian { std::shared_ptr GetLocale (); } - namespace russian { std::shared_ptr GetLocale (); } - namespace spanish { std::shared_ptr GetLocale (); } - namespace swedish { std::shared_ptr GetLocale (); } - namespace turkmen { std::shared_ptr GetLocale (); } - namespace ukrainian { std::shared_ptr GetLocale (); } - namespace uzbek { std::shared_ptr GetLocale (); } + namespace afrikaans { std::shared_ptr GetLocale (); } + namespace armenian { std::shared_ptr GetLocale (); } + namespace chinese { std::shared_ptr GetLocale (); } + namespace czech { std::shared_ptr GetLocale (); } + namespace english { std::shared_ptr GetLocale (); } + namespace french { std::shared_ptr GetLocale (); } + namespace german { std::shared_ptr GetLocale (); } + namespace italian { std::shared_ptr GetLocale (); } + namespace polish { std::shared_ptr GetLocale (); } + namespace portuguese { std::shared_ptr GetLocale (); } + namespace russian { std::shared_ptr GetLocale (); } + namespace spanish { std::shared_ptr GetLocale (); } + namespace swedish { std::shared_ptr GetLocale (); } + namespace turkish { std::shared_ptr GetLocale (); } + namespace turkmen { std::shared_ptr GetLocale (); } + namespace ukrainian { std::shared_ptr GetLocale (); } + namespace uzbek { std::shared_ptr GetLocale (); } /** * That map contains international language name lower-case, name in it's language and it's code @@ -51,9 +54,12 @@ namespace i18n { "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, { "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} }, + { "polish", {"Polski", "pl", i2p::i18n::polish::GetLocale} }, + { "portuguese", {"Português", "pt", i2p::i18n::portuguese::GetLocale} }, { "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} }, { "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} }, { "swedish", {"Svenska", "sv", i2p::i18n::swedish::GetLocale} }, + { "turkish", {"Türk dili", "tr", i2p::i18n::turkish::GetLocale} }, { "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} }, { "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} }, { "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} }, diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index 07e436d7..c51e15a5 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -58,7 +58,6 @@ namespace italian // language namespace {"Unknown", "Sconosciuto"}, {"Proxy", "Proxy"}, {"Mesh", "Mesh"}, - {"Error", "Errore"}, {"Clock skew", "Orologio disallineato"}, {"Offline", "Disconnesso"}, {"Symmetric NAT", "NAT simmetrico"}, @@ -117,9 +116,9 @@ namespace italian // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "Data di fine"}, - {"not floodfill", "no floodfill"}, {"Queue size", "Dimensione della coda"}, {"Run peer test", "Esegui il test dei peer"}, + {"Reload tunnels configuration", "Ricarica la configurazione dei tunnel"}, {"Decline transit tunnels", "Rifiuta tunnel di transito"}, {"Accept transit tunnels", "Accetta tunnel di transito"}, {"Cancel graceful shutdown", "Annulla l'interruzione controllata"}, @@ -147,8 +146,8 @@ namespace italian // language namespace {"Destination not found", "Destinazione non trovata"}, {"StreamID can't be null", "Lo StreamID non può essere null"}, {"Return to destination page", "Ritorna alla pagina di destinazione"}, - {"You will be redirected in 5 seconds", "Verrai reindirizzato in 5 secondi"}, - {"Transit tunnels count must not exceed 65535", "Il numero di tunnel di transito non può superare i 65535"}, + {"You will be redirected in %d seconds", "Sarai reindirizzato tra %d secondi"}, + {"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"}, {"Back to commands list", "Ritorna alla lista dei comandi"}, {"Register at reg.i2p", "Registra a reg.i2p"}, {"Description", "Descrizione"}, @@ -166,32 +165,26 @@ namespace italian // language namespace {"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"}, {"Invalid request", "Richiesta non valida"}, {"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"}, - {"addresshelper is not supported", "addresshelper non è supportato"}, - {"Host", "Host"}, - {"added to router's addressbook from helper", "aggiunto alla rubrica tramite l'helper"}, - {"Click here to proceed:", "Clicca qui per procedere:"}, - {"Continue", "Continua"}, - {"Addresshelper found", "Addresshelper trovato"}, - {"already in router's addressbook", "già presente nella rubrica del router"}, - {"Click here to update record:", "Clicca qui per aggiornare l'elemento:"}, - {"invalid request uri", "uri della richiesta non valido"}, + {"To add host %s in router's addressbook, click here: Continue.", "Per aggiungere host %s nella rubrica del router, clicca qui: Continua."}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "L'host %s è già nella rubrica del router. Clicca qui per aggiornare il record: Continua."}, + {"Invalid request URI", "URI della richiesta non valido"}, {"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"}, {"Outproxy failure", "Fallimento del proxy di uscita"}, - {"bad outproxy settings", "impostazioni errate del proxy di uscita"}, - {"not inside I2P network, but outproxy is not enabled", "non all'interno della rete I2P, ma il proxy di uscita non è abilitato"}, - {"unknown outproxy url", "url del proxy di uscita sconosciuto"}, - {"cannot resolve upstream proxy", "impossibile identificare il flusso a monte del proxy"}, - {"hostname too long", "il nome dell'host è troppo lungo"}, - {"cannot connect to upstream socks proxy", "impossibile connettersi al flusso a monte del proxy socks"}, - {"Cannot negotiate with socks proxy", "Impossibile negoziare con il proxy socks"}, + {"Bad outproxy settings", "Impostazioni errate del proxy di uscita"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s non all'interno della rete I2P, ma il proxy di uscita non è abilitato"}, + {"Unknown outproxy URL", "URL del proxy di uscita sconosciuto"}, + {"Cannot resolve upstream proxy", "Impossibile identificare il flusso a monte del proxy"}, + {"Hostname is too long", "Il nome dell'host è troppo lungo"}, + {"Cannot connect to upstream SOCKS proxy", "Impossibile connettersi al flusso a monte del proxy SOCKS"}, + {"Cannot negotiate with SOCKS proxy", "Impossibile negoziare con il proxy SOCKS"}, {"CONNECT error", "Errore di connessione"}, - {"Failed to Connect", "Connessione fallita"}, - {"socks proxy error", "errore del proxy socks"}, - {"failed to send request to upstream", "invio della richiesta a monte non riuscito"}, - {"No Reply From socks proxy", "Nessuna risposta dal proxy socks"}, - {"cannot connect", "impossibile connettersi"}, - {"http out proxy not implemented", "proxy http di uscita non implementato"}, - {"cannot connect to upstream http proxy", "impossibile connettersi al proxy http a monte"}, + {"Failed to connect", "Connessione fallita"}, + {"SOCKS proxy error", "Errore del proxy SOCKS"}, + {"Failed to send request to upstream", "Invio della richiesta a monte non riuscito"}, + {"No reply from SOCKS proxy", "Nessuna risposta dal proxy SOCKS"}, + {"Cannot connect", "Impossibile connettersi"}, + {"HTTP out proxy not implemented", "Proxy HTTP di uscita non implementato"}, + {"Cannot connect to upstream HTTP proxy", "Impossibile connettersi al flusso a monte del proxy HTTP"}, {"Host is down", "L'host è offline"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."}, {"", ""}, diff --git a/i18n/Polish.cpp b/i18n/Polish.cpp new file mode 100644 index 00000000..26661231 --- /dev/null +++ b/i18n/Polish.cpp @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Polish localization file + +namespace i2p +{ +namespace i18n +{ +namespace polish // language namespace +{ + // language name in lowercase + static std::string language = "polish"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); + } + + static std::map strings + { + {"building", "Kompilowanie"}, + {"failed", "nieudane"}, + {"expiring", "wygasający"}, + {"established", "ustanowiony"}, + {"Main page", "Strona główna"}, + {"Router commands", "Komendy routera"}, + {"Tunnels", "Tunele"}, + {"OK", "Ok"}, + {"Uptime", "Czas pracy"}, + {"Sent", "Wysłane"}, + {"", ""}, + }; + + static std::map> plurals + { + {"", {"", "", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/Portuguese.cpp b/i18n/Portuguese.cpp new file mode 100644 index 00000000..528be389 --- /dev/null +++ b/i18n/Portuguese.cpp @@ -0,0 +1,219 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Portuguese localization file + +namespace i2p +{ +namespace i18n +{ +namespace portuguese // language namespace +{ + // language name in lowercase + static std::string language = "portuguese"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return n != 1 ? 1 : 0; + } + + static std::map strings + { + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, + {"building", "construindo"}, + {"failed", "falhou"}, + {"expiring", "expirando"}, + {"established", "estabelecido"}, + {"unknown", "desconhecido"}, + {"exploratory", "exploratório"}, + {"Purple I2P Webconsole", "Webconsole Purple I2P"}, + {"i2pd webconsole", "webconsole i2pd"}, + {"Main page", "Página Principal"}, + {"Router commands", "Comandos do Roteador"}, + {"Local Destinations", "Destinos Locais"}, + {"LeaseSets", "LeaseSets"}, + {"Tunnels", "Túneis"}, + {"Transit Tunnels", "Túneis de Trânsito"}, + {"Transports", "Transportes"}, + {"I2P tunnels", "Túneis I2P"}, + {"SAM sessions", "Sessões do SAM"}, + {"ERROR", "ERRO"}, + {"OK", "OK"}, + {"Testing", "Testando"}, + {"Firewalled", "Sob Firewall"}, + {"Unknown", "Desconhecido"}, + {"Proxy", "Proxy"}, + {"Mesh", "Malha"}, + {"Clock skew", "Defasagem do Relógio"}, + {"Offline", "Desligado"}, + {"Symmetric NAT", "NAT Simétrico"}, + {"Full cone NAT", "Full cone NAT"}, + {"No Descriptors", "Sem Descritores"}, + {"Uptime", "Tempo Ativo"}, + {"Network status", "Estado da rede"}, + {"Network status v6", "Estado da rede v6"}, + {"Stopping in", "Parando em"}, + {"Family", "Família"}, + {"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"}, + {"Received", "Recebido"}, + {"%.2f KiB/s", "%.2f KiB/s"}, + {"Sent", "Enviado"}, + {"Transit", "Trânsito"}, + {"Data path", "Caminho dos dados"}, + {"Hidden content. Press on text to see.", "Conteúdo oculto. Clique no texto para revelar."}, + {"Router Ident", "Identidade do Roteador"}, + {"Router Family", "Família do Roteador"}, + {"Router Caps", "Limites do Roteador"}, + {"Version", "Versão"}, + {"Our external address", "Nosso endereço externo"}, + {"supported", "suportado"}, + {"Routers", "Roteadores"}, + {"Floodfills", "Modo Inundação"}, + {"Client Tunnels", "Túneis de Clientes"}, + {"Services", "Serviços"}, + {"Enabled", "Ativado"}, + {"Disabled", "Desativado"}, + {"Encrypted B33 address", "Endereço B33 criptografado"}, + {"Address registration line", "Linha de cadastro de endereço"}, + {"Domain", "Domínio"}, + {"Generate", "Gerar"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", " Nota: A string resultante só pode ser usada para registrar domínios 2LD (exemplo.i2p). Para registrar subdomínios por favor utilize o i2pd-tools."}, + {"Address", "Endereço"}, + {"Type", "Tipo"}, + {"EncType", "Tipo de Criptografia"}, + {"Inbound tunnels", "Túneis de Entrada"}, + {"%dms", "%dms"}, + {"Outbound tunnels", "Túneis de Saída"}, + {"Tags", "Etiquetas"}, + {"Incoming", "Entradas"}, + {"Outgoing", "Saídas"}, + {"Destination", "Destinos"}, + {"Amount", "Quantidade"}, + {"Incoming Tags", "Etiquetas de Entrada"}, + {"Tags sessions", "Sessões de etiquetas"}, + {"Status", "Estado"}, + {"Local Destination", "Destinos Locais"}, + {"Streams", "Fluxos"}, + {"Close stream", "Fechar fluxo"}, + {"I2CP session not found", "Sessão do I2CP não encontrada"}, + {"I2CP is not enabled", "I2CP não está ativado"}, + {"Invalid", "Inválido"}, + {"Store type", "Tipo de armazenamento"}, + {"Expires", "Expira em"}, + {"Non Expired Leases", "Sessões não expiradas"}, + {"Gateway", "Gateway"}, + {"TunnelID", "TunnelID"}, + {"EndDate", "Data final"}, + {"floodfill mode is disabled", "Mode de inundação está desativado"}, + {"Queue size", "Tamanho da fila"}, + {"Run peer test", "Executar teste de peers"}, + {"Reload tunnels configuration", "Recarregar a configuração dos túneis"}, + {"Decline transit tunnels", "Negar túnel de trânsito"}, + {"Accept transit tunnels", "Aceitar túnel de trânsito"}, + {"Cancel graceful shutdown", "Cancelar desligamento gracioso"}, + {"Start graceful shutdown", "Iniciar desligamento gracioso"}, + {"Force shutdown", "Forçar desligamento"}, + {"Reload external CSS styles", "Recarregar estilos CSS externos"}, + {"Note: any action done here are not persistent and not changes your config files.", " Nota: Qualquer ação feita aqui não será permanente e não altera os seus arquivos de configuração."}, + {"Logging level", "Nível de registro"}, + {"Transit tunnels limit", "Limite nos túneis de trânsito"}, + {"Change", "Mudar"}, + {"Change language", "Trocar idioma"}, + {"no transit tunnels currently built", "Nenhum túnel de trânsito construido no momento"}, + {"SAM disabled", "SAM desativado"}, + {"no sessions currently running", "Nenhuma sessão funcionando no momento"}, + {"SAM session not found", "Nenhuma sessão do SAM encontrada"}, + {"SAM Session", "Sessão do SAM"}, + {"Server Tunnels", "Túneis de Servidor"}, + {"Client Forwards", "Túneis de Cliente"}, + {"Server Forwards", "Encaminhamentos de Servidor"}, + {"Unknown page", "Página desconhecida"}, + {"Invalid token", "Token Inválido"}, + {"SUCCESS", "SUCESSO"}, + {"Stream closed", "Fluxo fechado"}, + {"Stream not found or already was closed", "Fluxo não encontrado ou já encerrado"}, + {"Destination not found", "Destino não encontrado"}, + {"StreamID can't be null", "StreamID não pode ser nulo"}, + {"Return to destination page", "Retornar para à página de destino"}, + {"You will be redirected in %d seconds", "Você será redirecionado em %d segundos"}, + {"Transit tunnels count must not exceed %d", "A contagem de túneis de trânsito não deve exceder %d"}, + {"Back to commands list", "Voltar para a lista de comandos"}, + {"Register at reg.i2p", "Registrar na reg.i2p"}, + {"Description", "Descrição"}, + {"A bit information about service on domain", "Algumas informações sobre o serviço no domínio"}, + {"Submit", "Enviar"}, + {"Domain can't end with .b32.i2p", "O domínio não pode terminar com .b32.i2p"}, + {"Domain must end with .i2p", "O domínio não pode terminar com .i2p"}, + {"Such destination is not found", "Tal destino não foi encontrado"}, + {"Unknown command", "Comando desconhecido"}, + {"Command accepted", "Comando aceito"}, + {"Proxy error", "Erro no proxy"}, + {"Proxy info", "Informações do proxy"}, + {"Proxy error: Host not found", "Erro no proxy: Host não encontrado"}, + {"Remote host not found in router's addressbook", "O host remoto não foi encontrado no livro de endereços do roteador"}, + {"You may try to find this host on jump services below", "Você pode tentar encontrar este host nos jump services abaixo"}, + {"Invalid request", "Requisição inválida"}, + {"Proxy unable to parse your request", "O proxy foi incapaz de processar a sua requisição"}, + {"Addresshelper is not supported", "O Auxiliar de Endereços não é suportado"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "O host %s já está no catálogo de endereços do roteador. Cuidado: a fonte desta URL pode ser perigosa! Clique aqui para atualizar o registro: Continuar."}, + {"Addresshelper forced update rejected", "A atualização forçada do Auxiliar de Endereços foi rejeitada"}, + {"To add host %s in router's addressbook, click here: Continue.", "Para adicionar o host %s ao catálogo de endereços do roteador, clique aqui: Continuar ."}, + {"Addresshelper request", "Requisição do Auxiliar de Endereços"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "O host %s foi adicionado ao catálogo de endereços do roteador por um auxiliar. Clique aqui para proceder: Continuar ."}, + {"Addresshelper adding", "Auxiliar de Endereço adicionando"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "O host %s já está no catálogo de endereços do roteador . Clique aqui para atualizar o registro: Continuar."}, + {"Addresshelper update", "Atualização do Auxiliar de Endereços"}, + {"Invalid request URI", "A URI de requisição é inválida"}, + {"Can't detect destination host from request", "Incapaz de detectar o host de destino da requisição"}, + {"Outproxy failure", "Falha no outproxy"}, + {"Bad outproxy settings", "Configurações ruins de outproxy"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "O host %s não está dentro da rede I2P, mas o outproxy não está ativado"}, + {"Unknown outproxy URL", "URL de outproxy desconhecida"}, + {"Cannot resolve upstream proxy", "Não é possível resolver o proxy de entrada"}, + {"Hostname is too long", "O hostname é muito longo"}, + {"Cannot connect to upstream SOCKS proxy", "Não é possível se conectar ao proxy SOCKS de entrada"}, + {"Cannot negotiate with SOCKS proxy", "Não é possível negociar com o proxy SOCKS"}, + {"CONNECT error", "Erro de CONEXÃO"}, + {"Failed to connect", "Falha ao conectar"}, + {"SOCKS proxy error", "Erro no proxy SOCKS"}, + {"Failed to send request to upstream", "Falha ao enviar requisição para o fluxo de entrada"}, + {"No reply from SOCKS proxy", "Sem resposta do proxy SOCKS"}, + {"Cannot connect", "Impossível conectar"}, + {"HTTP out proxy not implemented", "proxy de saída HTTP não implementado"}, + {"Cannot connect to upstream HTTP proxy", "Não é possível conectar ao proxy HTTP de entrada"}, + {"Host is down", "Host está desligado"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Não é possível se conectar ao host requisitado, talvez ele esteja for do ar. Por favor, tente novamente mais tarde."}, + {"", ""}, + }; + + static std::map> plurals + { + {"%d days", {"%d Dia", "%d Dias"}}, + {"%d hours", {"%d hora", "%d horas"}}, + {"%d minutes", {"%d minuto", "%d minutos"}}, + {"%d seconds", {"%d Segundo", "%d segundos"}}, + {"", {"", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index 7d875f01..dbfb13f2 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,6 +40,7 @@ namespace russian // language namespace {"established", "работает"}, {"unknown", "неизвестно"}, {"exploratory", "исследовательский"}, + {"Purple I2P Webconsole", "Веб-консоль Purple I2P"}, {"i2pd webconsole", "Веб-консоль i2pd"}, {"Main page", "Главная"}, {"Router commands", "Команды роутера"}, @@ -57,10 +58,11 @@ namespace russian // language namespace {"Unknown", "Неизвестно"}, {"Proxy", "Прокси"}, {"Mesh", "MESH-сеть"}, - {"Error", "Ошибка"}, {"Clock skew", "Не точное время"}, {"Offline", "Оффлайн"}, {"Symmetric NAT", "Симметричный NAT"}, + {"Full cone NAT", "Full cone NAT"}, + {"No Descriptors", "Нет дескрипторов"}, {"Uptime", "В сети"}, {"Network status", "Сетевой статус"}, {"Network status v6", "Сетевой статус v6"}, @@ -116,9 +118,10 @@ namespace russian // language namespace {"Gateway", "Шлюз"}, {"TunnelID", "ID туннеля"}, {"EndDate", "Заканчивается"}, - {"not floodfill", "не флудфил"}, + {"floodfill mode is disabled", "режим флудфила отключен"}, {"Queue size", "Размер очереди"}, {"Run peer test", "Запустить тестирование"}, + {"Reload tunnels configuration", "Перезагрузить конфигурацию туннелей"}, {"Decline transit tunnels", "Отклонять транзитные туннели"}, {"Accept transit tunnels", "Принимать транзитные туннели"}, {"Cancel graceful shutdown", "Отменить плавную остановку"}, @@ -146,8 +149,8 @@ namespace russian // language namespace {"Destination not found", "Точка назначения не найдена"}, {"StreamID can't be null", "StreamID не может быть пустым"}, {"Return to destination page", "Вернуться на страницу точки назначения"}, - {"You will be redirected in 5 seconds", "Вы будете переадресованы через 5 секунд"}, - {"Transit tunnels count must not exceed 65535", "Число транзитных туннелей не должно превышать 65535"}, + {"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"}, + {"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"}, {"Back to commands list", "Вернуться к списку команд"}, {"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, {"Description", "Описание"}, @@ -165,32 +168,33 @@ namespace russian // language namespace {"You may try to find this host on jump services below", "Вы можете попробовать найти узел через джамп сервисы ниже"}, {"Invalid request", "Некорректный запрос"}, {"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"}, - {"addresshelper is not supported", "addresshelper не поддерживается"}, - {"Host", "Узел"}, - {"added to router's addressbook from helper", "добавлен в адресную книгу роутера через хелпер"}, - {"Click here to proceed:", "Нажмите здесь, чтобы продолжить:"}, - {"Continue", "Продолжить"}, - {"Addresshelper found", "Найден addresshelper"}, - {"already in router's addressbook", "уже в адресной книге роутера"}, - {"Click here to update record:", "Нажмите здесь, чтобы обновить запись:"}, - {"invalid request uri", "некорректный URI запроса"}, + {"Addresshelper is not supported", "Addresshelper не поддерживается"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "Узел %s уже в адресной книге роутера. Будьте осторожны: источник данной ссылки может быть вредоносным! Нажмите здесь, чтобы обновить запись: Продолжить."}, + {"Addresshelper forced update rejected", "Принудительное обновление через Addresshelper отклонено"}, + {"To add host %s in router's addressbook, click here: Continue.", "Чтобы добавить узел %s в адресную книгу роутера, нажмите здесь: Продолжить."}, + {"Addresshelper request", "Запрос добавления Addresshelper"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Узел %s добавлен в адресную книгу роутера через хелпер. Нажмите здесь, чтобы продолжить: Продолжить."}, + {"Addresshelper adding", "Добавление Addresshelper"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "Узел %s уже в адресной книге роутера. Нажмите здесь, чтобы обновить запись: Продолжить."}, + {"Addresshelper update", "Обновление записи через Addresshelper"}, + {"Invalid request URI", "Некорректный URI запроса"}, {"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"}, {"Outproxy failure", "Ошибка внешнего прокси"}, - {"bad outproxy settings", "некорректные настройки внешнего прокси"}, - {"not inside I2P network, but outproxy is not enabled", "не в I2P сети, но внешний прокси не включен"}, - {"unknown outproxy url", "неизвестный URL внешнего прокси"}, - {"cannot resolve upstream proxy", "не удается определить вышестоящий прокси"}, - {"hostname too long", "имя хоста слишком длинное"}, - {"cannot connect to upstream socks proxy", "не удается подключиться к вышестоящему SOCKS прокси"}, - {"Cannot negotiate with socks proxy", "Не удается договориться с вышестоящим SOCKS прокси"}, + {"Bad outproxy settings", "Некорректные настройки внешнего прокси"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Узел %s не в I2P сети, но внешний прокси не включен"}, + {"Unknown outproxy URL", "Неизвестный URL внешнего прокси"}, + {"Cannot resolve upstream proxy", "Не удается определить вышестоящий прокси"}, + {"Hostname is too long", "Имя хоста слишком длинное"}, + {"Cannot connect to upstream SOCKS proxy", "Не удалось подключиться к вышестоящему SOCKS прокси серверу"}, + {"Cannot negotiate with SOCKS proxy", "Не удается договориться с вышестоящим SOCKS прокси"}, {"CONNECT error", "Ошибка CONNECT запроса"}, - {"Failed to Connect", "Не удалось подключиться"}, - {"socks proxy error", "ошибка SOCKS прокси"}, - {"failed to send request to upstream", "не удалось отправить запрос вышестоящему прокси"}, - {"No Reply From socks proxy", "Нет ответа от SOCKS прокси сервера"}, - {"cannot connect", "не удалось подключиться"}, - {"http out proxy not implemented", "поддержка внешнего HTTP прокси сервера не реализована"}, - {"cannot connect to upstream http proxy", "не удалось подключиться к вышестоящему HTTP прокси серверу"}, + {"Failed to connect", "Не удалось соединиться"}, + {"SOCKS proxy error", "Ошибка SOCKS прокси"}, + {"Failed to send request to upstream", "Не удалось отправить запрос вышестоящему прокси серверу"}, + {"No reply from SOCKS proxy", "Нет ответа от SOCKS прокси сервера"}, + {"Cannot connect", "Не удалось подключиться"}, + {"HTTP out proxy not implemented", "Поддержка внешнего HTTP прокси сервера не реализована"}, + {"Cannot connect to upstream HTTP proxy", "Не удалось подключиться к вышестоящему HTTP прокси серверу"}, {"Host is down", "Узел недоступен"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному узлу, возможно он не в сети. Попробуйте повторить запрос позже."}, {"", ""}, diff --git a/i18n/Spanish.cpp b/i18n/Spanish.cpp index 8b0e927a..a5ecc30a 100644 --- a/i18n/Spanish.cpp +++ b/i18n/Spanish.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022, The PurpleI2P Project +* Copyright (c) 2022-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -58,7 +58,6 @@ namespace spanish // language namespace {"Unknown", "Desconocido"}, {"Proxy", "Proxy"}, {"Mesh", "Malla"}, - {"Error", "Error"}, {"Clock skew", "Reloj desfasado"}, {"Offline", "Desconectado"}, {"Symmetric NAT", "NAT simétrico"}, @@ -117,7 +116,6 @@ namespace spanish // language namespace {"Gateway", "Puerta de enlace"}, {"TunnelID", "TunnelID"}, {"EndDate", "FechaVenc"}, - {"not floodfill", "no inundado"}, {"Queue size", "Tamaño de cola"}, {"Run peer test", "Ejecutar prueba de par"}, {"Decline transit tunnels", "Rechazar túneles de tránsito"}, @@ -147,8 +145,6 @@ namespace spanish // language namespace {"Destination not found", "Destino no encontrado"}, {"StreamID can't be null", "StreamID no puede ser nulo"}, {"Return to destination page", "Volver a la página de destino"}, - {"You will be redirected in 5 seconds", "Serás redirigido en 5 segundos"}, - {"Transit tunnels count must not exceed 65535", "La cantidad de túneles de tránsito no puede exceder 65535"}, {"Back to commands list", "Volver a lista de comandos"}, {"Register at reg.i2p", "Registrar en reg.i2p"}, {"Description", "Descripción"}, @@ -166,32 +162,24 @@ namespace spanish // language namespace {"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"}, {"Invalid request", "Solicitud inválida"}, {"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"}, - {"addresshelper is not supported", "ayudante de dirección no soportado"}, - {"Host", "Dominio"}, - {"added to router's addressbook from helper", "añadido a la libreta de direcciones desde el ayudante"}, - {"Click here to proceed:", "Haga clic aquí para continuar:"}, - {"Continue", "Continuar"}, - {"Addresshelper found", "Se encontró ayudante de dirección"}, - {"already in router's addressbook", "ya se encontró en libreta de direcciones"}, - {"Click here to update record:", "Haga clic aquí para actualizar el registro:"}, - {"invalid request uri", "uri de solicitud inválida"}, + {"Invalid request URI", "URI de solicitud inválida"}, {"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"}, {"Outproxy failure", "Fallo en el proxy saliente"}, - {"bad outproxy settings", "configuración de outproxy incorrecta"}, - {"not inside I2P network, but outproxy is not enabled", "no está dentro de la red I2P, pero el proxy de salida no está activado"}, - {"unknown outproxy url", "url de proxy outproxy desconocido"}, - {"cannot resolve upstream proxy", "no se puede resolver el proxy de upstream"}, - {"hostname too long", "nombre de dominio muy largo"}, - {"cannot connect to upstream socks proxy", "no se puede conectar al proxy socks principal"}, - {"Cannot negotiate with socks proxy", "No se puede negociar con el proxy socks"}, + {"Bad outproxy settings", "Configuración de outproxy incorrecta"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Dominio %s no está dentro de la red I2P, pero el proxy de salida no está activado"}, + {"Unknown outproxy URL", "URL de proxy outproxy desconocido"}, + {"Cannot resolve upstream proxy", "No se puede resolver el proxy de upstream"}, + {"Hostname is too long", "Nombre de dominio muy largo"}, + {"Cannot connect to upstream SOCKS proxy", "No se puede conectar al proxy SOCKS principal"}, + {"Cannot negotiate with SOCKS proxy", "No se puede negociar con el proxy SOCKS"}, {"CONNECT error", "Error de CONNECT"}, - {"Failed to Connect", "Error al Conectar"}, - {"socks proxy error", "error de proxy socks"}, - {"failed to send request to upstream", "no se pudo enviar petición al principal"}, - {"No Reply From socks proxy", "Sin respuesta del proxy socks"}, - {"cannot connect", "no se puede conectar"}, - {"http out proxy not implemented", "proxy externo http no implementado"}, - {"cannot connect to upstream http proxy", "no se puede conectar al proxy http principal"}, + {"Failed to connect", "Error al conectar"}, + {"SOCKS proxy error", "Error de proxy SOCKS"}, + {"Failed to send request to upstream", "No se pudo enviar petición al principal"}, + {"No reply from SOCKS proxy", "Sin respuesta del proxy SOCKS"}, + {"Cannot connect", "No se puede conectar"}, + {"HTTP out proxy not implemented", "Proxy externo HTTP no implementado"}, + {"Cannot connect to upstream HTTP proxy", "No se puede conectar al proxy HTTP principal"}, {"Host is down", "Servidor caído"}, {"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."}, {"", ""}, diff --git a/i18n/Swedish.cpp b/i18n/Swedish.cpp index 180f74aa..e7f84e69 100644 --- a/i18n/Swedish.cpp +++ b/i18n/Swedish.cpp @@ -41,7 +41,7 @@ namespace swedish // language namespace {"unknown", "okänt"}, {"exploratory", "utforskande"}, {"Purple I2P Webconsole", "Purple I2P Webbkonsoll"}, - {"i2pd webbkonsoll", "i2pd-Webbkonsoll"}, + {"i2pd webconsole", "i2pd-Webbkonsoll"}, {"Main page", "Huvudsida"}, {"Router commands", "Routerkommandon"}, {"Local Destinations", "Lokala Platser"}, @@ -58,7 +58,6 @@ namespace swedish // language namespace {"Unknown", "Okänt"}, {"Proxy", "Proxy"}, {"Mesh", "Mesh"}, - {"Error", "Fel"}, {"Clock skew", "Tidsförskjutning"}, {"Offline", "Nedkopplad"}, {"Symmetric NAT", "Symmetrisk NAT"}, @@ -117,7 +116,6 @@ namespace swedish // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "EndDate"}, - {"not floodfill", "inte Översvämningsfyllare"}, {"Queue size", "Köstorlek"}, {"Run peer test", "Utför utsiktstest"}, {"Decline transit tunnels", "Avvisa förmedlande tunnlar"}, @@ -147,8 +145,8 @@ namespace swedish // language namespace {"Destination not found", "Plats hittades ej"}, {"StreamID can't be null", "Ström-ID kan inte vara null"}, {"Return to destination page", "Återvänd till platssidan"}, - {"You will be redirected in 5 seconds", "Du omdirigeras inom fem sekunder"}, - {"Transit tunnels count must not exceed 65535", "Förmedlande tunnlar får inte överstiga 65535"}, + {"You will be redirected in %d seconds", "Du omdirigeras inom %d sekunder"}, + {"Transit tunnels count must not exceed %d", "Förmedlande tunnlar får inte överstiga %d"}, {"Back to commands list", "Tillbaka till kommandolistan"}, {"Register at reg.i2p", "Registrera vid reg.i2p"}, {"Description", "Beskrivning"}, @@ -166,32 +164,25 @@ namespace swedish // language namespace {"You may try to find this host on jump services below", "Du kan försöka att hitta värden genom hopptjänsterna nedan"}, {"Invalid request", "Ogiltig förfrågan"}, {"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"}, - {"addresshelper is not supported", "adresshjälparen stöds ej"}, - {"Host", "Värd"}, - {"added to router's addressbook from helper", "tillagd i routerns adressbok från adresshjälparen"}, - {"Click here to proceed:", "Tryck här för att fortsätta:"}, - {"Continue", "Fortsätt"}, - {"Addresshelper found", "Adresshjälpare hittad"}, - {"already in router's addressbook", "finns redan i routerns adressbok"}, - {"Click here to update record:", "Tryck här för att uppdatera:"}, - {"invalid request uri", "ogiltig förfrågnings-URI"}, + {"Addresshelper is not supported", "Adresshjälparen stöds ej"}, + {"Invalid request URI", "Ogiltig förfrågnings-URI"}, {"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"}, {"Outproxy failure", "Utproxyfel"}, - {"bad outproxy settings", "ogiltig utproxyinställning"}, - {"not inside I2P network, but outproxy is not enabled", "adressen är inte inom I2P-näverket, men utproxy är inte påslaget"}, - {"unknown outproxy url", "okänt Utproxy-URL"}, - {"cannot resolve upstream proxy", "hittar inte uppströmsproxyt"}, - {"hostname too long", "värdnamnet är för långt"}, - {"cannot connect to upstream socks proxy", "kan inte ansluta till uppströmsproxyt"}, - {"Cannot negotiate with socks proxy", "Kan inte förhandla med socksproxyt"}, + {"Bad outproxy settings", "Ogiltig utproxyinställning"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Värd %s är inte inom I2P-näverket, men utproxy är inte påslaget"}, + {"Unknown outproxy URL", "okänt Utproxy-URL"}, + {"Cannot resolve upstream proxy", "Hittar inte uppströmsproxyt"}, + {"Hostname is too long", "Värdnamnet är för långt"}, + {"Cannot connect to upstream SOCKS proxy", "Kan inte ansluta till uppström SOCKS-proxy"}, + {"Cannot negotiate with SOCKS proxy", "Kan inte förhandla med SOCKSproxyt"}, {"CONNECT error", "CONNECT-fel"}, - {"Failed to Connect", "Anslutningen misslyckades"}, - {"socks proxy error", "Socksproxyfel"}, - {"failed to send request to upstream", "förfrågan uppströms kunde ej skickas"}, - {"No Reply From socks proxy", "Fick inget svar från socksproxyt"}, - {"cannot connect", "kan inte ansluta"}, - {"http out proxy not implemented", "HTTP-Utproxy ej implementerat"}, - {"cannot connect to upstream http proxy", "Kan inte ansluta till uppströms HTTP-proxy"}, + {"Failed to connect", "Anslutningen misslyckades"}, + {"SOCKS proxy error", "SOCKSproxyfel"}, + {"Failed to send request to upstream", "Förfrågan uppströms kunde ej skickas"}, + {"No reply from SOCKS proxy", "Fick inget svar från SOCKSproxyt"}, + {"Cannot connect", "Kan inte ansluta"}, + {"HTTP out proxy not implemented", "HTTP-Utproxy ej implementerat"}, + {"Cannot connect to upstream HTTP proxy", "Kan inte ansluta till uppströms HTTP-proxy"}, {"Host is down", "Värden är nere"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Kan inte ansluta till värden, den kan vara nere. Vänligen försök senare."}, {"", ""}, @@ -199,10 +190,10 @@ namespace swedish // language namespace static std::map> plurals { - {"%d days", {"%d Dag", "%d Dagar"}}, - {"%d hours", {"%d Timme", "%d Timmar"}}, - {"%d minutes", {"%d Minut", "%d Minuter"}}, - {"%d seconds", {"%d Sekund", "%d Sekunder"}}, + {"%d days", {"%d dag", "%d dagar"}}, + {"%d hours", {"%d timme", "%d timmar"}}, + {"%d minutes", {"%d minut", "%d minuter"}}, + {"%d seconds", {"%d sekund", "%d sekunder"}}, {"", {"", ""}}, }; diff --git a/i18n/Turkish.cpp b/i18n/Turkish.cpp new file mode 100644 index 00000000..d4398ebe --- /dev/null +++ b/i18n/Turkish.cpp @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Turkish localization file + +namespace i2p +{ +namespace i18n +{ +namespace turkish // language namespace +{ + // language name in lowercase + static std::string language = "turkish"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return n != 1 ? 1 : 0; + } + + static std::map strings + { + {"%.2f KiB", "%.2f KiB"}, + {"%.2f MiB", "%.2f MiB"}, + {"%.2f GiB", "%.2f GiB"}, + {"building", "kuruluyor"}, + {"failed", "başarısız"}, + {"expiring", "süresi geçiyor"}, + {"established", "kurulmuş"}, + {"unknown", "bilinmeyen"}, + {"Purple I2P Webconsole", "Mor I2P Webkonsolu"}, + {"i2pd webconsole", "i2pd webkonsolu"}, + {"Main page", "Ana sayfa"}, + {"Router commands", "Router komutları"}, + {"Local Destinations", "Yerel Hedefler"}, + {"Tunnels", "Tüneller"}, + {"Transit Tunnels", "Transit Tünelleri"}, + {"Transports", "Taşıma"}, + {"I2P tunnels", "I2P tünelleri"}, + {"SAM sessions", "SAM oturumları"}, + {"ERROR", "HATA"}, + {"OK", "TAMAM"}, + {"Testing", "Test ediliyor"}, + {"Firewalled", "Güvenlik Duvarı Kısıtlaması"}, + {"Unknown", "Bilinmeyen"}, + {"Proxy", "Proxy"}, + {"Clock skew", "Saat sorunu"}, + {"Offline", "Çevrimdışı"}, + {"Symmetric NAT", "Simetrik NAT"}, + {"Full cone NAT", "Full cone NAT"}, + {"No Descriptors", "Tanımlayıcı Yok"}, + {"Uptime", "Bağlantı süresi"}, + {"Network status", "Ağ durumu"}, + {"Network status v6", "Ağ durumu v6"}, + {"Family", "Aile"}, + {"Tunnel creation success rate", "Tünel oluşturma başarı oranı"}, + {"Received", "Alındı"}, + {"%.2f KiB/s", "%.2f KiB/s"}, + {"Sent", "Gönderildi"}, + {"Transit", "Transit"}, + {"Data path", "Veri yolu"}, + {"Hidden content. Press on text to see.", "Gizlenmiş içerik. Görmek için yazıya tıklayınız."}, + {"Router Family", "Router Familyası"}, + {"Decline transit tunnels", "Transit tünellerini reddet"}, + {"Accept transit tunnels", "Transit tünellerini kabul et"}, + {"Cancel graceful shutdown", "Düzgün durdurmayı iptal Et"}, + {"Start graceful shutdown", "Düzgün durdurmayı başlat"}, + {"Force shutdown", "Durdurmaya zorla"}, + {"Reload external CSS styles", "Harici CSS stilini yeniden yükle"}, + {"Note: any action done here are not persistent and not changes your config files.", "Not: burada yapılan ayarların hiçbiri kalıcı değildir ve ayar dosyalarınızı değiştirmez."}, + {"Logging level", "Kayıt tutma seviyesi"}, + {"Transit tunnels limit", "Transit tünel limiti"}, + {"Change", "Değiştir"}, + {"Change language", "Dil değiştir"}, + {"no transit tunnels currently built", "kurulmuş bir transit tüneli bulunmamakta"}, + {"SAM disabled", "SAM devre dışı"}, + {"no sessions currently running", "hiçbir oturum şu anda çalışmıyor"}, + {"SAM session not found", "SAM oturumu bulunamadı"}, + {"SAM Session", "SAM oturumu"}, + {"Server Tunnels", "Sunucu Tünelleri"}, + {"Unknown page", "Bilinmeyen sayfa"}, + {"Invalid token", "Geçersiz token"}, + {"SUCCESS", "BAŞARILI"}, + {"", ""}, + }; + + static std::map> plurals + { + {"%d days", {"%d gün", "%d gün"}}, + {"%d hours", {"%d saat", "%d saat"}}, + {"%d minutes", {"%d dakika", "%d dakika"}}, + {"%d seconds", {"%d saniye", "%d saniye"}}, + {"", {"", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/Turkmen.cpp b/i18n/Turkmen.cpp index 7e7a24f0..35ee0f89 100644 --- a/i18n/Turkmen.cpp +++ b/i18n/Turkmen.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,6 +40,7 @@ namespace turkmen // language namespace {"established", "işleýär"}, {"unknown", "näbelli"}, {"exploratory", "gözleg"}, + {"Purple I2P Webconsole", "Web konsoly Purple I2P"}, {"i2pd webconsole", "Web konsoly i2pd"}, {"Main page", "Esasy sahypa"}, {"Router commands", "Marşrutizator buýruklary"}, @@ -57,7 +58,6 @@ namespace turkmen // language namespace {"Unknown", "Näbelli"}, {"Proxy", "Proksi"}, {"Mesh", "MESH-tor"}, - {"Error", "Ýalňyşlyk"}, {"Clock skew", "Takyk wagt däl"}, {"Offline", "Awtonom"}, {"Symmetric NAT", "Simmetriklik NAT"}, @@ -116,7 +116,6 @@ namespace turkmen // language namespace {"Gateway", "Derweze"}, {"TunnelID", "Tuneliň ID"}, {"EndDate", "Gutarýar"}, - {"not floodfill", "fludfil däl"}, {"Queue size", "Nobatyň ululygy"}, {"Run peer test", "Synag başlaň"}, {"Decline transit tunnels", "Tranzit tunellerini ret ediň"}, @@ -146,8 +145,6 @@ namespace turkmen // language namespace {"Destination not found", "Niýetlenen ýeri tapylmady"}, {"StreamID can't be null", "StreamID boş bolup bilmez"}, {"Return to destination page", "Barmaly nokadynyň nokadyna gaýdyp geliň"}, - {"You will be redirected in 5 seconds", "5 sekuntdan soň täzeden ugrukdyrylarsyňyz"}, - {"Transit tunnels count must not exceed 65535", "Tranzit tagtalaryň sany 65535-den geçmeli däldir"}, {"Back to commands list", "Topar sanawyna dolan"}, {"Register at reg.i2p", "Reg.i2P-de hasaba duruň"}, {"Description", "Beýany"}, @@ -165,32 +162,24 @@ namespace turkmen // language namespace {"You may try to find this host on jump services below", "Aşakdaky böküş hyzmatlarynda bu öý eýesini tapmaga synanyşyp bilersiňiz"}, {"Invalid request", "Nädogry haýyş"}, {"Proxy unable to parse your request", "Proksi haýyşyňyzy derňäp bilmeýär"}, - {"addresshelper is not supported", "Salgylandyryjy goldanok"}, - {"Host", "Adres"}, - {"added to router's addressbook from helper", "marşruteriň adresini kömekçiden goşdy"}, - {"Click here to proceed:", "Dowam etmek bu ýerde basyň:"}, - {"Continue", "Dowam et"}, - {"Addresshelper found", "Forgelper tapyldy"}, - {"already in router's addressbook", "marşruteriň adres kitaby"}, - {"Click here to update record:", "Recordazgyny täzelemek üçin bu ýerde basyň:"}, - {"invalid request uri", "nädogry haýyş URI"}, + {"Invalid request URI", "Nädogry haýyş URI"}, {"Can't detect destination host from request", "Haýyşdan barmaly ýerini tapyp bilemok"}, {"Outproxy failure", "Daşarky proksi ýalňyşlyk"}, - {"bad outproxy settings", "daşarky daşarky proksi sazlamalary nädogry"}, - {"not inside I2P network, but outproxy is not enabled", "I2P torunda däl, ýöne daşarky proksi goşulmaýar"}, - {"unknown outproxy url", "näbelli daşarky proksi URL"}, - {"cannot resolve upstream proxy", "has ýokary proksi kesgitläp bilmeýär"}, - {"hostname too long", "hoster eýesi ady gaty uzyn"}, - {"cannot connect to upstream socks proxy", "ýokary jorap SOCKS proksi bilen birigip bolmaýar"}, - {"Cannot negotiate with socks proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"}, + {"Bad outproxy settings", "Daşarky Daşarky proksi sazlamalary nädogry"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Adres %s I2P torunda däl, ýöne daşarky proksi goşulmaýar"}, + {"Unknown outproxy URL", "Näbelli daşarky proksi URL"}, + {"Cannot resolve upstream proxy", "Has ýokary proksi kesgitläp bilmeýär"}, + {"Hostname is too long", "Hoster eýesi ady gaty uzyn"}, + {"Cannot connect to upstream SOCKS proxy", "Ýokary jorap SOCKS proksi bilen birigip bolmaýar"}, + {"Cannot negotiate with SOCKS proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"}, {"CONNECT error", "Bagyr haýyşy säwligi"}, - {"Failed to Connect", "Birikdirip bilmedi"}, - {"socks proxy error", "socks proksi ýalňyşlygy"}, - {"failed to send request to upstream", "öý eýesi proksi üçin haýyş iberip bilmedi"}, - {"No Reply From socks proxy", "Jorap proksi serwerinden hiç hili jogap ýok"}, - {"cannot connect", "birikdirip bilmedi"}, - {"http out proxy not implemented", "daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"}, - {"cannot connect to upstream http proxy", "ýokary akym HTTP proksi serwerine birigip bilmedi"}, + {"Failed to connect", "Birikdirip bilmedi"}, + {"SOCKS proxy error", "SOCKS proksi ýalňyşlygy"}, + {"Failed to send request to upstream", "Öý eýesi proksi üçin haýyş iberip bilmedi"}, + {"No reply from SOCKS proxy", "Jorap SOCKS proksi serwerinden hiç hili jogap ýok"}, + {"Cannot connect", "Birikdirip bilmedi"}, + {"HTTP out proxy not implemented", "Daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"}, + {"Cannot connect to upstream HTTP proxy", "Ýokary jorap HTTP proksi bilen birigip bolmaýar"}, {"Host is down", "Salgy elýeterli däl"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Talap edilýän salgyda birikmäni gurup bilmedim, onlaýn bolup bilmez. Soňra haýyşy soň gaýtalamaga synanyşyň."}, {"", ""}, diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index 991f46ab..c1e222ea 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,6 +40,7 @@ namespace ukrainian // language namespace {"established", "працює"}, {"unknown", "невідомо"}, {"exploratory", "дослідницький"}, + {"Purple I2P Webconsole", "Веб-консоль Purple I2P"}, {"i2pd webconsole", "Веб-консоль i2pd"}, {"Main page", "Головна"}, {"Router commands", "Команди маршрутизатора"}, @@ -57,10 +58,11 @@ namespace ukrainian // language namespace {"Unknown", "Невідомо"}, {"Proxy", "Проксі"}, {"Mesh", "MESH-мережа"}, - {"Error", "Помилка"}, {"Clock skew", "Неточний час"}, {"Offline", "Офлайн"}, {"Symmetric NAT", "Симетричний NAT"}, + {"Full cone NAT", "Повний NAT"}, + {"No Descriptors", "Немає Описів"}, {"Uptime", "У мережі"}, {"Network status", "Мережевий статус"}, {"Network status v6", "Мережевий статус v6"}, @@ -116,9 +118,10 @@ namespace ukrainian // language namespace {"Gateway", "Шлюз"}, {"TunnelID", "ID тунеля"}, {"EndDate", "Закінчується"}, - {"not floodfill", "не флудфіл"}, + {"floodfill mode is disabled", "режим floodfill вимкнено"}, {"Queue size", "Розмір черги"}, {"Run peer test", "Запустити тестування"}, + {"Reload tunnels configuration", "Перезавантажити налаштування тунелів"}, {"Decline transit tunnels", "Відхиляти транзитні тунелі"}, {"Accept transit tunnels", "Ухвалювати транзитні тунелі"}, {"Cancel graceful shutdown", "Скасувати плавну зупинку"}, @@ -146,8 +149,8 @@ namespace ukrainian // language namespace {"Destination not found", "Точка призначення не знайдена"}, {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, {"Return to destination page", "Повернутися на сторінку точки призначення"}, - {"You will be redirected in 5 seconds", "Ви будете переадресовані через 5 секунд"}, - {"Transit tunnels count must not exceed 65535", "Кількість транзитних тунелів не повинна перевищувати 65535"}, + {"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"}, + {"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"}, {"Back to commands list", "Повернутися до списку команд"}, {"Register at reg.i2p", "Зареєструвати на reg.i2p"}, {"Description", "Опис"}, @@ -165,32 +168,33 @@ namespace ukrainian // language namespace {"You may try to find this host on jump services below", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"}, {"Invalid request", "Некоректний запит"}, {"Proxy unable to parse your request", "Проксі не може розібрати ваш запит"}, - {"addresshelper is not supported", "addresshelper не підтримується"}, - {"Host", "Адреса"}, - {"added to router's addressbook from helper", "доданий в адресну книгу маршрутизатора через хелпер"}, - {"Click here to proceed:", "Натисніть тут щоб продовжити:"}, - {"Continue", "Продовжити"}, - {"Addresshelper found", "Знайдено addresshelper"}, - {"already in router's addressbook", "вже в адресній книзі маршрутизатора"}, - {"Click here to update record:", "Натисніть тут щоб оновити запис:"}, - {"invalid request uri", "некоректний URI запиту"}, + {"Addresshelper is not supported", "Адресна книга не підтримується"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "Хост %s вже в адресній книзі маршрутизатора. Будьте обережні: джерело цієї адреси може зашкодити! Натисніть тут, щоб оновити запис: Продовжити."}, + {"Addresshelper forced update rejected", "Адресна книга відхилила примусове оновлення"}, + {"To add host %s in router's addressbook, click here: Continue.", "Щоб додати хост %s в адресі маршрутизатора, натисніть тут: Продовжити."}, + {"Addresshelper request", "Запит на адресну сторінку"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Хост %s доданий в адресну книгу маршрутизатора від помічника. Натисніть тут, щоб продовжити: Продовжити."}, + {"Addresshelper adding", "Адреса додана"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "Хост %s вже в адресній книзі маршрутизатора. Натисніть тут, щоб оновити запис: Продовжити."}, + {"Addresshelper update", "Оновлення адресної книги"}, + {"Invalid request URI", "Некоректний URI запиту"}, {"Can't detect destination host from request", "Не вдалось визначити адресу призначення з запиту"}, {"Outproxy failure", "Помилка зовнішнього проксі"}, - {"bad outproxy settings", "некоректні налаштування зовнішнього проксі"}, - {"not inside I2P network, but outproxy is not enabled", "не в I2P мережі, але зовнішній проксі не включений"}, - {"unknown outproxy url", "невідомий URL зовнішнього проксі"}, - {"cannot resolve upstream proxy", "не вдається визначити висхідний проксі"}, - {"hostname too long", "ім'я вузла надто довге"}, - {"cannot connect to upstream socks proxy", "не вдається підключитися до висхідного SOCKS проксі"}, - {"Cannot negotiate with socks proxy", "Не вдається домовитися з висхідним SOCKS проксі"}, + {"Bad outproxy settings", "Некоректні налаштування зовнішнього проксі"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Адрес %s не в I2P мережі, але зовнішній проксі не включений"}, + {"Unknown outproxy URL", "Невідомий URL зовнішнього проксі"}, + {"Cannot resolve upstream proxy", "Не вдається визначити висхідний проксі"}, + {"Hostname is too long", "Ім'я вузла надто довге"}, + {"Cannot connect to upstream SOCKS proxy", "Не вдалося підключитися до висхідного SOCKS проксі сервера"}, + {"Cannot negotiate with SOCKS proxy", "Не вдається домовитися з висхідним SOCKS проксі"}, {"CONNECT error", "Помилка CONNECT запиту"}, - {"Failed to Connect", "Не вдалося підключитися"}, - {"socks proxy error", "помилка SOCKS проксі"}, - {"failed to send request to upstream", "не вдалося відправити запит висхідному проксі"}, - {"No Reply From socks proxy", "Немає відповіді від SOCKS проксі сервера"}, - {"cannot connect", "не вдалося підключитися"}, - {"http out proxy not implemented", "підтримка зовнішнього HTTP проксі сервера не реалізована"}, - {"cannot connect to upstream http proxy", "не вдалося підключитися до висхідного HTTP проксі сервера"}, + {"Failed to connect", "Не вдалося підключитися"}, + {"SOCKS proxy error", "Помилка SOCKS проксі"}, + {"Failed to send request to upstream", "Не вдалося відправити запит висхідному проксі"}, + {"No reply from SOCKS proxy", "Немає відповіді від SOCKS проксі сервера"}, + {"Cannot connect", "Не вдалося підключитися"}, + {"HTTP out proxy not implemented", "Підтримка зовнішнього HTTP проксі сервера не реалізована"}, + {"Cannot connect to upstream HTTP proxy", "Не вдалося підключитися до висхідного HTTP проксі сервера"}, {"Host is down", "Вузол недоступний"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."}, {"", ""}, diff --git a/i18n/Uzbek.cpp b/i18n/Uzbek.cpp index 7355471b..9d798be4 100644 --- a/i18n/Uzbek.cpp +++ b/i18n/Uzbek.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022, The PurpleI2P Project +* Copyright (c) 2021-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -40,6 +40,7 @@ namespace uzbek // language namespace {"established", "aloqa o'rnatildi"}, {"unknown", "noma'lum"}, {"exploratory", "tadqiqiy"}, + {"Purple I2P Webconsole", "Veb-konsoli Purple I2P"}, {"i2pd webconsole", "i2pd veb-konsoli"}, {"Main page", "Asosiy sahifa"}, {"Router commands", "Router buyruqlari"}, @@ -57,10 +58,11 @@ namespace uzbek // language namespace {"Unknown", "Notanish"}, {"Proxy", "Proksi"}, {"Mesh", "Mesh To'r"}, - {"Error", "Xato"}, {"Clock skew", "Aniq vaqt emas"}, {"Offline", "Oflayn"}, {"Symmetric NAT", "Simmetrik NAT"}, + {"Full cone NAT", "Full cone NAT"}, + {"No Descriptors", "Deskriptorlar yo'q"}, {"Uptime", "Ish vaqti"}, {"Network status", "Tarmoq holati"}, {"Network status v6", "Tarmoq holati v6"}, @@ -116,9 +118,10 @@ namespace uzbek // language namespace {"Gateway", "Kirish yo'li"}, {"TunnelID", "TunnelID"}, {"EndDate", "Tugash Sanasi"}, - {"not floodfill", "floodfill emas"}, + {"floodfill mode is disabled", "floodfill rejimi o'chirilgan"}, {"Queue size", "Navbat hajmi"}, {"Run peer test", "Sinovni boshlang"}, + {"Reload tunnels configuration", "Tunnel konfiguratsiyasini qayta yuklash"}, {"Decline transit tunnels", "Tranzit tunnellarini rad etish"}, {"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"}, {"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"}, @@ -146,8 +149,8 @@ namespace uzbek // language namespace {"Destination not found", "Yo'nalish topilmadi"}, {"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"}, {"Return to destination page", "Manzilgoh sahifasiga qaytish"}, - {"You will be redirected in 5 seconds", "Siz 5 soniya ichida qayta yo'naltirilasiz"}, - {"Transit tunnels count must not exceed 65535", "Tranzit tunnellar soni 65535 dan oshmasligi kerak"}, + {"You will be redirected in %d seconds", "Siz %d soniyadan so‘ng boshqa yo‘nalishga yo‘naltirilasiz"}, + {"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"}, {"Back to commands list", "Buyruqlar ro'yxatiga qaytish"}, {"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"}, {"Description", "Tavsif"}, @@ -165,32 +168,33 @@ namespace uzbek // language namespace {"You may try to find this host on jump services below", "Siz xost quyida o'tish xizmatlari orqali topishga harakat qilishingiz mumkin"}, {"Invalid request", "Noto‘g‘ri so‘rov"}, {"Proxy unable to parse your request", "Proksi sizning so'rovingizni aniqlab ololmayapti"}, - {"addresshelper is not supported", "addresshelper qo'llab -quvvatlanmaydi"}, - {"Host", "Xost"}, - {"added to router's addressbook from helper", "'helper'dan routerning 'addressbook'ga qo'shildi"}, - {"Click here to proceed:", "Davom etish uchun shu yerni bosing:"}, - {"Continue", "Davom etish"}, - {"Addresshelper found", "Addresshelper topildi"}, - {"already in router's addressbook", "allaqachon 'addressbook'da yozilgan"}, - {"Click here to update record:", "Yozuvni yangilash uchun shu yerni bosing:"}, - {"invalid request uri", "noto'g'ri URI so'rovi"}, + {"Addresshelper is not supported", "Addresshelper qo'llab-quvvatlanmaydi"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "%s xosti allaqachon routerning manzillar kitobida. Ehtiyot bo'ling: bu URL manbasi zararli bo'lishi mumkin! Yozuvni yangilash uchun bu yerni bosing: Davom etish."}, + {"Addresshelper forced update rejected", "Addresshelperni majburiy yangilash rad etildi"}, + {"To add host %s in router's addressbook, click here: Continue.", "Routerning manzillar kitobiga %s xostini qo'shish uchun bu yerni bosing: Davom etish."}, + {"Addresshelper request", "Addresshelper so'rovi"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Yordamchidan router manzillar kitobiga %s xost qo‘shildi. Davom etish uchun bu yerga bosing: Davom etish."}, + {"Addresshelper adding", "Addresshelperni qo'shish"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "%s xosti allaqachon routerning manzillar kitobida. Yozuvni yangilash uchun shu yerni bosing: Davom etish."}, + {"Addresshelper update", "Addresshelperni yangilash"}, + {"Invalid request URI", "Noto'g'ri URI so'rovi"}, {"Can't detect destination host from request", "So‘rov orqali manzil xostini aniqlab bo'lmayapti"}, {"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"}, - {"bad outproxy settings", "noto'g'ri tashqi proksi-server sozlamalari"}, - {"not inside I2P network, but outproxy is not enabled", "I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"}, - {"unknown outproxy url", "noma'lum outproxy url"}, - {"cannot resolve upstream proxy", "yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"}, - {"hostname too long", "xost nomi juda uzun"}, - {"cannot connect to upstream socks proxy", "yuqori 'socks proxy'ga ulanib bo'lmayapti"}, - {"Cannot negotiate with socks proxy", "'Socks proxy' bilan muzokara olib bo'lmaydi"}, + {"Bad outproxy settings", "Noto'g'ri tashqi proksi-server sozlamalari"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "Xost %s I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"}, + {"Unknown outproxy URL", "Noma'lum outproxy URL"}, + {"Cannot resolve upstream proxy", "Yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"}, + {"Hostname is too long", "Xost nomi juda uzun"}, + {"Cannot connect to upstream SOCKS proxy", "Yuqori 'SOCKS proxy'ga ulanib bo'lmayapti"}, + {"Cannot negotiate with SOCKS proxy", "'SOCKS proxy' bilan muzokara olib bo'lmaydi"}, {"CONNECT error", "CONNECT xatosi"}, - {"Failed to Connect", "Ulanib bo'lmayapti"}, - {"socks proxy error", "'socks proxy' xatosi"}, - {"failed to send request to upstream", "yuqori http proksi-serveriga so'rovni uborib bo'lmadi"}, - {"No Reply From socks proxy", "'Socks proxy'dan javob yo'q"}, - {"cannot connect", "ulanib bo'lmaydi"}, - {"http out proxy not implemented", "tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"}, - {"cannot connect to upstream http proxy", "yuqori http 'proxy-server'iga ulanib bo'lmayapti"}, + {"Failed to connect", "Ulanib bo'lmayapti"}, + {"SOCKS proxy error", "'SOCKS proxy' xatosi"}, + {"Failed to send request to upstream", "Yuqori proksi-serveriga so'rovni uborib bo'lmadi"}, + {"No reply from SOCKS proxy", "'SOCKS proxy'dan javob yo'q"}, + {"Cannot connect", "Ulanib bo'lmaydi"}, + {"HTTP out proxy not implemented", "Tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"}, + {"Cannot connect to upstream HTTP proxy", "Yuqori 'HTTP proxy'ga ulanib bo'lmayapti"}, {"Host is down", "Xost ishlamayapti"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."}, {"", ""}, From 1da9e2e1c0d3b6e95f576f933509126e129cb1b1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 15 Feb 2023 21:59:06 +0000 Subject: [PATCH 165/179] 2.46.0 Signed-off-by: R4SAS --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4606a69b..1ef24b13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ ## [2.46.0] - 2023-02-15 ### Added - Limit number of acked SSU2 packets to 511 -- Localization to Swedish +- Localization to Swedish, Portuguese, Turkish, Polish - Periodically send Datetime block in NTCP2 and SSU2 - Don't select random port from reserved - In memory table for peer profiles From b8590075e6d341e6a9f5882e3eed2201ee08405c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Feb 2023 22:14:02 -0500 Subject: [PATCH 166/179] initial commit for Kademlia DHT --- libi2pd/KadDHT.cpp | 238 +++++++++++++++++++++++++++++++++++++++++++++ libi2pd/KadDHT.h | 64 ++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 libi2pd/KadDHT.cpp create mode 100644 libi2pd/KadDHT.h diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp new file mode 100644 index 00000000..29664f79 --- /dev/null +++ b/libi2pd/KadDHT.cpp @@ -0,0 +1,238 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#include "KadDHT.h" + +namespace i2p +{ +namespace data +{ + DHTNode::DHTNode (): + zero (nullptr), one (nullptr), hash (nullptr) + { + } + + DHTNode::~DHTNode () + { + if (zero) delete zero; + if (one) delete one; + if (hash) delete hash; + } + + void DHTNode::MoveHashUp (bool fromOne) + { + DHTNode *& side = fromOne ? one : zero; + if (side) + { + if (hash) delete hash; // shouldn't happen + hash = side->hash; + side->hash = nullptr; + delete side; + side = nullptr; + } + } + + DHTTable::DHTTable (): + m_Size (0) + { + m_Root = new DHTNode; + } + + DHTTable::~DHTTable () + { + delete m_Root; + } + + DHTNode * DHTTable::Insert (const IdentHash& h) + { + return Insert (new IdentHash (h), m_Root, 0); + } + + DHTNode * DHTTable::Insert (IdentHash * h, DHTNode * root, int level) + { + if (root->hash) + { + if (*(root->hash) == *h) + { + delete h; + return root; + } + auto h2 = root->hash; + root->hash = nullptr; m_Size--; + int bit1, bit2; + do + { + bit1 = h->GetBit (level); + bit2 = h2->GetBit (level); + if (bit1 == bit2) + { + if (bit1) + { + if (root->one) return nullptr; // someting wrong + root->one = new DHTNode; + root = root->one; + } + else + { + if (root->zero) return nullptr; // someting wrong + root->zero = new DHTNode; + root = root->zero; + } + level++; + } + } + while (bit1 == bit2); + + if (!root->zero) + root->zero = new DHTNode; + if (!root->one) + root->one = new DHTNode; + if (bit1) + { + Insert (h2, root->zero, level + 1); + return Insert (h, root->one, level + 1); + } + else + { + Insert (h2, root->one, level + 1); + return Insert (h, root->zero, level + 1); + } + } + else + { + if (!root->zero && !root->one) + { + root->hash = h; m_Size++; + return root; + } + int bit = h->GetBit (level); + if (bit) + { + if (!root->one) + root->one = new DHTNode; + return Insert (h, root->one, level + 1); + } + else + { + if (!root->zero) + root->zero = new DHTNode; + return Insert (h, root->zero, level + 1); + } + } + return nullptr; + } + + bool DHTTable::Remove (const IdentHash& h) + { + return Remove (h, m_Root, 0); + } + + bool DHTTable::Remove (const IdentHash& h, DHTNode * root, int level) + { + if (root) + { + if (root->hash && *(root->hash) == h) + { + delete root->hash; root->hash = nullptr; + m_Size--; + return true; + } + int bit = h.GetBit (level); + if (bit) + { + if (root->one && Remove (h, root->one, level + 1)) + { + if (root->one->IsEmpty ()) + { + delete root->one; + root->one = nullptr; + if (root->zero && root->zero->hash) + root->MoveHashUp (false); + } + else if (root->one->hash && !root->zero) + root->MoveHashUp (true); + return true; + } + } + else + { + if (root->zero && Remove (h, root->zero, level + 1)) + { + if (root->zero->IsEmpty ()) + { + delete root->zero; + root->zero = nullptr; + if (root->one && root->one->hash) + root->MoveHashUp (true); + } + else if (root->zero->hash && !root->one) + root->MoveHashUp (false); + return true; + } + } + } + return false; + } + + IdentHash * DHTTable::FindClosest (const IdentHash& h) + { + return FindClosest (h, m_Root, 0); + } + + IdentHash * DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) + { + if (root->hash) return root->hash; + int bit = h.GetBit (level); + if (bit) + { + if (root->one) + return FindClosest (h, root->one, level + 1); + if (root->zero) + return FindClosest (h, root->zero, level + 1); + } + else + { + if (root->zero) + return FindClosest (h, root->zero, level + 1); + if (root->one) + return FindClosest (h, root->one, level + 1); + } + return nullptr; + } + + void DHTTable::Print (std::stringstream& s) + { + Print (s, m_Root, 0); + } + + void DHTTable::Print (std::stringstream& s, DHTNode * root, int level) + { + if (!root) return; + s << std::string (level, '-'); + if (root->hash) + { + if (!root->zero && !root->one) + s << '>' << GetIdentHashAbbreviation (*(root->hash)); + else + s << "error"; + } + s << std::endl; + if (root->zero) + { + s << std::string (level, '-') << "0" << std::endl; + Print (s, root->zero, level + 1); + } + if (root->one) + { + s << std::string (level, '-') << "1" << std::endl; + Print (s, root->one, level + 1); + } + } +} +} diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h new file mode 100644 index 00000000..4a1b61b6 --- /dev/null +++ b/libi2pd/KadDHT.h @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#ifndef KADDHT_H__ +#define KADDHT_H__ + +#include +#include +#include "Identity.h" + +// Kademlia DHT (XOR distance) + +namespace i2p +{ +namespace data +{ + struct DHTNode + { + DHTNode * zero, * one; + IdentHash * hash; + + DHTNode (); + ~DHTNode (); + + bool IsEmpty () const { return !zero && !one && !hash; }; + void MoveHashUp (bool fromOne); + }; + + class DHTTable + { + public: + + DHTTable (); + ~DHTTable (); + + DHTNode * Insert (const IdentHash& h); + bool Remove (const IdentHash& h); + IdentHash * FindClosest (const IdentHash& h); + + void Print (std::stringstream& s); + size_t GetSize () const { return m_Size; }; + + private: + + DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive + bool Remove (const IdentHash& h, DHTNode * root, int level); + IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); + void Print (std::stringstream& s, DHTNode * root, int level); + + private: + + DHTNode * m_Root; + size_t m_Size; + }; +} +} + +#endif From bff12b06f417938168951ac7df429d61ebaf462d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 10:34:14 -0500 Subject: [PATCH 167/179] fixed race condition --- libi2pd/RouterInfo.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index afa8cbe0..f33e4198 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -945,9 +945,13 @@ namespace data std::shared_ptr RouterInfo::GetProfile () const { - if (!m_Profile) - m_Profile = GetRouterProfile (GetIdentHash ()); - return m_Profile; + auto profile = m_Profile; + if (!profile) + { + profile = GetRouterProfile (GetIdentHash ()); + m_Profile = profile; + } + return profile; } void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted) const From 289c3086003eaf624e1e42bcbe0bc0901f015bb7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 20:08:05 -0500 Subject: [PATCH 168/179] set proper caps if host is unspecified --- libi2pd/RouterInfo.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index f33e4198..3fb95814 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -661,11 +661,16 @@ namespace data addr->host = host; addr->port = port; addr->transportStyle = eTransportNTCP2; - addr->caps = 0; addr->date = 0; addr->published = true; memcpy (addr->s, staticKey, 32); memcpy (addr->i, iv, 16); + addr->caps = 0; + if (host.is_unspecified ()) + { + if (host.is_v4 ()) addr->caps |= eV4; + if (host.is_v6 ()) addr->caps |= eV6; + } if (addr->IsV4 ()) { m_SupportedTransports |= eNTCP2V4; @@ -737,12 +742,19 @@ namespace data addr->host = host; addr->port = port; addr->published = true; - addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; addr->date = 0; addr->ssu.reset (new SSUExt ()); addr->ssu->mtu = 0; memcpy (addr->s, staticKey, 32); memcpy (addr->i, introKey, 32); + if (!host.is_unspecified ()) + addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; + else + { + addr->caps = 0; + if (host.is_v4 ()) addr->caps |= eV4; + if (host.is_v6 ()) addr->caps |= eV6; + } if (addr->IsV4 ()) { m_SupportedTransports |= eSSU2V4; From e190dab7d69d48ee0bfcc9358fd8489bb81e021a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 21:13:50 -0500 Subject: [PATCH 169/179] fixed crash when shows leasesets --- daemon/HTTPServer.cpp | 5 ++++- libi2pd/LeaseSet.cpp | 4 ++-- libi2pd/LeaseSet.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index f78057b3..e42efb36 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -625,7 +625,10 @@ namespace http { if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); else - ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + { + ls.reset (new i2p::data::LeaseSet2 (storeType)); + ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false); + } if (!ls) return; s << "
IsExpired()) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d23fdcb8..8ccfa771 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -315,7 +315,7 @@ namespace data { // standard LS2 header std::shared_ptr identity; - if (readIdentity) + if (readIdentity || !GetIdentity ()) { identity = std::make_shared(buf, len); SetIdentity (identity); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index a79a5870..566c4655 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -145,6 +145,7 @@ namespace data { public: + LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only uint8_t GetStoreType () const { return m_StoreType; }; From ce05cce33131be6fcf7f317412bedd7a2d77cb35 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Feb 2023 08:54:36 -0500 Subject: [PATCH 170/179] validate LeaseSet if signature verification was not requested --- libi2pd/LeaseSet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 8ccfa771..4d756bdb 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -366,6 +366,8 @@ namespace data VerifySignature (identity, buf, len, offset); SetIsValid (verified); } + else + SetIsValid (true); offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen (); if (offset > len) { LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len)); From eaca435a5bd65e40bc0415a7b227bef4fda56fa7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Feb 2023 19:45:31 -0500 Subject: [PATCH 171/179] find multiple closest hashes --- libi2pd/KadDHT.cpp | 33 +++++++++++++++++++++++++++++++++ libi2pd/KadDHT.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index 29664f79..c3905b7a 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -205,6 +205,39 @@ namespace data } return nullptr; } + + std::vector DHTTable::FindClosest (const IdentHash& h, size_t num) + { + std::vector vec; + if (num > 0) + FindClosest (h, num, m_Root, 0, vec); + return vec; + } + + void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes) + { + if (hashes.size () >= num) return; + if (root->hash) + { + hashes.push_back (root->hash); + return; + } + int bit = h.GetBit (level); + if (bit) + { + if (root->one) + FindClosest (h, num, root->one, level + 1, hashes); + if (hashes.size () < num && root->zero) + FindClosest (h, num, root->zero, level + 1, hashes); + } + else + { + if (root->zero) + FindClosest (h, num, root->zero, level + 1, hashes); + if (hashes.size () < num && root->one) + FindClosest (h, num, root->one, level + 1, hashes); + } + } void DHTTable::Print (std::stringstream& s) { diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h index 4a1b61b6..eb12aae7 100644 --- a/libi2pd/KadDHT.h +++ b/libi2pd/KadDHT.h @@ -11,6 +11,7 @@ #define KADDHT_H__ #include +#include #include #include "Identity.h" @@ -42,6 +43,7 @@ namespace data DHTNode * Insert (const IdentHash& h); bool Remove (const IdentHash& h); IdentHash * FindClosest (const IdentHash& h); + std::vector FindClosest (const IdentHash& h, size_t num); void Print (std::stringstream& s); size_t GetSize () const { return m_Size; }; @@ -51,6 +53,7 @@ namespace data DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive bool Remove (const IdentHash& h, DHTNode * root, int level); IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); + void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes); void Print (std::stringstream& s, DHTNode * root, int level); private: From b8a99878b67e93d642a11108a290fe49b10c06cc Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 19 Feb 2023 10:30:07 -0500 Subject: [PATCH 172/179] don't create profile for every new non-floodfill --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 34ad5efc..5bc9c47e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -315,7 +315,7 @@ namespace data else { r = std::make_shared (buf, len); - if (!r->IsUnreachable () && r->HasValidAddresses () && !r->GetProfile ()->IsUnreachable () && + if (!r->IsUnreachable () && r->HasValidAddresses () && (!r->IsFloodfill () || !r->GetProfile ()->IsUnreachable ()) && i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) { bool inserted = false; @@ -1398,7 +1398,7 @@ namespace data std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) { - if (!it->IsUnreachable ()) + if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ()) { XORMetric m = destKey ^ it->GetIdentHash (); if (closeThanUsOnly && ourMetric < m) continue; From 82ac0aa492f400dfd5a2071c97b8d85e5db010e3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 20 Feb 2023 05:49:59 +0300 Subject: [PATCH 173/179] 2.46.1 Signed-off-by: R4SAS --- ChangeLog | 6 ++++++ contrib/i2pd.conf | 3 ++- contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 2 +- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ef24b13..a361e198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.46.1] - 2023-02-20 +### Fixed +- Race condition while getting router's peer profile +- Creation of new router.info +- Displaying floodfills in the webconsole + ## [2.46.0] - 2023-02-15 ### Added - Limit number of acked SSU2 packets to 511 diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index c8baa046..84d00347 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -129,7 +129,8 @@ port = 7070 # pass = changeme ## Select webconsole language ## Currently supported english (default), afrikaans, armenian, chinese, czech, french, -## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages +## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian +## and uzbek languages # lang = english [httpproxy] diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index e902d1fd..e758d42b 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.46.0 +Version: 2.46.1 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 20 2023 r4sas - 2.46.1 +- update to 2.46.1 + * Wed Feb 15 2023 orignal - 2.46.0 - update to 2.46.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5ddd8727..6f413e52 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.46.0 +Version: 2.46.1 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 20 2023 r4sas - 2.46.1 +- update to 2.46.1 + * Wed Feb 15 2023 orignal - 2.46.0 - update to 2.46.0 diff --git a/debian/changelog b/debian/changelog index 91d8f1dc..f13587c6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.46.1-1) unstable; urgency=high + + * updated to version 2.46.1/0.9.57 + + -- r4sas Mon, 20 Feb 2023 02:45:00 +0000 + i2pd (2.46.0-1) unstable; urgency=high * updated to version 2.46.0/0.9.57 diff --git a/libi2pd/version.h b/libi2pd/version.h index e1206d21..b7de21a8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -17,7 +17,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 46 -#define I2PD_VERSION_MICRO 0 +#define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION GITVER From 200ad5524de253b3739edcedfdc9364fc9070dbe Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 20 Feb 2023 02:57:56 +0000 Subject: [PATCH 174/179] 2.46.1 Signed-off-by: R4SAS --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a361e198..870f2cc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ ### Fixed - Race condition while getting router's peer profile - Creation of new router.info -- Displaying floodfills in the webconsole +- Displaying LeaseSets in the webconsole ## [2.46.0] - 2023-02-15 ### Added From 3adff82d4a3ee40f854615d850955e7ce3f6f091 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Feb 2023 14:55:59 -0500 Subject: [PATCH 175/179] don't handle ack request for router --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index e240e925..7f9fb72d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -335,7 +335,8 @@ namespace garlic case eECIESx25519BlkAckRequest: { LogPrint (eLogDebug, "Garlic: Ack request"); - m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); + if (receiveTagset) + m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); break; } case eECIESx25519BlkTermination: From ebee6c5f1353f71ce3d325f08c29d07783cdc44d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 21 Feb 2023 05:53:51 +0300 Subject: [PATCH 176/179] 2.46.1-1 Signed-off-by: R4SAS --- ChangeLog | 1 + contrib/rpm/i2pd.spec | 2 +- debian/changelog | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 870f2cc9..385a3545 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ - Race condition while getting router's peer profile - Creation of new router.info - Displaying LeaseSets in the webconsole +- Crash when processing ACK request ## [2.46.0] - 2023-02-15 ### Added diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 6f413e52..32154a9c 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.46.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git diff --git a/debian/changelog b/debian/changelog index f13587c6..13691601 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.46.1-2) unstable; urgency=critical + + * re-pushed release due to new critical bug + + -- r4sas Mon, 20 Feb 2023 23:40:00 +0000 + i2pd (2.46.1-1) unstable; urgency=high * updated to version 2.46.1/0.9.57 From abf687ff095671a52b45832e90613d4ec38840e2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Feb 2023 19:08:12 -0500 Subject: [PATCH 177/179] store RouterInfo in DHT --- libi2pd/KadDHT.cpp | 213 +++++++++++++++++++++++++++++++++------------ libi2pd/KadDHT.h | 27 +++--- libi2pd/NetDb.cpp | 7 +- libi2pd/NetDb.hpp | 2 +- 4 files changed, 177 insertions(+), 72 deletions(-) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index c3905b7a..48486675 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -14,7 +14,7 @@ namespace i2p namespace data { DHTNode::DHTNode (): - zero (nullptr), one (nullptr), hash (nullptr) + zero (nullptr), one (nullptr) { } @@ -22,17 +22,16 @@ namespace data { if (zero) delete zero; if (one) delete one; - if (hash) delete hash; } - void DHTNode::MoveHashUp (bool fromOne) + void DHTNode::MoveRouterUp (bool fromOne) { DHTNode *& side = fromOne ? one : zero; if (side) { - if (hash) delete hash; // shouldn't happen - hash = side->hash; - side->hash = nullptr; + if (router) router = nullptr; // shouldn't happen + router = side->router; + side->router = nullptr; delete side; side = nullptr; } @@ -49,38 +48,46 @@ namespace data delete m_Root; } - DHTNode * DHTTable::Insert (const IdentHash& h) + void DHTTable::Clear () { - return Insert (new IdentHash (h), m_Root, 0); + m_Size = 0; + delete m_Root; + m_Root = new DHTNode; + } + + void DHTTable::Insert (const std::shared_ptr& r) + { + if (!r) return; + return Insert (r, m_Root, 0); } - DHTNode * DHTTable::Insert (IdentHash * h, DHTNode * root, int level) + void DHTTable::Insert (const std::shared_ptr& r, DHTNode * root, int level) { - if (root->hash) + if (root->router) { - if (*(root->hash) == *h) + if (root->router->GetIdentHash () == r->GetIdentHash ()) { - delete h; - return root; + root->router = r; // replace + return; } - auto h2 = root->hash; - root->hash = nullptr; m_Size--; + auto r2 = root->router; + root->router = nullptr; m_Size--; int bit1, bit2; do { - bit1 = h->GetBit (level); - bit2 = h2->GetBit (level); + bit1 = r->GetIdentHash ().GetBit (level); + bit2 = r2->GetIdentHash ().GetBit (level); if (bit1 == bit2) { if (bit1) { - if (root->one) return nullptr; // someting wrong + if (root->one) return; // someting wrong root->one = new DHTNode; root = root->one; } else { - if (root->zero) return nullptr; // someting wrong + if (root->zero) return; // someting wrong root->zero = new DHTNode; root = root->zero; } @@ -95,37 +102,36 @@ namespace data root->one = new DHTNode; if (bit1) { - Insert (h2, root->zero, level + 1); - return Insert (h, root->one, level + 1); + Insert (r2, root->zero, level + 1); + Insert (r, root->one, level + 1); } else { - Insert (h2, root->one, level + 1); - return Insert (h, root->zero, level + 1); + Insert (r2, root->one, level + 1); + Insert (r, root->zero, level + 1); } } else { if (!root->zero && !root->one) { - root->hash = h; m_Size++; - return root; + root->router = r; m_Size++; + return; } - int bit = h->GetBit (level); + int bit = r->GetIdentHash ().GetBit (level); if (bit) { if (!root->one) root->one = new DHTNode; - return Insert (h, root->one, level + 1); + Insert (r, root->one, level + 1); } else { if (!root->zero) root->zero = new DHTNode; - return Insert (h, root->zero, level + 1); + Insert (r, root->zero, level + 1); } } - return nullptr; } bool DHTTable::Remove (const IdentHash& h) @@ -137,9 +143,9 @@ namespace data { if (root) { - if (root->hash && *(root->hash) == h) + if (root->router && root->router->GetIdentHash () == h) { - delete root->hash; root->hash = nullptr; + root->router = nullptr; m_Size--; return true; } @@ -152,11 +158,11 @@ namespace data { delete root->one; root->one = nullptr; - if (root->zero && root->zero->hash) - root->MoveHashUp (false); + if (root->zero && root->zero->router) + root->MoveRouterUp (false); } - else if (root->one->hash && !root->zero) - root->MoveHashUp (true); + else if (root->one->router && !root->zero) + root->MoveRouterUp (true); return true; } } @@ -168,11 +174,11 @@ namespace data { delete root->zero; root->zero = nullptr; - if (root->one && root->one->hash) - root->MoveHashUp (true); + if (root->one && root->one->router) + root->MoveRouterUp (true); } - else if (root->zero->hash && !root->one) - root->MoveHashUp (false); + else if (root->zero->router && !root->one) + root->MoveRouterUp (false); return true; } } @@ -180,48 +186,95 @@ namespace data return false; } - IdentHash * DHTTable::FindClosest (const IdentHash& h) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, const Filter& filter) { - return FindClosest (h, m_Root, 0); + if (filter) m_Filter = filter; + auto r = FindClosest (h, m_Root, 0); + m_Filter = nullptr; + return r; } - IdentHash * DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) { - if (root->hash) return root->hash; + bool split = false; + do + { + if (root->router) + return (!m_Filter || m_Filter (root->router)) ? root->router : nullptr; + split = root->zero && root->one; + if (!split) + { + if (root->zero) root = root->zero; + else if (root->one) root = root->one; + else return nullptr; + level++; + } + } + while (!split); int bit = h.GetBit (level); if (bit) { if (root->one) - return FindClosest (h, root->one, level + 1); + { + auto r = FindClosest (h, root->one, level + 1); + if (r) return r; + } if (root->zero) - return FindClosest (h, root->zero, level + 1); + { + auto r = FindClosest (h, root->zero, level + 1); + if (r) return r; + } } else { if (root->zero) - return FindClosest (h, root->zero, level + 1); + { + auto r = FindClosest (h, root->zero, level + 1); + if (r) return r; + } if (root->one) - return FindClosest (h, root->one, level + 1); + { + auto r = FindClosest (h, root->one, level + 1); + if (r) return r; + } } return nullptr; } - std::vector DHTTable::FindClosest (const IdentHash& h, size_t num) + std::vector > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) { - std::vector vec; + std::vector > vec; if (num > 0) + { + if (filter) m_Filter = filter; FindClosest (h, num, m_Root, 0, vec); + m_Filter = nullptr; + } return vec; } - void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes) + void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes) { if (hashes.size () >= num) return; - if (root->hash) + bool split = false; + do { - hashes.push_back (root->hash); - return; - } + if (root->router) + { + if (!m_Filter || m_Filter (root->router)) + hashes.push_back (root->router); + return; + } + split = root->zero && root->one; + if (!split) + { + if (root->zero) root = root->zero; + else if (root->one) root = root->one; + else return; + level++; + } + } + while (!split); int bit = h.GetBit (level); if (bit) { @@ -238,6 +291,54 @@ namespace data FindClosest (h, num, root->one, level + 1, hashes); } } + + void DHTTable::Cleanup (Filter filter) + { + if (filter) + { + m_Filter = filter; + Cleanup (m_Root); + m_Filter = nullptr; + } + else + Clear (); + } + + void DHTTable::Cleanup (DHTNode * root) + { + if (!root) return; + if (root->router) + { + if (!m_Filter || !m_Filter (root->router)) + { + m_Size--; + root->router = nullptr; + } + return; + } + if (root->zero) + { + Cleanup (root->zero); + if (root->zero->IsEmpty ()) + { + delete root->zero; + root->zero = nullptr; + } + } + if (root->one) + { + Cleanup (root->one); + if (root->one->IsEmpty ()) + { + delete root->one; + root->one = nullptr; + if (root->zero && root->zero->router) + root->MoveRouterUp (false); + } + else if (root->one->router && !root->zero) + root->MoveRouterUp (true); + } + } void DHTTable::Print (std::stringstream& s) { @@ -248,10 +349,10 @@ namespace data { if (!root) return; s << std::string (level, '-'); - if (root->hash) + if (root->router) { if (!root->zero && !root->one) - s << '>' << GetIdentHashAbbreviation (*(root->hash)); + s << '>' << GetIdentHashAbbreviation (root->router->GetIdentHash ()); else s << "error"; } diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h index eb12aae7..c280a1de 100644 --- a/libi2pd/KadDHT.h +++ b/libi2pd/KadDHT.h @@ -13,7 +13,8 @@ #include #include #include -#include "Identity.h" +#include +#include "RouterInfo.h" // Kademlia DHT (XOR distance) @@ -24,42 +25,48 @@ namespace data struct DHTNode { DHTNode * zero, * one; - IdentHash * hash; + std::shared_ptr router; DHTNode (); ~DHTNode (); - bool IsEmpty () const { return !zero && !one && !hash; }; - void MoveHashUp (bool fromOne); + bool IsEmpty () const { return !zero && !one && !router; }; + void MoveRouterUp (bool fromOne); }; class DHTTable { + typedef std::function&)> Filter; public: DHTTable (); ~DHTTable (); - DHTNode * Insert (const IdentHash& h); + void Insert (const std::shared_ptr& r); bool Remove (const IdentHash& h); - IdentHash * FindClosest (const IdentHash& h); - std::vector FindClosest (const IdentHash& h, size_t num); + std::shared_ptr FindClosest (const IdentHash& h, const Filter& filter = nullptr); + std::vector > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr); void Print (std::stringstream& s); size_t GetSize () const { return m_Size; }; + void Clear (); + void Cleanup (Filter filter); private: - DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive + void Insert (const std::shared_ptr& r, DHTNode * root, int level); // recursive bool Remove (const IdentHash& h, DHTNode * root, int level); - IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); - void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes); + std::shared_ptr FindClosest (const IdentHash& h, DHTNode * root, int level); + void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes); + void Cleanup (DHTNode * root); void Print (std::stringstream& s, DHTNode * root, int level); private: DHTNode * m_Root; size_t m_Size; + // transient + Filter m_Filter; }; } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5bc9c47e..685189ed 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1355,15 +1355,12 @@ namespace data } std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, - const std::set& excluded, bool closeThanUsOnly) const + const std::set& excluded) const { std::shared_ptr r; XORMetric minMetric; IdentHash destKey = CreateRoutingKey (destination); - if (closeThanUsOnly) - minMetric = destKey ^ i2p::context.GetIdentHash (); - else - minMetric.SetMax (); + minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) { diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index f0315582..192d2644 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -93,7 +93,7 @@ namespace data std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::set& excluded) const; - std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly = false) const; + std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; From 85442831105dac2a879116c4f66b0224b3951dd6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Feb 2023 21:33:30 -0500 Subject: [PATCH 178/179] don't expire connected routers --- libi2pd/NetDb.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 685189ed..11cf8066 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -664,21 +664,26 @@ namespace data if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate || (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) it.second->SetUnreachable (false); - // find & mark expired routers - if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4)) - // non-reachable router, but reachable by ipv4 SSU2 means introducers - { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) - // RouterInfo expires after 1 hour if uses introducer + if (!it.second->IsUnreachable ()) + { + // find & mark expired routers + if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4)) + // non-reachable router, but reachable by ipv4 SSU2 means introducers + { + if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) + // RouterInfo expires after 1 hour if uses introducer + it.second->SetUnreachable (true); + } + else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); - } - else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) - it.second->SetUnreachable (true); - else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) - { - LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); - it.second->SetUnreachable (true); - } + else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) + { + LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); + it.second->SetUnreachable (true); + } + if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) + it.second->SetUnreachable (false); // don't expire connected router + } if (it.second->IsUnreachable ()) { From 95cc544c92a0d941fdcad62fb730b04280d3431e Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 22 Feb 2023 19:31:24 +0200 Subject: [PATCH 179/179] Check for null pointer before dereferencing it --- libi2pd/NTCP2.cpp | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 813ea6d5..eaa186f8 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1457,7 +1457,7 @@ namespace transport void NTCP2Server::HandleAccept (std::shared_ptr conn, const boost::system::error_code& error) { - if (!error) + if (!error && conn) { boost::system::error_code ec; auto ep = conn->GetSocket ().remote_endpoint(ec); @@ -1466,17 +1466,14 @@ namespace transport LogPrint (eLogDebug, "NTCP2: Connected from ", ep); if (!i2p::util::net::IsInReservedRange(ep.address ())) { - if (conn) + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { - if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - conn = nullptr; - } - else - LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); @@ -1507,7 +1504,7 @@ namespace transport void NTCP2Server::HandleAcceptV6 (std::shared_ptr conn, const boost::system::error_code& error) { - if (!error) + if (!error && conn) { boost::system::error_code ec; auto ep = conn->GetSocket ().remote_endpoint(ec); @@ -1517,17 +1514,14 @@ namespace transport if (!i2p::util::net::IsInReservedRange(ep.address ()) || i2p::util::net::IsYggdrasilAddress (ep.address ())) { - if (conn) + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { - if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - conn = nullptr; - } - else - LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ());