From 9475a2272830fd98ec22675076e9864845026a6a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 5 Apr 2023 21:30:36 -0400 Subject: [PATCH 001/264] update introducers. cleanup unreachable routers --- libi2pd/NetDb.cpp | 30 ++++++++++++++---------- libi2pd/NetDb.hpp | 2 +- libi2pd/RouterInfo.cpp | 53 +++++++++++++++++++++++++++++++++--------- libi2pd/RouterInfo.h | 6 +++-- libi2pd/TunnelPool.cpp | 7 +++--- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 447eb873..9fd9923a 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -106,7 +106,7 @@ namespace data { i2p::util::SetThreadName("NetDB"); - uint64_t lastSave = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; + uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch (); int16_t profilesCleanupVariance = 0; @@ -155,14 +155,14 @@ namespace data lastManageRequest = ts; } - if (ts - lastSave >= 60 || ts + 60 < lastSave) // save routers, manage leasesets and validate subscriptions every minute + if (ts - lastManage >= 60 || ts + 60 < lastManage) // manage routers and leasesets every minute { - if (lastSave) + if (lastManage) { - SaveUpdated (); + ManageRouterInfos (); ManageLeaseSets (); } - lastSave = ts; + lastManage = ts; } if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT || @@ -631,13 +631,8 @@ namespace data 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); - } + if (it.second->GetCompatibleTransports (true)) // non reachable by any transport + 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 ()) @@ -1348,6 +1343,17 @@ namespace data return r; } + void NetDb::ManageRouterInfos () + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + { + std::unique_lock l(m_RouterInfosMutex); + for (auto& it: m_RouterInfos) + it.second->UpdateIntroducers (ts); + } + SaveUpdated (); + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 71694d8d..d98d487e 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -40,7 +40,6 @@ namespace data const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds - const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60; 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 @@ -139,6 +138,7 @@ namespace data void Run (); // exploratory thread void Explore (int numDestinations); void Flood (const IdentHash& ident, std::shared_ptr floodMsg); + void ManageRouterInfos (); void ManageLeaseSets (); void ManageRequests (); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3ae5abd9..eb186ec9 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -400,18 +400,9 @@ namespace data { // exclude invalid introducers uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - int numValid = 0; - for (auto& it: address->ssu->introducers) - { - if (it.iTag && ts < it.iExp) - numValid++; - else - it.iTag = 0; - } - if (numValid) + UpdateIntroducers (address, ts); + if (!address->ssu->introducers.empty ()) // still has something m_ReachableTransports |= supportedTransports; - else - address->ssu->introducers.resize (0); } } if (supportedTransports) @@ -576,6 +567,21 @@ namespace data return caps; } + void RouterInfo::UpdateIntroducers (std::shared_ptr
address, uint64_t ts) + { + if (!address || !address->ssu) return; + int numValid = 0; + for (auto& it: address->ssu->introducers) + { + if (it.iTag && ts < it.iExp) + numValid++; + else + it.iTag = 0; + } + if (!numValid) + address->ssu->introducers.resize (0); + } + bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const { if (!m_RouterIdentity) return false; @@ -1036,6 +1042,31 @@ namespace data } } + void RouterInfo::UpdateIntroducers (uint64_t ts) + { + if (ts*1000 < m_Timestamp + INTRODUCER_UPDATE_INTERVAL) return; + if (m_ReachableTransports & eSSU2V4) + { + auto addr = (*GetAddresses ())[eSSU2V4Idx]; + if (addr && addr->UsesIntroducer ()) + { + UpdateIntroducers (addr, ts); + if (!addr->UsesIntroducer ()) // no more valid introducers + m_ReachableTransports &= ~eSSU2V4; + } + } + if (m_ReachableTransports & eSSU2V6) + { + auto addr = (*GetAddresses ())[eSSU2V6Idx]; + if (addr && addr->UsesIntroducer ()) + { + UpdateIntroducers (addr, ts); + if (!addr->UsesIntroducer ()) // no more valid introducers + m_ReachableTransports &= ~eSSU2V6; + } + } + } + void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len) { if (!m_Buffer) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index f258b018..273e7a75 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -61,6 +61,7 @@ namespace data const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later const int HIGH_CONGESTION_INTERVAL = 15*60; // in seconds, 15 minutes + const int INTRODUCER_UPDATE_INTERVAL = 20*60*1000; // in milliseconds, 20 minutes class RouterInfo: public RoutingDestination { @@ -221,8 +222,8 @@ namespace data void RemoveSSU2Address (bool v4); void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps void UpdateSupportedTransports (); + void UpdateIntroducers (uint64_t ts); // ts in seconds bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; }; - bool IsReachable () const { return m_Caps & Caps::eReachable; }; bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsNTCP2 (bool v4only = true) const; bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; }; @@ -302,6 +303,7 @@ namespace data size_t ReadString (char* str, size_t len, std::istream& s) const; void ExtractCaps (const char * value); uint8_t ExtractAddressCaps (const char * value) const; + void UpdateIntroducers (std::shared_ptr
address, uint64_t ts); template std::shared_ptr GetAddress (Filter filter) const; virtual std::shared_ptr NewBuffer () const; @@ -315,7 +317,7 @@ namespace data std::shared_ptr m_RouterIdentity; std::shared_ptr m_Buffer; size_t m_BufferLen; - uint64_t m_Timestamp; + uint64_t m_Timestamp; // in milliseconds boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 bool m_IsUpdated, m_IsUnreachable; CompatibleTransports m_SupportedTransports, m_ReachableTransports; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index cf146218..c1102d25 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -498,7 +498,8 @@ namespace tunnel { 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 + (numHops > 1 || (r->IsV4 () && (!inbound || + r->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4))))) // first inbound must be reachable { prevHop = r; path.Add (r); @@ -520,8 +521,8 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || // doesn't support ipv4 - (inbound && !hop->IsReachable ()))) // IBGW is not reachable + if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && // doesn't support ipv4 + !hop->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4)))) // IBGW is not reachable { auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; From d580c0155ac8ff31f26ac0378719b63750f555e5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 5 Apr 2023 21:49:49 -0400 Subject: [PATCH 002/264] fixed typo --- libi2pd/NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9fd9923a..3847f24f 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -631,7 +631,7 @@ namespace data if (!it.second->IsUnreachable ()) { // find & mark expired routers - if (it.second->GetCompatibleTransports (true)) // non reachable by any transport + if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); From caff003a85c0cfbd807d7c71333ac9ac34f1eba7 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Apr 2023 16:03:15 -0400 Subject: [PATCH 003/264] check for published ipv4 addresses for floodfills and IBGW --- libi2pd/RouterInfo.cpp | 20 ++++++++++++++++---- libi2pd/RouterInfo.h | 1 + libi2pd/TunnelPool.cpp | 6 ++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index eb186ec9..ad1de04a 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -366,7 +366,7 @@ namespace data { if (isStaticKey) { - if (isHost) + if (isHost && address->port) { if (address->host.is_v6 ()) supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); @@ -374,8 +374,9 @@ namespace data supportedTransports |= eNTCP2V4; m_ReachableTransports |= supportedTransports; } - else if (!address->published) + else { + address->published = false; if (address->caps) { if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; @@ -982,11 +983,22 @@ namespace data bool RouterInfo::IsEligibleFloodfill () const { - // floodfill must be reachable by ipv4, >= 0.9.38 and not DSA - return IsReachableBy (eNTCP2V4 | eSSU2V4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION && + // floodfill must have published ipv4, >= 0.9.38 and not DSA + return m_Version >= NETDB_MIN_FLOODFILL_VERSION && IsPublished (true) && GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; } + bool RouterInfo::IsPublished (bool v4) const + { + auto addr = GetAddresses (); + if (v4) + return ((*addr)[eNTCP2V4] && ((*addr)[eNTCP2V4])->published) || + ((*addr)[eSSU2V4] && ((*addr)[eSSU2V4])->published); + else + return ((*addr)[eNTCP2V6] && ((*addr)[eNTCP2V6])->published) || + ((*addr)[eSSU2V6] && ((*addr)[eSSU2V6])->published); + } + bool RouterInfo::IsSSU2PeerTesting (bool v4) const { if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 273e7a75..3789438d 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -247,6 +247,7 @@ namespace data bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; bool IsEligibleFloodfill () const; + bool IsPublished (bool v4) const; bool IsSSU2PeerTesting (bool v4) const; bool IsSSU2Introducer (bool v4) const; bool IsHighCongestion () const; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index c1102d25..aee466a1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -498,8 +498,7 @@ namespace tunnel { auto r = i2p::transport::transports.GetRandomPeer (!IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && - (numHops > 1 || (r->IsV4 () && (!inbound || - r->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4))))) // first inbound must be reachable + (numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4 { prevHop = r; path.Add (r); @@ -521,8 +520,7 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && // doesn't support ipv4 - !hop->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4)))) // IBGW is not reachable + if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 { auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; From c1f19cb2582bb51d1fe1c9b49459557da1e45ab3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Apr 2023 16:19:56 -0400 Subject: [PATCH 004/264] fixed typo --- libi2pd/RouterInfo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index ad1de04a..34bd705d 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -992,11 +992,11 @@ namespace data { auto addr = GetAddresses (); if (v4) - return ((*addr)[eNTCP2V4] && ((*addr)[eNTCP2V4])->published) || - ((*addr)[eSSU2V4] && ((*addr)[eSSU2V4])->published); + return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || + ((*addr)[eSSU2V4Idx] && ((*addr)[eSSU2V4Idx])->published); else - return ((*addr)[eNTCP2V6] && ((*addr)[eNTCP2V6])->published) || - ((*addr)[eSSU2V6] && ((*addr)[eSSU2V6])->published); + return ((*addr)[eNTCP2V6Idx] && ((*addr)[eNTCP2V6Idx])->published) || + ((*addr)[eSSU2V6Idx] && ((*addr)[eSSU2V6Idx])->published); } bool RouterInfo::IsSSU2PeerTesting (bool v4) const From 572694b141720183ff65bdb5e081ff60772c224e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 9 Apr 2023 21:32:44 -0400 Subject: [PATCH 005/264] check routers' congestion before recreating a tunnel --- libi2pd/TunnelPool.cpp | 31 ++++++++++++++++++++++++++----- libi2pd/TunnelPool.h | 1 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index aee466a1..d21347e6 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -637,8 +637,13 @@ namespace tunnel outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel..."); std::shared_ptr config; - if (m_NumInboundHops > 0 && tunnel->GetPeers().size()) - config = std::make_shared(tunnel->GetPeers (), tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + if (m_NumInboundHops > 0) + { + auto peers = tunnel->GetPeers(); + if (peers.size ()&& ValidatePeers (peers)) + config = std::make_shared(tunnel->GetPeers (), + tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + } if (!m_NumInboundHops || config) { auto newTunnel = tunnels.CreateInboundTunnel (config, shared_from_this(), outboundTunnel); @@ -702,10 +707,12 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; - if (m_NumOutboundHops > 0 && tunnel->GetPeers().size()) + if (m_NumOutboundHops > 0) { - config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), - inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + auto peers = tunnel->GetPeers(); + if (peers.size () && ValidatePeers (peers)) + config = std::make_shared(peers, inboundTunnel->GetNextTunnelID (), + inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); } if (!m_NumOutboundHops || config) { @@ -746,6 +753,20 @@ namespace tunnel return m_CustomPeerSelector != nullptr; } + bool TunnelPool::ValidatePeers (std::vector >& peers) + { + for (auto it: peers) + { + auto r = i2p::data::netdb.FindRouter (it->GetIdentHash ()); + if (r) + { + if (r->IsHighCongestion ()) return false; + it = r->GetIdentity (); // use identity from updated RouterInfo + } + } + return true; + } + std::shared_ptr TunnelPool::GetLowestLatencyInboundTunnel(std::shared_ptr exclude) const { std::shared_ptr tun = nullptr; diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 7d952559..f49ce309 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -126,6 +126,7 @@ namespace tunnel typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const; bool SelectPeers (Path& path, bool isInbound); bool SelectExplicitPeers (Path& path, bool isInbound); + static bool ValidatePeers (std::vector >& peers); private: From 4ebc7c970a168257c21f823b9fff792458a1ab25 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 10 Apr 2023 23:04:38 -0400 Subject: [PATCH 006/264] bypass medium congestion(D) routers for client tunnels --- libi2pd/NetDb.cpp | 4 ++-- libi2pd/RouterInfo.cpp | 24 ++++++++++++++++++------ libi2pd/RouterInfo.h | 2 +- libi2pd/TunnelPool.cpp | 5 +++-- libi2pd/TunnelPool.h | 2 +- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 3847f24f..c9c92b64 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1172,7 +1172,7 @@ namespace data return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - router->IsECIES (); + router->IsECIES () && !router->IsHighCongestion (false); }); } @@ -1206,7 +1206,7 @@ namespace data router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES () && !router->IsHighCongestion (); + router->IsECIES () && !router->IsHighCongestion (true); }); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 34bd705d..c18e0521 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1113,13 +1113,25 @@ namespace data m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } - bool RouterInfo::IsHighCongestion () const + bool RouterInfo::IsHighCongestion (bool highBandwidth) const { - if (m_Congestion == eLowCongestion || m_Congestion == eMediumCongestion) return false; - if (m_Congestion == eRejectAll) return true; - if (m_Congestion == eHighCongestion) - return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL) ? true : false; - return false; + switch (m_Congestion) + { + case eLowCongestion: + return false; + break; + case eMediumCongestion: + return highBandwidth; + break; + case eHighCongestion: + return i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL; + break; + case eRejectAll: + return true; + break; + default: + return false; + } } void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 3789438d..070737e8 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -250,7 +250,7 @@ namespace data bool IsPublished (bool v4) const; bool IsSSU2PeerTesting (bool v4) const; bool IsSSU2Introducer (bool v4) const; - bool IsHighCongestion () const; + bool IsHighCongestion (bool highBandwidth) const; uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps) { m_Caps = caps; }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index d21347e6..3dc0256e 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -753,14 +753,15 @@ namespace tunnel return m_CustomPeerSelector != nullptr; } - bool TunnelPool::ValidatePeers (std::vector >& peers) + bool TunnelPool::ValidatePeers (std::vector >& peers) const { + bool highBandwidth = !IsExploratory (); for (auto it: peers) { auto r = i2p::data::netdb.FindRouter (it->GetIdentHash ()); if (r) { - if (r->IsHighCongestion ()) return false; + if (r->IsHighCongestion (highBandwidth)) return false; it = r->GetIdentity (); // use identity from updated RouterInfo } } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index f49ce309..e9dd142e 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -126,7 +126,7 @@ namespace tunnel typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const; bool SelectPeers (Path& path, bool isInbound); bool SelectExplicitPeers (Path& path, bool isInbound); - static bool ValidatePeers (std::vector >& peers); + bool ValidatePeers (std::vector >& peers) const; private: From b8d21a1282cc00f4808cedbf3442b42eac820002 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 07:46:50 -0400 Subject: [PATCH 007/264] create non-default port destination explicitly --- libi2pd_client/I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index db0d0c04..07cb0224 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -693,7 +693,7 @@ namespace client { if (!inport) inport = port; m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination) + if (!m_PortDestination || (inport && (m_PortDestination == localDestination->GetStreamingDestination ()))) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } From 132557f941eded30e5e3a21df1c9c7cf5ab3d4ab Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 13:33:20 -0400 Subject: [PATCH 008/264] don't return default destination if port is specified explicitly --- libi2pd/Destination.cpp | 6 ++++-- libi2pd_client/I2PTunnel.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9e5fbe20..1a93f163 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1083,6 +1083,7 @@ namespace client { // streaming protocol auto dest = GetStreamingDestination (toPort); + if (!dest) dest = m_StreamingDestination; // if no destination on port use default if (dest) dest->HandleDataMessagePayload (buf, length); else @@ -1236,8 +1237,9 @@ namespace client if (it != m_StreamingDestinationsByPorts.end ()) return it->second; } - // if port is zero or not found, use default destination - return m_StreamingDestination; + else // if port is zero, use default destination + return m_StreamingDestination; + return nullptr; } void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 07cb0224..78634b7e 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -693,7 +693,7 @@ namespace client { if (!inport) inport = port; m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination || (inport && (m_PortDestination == localDestination->GetStreamingDestination ()))) // default destination + if (!m_PortDestination) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } From e20acb93cfdb7880ad200fe55b6d5d58a07093a0 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 15:28:15 -0400 Subject: [PATCH 009/264] don't lookup streaming destination for each message --- libi2pd/Destination.cpp | 16 +++++++++++----- libi2pd/Destination.h | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 1a93f163..7b878fbe 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -930,7 +930,7 @@ namespace client bool isPublic, const std::map * params): LeaseSetDestination (service, isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), - m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), + m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(service) { @@ -1058,6 +1058,7 @@ namespace client //it.second->SetOwner (nullptr); } m_StreamingDestinationsByPorts.clear (); + m_LastStreamingDestination = nullptr; if (m_DatagramDestination) { delete m_DatagramDestination; @@ -1082,10 +1083,15 @@ namespace client case PROTOCOL_TYPE_STREAMING: { // streaming protocol - auto dest = GetStreamingDestination (toPort); - if (!dest) dest = m_StreamingDestination; // if no destination on port use default - if (dest) - dest->HandleDataMessagePayload (buf, length); + if (toPort != m_LastPort || !m_LastStreamingDestination) + { + m_LastStreamingDestination = GetStreamingDestination (toPort); + if (!m_LastStreamingDestination) + m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default + m_LastPort = toPort; + } + if (m_LastStreamingDestination) + m_LastStreamingDestination->HandleDataMessagePayload (buf, length); else LogPrint (eLogError, "Destination: Missing streaming destination"); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 9e2d171f..96b20a54 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.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 * @@ -297,6 +297,7 @@ namespace client bool m_IsStreamingAnswerPings; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; + std::shared_ptr m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels i2p::datagram::DatagramDestination * m_DatagramDestination; int m_RefCounter; // how many clients(tunnels) use this destination From cd5bfaabb5b209f3d7239568e5e2d975a1d9bc16 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Apr 2023 22:16:31 -0400 Subject: [PATCH 010/264] mark and check unreachable ident hashes --- libi2pd/Transports.cpp | 21 +++++++++++++++------ libi2pd/Transports.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c2aeb964..940e17d8 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -458,8 +458,20 @@ namespace transport it->second.sessions.front ()->SendI2NPMessages (msgs); else { - if (it->second.delayedMessages.size () < MAX_NUM_DELAYED_MESSAGES) + auto sz = it->second.delayedMessages.size (); + if (sz < MAX_NUM_DELAYED_MESSAGES) { + if (sz > CHECK_PROFILE_NUM_DELAYED_MESSAGES) + { + auto profile = i2p::data::GetRouterProfile (ident); + if (profile && profile->IsUnreachable ()) + { + LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), "reports unreachable. Dropped"); + std::unique_lock l(m_PeersMutex); + m_Peers.erase (it); + return; + } + } for (auto& it1: msgs) it->second.delayedMessages.push_back (it1); } @@ -775,11 +787,8 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - auto profile = i2p::data::GetRouterProfile(it->first); - if (profile) - { - profile->TunnelNonReplied(); - } + auto profile = i2p::data::GetRouterProfile (it->first); + if (profile) profile->Unreachable (); std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 1058d31b..a8f2a16a 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -106,6 +106,7 @@ namespace transport const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds const int PEER_TEST_INTERVAL = 71; // in minutes const int MAX_NUM_DELAYED_MESSAGES = 150; + const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after class Transports { public: From 527ee3b3c5435553e3172fdcfe44f8c941a7bf01 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 16 Apr 2023 08:18:41 -0400 Subject: [PATCH 011/264] check if ident is unrechable only once --- libi2pd/Transports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 940e17d8..fcdfc105 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -461,7 +461,7 @@ namespace transport auto sz = it->second.delayedMessages.size (); if (sz < MAX_NUM_DELAYED_MESSAGES) { - if (sz > CHECK_PROFILE_NUM_DELAYED_MESSAGES) + if (sz < CHECK_PROFILE_NUM_DELAYED_MESSAGES && sz + msgs.size () >= CHECK_PROFILE_NUM_DELAYED_MESSAGES) { auto profile = i2p::data::GetRouterProfile (ident); if (profile && profile->IsUnreachable ()) From b77ae0838859505182f99a80a8a12d575f49cb10 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 14:35:13 -0400 Subject: [PATCH 012/264] exclude previously non-reachable transports --- libi2pd/NetDb.cpp | 20 +++++++++++++++----- libi2pd/NetDb.hpp | 1 + libi2pd/RouterInfo.h | 1 + libi2pd/Transports.cpp | 11 +++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index c9c92b64..1f9797f2 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -409,19 +409,29 @@ namespace data void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable) { - auto it = m_RouterInfos.find (ident); - if (it != m_RouterInfos.end ()) + auto r = FindRouter (ident); + if (r) { - it->second->SetUnreachable (unreachable); + r->SetUnreachable (unreachable); if (unreachable) { - auto profile = it->second->GetProfile (); + auto profile = r->GetProfile (); if (profile) profile->Unreachable (); } - } + } } + void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports) + { + auto r = FindRouter (ident); + if (r) + { + std::unique_lock l(m_RouterInfosMutex); + r->ExcludeReachableTransports (transports); + } + } + void NetDb::Reseed () { if (!m_Reseeder) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index d98d487e..b6dc8ce7 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -94,6 +94,7 @@ namespace data std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; std::shared_ptr GetRandomRouterInFamily (FamilyID fam) const; void SetUnreachable (const IdentHash& ident, bool unreachable); + void ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports); void PostI2NPMsg (std::shared_ptr msg); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 070737e8..35737c9b 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -259,6 +259,7 @@ namespace data void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; + void ExcludeReachableTransports (CompatibleTransports transports) { m_ReachableTransports &= ~transports; }; const uint8_t * GetBuffer () const { return m_Buffer ? m_Buffer->data () : nullptr; }; const uint8_t * LoadBuffer (const std::string& fullPath); // load if necessary diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index fcdfc105..258ceca3 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -700,6 +700,17 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { + if (it->second.numAttempts > 1) + { + // exclude failed transports + i2p::data::RouterInfo::CompatibleTransports transports = 0; + int numExcluded = it->second.numAttempts - 1; + if (numExcluded > (int)it->second.priority.size ()) numExcluded = it->second.priority.size (); + for (int i = 0; i < numExcluded; i++) + transports |= it->second.priority[i]; + i2p::data::netdb.ExcludeReachableTransports (ident, transports); + } + it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect bool sendDatabaseStore = true; if (it->second.delayedMessages.size () > 0) From 7a12b5ca4beb13dbc4f8a6c7148f94f927eb47ed Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 19:25:15 -0400 Subject: [PATCH 013/264] handle incomplete HTTP header lines --- libi2pd_client/I2PTunnel.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 78634b7e..23a3ad52 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -346,7 +346,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) @@ -409,7 +414,7 @@ namespace client matched = true; break; } - if (matched) break; + if (matched) continue; // replace some headers if (!m_Host.empty () && boost::iequals (line.substr (0, 5), "Host:")) @@ -428,7 +433,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) @@ -496,7 +506,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) From 6206616347f36f099c5b146cac6febfa1cbe7d67 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 20:21:22 -0400 Subject: [PATCH 014/264] don't set unreachable twice --- libi2pd/Transports.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 258ceca3..304081ba 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -466,7 +466,7 @@ namespace transport auto profile = i2p::data::GetRouterProfile (ident); if (profile && profile->IsUnreachable ()) { - LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), "reports unreachable. Dropped"); + LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), " reports unreachable. Dropped"); std::unique_lock l(m_PeersMutex); m_Peers.erase (it); return; @@ -798,8 +798,12 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - auto profile = i2p::data::GetRouterProfile (it->first); - if (profile) profile->Unreachable (); + if (!it->second.router) + { + // if router for ident not found mark it unreachable + auto profile = i2p::data::GetRouterProfile (it->first); + if (profile) profile->Unreachable (); + } std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } From c22fc7537052260b11f9f1c3015b0600cc846975 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Apr 2023 19:48:09 -0400 Subject: [PATCH 015/264] set router properties from incoming connections --- libi2pd/Transports.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 304081ba..e66a831c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -729,7 +729,7 @@ namespace transport session->SendI2NPMessages (it->second.delayedMessages); it->second.delayedMessages.clear (); } - else // incoming connection + else // incoming connection or peer test { if(RoutesRestricted() && ! IsRestrictedPeer(ident)) { // not trusted @@ -737,11 +737,14 @@ namespace transport session->Done(); return; } - session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore + if (!session->IsOutgoing ()) // incoming + session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore + auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed auto ts = i2p::util::GetSecondsSinceEpoch (); std::unique_lock l(m_PeersMutex); - auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first; + auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first; it->second.sessions.push_back (session); + it->second.router = nullptr; } }); } From dc265367dcb33c54480389972ea08b5afb9fdabe Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 20 Apr 2023 14:23:41 -0400 Subject: [PATCH 016/264] drop unexpected I2NP messages --- libi2pd/I2NPProtocol.cpp | 24 +++++++++++++++++++----- libi2pd/Transports.cpp | 4 ++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5303edbf..1a5b1cde 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -785,10 +785,12 @@ namespace i2p switch (typeID) { case eI2NPTunnelData: - i2p::tunnel::tunnels.PostTunnelData (msg); + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); break; case eI2NPTunnelGateway: - i2p::tunnel::tunnels.PostTunnelData (msg); + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); break; case eI2NPGarlic: { @@ -799,11 +801,19 @@ namespace i2p break; } case eI2NPDatabaseStore: + // forward to netDb if came directly or through exploratory tunnel as response to our request + if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ()) + i2p::data::netdb.PostI2NPMsg (msg); + break; case eI2NPDatabaseSearchReply: - case eI2NPDatabaseLookup: // forward to netDb i2p::data::netdb.PostI2NPMsg (msg); break; + case eI2NPDatabaseLookup: + // forward to netDb if floodfill and came directly + if (!msg->from && i2p::context.IsFloodfill ()) + i2p::data::netdb.PostI2NPMsg (msg); + break; case eI2NPDeliveryStatus: { if (msg->from && msg->from->GetTunnelPool ()) @@ -813,10 +823,14 @@ namespace i2p break; } case eI2NPVariableTunnelBuild: - case eI2NPVariableTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: case eI2NPShortTunnelBuild: + // forward to tunnel thread + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); + break; + case eI2NPVariableTunnelBuildReply: + case eI2NPTunnelBuildReply: case eI2NPShortTunnelBuildReply: // forward to tunnel thread i2p::tunnel::tunnels.PostTunnelData (msg); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index e66a831c..c6e9f372 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -801,12 +801,12 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - if (!it->second.router) + /* if (!it->second.router) { // if router for ident not found mark it unreachable auto profile = i2p::data::GetRouterProfile (it->first); if (profile) profile->Unreachable (); - } + } */ std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } From 5769a41208dc696fb64ea519bfbceb9c2b7e46ff Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 14:54:54 -0400 Subject: [PATCH 017/264] use unordered_map for LeaseSets --- libi2pd/Destination.cpp | 11 ----------- libi2pd/Destination.h | 5 +++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 7b878fbe..6bcedb4e 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -262,17 +262,6 @@ namespace client return nullptr; } } - else - { - auto ls = i2p::data::netdb.FindLeaseSet (ident); - if (ls && !ls->IsExpired ()) - { - ls->PopulateLeases (); // since we don't store them in netdb - std::lock_guard _lock(m_RemoteLeaseSetsMutex); - m_RemoteLeaseSets[ident] = ls; - return ls; - } - } return nullptr; } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 96b20a54..76508e49 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -184,8 +185,8 @@ namespace client boost::asio::io_service& m_Service; mutable std::mutex m_RemoteLeaseSetsMutex; - std::map > m_RemoteLeaseSets; - std::map > m_LeaseSetRequests; + std::unordered_map > m_RemoteLeaseSets; + std::unordered_map > m_LeaseSetRequests; std::shared_ptr m_Pool; std::mutex m_LeaseSetMutex; From c34df2090cc2921736d0667bb635a53183844bbe Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 21:31:14 -0400 Subject: [PATCH 018/264] don't reply to DatabaseStore messages extracted from transit --- libi2pd/Tunnel.cpp | 12 +++++++++--- libi2pd/TunnelEndpoint.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 05359390..76bdb4c7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -586,10 +586,16 @@ namespace tunnel auto typeID = msg->GetTypeID (); LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID); - if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply) - // transit DatabaseStore my contain new/updated RI - // or DatabaseSearchReply with new routers + if (typeID == eI2NPDatabaseSearchReply) + // DatabaseSearchReply with new routers i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); + else if (IsRouterInfoMsg (msg)) + { + // transit DatabaseStore might contain new/updated RI + auto m = CopyI2NPMessage (msg); + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + i2p::data::netdb.PostI2NPMsg (m); + } tunnel->SendTunnelDataMsg (msg); } diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 7d3b3cbe..f2d8a085 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -324,9 +324,17 @@ namespace tunnel uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); // catch RI or reply with new list of routers - if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) && - !m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); + if (!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) + { + if (typeID == eI2NPDatabaseSearchReply) + i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); + else if (IsRouterInfoMsg (msg.data)) + { + auto m = CopyI2NPMessage (msg.data); + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + i2p::data::netdb.PostI2NPMsg (m); + } + } switch (msg.deliveryType) { From 786c27c8eca566bdbd57c429f1c1ad57a2147108 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 22:27:55 -0400 Subject: [PATCH 019/264] publish encrypted RouterInfo --- libi2pd/RouterContext.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index d6c3c57b..3e7d7a2c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1348,8 +1348,12 @@ namespace i2p auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (inbound && outbound) - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); + { + // encrypt for floodfill + auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } else LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds"); } From f21e1c75d571d52a1a880116d3c3f8e1501c9d59 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Apr 2023 15:31:24 -0400 Subject: [PATCH 020/264] check tagset for null --- libi2pd/Garlic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index c351f6d6..3f885186 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -588,7 +588,7 @@ namespace garlic auto it = m_ECIESx25519Tags.find (tag); if (it != m_ECIESx25519Tags.end ()) { - if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index)) m_LastTagset = it->second.tagset; else LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); From edfcd23b01c04b6b7cb1b29fd7cfe26acd13002c Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:01:21 +0300 Subject: [PATCH 021/264] [webconsole] added a button to prematurely release a leaseset Signed-off-by: r4sas --- daemon/HTTPServer.cpp | 52 +++++++++++++++++++++++++++++++++++++++---- libi2pd/LeaseSet.h | 3 +++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index dceee06a..f9b034ae 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -87,6 +87,7 @@ 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_COMMAND_EXPIRELEASE[] = "expirelease"; static std::string ConvertTime (uint64_t time) { @@ -434,12 +435,11 @@ namespace http { if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ()) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - auto base32 = dest->GetIdentHash ().ToBase32 (); s << "
\r\n\r\n
\r\n" "
\r\n" " \r\n" " \r\n" - " \r\n" + " GetIdentHash ().ToBase32 () << "\">\r\n" " " << tr("Domain") << ":\r\n\r\n" " \r\n" "
\r\n" << tr("Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "\r\n
\r\n
\r\n
\r\n"; @@ -448,9 +448,23 @@ namespace http { if (dest->GetNumRemoteLeaseSets()) { s << "
\r\n\r\n
\r\n"; + << "\r\n\r\n
\r\n" + << "
"<< tr("Address") << "" << tr("Type") << "" << tr("EncType") << "
" + << "" + << "" // LeaseSet expiration button column + << "" + << "" + << ""; for(auto& it: dest->GetLeaseSets ()) - s << "\r\n"; + { + s << "" + << "" + << "" + << "" + << "" + << "\r\n"; + } s << "
" << tr("Address") << " " << tr("Type") << "" << tr("EncType") << "
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
\r\n
\r\n
\r\n
\r\n"; } else s << "" << tr("LeaseSets") << ": 0
\r\n
\r\n"; @@ -1312,6 +1326,36 @@ namespace http { res.add_header("Refresh", redirect.c_str()); return; } + else if (cmd == HTTP_COMMAND_EXPIRELEASE) + { + std::string b32 = params["b32"]; + std::string lease = params["lease"]; + + i2p::data::IdentHash ident, leaseident; + ident.FromBase32 (b32); + leaseident.FromBase32 (lease); + auto dest = i2p::client::context.FindLocalDestination (ident); + + if (dest) + { + auto leaseset = dest->FindLeaseSet (leaseident); + if (leaseset) + { + leaseset->ExpireLease (); + s << "" << tr("SUCCESS") << ": " << tr("LeaseSet expiration time updated") << "
\r\n
\r\n"; + } + else + s << "" << tr("ERROR") << ": " << tr("LeaseSet is not found or already expired") << "
\r\n
\r\n"; + } + else + s << "" << tr("ERROR") << ": " << tr("Destination not found") << "
\r\n
\r\n"; + + s << "" << tr("Return to destination page") << "
\r\n"; + s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; + redirect = std::to_string(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); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 566c4655..4b1311a5 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -96,6 +96,9 @@ namespace data void Encrypt (const uint8_t * data, uint8_t * encrypted) const; bool IsDestination () const { return true; }; + // used in webconsole + void ExpireLease () { m_ExpirationTime = i2p::util::GetSecondsSinceEpoch (); }; + protected: void UpdateLeasesBegin (); From 76adac31c3b8f717622e3b2d00bbc6cff90b1aa9 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Apr 2023 19:25:26 -0400 Subject: [PATCH 022/264] enrcrypt lookup if being sent through a tunnel --- libi2pd/NetDb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 1f9797f2..1abe9748 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -722,7 +722,11 @@ namespace data auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (outbound && inbound) - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound)); + { + auto msg = dest->CreateRequestMessage (floodfill, inbound); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); From 0ce15ffc91971a21bcf73adaf7c2f906a097a38f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Apr 2023 21:34:22 -0400 Subject: [PATCH 023/264] check for incomplete HTTP header --- libi2pd_client/I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 23a3ad52..d1006f26 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -397,7 +397,8 @@ namespace client while (!endOfHeader) { std::getline(m_InHeader, line); - if (!m_InHeader.fail ()) + if (m_InHeader.fail ()) break; + if (!m_InHeader.eof ()) { if (line == "\r") endOfHeader = true; else @@ -485,7 +486,8 @@ namespace client while (!endOfHeader) { std::getline(m_InHeader, line); - if (!m_InHeader.fail ()) + if (m_InHeader.fail ()) break; + if (!m_InHeader.eof ()) { if (line == "\r") endOfHeader = true; else From ead6a6dca35c7a4036bc775f1bfe215f6a866583 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 27 Apr 2023 21:37:30 -0400 Subject: [PATCH 024/264] correct parsing of caught RouterInfo at IBGW and OBEP --- libi2pd/NetDb.cpp | 25 ++++++++++++++----------- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelEndpoint.cpp | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 1abe9748..a271d459 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -791,20 +791,23 @@ 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; - if (!tunnelID) // send response directly - transports.SendMessage (buf + offset, deliveryStatus); - else - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; - if (outbound) - outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus); + if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW + { + auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); + if (!tunnelID) // send response directly + transports.SendMessage (buf + offset, deliveryStatus); else - LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); - } + { + auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; + if (outbound) + outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus); + else + LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); + } + } offset += 32; } // we must send reply back before this check diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 76bdb4c7..bf1bad46 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -593,7 +593,7 @@ namespace tunnel { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } tunnel->SendTunnelDataMsg (msg); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index f2d8a085..fe90da60 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -331,7 +331,7 @@ namespace tunnel else if (IsRouterInfoMsg (msg.data)) { auto m = CopyI2NPMessage (msg.data); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } } From 2af4a2b58dcf39f26bcf775d1494e3ec350e1eaa Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Apr 2023 08:01:02 -0400 Subject: [PATCH 025/264] override reply token only if non-zero --- libi2pd/Tunnel.cpp | 3 ++- libi2pd/TunnelEndpoint.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index bf1bad46..249f0a31 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -593,7 +593,8 @@ namespace tunnel { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply + if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } tunnel->SendTunnelDataMsg (msg); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index fe90da60..b2a0c837 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -331,7 +331,8 @@ namespace tunnel else if (IsRouterInfoMsg (msg.data)) { auto m = CopyI2NPMessage (msg.data); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply + if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } } From 7c535159bc442b2ad539c4eb22eda00b018cc47d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 30 Apr 2023 20:05:35 -0400 Subject: [PATCH 026/264] static keys table --- libi2pd/NTCP2.cpp | 1 + libi2pd/Profiling.cpp | 28 ++++++++++++++++++++++++++++ libi2pd/Profiling.h | 4 ++++ libi2pd/SSU2Session.cpp | 1 + libi2pd/Transports.cpp | 15 +++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 91bc9b3d..aceef0f5 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -714,6 +714,7 @@ namespace transport Terminate (); return; } + i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key 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/Profiling.cpp b/libi2pd/Profiling.cpp index 311d1c86..3144bd9c 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -301,5 +301,33 @@ namespace data } } } + +// static keys + + struct StaticKeyProfile + { + i2p::data::IdentHash ident; + boost::posix_time::ptime lastUpdateTime; + }; + //static i2p::fs::HashedStorage g_StaticKeysProfilesStorage("statickeysProfiles", "s", "statickey-", "txt"); + static std::unordered_map, std::shared_ptr > g_StaticKeysProfiles; + static std::mutex g_StaticKeysProfilesMutex; + + bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) + { + std::unique_lock l(g_StaticKeysProfilesMutex); + auto it = g_StaticKeysProfiles.find (staticKey); + if (it != g_StaticKeysProfiles.end ()) + return it->second->ident == ident; + return true; + } + + void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) + { + std::unique_lock l(g_StaticKeysProfilesMutex); + auto res = g_StaticKeysProfiles.emplace (staticKey, std::make_shared(StaticKeyProfile{ident, GetTime ()})); + if (!res.second) + res.first->second->lastUpdateTime = GetTime (); + } } } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 752d6190..2f60f961 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -85,6 +85,10 @@ namespace data void DeleteObsoleteProfiles (); void SaveProfiles (); void PersistProfiles (); + + // static keys + bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); + void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 47d59ea4..46319bd9 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1073,6 +1073,7 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); + i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now m_RemoteTransports = ri->GetCompatibleTransports (false); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c6e9f372..5693719c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -507,6 +507,11 @@ namespace transport peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: NTCP2 address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -526,6 +531,11 @@ namespace transport peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: SSU2 address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address && address->IsReachableSSU ()) { if (m_SSU2Server->CreateSession (peer.router, address)) @@ -537,6 +547,11 @@ namespace transport { if (!m_NTCP2Server) continue; auto address = peer.router->GetYggdrasilAddress (); + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: Yggdrasil address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); From ec2297ed9dd87c1690ff0bce3565fbeee173b35f Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 1 May 2023 19:28:32 +0000 Subject: [PATCH 027/264] Recognize invalid static key --- libi2pd/RouterInfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index c18e0521..9334ed60 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -362,6 +362,10 @@ namespace data } if (!s) return; } + + if (!i2p::data::CheckStaticKey(address->s, (*m_RouterIdentity).GetIdentHash())) + continue; // skip address + if (address->transportStyle == eTransportNTCP2) { if (isStaticKey) From dab34e90519062a0cc91e0ea5a0433e131d6acbd Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 1 May 2023 20:08:08 +0000 Subject: [PATCH 028/264] get indent hash directly --- libi2pd/RouterInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 9334ed60..f72c3322 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,7 @@ namespace data if (!s) return; } - if (!i2p::data::CheckStaticKey(address->s, (*m_RouterIdentity).GetIdentHash())) + if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) continue; // skip address if (address->transportStyle == eTransportNTCP2) From 7418f11651c9673b98bf5cc0b27301de08094a10 Mon Sep 17 00:00:00 2001 From: contextswap Date: Wed, 3 May 2023 19:04:16 +0900 Subject: [PATCH 029/264] limit aesni inline asm to x86 Signed-off-by: contextswap --- libi2pd/Crypto.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index c9670f6c..4a4d5ef4 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -555,7 +555,7 @@ namespace crypto } // AES -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +580,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +621,7 @@ namespace crypto #endif -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,7 +642,7 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -660,7 +660,7 @@ namespace crypto } } -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,7 +681,7 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -699,7 +699,7 @@ namespace crypto } } -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +708,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,7 +722,7 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first @@ -754,7 +754,7 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -799,7 +799,7 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -823,7 +823,7 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -869,7 +869,7 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -893,7 +893,7 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -934,7 +934,7 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ From 12d0abda55d19ce87e6eedbb402961ba8b1c7fb6 Mon Sep 17 00:00:00 2001 From: contextswap Date: Wed, 3 May 2023 19:10:16 +0900 Subject: [PATCH 030/264] [ Signed-off-by: contextswap --- libi2pd/Crypto.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4a4d5ef4..4a78f2b1 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -555,7 +555,7 @@ namespace crypto } // AES -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +580,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +621,7 @@ namespace crypto #endif -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,7 +642,7 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -660,7 +660,7 @@ namespace crypto } } -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,7 +681,7 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -699,7 +699,7 @@ namespace crypto } } -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +708,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,7 +722,7 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first @@ -754,7 +754,7 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -799,7 +799,7 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -823,7 +823,7 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -869,7 +869,7 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -893,7 +893,7 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -934,7 +934,7 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ From 4ce2ef1d8381c2d93ebcdd77e8017123ae3a23c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 3 May 2023 07:43:28 -0400 Subject: [PATCH 031/264] make router unreachable if AEAD fails in SessionCreated --- libi2pd/NTCP2.cpp | 4 ++++ libi2pd/NetDb.cpp | 2 +- libi2pd/SSU2Session.cpp | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index aceef0f5..3f80bcd2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -566,7 +566,11 @@ namespace transport SendSessionConfirmed (); } else + { + if (GetRemoteIdentity ()) + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key Terminate (); + } } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index a271d459..d3346236 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -607,7 +607,7 @@ namespace data uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); - bool isLowRate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; + bool isLowRate = false; // i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 46319bd9..9bfa4ce0 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -809,6 +809,8 @@ namespace transport m_NoiseState->m_CK + 32, nonce, decryptedPayload.data (), decryptedPayload.size (), false)) { LogPrint (eLogWarning, "SSU2: SessionCreated AEAD verification failed "); + if (GetRemoteIdentity ()) + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key return false; } m_NoiseState->MixHash (payload, len - 64); // h = SHA256(h || encrypted payload from SessionCreated) for SessionConfirmed From 3b13a3f2a1f177f1caf0614c574c5d4c3936df39 Mon Sep 17 00:00:00 2001 From: SidorKozlov Date: Wed, 3 May 2023 15:59:35 +0200 Subject: [PATCH 032/264] Configurable minimum successful tunnels --- libi2pd/Config.cpp | 1 + libi2pd/NetDb.cpp | 56 ++++++++++++++++++++++++---------------------- libi2pd/NetDb.hpp | 1 - libi2pd/Tunnel.h | 9 ++++---- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 39af997b..6b515ef9 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -78,6 +78,7 @@ namespace config { ("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(5000), "Maximum active transit tunnels (default:5000)") + ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("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/NetDb.cpp b/libi2pd/NetDb.cpp index d3346236..aea97adc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -245,19 +245,19 @@ namespace data updated = false; m_Requests.RequestComplete (ident, r); 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->GetIdentHash ()); - } + } m_Requests.RequestComplete (ident, nullptr); - return nullptr; - } + return nullptr; + } } LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated @@ -419,7 +419,7 @@ namespace data if (profile) profile->Unreachable (); } - } + } } void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports) @@ -429,9 +429,9 @@ namespace data { std::unique_lock l(m_RouterInfosMutex); r->ExcludeReachableTransports (transports); - } - } - + } + } + void NetDb::Reseed () { if (!m_Reseeder) @@ -607,7 +607,9 @@ namespace data uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); - bool isLowRate = false; // i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; + double minTunnelCreationSuccessRate; + i2p::config::GetOption("limits.zombies", minTunnelCreationSuccessRate); + bool isLowRate = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < minTunnelCreationSuccessRate; // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour @@ -622,12 +624,12 @@ namespace data if (it.second->IsUpdated ()) { 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); updatedCount++; continue; @@ -639,7 +641,7 @@ namespace data (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) it.second->SetUnreachable (false); if (!it.second->IsUnreachable ()) - { + { // find & mark expired routers if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); @@ -652,7 +654,7 @@ namespace data } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router - } + } if (it.second->IsUnreachable ()) { @@ -667,7 +669,7 @@ namespace data m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt (); - m_IdentitiesPool.CleanUpMt (); + m_IdentitiesPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); @@ -682,10 +684,10 @@ namespace data if (it->second->IsUnreachable ()) it = m_RouterInfos.erase (it); else - { + { it->second->DropProfile (); it++; - } + } } } // clean up expired floodfills or not floodfills anymore @@ -724,9 +726,9 @@ namespace data if (outbound && inbound) { auto msg = dest->CreateRequestMessage (floodfill, inbound); - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); - } + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); @@ -794,7 +796,7 @@ namespace data uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW - { + { auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); if (!tunnelID) // send response directly transports.SendMessage (buf + offset, deliveryStatus); @@ -807,7 +809,7 @@ namespace data else LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); } - } + } offset += 32; } // we must send reply back before this check @@ -1315,16 +1317,16 @@ namespace data return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && !excluded.count (r->GetIdentHash ()); }); - } + } if (v.empty ()) return res; - + XORMetric ourMetric; if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); for (auto& it: v) { if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break; res.push_back (it->GetIdentHash ()); - } + } return res; } @@ -1367,10 +1369,10 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto& it: m_RouterInfos) it.second->UpdateIntroducers (ts); - } + } SaveUpdated (); - } - + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b6dc8ce7..0222de0d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,7 +38,6 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; - const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 5810a7a8..e6e3c3a5 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -45,7 +45,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 @@ -232,8 +232,8 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; - + bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + private: template @@ -292,7 +292,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - uint16_t m_MaxNumTransitTunnels; + uint16_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; @@ -311,6 +311,7 @@ namespace tunnel int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents + double GetPreciseTunnelCreationSuccessRate () const { return m_TunnelCreationSuccessRate * 100; } // in percents int GetTotalTunnelCreationSuccessRate () const // in percents { int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations; From 1bd6390f7801addfa9e4d2a80c864afa8c9e0b03 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 08:20:38 -0400 Subject: [PATCH 033/264] check if s is x25519 public key --- libi2pd/RouterInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index f72c3322..7f8abec3 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,7 @@ namespace data if (!s) return; } - if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) + if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) continue; // skip address if (address->transportStyle == eTransportNTCP2) From c1168c2aa0f3dec34aa2a1c35d9bf45e0d14443e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 09:39:37 -0400 Subject: [PATCH 034/264] don't catch RouterInfo at OBEP --- libi2pd/TunnelEndpoint.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index b2a0c837..3dc0dc07 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -323,20 +323,7 @@ namespace tunnel } uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); - // catch RI or reply with new list of routers - if (!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) - { - if (typeID == eI2NPDatabaseSearchReply) - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); - else if (IsRouterInfoMsg (msg.data)) - { - auto m = CopyI2NPMessage (msg.data); - if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply - i2p::data::netdb.PostI2NPMsg (m); - } - } - + switch (msg.deliveryType) { case eDeliveryTypeLocal: From 2f74e670a5948c6318c685d62fed2fcc9b53ed46 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 15:32:19 -0400 Subject: [PATCH 035/264] invalidate routers with incorrect family signature --- libi2pd/RouterInfo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7f8abec3..0cf5a0c5 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -487,7 +487,10 @@ namespace data if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) m_FamilyID = netdb.GetFamilies ().GetFamilyID (family); else + { LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed"); + SetUnreachable (true); + } } if (!s) return; From b6de474fdafbfffe020852d4db95a1aaf81885f8 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 16:14:54 -0400 Subject: [PATCH 036/264] don't include unconfirmed floodfill to the list if we have enough floodfills already --- libi2pd/NTCP2.cpp | 1 + libi2pd/NetDb.cpp | 6 ++++-- libi2pd/NetDb.hpp | 1 + libi2pd/Profiling.cpp | 10 +++++++++- libi2pd/Profiling.h | 6 +++++- libi2pd/SSU2Session.cpp | 1 + 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 3f80bcd2..be584eb1 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -718,6 +718,7 @@ namespace transport Terminate (); return; } + ri.GetProfile ()->Connected (); i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key 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/NetDb.cpp b/libi2pd/NetDb.cpp index aea97adc..3575b052 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -290,8 +290,10 @@ namespace data if (inserted) { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); - if (r->IsFloodfill () && r->IsEligibleFloodfill ()) - { + if (r->IsFloodfill () && r->IsEligibleFloodfill () && + (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || + r->GetProfile ()->IsReal ())) // don't insert floodfill until it's known real if we have enough + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Insert (r); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 0222de0d..4aa69d59 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,6 +38,7 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1000; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 3144bd9c..d20e48b9 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data 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) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false) { } @@ -52,6 +52,7 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); + participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); @@ -112,6 +113,7 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); + m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -167,6 +169,12 @@ namespace data UpdateTime (); } + void RouterProfile::Connected () + { + m_HasConnected = true; + UpdateTime (); + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 2f60f961..08721bec 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -28,7 +28,8 @@ namespace data const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; const char PEER_PROFILE_USAGE_TAKEN[] = "taken"; const char PEER_PROFILE_USAGE_REJECTED[] = "rejected"; - + const char PEER_PROFILE_USAGE_CONNECTED[] = "connected"; + 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) @@ -48,11 +49,13 @@ namespace data bool IsBad (); bool IsUnreachable (); + bool IsReal () const { return m_HasConnected || m_NumTunnelsAgreed > 0 || m_NumTunnelsDeclined > 0; } void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); void Unreachable (); + void Connected (); boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; @@ -78,6 +81,7 @@ namespace data // usage uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; + bool m_HasConnected; // incoming connection received }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9bfa4ce0..efe7117d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1075,6 +1075,7 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); + ri->GetProfile ()->Connected (); i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now From 7646147ed26319e6dd64697f6fd7663921cfefc9 Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 21:30:44 +0000 Subject: [PATCH 037/264] save only non-default peer profile --- libi2pd/Profiling.cpp | 14 +++++++++----- libi2pd/Profiling.h | 4 ++++ libi2pd/RouterInfo.cpp | 4 ++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index d20e48b9..63d39004 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data 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), m_HasConnected (false) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false), m_IsUseful (0) { } @@ -145,22 +145,25 @@ namespace data UpdateTime (); if (ret > 0) { - m_NumTunnelsDeclined++; + if (++m_NumTunnelsDeclined > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } else { - m_NumTunnelsAgreed++; + if (++m_NumTunnelsAgreed > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; m_LastDeclineTime = 0; } } void RouterProfile::TunnelNonReplied () { - m_NumTunnelsNonReplied++; + if (++m_NumTunnelsNonReplied > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; UpdateTime (); if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3) + { m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); + m_IsUseful = true; + } } void RouterProfile::Unreachable () @@ -206,6 +209,7 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; + m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; @@ -275,7 +279,7 @@ namespace data } auto ts = GetTime (); for (auto& it: tmp) - if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 08721bec..c8654805 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -36,6 +36,7 @@ namespace data const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + const int PEER_PROFILE_USEFUL_THRESHOLD = 3; class RouterProfile { @@ -59,6 +60,7 @@ namespace data boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; + bool IsUseful() const { return m_IsUseful; }; private: @@ -82,6 +84,8 @@ namespace data uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; bool m_HasConnected; // incoming connection received + // is need to be saved + bool m_IsUseful; }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 0cf5a0c5..3352f262 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,11 @@ namespace data if (!s) return; } +<<<<<<< HEAD if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) +======= + if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) +>>>>>>> 146e446b (save only non-default peer profile) continue; // skip address if (address->transportStyle == eTransportNTCP2) From 8fcab7b0c1c832d2c5dabce6b272cf3048d9ce8a Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 21:55:31 +0000 Subject: [PATCH 038/264] fix incorrect merge conflict resolve --- libi2pd/RouterInfo.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3352f262..0cf5a0c5 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,11 +363,7 @@ namespace data if (!s) return; } -<<<<<<< HEAD if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) -======= - if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) ->>>>>>> 146e446b (save only non-default peer profile) continue; // skip address if (address->transportStyle == eTransportNTCP2) From c757b6d0201f7353807136f7ff07dde070c34c89 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 18:22:11 -0400 Subject: [PATCH 039/264] reset floodfill cap for unknown floodfills --- libi2pd/NetDb.cpp | 21 +++++++++++++++------ libi2pd/RouterInfo.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 3575b052..18b6694b 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -267,7 +267,12 @@ namespace data if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) - m_Floodfills.Insert (r); + { + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) + m_Floodfills.Insert (r); + else + r->ResetFlooldFill (); + } } } else @@ -290,12 +295,16 @@ namespace data if (inserted) { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); - if (r->IsFloodfill () && r->IsEligibleFloodfill () && - (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || - r->GetProfile ()->IsReal ())) // don't insert floodfill until it's known real if we have enough + if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { - std::unique_lock l(m_FloodfillsMutex); - m_Floodfills.Insert (r); + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || + r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough + { + std::unique_lock l(m_FloodfillsMutex); + m_Floodfills.Insert (r); + } + else + r->ResetFlooldFill (); } } else diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 35737c9b..47ee1dae 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -224,6 +224,7 @@ namespace data void UpdateSupportedTransports (); void UpdateIntroducers (uint64_t ts); // ts in seconds bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; }; + void ResetFlooldFill () { m_Caps &= ~Caps::eFloodfill; }; bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsNTCP2 (bool v4only = true) const; bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; }; From 2e2cbe7803d2e324d882fba4aa55a9557feadc3b Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 22:46:48 +0000 Subject: [PATCH 040/264] save profile if has connected --- libi2pd/Profiling.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 63d39004..a290aa0a 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -175,6 +175,7 @@ namespace data void RouterProfile::Connected () { m_HasConnected = true; + m_IsUseful = true; UpdateTime (); } @@ -209,7 +210,8 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; - m_IsUseful = false; + // we do not reset m_HasConnected here + // m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; From e068a3cf22089484cff82af0649cf9dad4d3edd8 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 19:58:58 -0400 Subject: [PATCH 041/264] store 'connected' in 'usage' section --- libi2pd/Profiling.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index d20e48b9..b3617db5 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); - participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); + usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,7 +113,6 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -125,6 +124,7 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); + m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { From 3bc56ba4238e458889860c4f7a7b256e6f300312 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 19:58:58 -0400 Subject: [PATCH 042/264] store 'connected' in 'usage' section --- libi2pd/Profiling.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index a290aa0a..dc11df4a 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); - participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); + usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,7 +113,6 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -125,6 +124,7 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); + m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { From 1d8a91c5cccdbb0134d2cf8a1eb182e48a272e0a Mon Sep 17 00:00:00 2001 From: weko Date: Sat, 6 May 2023 07:59:40 +0000 Subject: [PATCH 043/264] redo no save useless profiles --- libi2pd/Profiling.cpp | 25 +++++++++++++++---------- libi2pd/Profiling.h | 5 ++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index dc11df4a..9d795451 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data 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), m_HasConnected (false), m_IsUseful (0) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false) { } @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); + participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); - usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,6 +113,7 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); + m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -124,7 +125,6 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); - m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -145,24 +145,23 @@ namespace data UpdateTime (); if (ret > 0) { - if (++m_NumTunnelsDeclined > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsDeclined++; m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } else { - if (++m_NumTunnelsAgreed > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsAgreed++; m_LastDeclineTime = 0; } } void RouterProfile::TunnelNonReplied () { - if (++m_NumTunnelsNonReplied > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsNonReplied++; UpdateTime (); if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3) { m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); - m_IsUseful = true; } } @@ -175,7 +174,6 @@ namespace data void RouterProfile::Connected () { m_HasConnected = true; - m_IsUseful = true; UpdateTime (); } @@ -210,8 +208,6 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; - // we do not reset m_HasConnected here - // m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; @@ -227,6 +223,15 @@ namespace data m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; } + + bool RouterProfile::IsUseful() const { + return + m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || + m_NumTunnelsDeclined >= PEER_PROFILE_USEFUL_THRESHOLD || + m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD || + m_HasConnected; + } + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index c8654805..2520a6af 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -60,7 +60,8 @@ namespace data boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; - bool IsUseful() const { return m_IsUseful; }; + + bool IsUseful() const; private: @@ -84,8 +85,6 @@ namespace data uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; bool m_HasConnected; // incoming connection received - // is need to be saved - bool m_IsUseful; }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); From 8a52295882ced0e7080dda57e6c0f2456f937d00 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 May 2023 16:43:09 -0400 Subject: [PATCH 044/264] make router real upon successive outgoing NTCP2 session. Eliminate static keys table --- libi2pd/NTCP2.cpp | 2 -- libi2pd/Profiling.cpp | 28 ---------------------------- libi2pd/Profiling.h | 6 +----- libi2pd/RouterInfo.cpp | 8 +++----- libi2pd/SSU2Session.cpp | 2 -- libi2pd/Transports.cpp | 25 +++++++++---------------- 6 files changed, 13 insertions(+), 58 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index be584eb1..5e1cbaf6 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -718,8 +718,6 @@ namespace transport Terminate (); return; } - ri.GetProfile ()->Connected (); - i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key 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/Profiling.cpp b/libi2pd/Profiling.cpp index 45e4ae22..754a2ce3 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -320,33 +320,5 @@ namespace data } } } - -// static keys - - struct StaticKeyProfile - { - i2p::data::IdentHash ident; - boost::posix_time::ptime lastUpdateTime; - }; - //static i2p::fs::HashedStorage g_StaticKeysProfilesStorage("statickeysProfiles", "s", "statickey-", "txt"); - static std::unordered_map, std::shared_ptr > g_StaticKeysProfiles; - static std::mutex g_StaticKeysProfilesMutex; - - bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) - { - std::unique_lock l(g_StaticKeysProfilesMutex); - auto it = g_StaticKeysProfiles.find (staticKey); - if (it != g_StaticKeysProfiles.end ()) - return it->second->ident == ident; - return true; - } - - void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) - { - std::unique_lock l(g_StaticKeysProfilesMutex); - auto res = g_StaticKeysProfiles.emplace (staticKey, std::make_shared(StaticKeyProfile{ident, GetTime ()})); - if (!res.second) - res.first->second->lastUpdateTime = GetTime (); - } } } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 2520a6af..6b814893 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -84,7 +84,7 @@ namespace data // usage uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; - bool m_HasConnected; // incoming connection received + bool m_HasConnected; // successful trusted(incoming or NTCP2) connection }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); @@ -92,10 +92,6 @@ namespace data void DeleteObsoleteProfiles (); void SaveProfiles (); void PersistProfiles (); - - // static keys - bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); - void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); } } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 0cf5a0c5..5ba8a5b1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -293,7 +293,8 @@ namespace data else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key { Base64ToByteStream (value, strlen (value), address->s, 32); - isStaticKey = true; + if (!(address->s[31] & 0x80)) // check if x25519 public key + isStaticKey = true; } else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro { @@ -363,9 +364,6 @@ namespace data if (!s) return; } - if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) - continue; // skip address - if (address->transportStyle == eTransportNTCP2) { if (isStaticKey) @@ -391,7 +389,7 @@ namespace data } } } - else if (address->transportStyle == eTransportSSU2 && isV2) + else if (address->transportStyle == eTransportSSU2 && isV2 && isStaticKey) { if (address->IsV4 ()) supportedTransports |= eSSU2V4; if (address->IsV6 ()) supportedTransports |= eSSU2V6; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index efe7117d..49004437 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1075,8 +1075,6 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); - ri->GetProfile ()->Connected (); - i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now m_RemoteTransports = ri->GetCompatibleTransports (false); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 5693719c..f66a8f96 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -507,11 +507,6 @@ namespace transport peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: NTCP2 address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -531,11 +526,6 @@ namespace transport peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: SSU2 address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address && address->IsReachableSSU ()) { if (m_SSU2Server->CreateSession (peer.router, address)) @@ -547,11 +537,6 @@ namespace transport { if (!m_NTCP2Server) continue; auto address = peer.router->GetYggdrasilAddress (); - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: Yggdrasil address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -606,7 +591,7 @@ namespace transport peer.router->GetCompatibleTransports (true); peer.numAttempts = 0; peer.priority.clear (); - bool ssu2 = rand () & 1; + bool ssu2 = peer.router->GetProfile ()->IsReal () ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; for (auto transport: priority) if (transport & compatibleTransports) @@ -724,6 +709,13 @@ namespace transport for (int i = 0; i < numExcluded; i++) transports |= it->second.priority[i]; i2p::data::netdb.ExcludeReachableTransports (ident, transports); + } + if (it->second.router) + { + auto transport = it->second.priority[it->second.numAttempts]; + if (transport == i2p::data::RouterInfo::eNTCP2V4 || + transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) + it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real } it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect @@ -755,6 +747,7 @@ namespace transport if (!session->IsOutgoing ()) // incoming session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed + if (r) r->GetProfile ()->Connected (); auto ts = i2p::util::GetSecondsSinceEpoch (); std::unique_lock l(m_PeersMutex); auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first; From 623c3f4605b805fdc6b4c5e90d8735eae72107c1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 May 2023 18:07:21 -0400 Subject: [PATCH 045/264] check for max number of records in tunnel build and tunnel build reply messages --- libi2pd/I2NPProtocol.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 1a5b1cde..f100c6e5 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -424,6 +424,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records"); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num); + return; + } if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len); @@ -477,6 +482,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num); + return; + } size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; if (len < num*recordSize + 1) { @@ -508,6 +518,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records"); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num); + return; + } if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len); From a15864715390e33f566b1133ed69edf05004e7dc Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 8 May 2023 14:50:27 +0000 Subject: [PATCH 046/264] refactor TBM hadling --- libi2pd/I2NPProtocol.cpp | 74 ++++++++++++++++++---------------------- libi2pd/I2NPProtocol.h | 2 +- libi2pd/Tunnel.cpp | 8 ++--- 3 files changed, 38 insertions(+), 46 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index f100c6e5..623132ea 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -40,7 +40,7 @@ namespace i2p { return std::make_shared >(); } - + std::shared_ptr NewI2NPTunnelMessage (bool endpoint) { return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint); @@ -51,7 +51,7 @@ namespace i2p len += I2NP_HEADER_SIZE + 2; if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage (); if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage (); - return NewI2NPMessage (); + return NewI2NPMessage (); } void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum) @@ -748,46 +748,38 @@ namespace i2p return l; } - void HandleI2NPMessage (uint8_t * msg, size_t len) + void HandleTunnlBuildI2NPMessage (std::shared_ptr msg) { - if (len < I2NP_HEADER_SIZE) + if (msg) { - LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header"); - return; - } - uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; - uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); - LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); - uint8_t * buf = msg + I2NP_HEADER_SIZE; - auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); - len -= I2NP_HEADER_SIZE; - if (size > len) - { - LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len); - size = len; - } - switch (typeID) - { - case eI2NPVariableTunnelBuild: - HandleVariableTunnelBuildMsg (msgID, buf, size); - break; - case eI2NPShortTunnelBuild: - HandleShortTunnelBuildMsg (msgID, buf, size); - break; - case eI2NPVariableTunnelBuildReply: - HandleTunnelBuildReplyMsg (msgID, buf, size, false); - break; - case eI2NPShortTunnelBuildReply: - HandleTunnelBuildReplyMsg (msgID, buf, size, true); - break; - case eI2NPTunnelBuild: - HandleTunnelBuildMsg (buf, size); - break; - case eI2NPTunnelBuildReply: - // TODO: - break; - default: - LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID); + uint8_t typeID = msg->GetTypeID(); + uint32_t msgID = msg->GetMsgID(); + LogPrint (eLogDebug, "I2NP: Handling tunnel build message with len=", msg->GetLength(),", type=", (int)typeID, ", msgID=", (unsigned int)msgID); + uint8_t * payload = msg->GetPayload(); + auto size = msg->GetPayloadLength(); + switch (typeID) + { + case eI2NPVariableTunnelBuild: + HandleVariableTunnelBuildMsg (msgID, payload, size); + break; + case eI2NPShortTunnelBuild: + HandleShortTunnelBuildMsg (msgID, payload, size); + break; + case eI2NPVariableTunnelBuildReply: + HandleTunnelBuildReplyMsg (msgID, payload, size, false); + break; + case eI2NPShortTunnelBuildReply: + HandleTunnelBuildReplyMsg (msgID, payload, size, true); + break; + case eI2NPTunnelBuild: + HandleTunnelBuildMsg (payload, size); + break; + case eI2NPTunnelBuildReply: + // TODO: + break; + default: + LogPrint (eLogError, "I2NP: Unexpected message with type", (int)typeID, " during handling TBM; skipping"); + } } } @@ -851,7 +843,7 @@ namespace i2p i2p::tunnel::tunnels.PostTunnelData (msg); break; default: - HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); + LogPrint(eLogError, "I2NP: Unexpected I2NP message with type ", int(typeID), " during handling; skipping"); } } } diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index c0685190..5efd8f70 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -295,7 +295,7 @@ namespace tunnel std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); size_t GetI2NPMessageLength (const uint8_t * msg, size_t len); - void HandleI2NPMessage (uint8_t * msg, size_t len); + void HandleTunnlBuildI2NPMessage (std::shared_ptr msg); void HandleI2NPMessage (std::shared_ptr msg); class I2NPMessagesHandler diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 249f0a31..99824ab7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -516,7 +516,7 @@ namespace tunnel case eI2NPShortTunnelBuildReply: case eI2NPTunnelBuild: case eI2NPTunnelBuildReply: - HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); + HandleTunnlBuildI2NPMessage (msg); break; default: LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); @@ -590,13 +590,13 @@ namespace tunnel // DatabaseSearchReply with new routers i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); else if (IsRouterInfoMsg (msg)) - { + { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); - } + } tunnel->SendTunnelDataMsg (msg); } @@ -986,6 +986,6 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels); m_MaxNumTransitTunnels = maxNumTransitTunnels; } - } + } } } From d44be2fd73269d256295ede9b0637f33f27a7b85 Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 8 May 2023 15:33:40 +0000 Subject: [PATCH 047/264] fix typo --- libi2pd/I2NPProtocol.cpp | 8 ++++---- libi2pd/I2NPProtocol.h | 2 +- libi2pd/Tunnel.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 623132ea..8a6f443c 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -428,7 +428,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num); return; - } + } if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len); @@ -486,7 +486,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num); return; - } + } size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; if (len < num*recordSize + 1) { @@ -522,7 +522,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num); return; - } + } if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len); @@ -748,7 +748,7 @@ namespace i2p return l; } - void HandleTunnlBuildI2NPMessage (std::shared_ptr msg) + void HandleTunnelBuildI2NPMessage (std::shared_ptr msg) { if (msg) { diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 5efd8f70..6c64f2ab 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -295,7 +295,7 @@ namespace tunnel std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); size_t GetI2NPMessageLength (const uint8_t * msg, size_t len); - void HandleTunnlBuildI2NPMessage (std::shared_ptr msg); + void HandleTunnelBuildI2NPMessage (std::shared_ptr msg); void HandleI2NPMessage (std::shared_ptr msg); class I2NPMessagesHandler diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 99824ab7..db6f74f9 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -516,7 +516,7 @@ namespace tunnel case eI2NPShortTunnelBuildReply: case eI2NPTunnelBuild: case eI2NPTunnelBuildReply: - HandleTunnlBuildI2NPMessage (msg); + HandleTunnelBuildI2NPMessage (msg); break; default: LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); From c984f89dfb721a90dbb31f4c3bb169f6721fc82b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 May 2023 18:43:58 -0400 Subject: [PATCH 048/264] don't handle unecnrypted DatabaseSearchReply msg if came throug client tunnel --- libi2pd/I2NPProtocol.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 8a6f443c..b8147555 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -808,14 +808,12 @@ namespace i2p break; } case eI2NPDatabaseStore: + case eI2NPDatabaseSearchReply: // forward to netDb if came directly or through exploratory tunnel as response to our request if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ()) i2p::data::netdb.PostI2NPMsg (msg); break; - case eI2NPDatabaseSearchReply: - // forward to netDb - i2p::data::netdb.PostI2NPMsg (msg); - break; + case eI2NPDatabaseLookup: // forward to netDb if floodfill and came directly if (!msg->from && i2p::context.IsFloodfill ()) From e95fb3ab8941ae9e651bfc06b4e810b840c9460d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 May 2023 08:58:04 -0400 Subject: [PATCH 049/264] allow user/password authentication --- libi2pd_client/SOCKS.cpp | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index ca87e22a..c40cb479 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.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 * @@ -66,6 +66,11 @@ namespace proxy GET5_IPV6, GET5_HOST_SIZE, GET5_HOST, + GET5_USERPASSWD, + GET5_USER_SIZE, + GET5_USER, + GET5_PASSWD_SIZE, + GET5_PASSWD, READY, UPSTREAM_RESOLVE, UPSTREAM_CONNECT, @@ -129,6 +134,7 @@ namespace proxy boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); boost::asio::const_buffers_1 GenerateUpstreamRequest(); bool Socks5ChooseAuth(); + void Socks5UserPasswdResponse (); void SocksRequestFailed(errTypes error); void SocksRequestSuccess(); void SentSocksFailed(const boost::system::error_code & ecode); @@ -324,6 +330,15 @@ namespace proxy } } + void SOCKSHandler::Socks5UserPasswdResponse () + { + m_response[0] = 5; // Version + m_response[1] = 0; // Response code + LogPrint(eLogDebug, "SOCKS: v5 user/password response"); + boost::asio::async_write(*m_sock, boost::asio::const_buffers_1(m_response, 2), + std::bind(&SOCKSHandler::SentSocksResponse, shared_from_this(), std::placeholders::_1)); + } + /* All hope is lost beyond this point */ void SOCKSHandler::SocksRequestFailed(SOCKSHandler::errTypes error) { @@ -438,10 +453,15 @@ namespace proxy m_parseleft --; if (*sock_buff == AUTH_NONE) m_authchosen = AUTH_NONE; + else if (*sock_buff == AUTH_USERPASSWD) + m_authchosen = AUTH_USERPASSWD; if ( m_parseleft == 0 ) { if (!Socks5ChooseAuth()) return false; - EnterState(GET5_REQUESTV); + if (m_authchosen == AUTH_USERPASSWD) + EnterState(GET5_USERPASSWD); + else + EnterState(GET5_REQUESTV); } break; case GET_COMMAND: @@ -557,6 +577,35 @@ namespace proxy m_parseleft--; if (m_parseleft == 0) EnterState(GET_PORT); break; + case GET5_USERPASSWD: + if (*sock_buff != 1) + { + LogPrint(eLogError,"SOCKS: v5 rejected invalid username/password subnegotiation: ", ((int)*sock_buff)); + SocksRequestFailed(SOCKS5_GEN_FAIL); + return false; + } + EnterState(GET5_USER_SIZE); + break; + case GET5_USER_SIZE: + EnterState(GET5_USER, *sock_buff); + break; + case GET5_USER: + // skip user for now + m_parseleft--; + if (m_parseleft == 0) EnterState(GET5_PASSWD_SIZE); + break; + case GET5_PASSWD_SIZE: + EnterState(GET5_PASSWD, *sock_buff); + break; + case GET5_PASSWD: + // skip passwd for now + m_parseleft--; + if (m_parseleft == 0) + { + Socks5UserPasswdResponse (); + EnterState(GET5_REQUESTV); + } + break; default: LogPrint(eLogError, "SOCKS: Parse state?? ", m_state); Terminate(); From e56d243c3f883c3ba7addf1c5bc769ed9ebeef8a Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:04:56 +0300 Subject: [PATCH 050/264] [win32] suppress fallthrough warning Signed-off-by: r4sas --- Win32/Win32App.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 9eae7a95..fc61a8ac 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -348,6 +348,9 @@ namespace win32 } } } +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif } case WM_TRAYICON: { From a2726cf206a52360ab9798c1666059d5360a4cba Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:07:12 +0300 Subject: [PATCH 051/264] [cmake] print commit-based version if option is used Signed-off-by: r4sas --- build/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 05401b1f..f5d01a0b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -329,7 +329,11 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}") message(STATUS " BINARY : ${WITH_BINARY}") message(STATUS " STATIC BUILD : ${WITH_STATIC}") message(STATUS " UPnP : ${WITH_UPNP}") +if(WITH_GIT_VERSION) +message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})") +else() message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}") +endif() message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}") message(STATUS "---------------------------------------") From fdf38f45d966454ee0d7eb9092de7809bce2677d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 29 Apr 2023 22:00:13 +0300 Subject: [PATCH 052/264] more debug messages at destinations stop Signed-off-by: r4sas --- libi2pd/Destination.cpp | 11 +++++++++-- libi2pd_client/ClientContext.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6bcedb4e..a755347d 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1036,11 +1036,15 @@ namespace client void ClientDestination::Stop () { + LogPrint(eLogDebug, "Destination: Stopping destination ", GetIdentHash().ToBase32(), ".b32.i2p"); LeaseSetDestination::Stop (); m_ReadyChecker.cancel(); + LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination"); m_StreamingDestination->Stop (); //m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; + + LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination by ports"); for (auto& it: m_StreamingDestinationsByPorts) { it.second->Stop (); @@ -1048,11 +1052,14 @@ namespace client } m_StreamingDestinationsByPorts.clear (); m_LastStreamingDestination = nullptr; + if (m_DatagramDestination) { + LogPrint(eLogDebug, "Destination: -> Stopping Datagram Destination"); delete m_DatagramDestination; m_DatagramDestination = nullptr; } + LogPrint(eLogDebug, "Destination: -> Stopping done"); } void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) @@ -1075,10 +1082,10 @@ namespace client if (toPort != m_LastPort || !m_LastStreamingDestination) { m_LastStreamingDestination = GetStreamingDestination (toPort); - if (!m_LastStreamingDestination) + if (!m_LastStreamingDestination) m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default m_LastPort = toPort; - } + } if (m_LastStreamingDestination) m_LastStreamingDestination->HandleDataMessagePayload (buf, length); else diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index dadb9ae5..afb34c2a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -186,22 +186,30 @@ namespace client LogPrint(eLogInfo, "Clients: Stopping AddressBook"); m_AddressBook.Stop (); + LogPrint(eLogInfo, "Clients: Stopping UDP Tunnels"); { std::lock_guard lock(m_ForwardsMutex); m_ServerForwards.clear(); m_ClientForwards.clear(); } + LogPrint(eLogInfo, "Clients: Stopping UDP Tunnels timers"); if (m_CleanupUDPTimer) { m_CleanupUDPTimer->cancel (); m_CleanupUDPTimer = nullptr; } - for (auto& it: m_Destinations) - it.second->Stop (); - m_Destinations.clear (); + { + LogPrint(eLogInfo, "Clients: Stopping Destinations"); + std::lock_guard lock(m_DestinationsMutex); + for (auto& it: m_Destinations) + it.second->Stop (); + LogPrint(eLogInfo, "Clients: Stopping Destinations - Clear"); + m_Destinations.clear (); + } + LogPrint(eLogInfo, "Clients: Stopping SharedLocalDestination"); m_SharedLocalDestination->Release (); m_SharedLocalDestination = nullptr; } From dc6a42c26ff1572b97b59d64a2fd86bf5383053c Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 8 May 2023 22:49:12 +0300 Subject: [PATCH 053/264] [contrib] update example config file comments, remove ssu option Signed-off-by: r4sas --- contrib/i2pd.conf | 109 ++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 5d09c90a..5facbbd5 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -19,7 +19,7 @@ ## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates # certsdir = /var/lib/i2pd/certificates -## Where to write pidfile (default: i2pd.pid, not used in Windows) +## Where to write pidfile (default: /run/i2pd.pid, not used in Windows) # pidfile = /run/i2pd.pid ## Logging configuration section @@ -31,7 +31,7 @@ ## * file - log entries to a file ## * syslog - use syslog, see man 3 syslog # log = file -## Path to logfile (default - autodetect) +## Path to logfile (default: autodetect) # logfile = /var/log/i2pd/i2pd.log ## Log messages above this level (debug, info, *warn, error, critical, none) ## If you set it to none, logging will be disabled @@ -40,6 +40,7 @@ # logclftime = true ## Daemon mode. Router will go to background after start. Ignored on Windows +## (default: true) # daemon = true ## Specify a family, router belongs to (default - none) @@ -70,58 +71,60 @@ ## don't just uncomment this # port = 4567 -## Enable communication through ipv4 +## Enable communication through ipv4 (default: true) ipv4 = true -## Enable communication through ipv6 +## Enable communication through ipv6 (default: false) ipv6 = false -## Enable SSU transport -ssu = false - ## Bandwidth configuration -## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec, +## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec, ## X - unlimited -## Default is L (regular node) and X if floodfill mode enabled. If you want to -## share more bandwidth without floodfill mode, uncomment that line and adjust -## value to your possibilities +## Default is L (regular node) and X if floodfill mode enabled. +## If you want to share more bandwidth without floodfill mode, uncomment +## that line and adjust value to your possibilities. Value can be set to +## integer in kilobytes, it will apply that limit and flag will be used +## from next upper limit (example: if you set 4096 flag will be X, but real +## limit will be 4096 KB/s). Same can be done when floodfill mode is used, +## but keep in mind that low values may be negatively evaluated by Java +## router algorithms. # bandwidth = L -## Max % of bandwidth limit for transit. 0-100. 100 by default +## Max % of bandwidth limit for transit. 0-100 (default: 100) # share = 100 ## Router will not accept transit tunnels, disabling transit traffic completely -## (default = false) +## (default: false) # notransit = true -## Router will be floodfill +## Router will be floodfill (default: false) ## Note: that mode uses much more network connections and CPU! # floodfill = true [ntcp2] -## Enable NTCP2 transport (default = true) +## Enable NTCP2 transport (default: true) # enabled = true -## Publish address in RouterInfo (default = true) +## Publish address in RouterInfo (default: true) # published = true ## Port for incoming connections (default is global port option value) # port = 4567 [ssu2] -## Enable SSU2 transport +## Enable SSU2 transport (default: true) # enabled = true -## Publish address in RouterInfo +## Publish address in RouterInfo (default: true) # published = true -## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled) +## Port for incoming connections (default is global port option value) # port = 4567 [http] ## Web Console settings -## Uncomment and set to 'false' to disable Web Console +## Enable the Web Console (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 7070 -## Path to web console, default "/" +## Address and port service will listen on (default: 127.0.0.1:7070) +# address = 127.0.0.1 +# port = 7070 +## Path to web console (default: /) # webroot = / -## Uncomment following lines to enable Web Console authentication +## Enable Web Console authentication (default: false) ## You should not use Web Console via public networks without additional encryption. ## HTTP authentication is not encryption layer! # auth = true @@ -134,12 +137,12 @@ port = 7070 # lang = english [httpproxy] -## Uncomment and set to 'false' to disable HTTP Proxy +## Enable the HTTP proxy (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 4444 -## Optional keys file for proxy local destination +## Address and port service will listen on (default: 127.0.0.1:4444) +# address = 127.0.0.1 +# port = 4444 +## Optional keys file for proxy local destination (default: http-proxy-keys.dat) # 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, @@ -150,15 +153,15 @@ port = 4444 ## httpproxy section also accepts I2CP parameters, like "inbound.length" etc. [socksproxy] -## Uncomment and set to 'false' to disable SOCKS Proxy +## Enable the SOCKS proxy (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 4447 -## Optional keys file for proxy local destination +## Address and port service will listen on (default: 127.0.0.1:4447) +# address = 127.0.0.1 +# port = 4447 +## Optional keys file for proxy local destination (default: socks-proxy-keys.dat) # keys = socks-proxy-keys.dat ## Socks outproxy. Example below is set to use Tor for all connections except i2p -## Uncomment and set to 'true' to enable using of SOCKS outproxy +## Enable using of SOCKS outproxy (works only with SOCKS4, default: false) # outproxy.enabled = false ## Address and port of outproxy # outproxy = 127.0.0.1 @@ -166,34 +169,34 @@ port = 4447 ## socksproxy section also accepts I2CP parameters, like "inbound.length" etc. [sam] -## Comment or set to 'false' to disable SAM Bridge -enabled = true -## Address and ports service will listen on +## Enable the SAM bridge (default: true) +# enabled = false +## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655) # address = 127.0.0.1 # port = 7656 # portudp = 7655 [bob] -## Uncomment and set to 'true' to enable BOB command channel +## Enable the BOB command channel (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:2827) # address = 127.0.0.1 # port = 2827 [i2cp] -## Uncomment and set to 'true' to enable I2CP protocol +## Enable the I2CP protocol (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:7654) # address = 127.0.0.1 # port = 7654 [i2pcontrol] -## Uncomment and set to 'true' to enable I2PControl protocol +## Enable the I2PControl protocol (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:7650) # address = 127.0.0.1 # port = 7650 -## Authentication password. "itoopie" by default +## Authentication password (default: itoopie) # password = itoopie [precomputation] @@ -204,11 +207,11 @@ enabled = true [upnp] ## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID) # enabled = false -## Name i2pd appears in UPnP forwardings list (default = I2Pd) +## Name i2pd appears in UPnP forwardings list (default: I2Pd) # name = I2Pd [meshnets] -## Enable connectivity over the Yggdrasil network +## Enable connectivity over the Yggdrasil network (default: false) # yggdrasil = false ## You can bind address from your Yggdrasil subnet 300::/64 ## The address must first be added to the network interface @@ -216,7 +219,7 @@ enabled = true [reseed] ## Options for bootstrapping into I2P network, aka reseeding -## Enable or disable reseed data verification. +## Enable reseed data verification (default: true) verify = true ## URLs to request reseed data from, separated by comma ## Default: "mainline" I2P Network reseeds @@ -232,7 +235,7 @@ verify = true ## If you run i2pd behind a proxy server, set proxy server for reseeding here ## Should be http://address:port or socks://address:port # proxy = http://127.0.0.1:8118 -## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default +## Minimum number of known routers, below which i2pd triggers reseeding (default: 25) # threshold = 25 [addressbook] @@ -252,13 +255,13 @@ verify = true # coresize = 0 [trust] -## Enable explicit trust options. false by default +## Enable explicit trust options. (default: false) # enabled = true ## Make direct I2P connections only to routers in specified Family. # family = MyFamily ## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities. # routers = -## Should we hide our router from other routers? false by default +## Should we hide our router from other routers? (default: false) # hidden = true [exploratory] @@ -279,6 +282,6 @@ verify = true # aesni = true ## Use CPU AVX instructions set when work with cryptography when available (default: true) # avx = true -## Force usage of CPU instructions set, even if they not found +## Force usage of CPU instructions set, even if they not found (default: false) ## DO NOT TOUCH that option if you really don't know what are you doing! # force = false From ae439b5385944215ce9cba75eba55a2789b9989e Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 27 May 2023 01:00:19 +0300 Subject: [PATCH 054/264] SSU2: check if socket is opened before sending data, handle network_reset error Signed-off-by: r4sas --- libi2pd/Profiling.cpp | 24 ++++++++++++------------ libi2pd/SSU2.cpp | 23 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 754a2ce3..4fbf0fa2 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -30,7 +30,7 @@ namespace data { return boost::posix_time::second_clock::local_time(); } - + RouterProfile::RouterProfile (): m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), @@ -175,8 +175,8 @@ namespace data { m_HasConnected = true; UpdateTime (); - } - + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate @@ -223,7 +223,7 @@ namespace data m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; } - + bool RouterProfile::IsUseful() const { return m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || @@ -240,7 +240,7 @@ namespace data 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); @@ -261,7 +261,7 @@ namespace data { 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 ()) @@ -270,11 +270,11 @@ namespace data } else it++; - } + } } for (auto& it: tmp) if (it.second) it.second->Save (it.first); - } + } void SaveProfiles () { @@ -288,22 +288,22 @@ namespace data for (auto& it: tmp) if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); - } - + } + void DeleteObsoleteProfiles () { { 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); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5df4d33a..a9e04790 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -78,6 +78,7 @@ namespace transport if (address->IsV4 ()) { found = true; + LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port)); m_ReceiveService.GetService ().post( [this]() @@ -89,6 +90,7 @@ namespace transport if (address->IsV6 ()) { found = true; + LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port)); m_ReceiveService.GetService ().post( [this]() @@ -243,10 +245,12 @@ namespace transport if (!ecode || ecode == boost::asio::error::connection_refused || ecode == boost::asio::error::connection_reset + || ecode == boost::asio::error::network_reset || ecode == boost::asio::error::network_unreachable || ecode == boost::asio::error::host_unreachable #ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO || ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_ + || ecode.value() == boost::winapi::WSAENETRESET_ // 10052 || ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_ || ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_ #endif @@ -303,7 +307,7 @@ namespace transport else { auto ep = socket.local_endpoint (); - socket.close (); + LogPrint (eLogCritical, "SSU2: Reopening socket in HandleReceivedFrom: code ", ecode.value(), ": ", ecode.message ()); OpenSocket (ep); Receive (socket); } @@ -558,16 +562,25 @@ namespace transport SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to); return; } + std::vector bufs { boost::asio::buffer (header, headerLen), boost::asio::buffer (payload, payloadLen) }; + boost::system::error_code ec; if (to.address ().is_v6 ()) + { + if (!m_SocketV6.is_open ()) return; m_SocketV6.send_to (bufs, to, 0, ec); + } else + { + if (!m_SocketV4.is_open ()) return; m_SocketV4.send_to (bufs, to, 0, ec); + } + if (!ec) i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); else @@ -582,17 +595,25 @@ namespace transport SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to); return; } + std::vector bufs { boost::asio::buffer (header, headerLen), boost::asio::buffer (headerX, headerXLen), boost::asio::buffer (payload, payloadLen) }; + boost::system::error_code ec; if (to.address ().is_v6 ()) + { + if (!m_SocketV6.is_open ()) return; m_SocketV6.send_to (bufs, to, 0, ec); + } else + { + if (!m_SocketV4.is_open ()) return; m_SocketV4.send_to (bufs, to, 0, ec); + } if (!ec) i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen); From 86173400d5dda64da4a9c30bd4bd851d6bac7bcb Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 May 2023 08:49:45 -0400 Subject: [PATCH 055/264] don't drop profile of real router too early --- libi2pd/NetDb.hpp | 2 +- libi2pd/Profiling.cpp | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 4aa69d59..adfdcde7 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,7 +38,7 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; - const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1000; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 4fbf0fa2..47fc15e7 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -224,15 +224,11 @@ namespace data return (bool)m_LastUnreachableTime; } - bool RouterProfile::IsUseful() const { - return - m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || - m_NumTunnelsDeclined >= PEER_PROFILE_USEFUL_THRESHOLD || - m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD || - m_HasConnected; + bool RouterProfile::IsUseful() const + { + return IsReal () || m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD; } - std::shared_ptr GetRouterProfile (const IdentHash& identHash) { { @@ -286,7 +282,7 @@ namespace data } auto ts = GetTime (); for (auto& it: tmp) - if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + if (it.second->IsUseful() && (it.second->IsUpdated () || (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600)) it.second->Save (it.first); } From d5ee1f602fdc7a47ccc9a4e239ea720dd63f123a Mon Sep 17 00:00:00 2001 From: AsciiMoth Date: Tue, 30 May 2023 18:27:40 +0400 Subject: [PATCH 056/264] Update dates in license (#1934) Update copyright timestamp in LICENSE file from 2020 to actual 2023 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 9a1e4527..93280084 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2020, The PurpleI2P Project +Copyright (c) 2013-2023, The PurpleI2P Project All rights reserved. From dfe5df29e18afa7f93fa3c452ebe12398178ad6b Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 30 May 2023 21:05:15 +0300 Subject: [PATCH 057/264] suppress build warnings on windows Signed-off-by: r4sas --- libi2pd/util.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 2426f13a..088a7af5 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -201,7 +201,7 @@ namespace net int GetMTUWindowsIpv4 (sockaddr_in inputAddress, int fallback) { typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size); - IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); + IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found ULONG outBufLen = 0; @@ -262,7 +262,7 @@ namespace net int GetMTUWindowsIpv6 (sockaddr_in6 inputAddress, int fallback) { typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size); - IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); + IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found ULONG outBufLen = 0; @@ -341,7 +341,7 @@ namespace net #endif typedef int (* IPN)(int af, const char *src, void *dst); - IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); + IPN inetpton = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found if (localAddress.is_v4()) From 09f233dbfb07fb1c3edd38a47d65e56a99589d50 Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 6 Jun 2023 01:00:07 +0300 Subject: [PATCH 058/264] NetDB: ignore LeaseSet store request if not floodfill Signed-off-by: r4sas --- libi2pd/NetDb.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 18b6694b..baf96f74 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -267,12 +267,12 @@ namespace data if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) - { - if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) + { + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) m_Floodfills.Insert (r); else r->ResetFlooldFill (); - } + } } } else @@ -296,10 +296,10 @@ namespace data { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); if (r->IsFloodfill () && r->IsEligibleFloodfill ()) - { + { if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || - r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough - { + r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Insert (r); } @@ -840,7 +840,12 @@ namespace data LogPrint (eLogError, "NetDb: Database store message is too long ", len); return; } - if (!m->from) // unsolicited LS must be received directly + if (!context.IsFloodfill ()) + { + LogPrint (eLogInfo, "NetDb: Not Floodfill, LeaseSet store request ignored for ", ident.ToBase32()); + return; + } + else if (!m->from) // unsolicited LS must be received directly { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 { From 4e426727e961eb944d2501cee733afe700fbb961 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 10 Jun 2023 04:08:56 +0300 Subject: [PATCH 059/264] Webconsole: fix output on i2p tunnels, add b32 on dest page Fixes: * adding of "Client Destinations" section header when there is no such tunnels * Print error when destination is not found instead of empty page Adds: * Print b32 on destination page Signed-off-by: r4sas --- daemon/HTTPServer.cpp | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index f9b034ae..50666940 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -422,8 +422,12 @@ namespace http { static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest, uint32_t token) { + s << "Base32:
\r\n
\r\n
\r\n"; + s << "Base64:
\r\n
\r\n
\r\n"; + if (dest->IsEncryptedLeaseSet ()) { i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ()); @@ -605,6 +609,8 @@ namespace http { } s << "\r\n"; } + else + ShowError(s, tr("Such destination is not found")); } void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id) @@ -972,34 +978,42 @@ namespace http { void ShowI2PTunnels (std::stringstream& s) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - s << "" << tr("Client Tunnels") << ":
\r\n

\r\n"; - for (auto& it: i2p::client::context.GetClientTunnels ()) - { - auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << it.second->GetName () << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; - } + + auto& clientTunnels = i2p::client::context.GetClientTunnels (); auto httpProxy = i2p::client::context.GetHttpProxy (); - if (httpProxy) - { - auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << "HTTP " << tr("Proxy") << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; - } auto socksProxy = i2p::client::context.GetSocksProxy (); - if (socksProxy) + if (!clientTunnels.empty () || httpProxy || socksProxy) { - auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << "SOCKS " << tr("Proxy") << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "" << tr("Client Tunnels") << ":
\r\n
\r\n"; + if (!clientTunnels.empty ()) + { + for (auto& it: clientTunnels) + { + auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << it.second->GetName () << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + } + if (httpProxy) + { + auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << "HTTP " << tr("Proxy") << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + if (socksProxy) + { + auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << "SOCKS " << tr("Proxy") << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + s << "
\r\n"; } - s << "
\r\n"; auto& serverTunnels = i2p::client::context.GetServerTunnels (); if (!serverTunnels.empty ()) { From 75aa9f2c0c79c09d9ddc85465edad090dfee884d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 10 Jun 2023 04:30:48 +0300 Subject: [PATCH 060/264] i18n: update translation file Signed-off-by: r4sas --- contrib/i18n/English.po | 402 +++++++++++++++++++++------------------- contrib/i18n/README.md | 2 +- 2 files changed, 211 insertions(+), 193 deletions(-) diff --git a/contrib/i18n/English.po b/contrib/i18n/English.po index 22010680..7782187f 100644 --- a/contrib/i18n/English.po +++ b/contrib/i18n/English.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: i2pd\n" "Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n" -"POT-Creation-Date: 2023-01-19 04:18\n" +"POT-Creation-Date: 2023-06-10 01:25\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -18,28 +18,28 @@ msgstr "" "X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n" "X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n" -#: daemon/HTTPServer.cpp:106 +#: daemon/HTTPServer.cpp:107 #, c-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:110 +#: daemon/HTTPServer.cpp:111 #, c-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:114 +#: daemon/HTTPServer.cpp:115 #, c-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:117 +#: daemon/HTTPServer.cpp:118 #, c-format msgid "%d second" msgid_plural "%d seconds" @@ -47,560 +47,578 @@ msgstr[0] "" msgstr[1] "" #. tr: Kibibyte -#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153 +#: daemon/HTTPServer.cpp:126 #, c-format msgid "%.2f KiB" msgstr "" #. tr: Mebibyte -#: daemon/HTTPServer.cpp:127 +#: daemon/HTTPServer.cpp:128 #, c-format msgid "%.2f MiB" msgstr "" #. tr: Gibibyte -#: daemon/HTTPServer.cpp:129 +#: daemon/HTTPServer.cpp:130 #, c-format msgid "%.2f GiB" msgstr "" -#: daemon/HTTPServer.cpp:146 +#: daemon/HTTPServer.cpp:147 msgid "building" msgstr "" -#: daemon/HTTPServer.cpp:147 +#: daemon/HTTPServer.cpp:148 msgid "failed" msgstr "" -#: daemon/HTTPServer.cpp:148 +#: daemon/HTTPServer.cpp:149 msgid "expiring" msgstr "" -#: daemon/HTTPServer.cpp:149 +#: daemon/HTTPServer.cpp:150 msgid "established" msgstr "" -#: daemon/HTTPServer.cpp:150 +#: daemon/HTTPServer.cpp:151 msgid "unknown" msgstr "" -#: daemon/HTTPServer.cpp:152 +#: daemon/HTTPServer.cpp:153 msgid "exploratory" msgstr "" #. tr: Webconsole page title -#: daemon/HTTPServer.cpp:183 +#: daemon/HTTPServer.cpp:185 msgid "Purple I2P Webconsole" msgstr "" -#: daemon/HTTPServer.cpp:188 +#: daemon/HTTPServer.cpp:190 msgid "i2pd webconsole" msgstr "" -#: daemon/HTTPServer.cpp:191 +#: daemon/HTTPServer.cpp:193 msgid "Main page" msgstr "" -#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712 +#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742 msgid "Router commands" msgstr "" -#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387 -#: daemon/HTTPServer.cpp:399 +#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395 +#: daemon/HTTPServer.cpp:407 msgid "Local Destinations" msgstr "" -#: 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 +#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:365 +#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:474 +#: daemon/HTTPServer.cpp:636 daemon/HTTPServer.cpp:682 +#: daemon/HTTPServer.cpp:686 msgid "LeaseSets" msgstr "" -#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662 +#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692 msgid "Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364 -#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797 +#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372 +#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830 msgid "Transit Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855 +#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898 msgid "Transports" msgstr "" -#: daemon/HTTPServer.cpp:202 +#: daemon/HTTPServer.cpp:204 msgid "I2P tunnels" msgstr "" -#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884 -#: daemon/HTTPServer.cpp:894 +#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927 +#: daemon/HTTPServer.cpp:937 msgid "SAM sessions" msgstr "" -#: 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 +#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1329 +#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1335 +#: daemon/HTTPServer.cpp:1362 daemon/HTTPServer.cpp:1365 +#: daemon/HTTPServer.cpp:1379 daemon/HTTPServer.cpp:1424 +#: daemon/HTTPServer.cpp:1427 daemon/HTTPServer.cpp:1430 msgid "ERROR" msgstr "" -#: daemon/HTTPServer.cpp:227 +#: daemon/HTTPServer.cpp:229 msgid "OK" msgstr "" -#: daemon/HTTPServer.cpp:228 +#: daemon/HTTPServer.cpp:230 msgid "Testing" msgstr "" -#: daemon/HTTPServer.cpp:229 +#: daemon/HTTPServer.cpp:231 msgid "Firewalled" msgstr "" -#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233 -#: daemon/HTTPServer.cpp:329 +#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235 +#: daemon/HTTPServer.cpp:336 msgid "Unknown" msgstr "" -#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374 -#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952 -#: daemon/HTTPServer.cpp:961 +#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382 +#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003 +#: daemon/HTTPServer.cpp:1011 msgid "Proxy" msgstr "" -#: daemon/HTTPServer.cpp:232 +#: daemon/HTTPServer.cpp:234 msgid "Mesh" msgstr "" -#: daemon/HTTPServer.cpp:240 +#: daemon/HTTPServer.cpp:242 msgid "Clock skew" msgstr "" -#: daemon/HTTPServer.cpp:243 +#: daemon/HTTPServer.cpp:245 msgid "Offline" msgstr "" -#: daemon/HTTPServer.cpp:246 +#: daemon/HTTPServer.cpp:248 msgid "Symmetric NAT" msgstr "" -#: daemon/HTTPServer.cpp:249 +#: daemon/HTTPServer.cpp:251 msgid "Full cone NAT" msgstr "" -#: daemon/HTTPServer.cpp:252 +#: daemon/HTTPServer.cpp:254 msgid "No Descriptors" msgstr "" -#: daemon/HTTPServer.cpp:261 +#: daemon/HTTPServer.cpp:263 msgid "Uptime" msgstr "" -#: daemon/HTTPServer.cpp:264 +#: daemon/HTTPServer.cpp:266 msgid "Network status" msgstr "" -#: daemon/HTTPServer.cpp:269 +#: daemon/HTTPServer.cpp:271 msgid "Network status v6" msgstr "" -#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282 +#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284 msgid "Stopping in" msgstr "" -#: daemon/HTTPServer.cpp:289 +#: daemon/HTTPServer.cpp:291 msgid "Family" msgstr "" -#: daemon/HTTPServer.cpp:290 +#: daemon/HTTPServer.cpp:292 msgid "Tunnel creation success rate" msgstr "" -#: daemon/HTTPServer.cpp:291 +#: daemon/HTTPServer.cpp:296 +msgid "Total tunnel creation success rate" +msgstr "" + +#: daemon/HTTPServer.cpp:298 msgid "Received" msgstr "" #. tr: Kibibyte/s -#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296 -#: daemon/HTTPServer.cpp:299 +#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303 +#: daemon/HTTPServer.cpp:306 #, c-format msgid "%.2f KiB/s" msgstr "" -#: daemon/HTTPServer.cpp:294 +#: daemon/HTTPServer.cpp:301 msgid "Sent" msgstr "" -#: daemon/HTTPServer.cpp:297 +#: daemon/HTTPServer.cpp:304 msgid "Transit" msgstr "" -#: daemon/HTTPServer.cpp:300 +#: daemon/HTTPServer.cpp:307 msgid "Data path" msgstr "" -#: daemon/HTTPServer.cpp:303 +#: daemon/HTTPServer.cpp:310 msgid "Hidden content. Press on text to see." msgstr "" -#: daemon/HTTPServer.cpp:307 +#: daemon/HTTPServer.cpp:314 msgid "Router Ident" msgstr "" -#: daemon/HTTPServer.cpp:309 +#: daemon/HTTPServer.cpp:316 msgid "Router Family" msgstr "" -#: daemon/HTTPServer.cpp:310 +#: daemon/HTTPServer.cpp:317 msgid "Router Caps" msgstr "" -#: daemon/HTTPServer.cpp:311 +#: daemon/HTTPServer.cpp:318 msgid "Version" msgstr "" -#: daemon/HTTPServer.cpp:312 +#: daemon/HTTPServer.cpp:319 msgid "Our external address" msgstr "" #. tr: Shown when router doesn't publish itself and have "Firewalled" state -#: daemon/HTTPServer.cpp:341 +#: daemon/HTTPServer.cpp:349 msgid "supported" msgstr "" -#: daemon/HTTPServer.cpp:355 +#: daemon/HTTPServer.cpp:363 msgid "Routers" msgstr "" -#: daemon/HTTPServer.cpp:356 +#: daemon/HTTPServer.cpp:364 msgid "Floodfills" msgstr "" -#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938 +#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987 msgid "Client Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:373 +#: daemon/HTTPServer.cpp:381 msgid "Services" msgstr "" -#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 -#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 -#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 +#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383 +#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385 +#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387 msgid "Enabled" msgstr "" -#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 -#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 -#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 +#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383 +#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385 +#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387 msgid "Disabled" msgstr "" -#: daemon/HTTPServer.cpp:422 +#: daemon/HTTPServer.cpp:434 msgid "Encrypted B33 address" msgstr "" -#: daemon/HTTPServer.cpp:431 +#: daemon/HTTPServer.cpp:442 msgid "Address registration line" msgstr "" -#: daemon/HTTPServer.cpp:436 +#: daemon/HTTPServer.cpp:447 msgid "Domain" msgstr "" -#: daemon/HTTPServer.cpp:437 +#: daemon/HTTPServer.cpp:448 msgid "Generate" msgstr "" -#: daemon/HTTPServer.cpp:438 +#: daemon/HTTPServer.cpp:449 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:444 +#: daemon/HTTPServer.cpp:457 msgid "Address" msgstr "" -#: daemon/HTTPServer.cpp:444 +#: daemon/HTTPServer.cpp:459 msgid "Type" msgstr "" -#: daemon/HTTPServer.cpp:444 +#: daemon/HTTPServer.cpp:460 msgid "EncType" msgstr "" -#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667 +#: daemon/HTTPServer.cpp:467 +msgid "Expire LeaseSet" +msgstr "" + +#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:697 msgid "Inbound tunnels" msgstr "" #. tr: Milliseconds -#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489 -#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701 +#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514 +#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731 #, c-format msgid "%dms" msgstr "" -#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686 +#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716 msgid "Outbound tunnels" msgstr "" -#: daemon/HTTPServer.cpp:496 +#: daemon/HTTPServer.cpp:521 msgid "Tags" msgstr "" -#: daemon/HTTPServer.cpp:497 +#: daemon/HTTPServer.cpp:522 msgid "Incoming" msgstr "" -#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510 +#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535 msgid "Outgoing" msgstr "" -#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526 +#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551 msgid "Destination" msgstr "" -#: daemon/HTTPServer.cpp:507 +#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814 msgid "Amount" msgstr "" -#: daemon/HTTPServer.cpp:515 +#: daemon/HTTPServer.cpp:540 msgid "Incoming Tags" msgstr "" -#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529 +#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554 msgid "Tags sessions" msgstr "" -#: daemon/HTTPServer.cpp:526 +#: daemon/HTTPServer.cpp:551 msgid "Status" msgstr "" -#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594 +#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621 msgid "Local Destination" msgstr "" -#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917 +#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960 msgid "Streams" msgstr "" -#: daemon/HTTPServer.cpp:570 +#: daemon/HTTPServer.cpp:595 msgid "Close stream" msgstr "" -#: daemon/HTTPServer.cpp:599 +#: daemon/HTTPServer.cpp:613 daemon/HTTPServer.cpp:1430 +msgid "Such destination is not found" +msgstr "" + +#: daemon/HTTPServer.cpp:626 msgid "I2CP session not found" msgstr "" -#: daemon/HTTPServer.cpp:602 +#: daemon/HTTPServer.cpp:629 msgid "I2CP is not enabled" msgstr "" -#: daemon/HTTPServer.cpp:628 +#: daemon/HTTPServer.cpp:658 msgid "Invalid" msgstr "" -#: daemon/HTTPServer.cpp:631 +#: daemon/HTTPServer.cpp:661 msgid "Store type" msgstr "" -#: daemon/HTTPServer.cpp:632 +#: daemon/HTTPServer.cpp:662 msgid "Expires" msgstr "" -#: daemon/HTTPServer.cpp:637 +#: daemon/HTTPServer.cpp:667 msgid "Non Expired Leases" msgstr "" -#: daemon/HTTPServer.cpp:640 +#: daemon/HTTPServer.cpp:670 msgid "Gateway" msgstr "" -#: daemon/HTTPServer.cpp:641 +#: daemon/HTTPServer.cpp:671 msgid "TunnelID" msgstr "" -#: daemon/HTTPServer.cpp:642 +#: daemon/HTTPServer.cpp:672 msgid "EndDate" msgstr "" -#: daemon/HTTPServer.cpp:652 +#: daemon/HTTPServer.cpp:682 msgid "floodfill mode is disabled" msgstr "" -#: daemon/HTTPServer.cpp:663 +#: daemon/HTTPServer.cpp:693 msgid "Queue size" msgstr "" -#: daemon/HTTPServer.cpp:713 +#: daemon/HTTPServer.cpp:743 msgid "Run peer test" msgstr "" -#: daemon/HTTPServer.cpp:714 +#: daemon/HTTPServer.cpp:744 msgid "Reload tunnels configuration" msgstr "" -#: daemon/HTTPServer.cpp:717 +#: daemon/HTTPServer.cpp:747 msgid "Decline transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:719 +#: daemon/HTTPServer.cpp:749 msgid "Accept transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728 +#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758 msgid "Cancel graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730 +#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760 msgid "Start graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:733 +#: daemon/HTTPServer.cpp:763 msgid "Force shutdown" msgstr "" -#: daemon/HTTPServer.cpp:734 +#: daemon/HTTPServer.cpp:764 msgid "Reload external CSS styles" msgstr "" -#: daemon/HTTPServer.cpp:737 +#: daemon/HTTPServer.cpp:767 msgid "" "Note: any action done here are not persistent and not changes your " "config files." msgstr "" -#: daemon/HTTPServer.cpp:739 +#: daemon/HTTPServer.cpp:770 msgid "Logging level" msgstr "" -#: daemon/HTTPServer.cpp:747 +#: daemon/HTTPServer.cpp:779 msgid "Transit tunnels limit" msgstr "" -#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771 +#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803 msgid "Change" msgstr "" -#: daemon/HTTPServer.cpp:759 +#: daemon/HTTPServer.cpp:791 msgid "Change language" msgstr "" -#: daemon/HTTPServer.cpp:797 +#: daemon/HTTPServer.cpp:830 msgid "no transit tunnels currently built" msgstr "" -#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901 +#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944 msgid "SAM disabled" msgstr "" -#: daemon/HTTPServer.cpp:894 +#: daemon/HTTPServer.cpp:937 msgid "no sessions currently running" msgstr "" -#: daemon/HTTPServer.cpp:907 +#: daemon/HTTPServer.cpp:950 msgid "SAM session not found" msgstr "" -#: daemon/HTTPServer.cpp:912 +#: daemon/HTTPServer.cpp:955 msgid "SAM Session" msgstr "" -#: daemon/HTTPServer.cpp:969 +#: daemon/HTTPServer.cpp:1020 msgid "Server Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:985 +#: daemon/HTTPServer.cpp:1036 msgid "Client Forwards" msgstr "" -#: daemon/HTTPServer.cpp:999 +#: daemon/HTTPServer.cpp:1050 msgid "Server Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1199 +#: daemon/HTTPServer.cpp:1250 msgid "Unknown page" msgstr "" -#: daemon/HTTPServer.cpp:1218 +#: daemon/HTTPServer.cpp:1269 msgid "Invalid token" msgstr "" -#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333 -#: daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359 +#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454 msgid "SUCCESS" msgstr "" -#: daemon/HTTPServer.cpp:1276 +#: daemon/HTTPServer.cpp:1327 msgid "Stream closed" msgstr "" -#: daemon/HTTPServer.cpp:1278 +#: daemon/HTTPServer.cpp:1329 msgid "Stream not found or already was closed" msgstr "" -#: daemon/HTTPServer.cpp:1281 +#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365 msgid "Destination not found" msgstr "" -#: daemon/HTTPServer.cpp:1284 +#: daemon/HTTPServer.cpp:1335 msgid "StreamID can't be null" msgstr "" -#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351 +#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367 +#: daemon/HTTPServer.cpp:1432 msgid "Return to destination page" msgstr "" -#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300 -#: daemon/HTTPServer.cpp:1375 +#: daemon/HTTPServer.cpp:1338 daemon/HTTPServer.cpp:1368 +#: daemon/HTTPServer.cpp:1381 daemon/HTTPServer.cpp:1456 #, c-format msgid "You will be redirected in %d seconds" msgstr "" -#: daemon/HTTPServer.cpp:1298 +#: daemon/HTTPServer.cpp:1359 +msgid "LeaseSet expiration time updated" +msgstr "" + +#: daemon/HTTPServer.cpp:1362 +msgid "LeaseSet is not found or already expired" +msgstr "" + +#: daemon/HTTPServer.cpp:1379 #, c-format msgid "Transit tunnels count must not exceed %d" msgstr "" -#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374 +#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455 msgid "Back to commands list" msgstr "" -#: daemon/HTTPServer.cpp:1335 +#: daemon/HTTPServer.cpp:1416 msgid "Register at reg.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1336 +#: daemon/HTTPServer.cpp:1417 msgid "Description" msgstr "" -#: daemon/HTTPServer.cpp:1336 +#: daemon/HTTPServer.cpp:1417 msgid "A bit information about service on domain" msgstr "" -#: daemon/HTTPServer.cpp:1337 +#: daemon/HTTPServer.cpp:1418 msgid "Submit" msgstr "" -#: daemon/HTTPServer.cpp:1343 +#: daemon/HTTPServer.cpp:1424 msgid "Domain can't end with .b32.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1346 +#: daemon/HTTPServer.cpp:1427 msgid "Domain must end with .i2p" msgstr "" -#: daemon/HTTPServer.cpp:1349 -msgid "Such destination is not found" -msgstr "" - -#: daemon/HTTPServer.cpp:1369 +#: daemon/HTTPServer.cpp:1450 msgid "Unknown command" msgstr "" -#: daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:1454 msgid "Command accepted" msgstr "" @@ -624,20 +642,20 @@ msgstr "" msgid "You may try to find this host on jump services below" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324 -#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435 +#: libi2pd_client/HTTPProxy.cpp:333 libi2pd_client/HTTPProxy.cpp:348 +#: libi2pd_client/HTTPProxy.cpp:417 libi2pd_client/HTTPProxy.cpp:460 msgid "Invalid request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:309 +#: libi2pd_client/HTTPProxy.cpp:333 msgid "Proxy unable to parse your request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:324 +#: libi2pd_client/HTTPProxy.cpp:348 msgid "Addresshelper is not supported" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:349 +#: libi2pd_client/HTTPProxy.cpp:373 #, c-format msgid "" "Host %s is already in router's addressbook. Be " @@ -645,121 +663,121 @@ msgid "" "Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:351 +#: libi2pd_client/HTTPProxy.cpp:375 msgid "Addresshelper forced update rejected" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:358 +#: libi2pd_client/HTTPProxy.cpp:382 #, c-format msgid "" -"To add host %s in router's addressbook, click here: Continue." +"To add host %s in router's addressbook, click here: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:360 +#: libi2pd_client/HTTPProxy.cpp:384 msgid "Addresshelper request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:369 +#: libi2pd_client/HTTPProxy.cpp:393 #, c-format msgid "" "Host %s added to router's addressbook from helper. Click here to proceed: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:370 +#: libi2pd_client/HTTPProxy.cpp:395 msgid "Addresshelper adding" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:377 +#: libi2pd_client/HTTPProxy.cpp:402 #, c-format msgid "" "Host %s is already in router's addressbook. Click " "here to update record: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:379 +#: libi2pd_client/HTTPProxy.cpp:404 msgid "Addresshelper update" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:392 +#: libi2pd_client/HTTPProxy.cpp:417 msgid "Invalid request URI" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:435 +#: libi2pd_client/HTTPProxy.cpp:460 msgid "Can't detect destination host from request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456 +#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481 msgid "Outproxy failure" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:452 +#: libi2pd_client/HTTPProxy.cpp:477 msgid "Bad outproxy settings" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:455 +#: libi2pd_client/HTTPProxy.cpp:480 #, c-format msgid "Host %s is not inside I2P network, but outproxy is not enabled" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:544 +#: libi2pd_client/HTTPProxy.cpp:569 msgid "Unknown outproxy URL" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:550 +#: libi2pd_client/HTTPProxy.cpp:575 msgid "Cannot resolve upstream proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:558 +#: libi2pd_client/HTTPProxy.cpp:583 msgid "Hostname is too long" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:585 +#: libi2pd_client/HTTPProxy.cpp:610 msgid "Cannot connect to upstream SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:591 +#: libi2pd_client/HTTPProxy.cpp:616 msgid "Cannot negotiate with SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:633 +#: libi2pd_client/HTTPProxy.cpp:658 msgid "CONNECT error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:633 +#: libi2pd_client/HTTPProxy.cpp:658 msgid "Failed to connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670 +#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695 msgid "SOCKS proxy error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:652 +#: libi2pd_client/HTTPProxy.cpp:677 msgid "Failed to send request to upstream" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:673 +#: libi2pd_client/HTTPProxy.cpp:698 msgid "No reply from SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:680 +#: libi2pd_client/HTTPProxy.cpp:705 msgid "Cannot connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:680 +#: libi2pd_client/HTTPProxy.cpp:705 msgid "HTTP out proxy not implemented" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:681 +#: libi2pd_client/HTTPProxy.cpp:706 msgid "Cannot connect to upstream HTTP proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:714 +#: libi2pd_client/HTTPProxy.cpp:739 msgid "Host is down" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:714 +#: libi2pd_client/HTTPProxy.cpp:739 msgid "" "Can't create connection to requested host, it may be down. Please try again " "later." diff --git a/contrib/i18n/README.md b/contrib/i18n/README.md index 56d76c5a..1a9bd289 100644 --- a/contrib/i18n/README.md +++ b/contrib/i18n/README.md @@ -2,7 +2,7 @@ --- ``` -xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp +xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp ``` Regex for transforming gettext translations to our format: From bb52056aec59a296df6bec7ee44184b7a4b75136 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Jun 2023 06:48:47 -0400 Subject: [PATCH 061/264] correct index for connected transport --- libi2pd/Transports.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index f66a8f96..8daf56ef 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -710,9 +710,9 @@ namespace transport transports |= it->second.priority[i]; i2p::data::netdb.ExcludeReachableTransports (ident, transports); } - if (it->second.router) + if (it->second.router && it->second.numAttempts) { - auto transport = it->second.priority[it->second.numAttempts]; + auto transport = it->second.priority[it->second.numAttempts-1]; if (transport == i2p::data::RouterInfo::eNTCP2V4 || transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real From 52b2d6c39397f27fbeb9cab52cdf69c3fba5e0cb Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Jun 2023 15:44:16 -0400 Subject: [PATCH 062/264] 2.48.0 --- ChangeLog | 27 +++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6005d4f..424aaee5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,33 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.48.0] - 2023-06-12 +### Added +- Allow user/password authentication method for SOCK5 proxy +- Publish reject all congestion cap 'G' if transit is not accepted +- 'critical' log level +- Print b32 on webconsole destination page +- Webconsole button to drop a remote LeaseSet +- limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup +- Recognize real routers if successfully connected or responded to tunnel build request +### Changed +- Bypass slow transport sessions for first hop selection +- Limit AESNI inline asm to x86/x64 +- Create smaller I2NP packets if possible +- Make router unreachable if AEAD tag verification fails in SessionCreated +- Don't include a router to floodfills list until it's confirmed as real +- Drop LeaseSet store request if not floodfill +- Bypass medium congestion('D') routers for client tunnels +- Publish encrypted RouterInfo through tunnels +- Check if s is valid x25519 public key +- Check if socket is open before sending data in SSU2 +### Fixed +- Webconsole empty page if destination is not found +- i2p.streaming.answerPings param +- Reload tunnels +- Address caps for unspecified ipv6 address +- Incomplete HTTP headers in I2P tunnels + ## [2.47.0] - 2023-03-11 ### Added - Congestion caps diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 4ee7a8df..62a28631 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.47.0 +Version: 2.48.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 Jun 12 2023 orignal - 2.48.0 +- update to 2.48.0 + * Sat Mar 11 2023 orignal - 2.47.0 - update to 2.47.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 407e2d43..19825237 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.47.0 +Version: 2.48.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jun 12 2023 orignal - 2.48.0 +- update to 2.48.0 + * Sat Mar 11 2023 orignal - 2.47.0 - update to 2.47.0 diff --git a/debian/changelog b/debian/changelog index 44b0b8b5..91b0abdf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.48.0-1) unstable; urgency=high + + * updated to version 2.48.0/0.9.59 + + -- orignal Mon, 12 Jun 2023 16:00:00 +0000 + i2pd (2.47.0-1) unstable; urgency=high * updated to version 2.47.0/0.9.58 diff --git a/libi2pd/version.h b/libi2pd/version.h index 7d5e79fb..903ceebc 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 47 +#define I2PD_VERSION_MINOR 48 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 58 +#define I2P_VERSION_MICRO 59 #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 3af1f4bc763d6a47d982944b6f8bcbb8eb8541a0 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 00:32:44 +0300 Subject: [PATCH 063/264] Use of 'server' type tunnel port as inport (#1936) Signed-off-by: r4sas --- ChangeLog | 8 +++++--- libi2pd_client/I2PTunnel.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 424aaee5..881e05d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,9 +5,9 @@ ### Added - Allow user/password authentication method for SOCK5 proxy - Publish reject all congestion cap 'G' if transit is not accepted -- 'critical' log level +- 'critical' log level - Print b32 on webconsole destination page -- Webconsole button to drop a remote LeaseSet +- Webconsole button to drop a remote LeaseSet - limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup - Recognize real routers if successfully connected or responded to tunnel build request ### Changed @@ -26,7 +26,9 @@ - i2p.streaming.answerPings param - Reload tunnels - Address caps for unspecified ipv6 address -- Incomplete HTTP headers in I2P tunnels +- Incomplete HTTP headers in I2P tunnels +- SSU2 socket network exceptions on Windows +- Use of 'server' type tunnel port as inport (#1936) ## [2.47.0] - 2023-03-11 ### Added diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index d1006f26..1118da24 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -351,7 +351,7 @@ namespace client m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -434,12 +434,12 @@ namespace client } } else - { + { // insert incomplete line back m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -508,12 +508,12 @@ namespace client } } else - { + { // insert incomplete line back m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -708,10 +708,10 @@ namespace client int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - if (!inport) inport = port; - m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination) // default destination - m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); + int inPort = (inport ? inport : port); + m_PortDestination = localDestination->GetStreamingDestination (inPort); + if (!m_PortDestination) // default destination + m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); } void I2PServerTunnel::Start () From 03cc6e05249be47be31ed1ad2c4455c6c537de75 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 05:10:32 +0300 Subject: [PATCH 064/264] use uint16_t for ports Signed-off-by: r4sas --- libi2pd/Destination.cpp | 18 +++++++++--------- libi2pd/Destination.h | 18 +++++++++--------- libi2pd_client/BOB.cpp | 26 ++++++++++++++++---------- libi2pd_client/BOB.h | 20 ++++++++++---------- libi2pd_client/ClientContext.cpp | 26 +++++++++++++------------- libi2pd_client/HTTPProxy.cpp | 2 +- libi2pd_client/HTTPProxy.h | 6 +++--- libi2pd_client/I2CP.cpp | 2 +- libi2pd_client/I2CP.h | 4 ++-- libi2pd_client/I2PService.cpp | 6 +++--- libi2pd_client/I2PService.h | 10 +++++----- libi2pd_client/I2PTunnel.cpp | 20 ++++++++++---------- libi2pd_client/I2PTunnel.h | 24 ++++++++++++------------ libi2pd_client/SAM.cpp | 4 ++-- libi2pd_client/SAM.h | 6 +++--- libi2pd_client/SOCKS.cpp | 2 +- libi2pd_client/SOCKS.h | 4 ++-- 17 files changed, 102 insertions(+), 96 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index a755347d..b9555abe 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1111,7 +1111,7 @@ namespace client } } - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port) { if (!streamRequestComplete) { @@ -1141,7 +1141,7 @@ namespace client } } - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, int port) + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, uint16_t port) { if (!streamRequestComplete) { @@ -1160,7 +1160,7 @@ namespace client } template - std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, int port) + std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, uint16_t port) { volatile bool done = false; std::shared_ptr stream; @@ -1184,17 +1184,17 @@ namespace client return stream; } - std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) + std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, uint16_t port) { return CreateStreamSync (dest, port); } - std::shared_ptr ClientDestination::CreateStream (std::shared_ptr dest, int port) + std::shared_ptr ClientDestination::CreateStream (std::shared_ptr dest, uint16_t port) { return CreateStreamSync (dest, port); } - std::shared_ptr ClientDestination::CreateStream (std::shared_ptr remote, int port) + std::shared_ptr ClientDestination::CreateStream (std::shared_ptr remote, uint16_t port) { if (m_StreamingDestination) return m_StreamingDestination->CreateNewOutgoingStream (remote, port); @@ -1231,7 +1231,7 @@ namespace client }); } - std::shared_ptr ClientDestination::GetStreamingDestination (int port) const + std::shared_ptr ClientDestination::GetStreamingDestination (uint16_t port) const { if (port) { @@ -1269,7 +1269,7 @@ namespace client m_StreamingDestination->AcceptOnce (acceptor); } - std::shared_ptr ClientDestination::CreateStreamingDestination (int port, bool gzip) + std::shared_ptr ClientDestination::CreateStreamingDestination (uint16_t port, bool gzip) { auto dest = std::make_shared (GetSharedFromThis (), port, gzip); if (port) @@ -1279,7 +1279,7 @@ namespace client return dest; } - std::shared_ptr ClientDestination::RemoveStreamingDestination (int port) + std::shared_ptr ClientDestination::RemoveStreamingDestination (uint16_t port) { if (port) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 76508e49..3b395f4d 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -242,15 +242,15 @@ namespace client int GetRefCounter () const { return m_RefCounter; }; // streaming - std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional - std::shared_ptr GetStreamingDestination (int port = 0) const; - std::shared_ptr RemoveStreamingDestination (int port); + std::shared_ptr CreateStreamingDestination (uint16_t port, bool gzip = true); // additional + std::shared_ptr GetStreamingDestination (uint16_t port = 0) const; + std::shared_ptr RemoveStreamingDestination (uint16_t port); // following methods operate with default streaming destination - void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0); - void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, int port = 0); - std::shared_ptr CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync - std::shared_ptr CreateStream (std::shared_ptr dest, int port = 0); // sync - std::shared_ptr CreateStream (std::shared_ptr remote, int port = 0); + void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0); + void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, uint16_t port = 0); + std::shared_ptr CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync + std::shared_ptr CreateStream (std::shared_ptr dest, uint16_t port = 0); // sync + std::shared_ptr CreateStream (std::shared_ptr remote, uint16_t port = 0); void SendPing (const i2p::data::IdentHash& to); void SendPing (std::shared_ptr to); void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor); @@ -286,7 +286,7 @@ namespace client void ReadAuthKey (const std::string& group, const std::map * params); template - std::shared_ptr CreateStreamSync (const Dest& dest, int port); + std::shared_ptr CreateStreamSync (const Dest& dest, uint16_t port); private: diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 5f738380..3e6590f2 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.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 * @@ -127,7 +127,7 @@ namespace client connection->I2PConnect (receiver->data, receiver->dataLen); } - BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& outhost, int port, + BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& outhost, uint16_t port, std::shared_ptr localDestination, bool quiet): BOBI2PTunnel (localDestination), m_Endpoint (boost::asio::ip::address::from_string (outhost), port), m_IsQuiet (quiet) { @@ -164,7 +164,7 @@ namespace client BOBDestination::BOBDestination (std::shared_ptr localDestination, const std::string &nickname, const std::string &inhost, const std::string &outhost, - const int inport, const int outport, const bool quiet): + const uint16_t inport, const uint16_t outport, const bool quiet): m_LocalDestination (localDestination), m_OutboundTunnel (nullptr), m_InboundTunnel (nullptr), m_Nickname(nickname), m_InHost(inhost), m_OutHost(outhost), @@ -209,7 +209,7 @@ namespace client } } - void BOBDestination::CreateInboundTunnel (int port, const std::string& inhost) + void BOBDestination::CreateInboundTunnel (uint16_t port, const std::string& inhost) { if (!m_InboundTunnel) { @@ -230,7 +230,7 @@ namespace client } } - void BOBDestination::CreateOutboundTunnel (const std::string& outhost, int port, bool quiet) + void BOBDestination::CreateOutboundTunnel (const std::string& outhost, uint16_t port, bool quiet) { if (!m_OutboundTunnel) { @@ -595,9 +595,12 @@ namespace client LogPrint (eLogDebug, "BOB: outport ", operand); if (*operand) { - m_OutPort = std::stoi(operand); - if (m_OutPort >= 0) + int port = std::stoi(operand); + if (port >= 0 && port < 65536) + { + m_OutPort = port; SendReplyOK ("outbound port set"); + } else SendReplyError ("port out of range"); } @@ -622,9 +625,12 @@ namespace client LogPrint (eLogDebug, "BOB: inport ", operand); if (*operand) { - m_InPort = std::stoi(operand); - if (m_InPort >= 0) + int port = std::stoi(operand); + if (port >= 0 && port < 65536) + { + m_InPort = port; SendReplyOK ("inbound port set"); + } else SendReplyError ("port out of range"); } @@ -814,7 +820,7 @@ namespace client } } - BOBCommandChannel::BOBCommandChannel (const std::string& address, int port): + BOBCommandChannel::BOBCommandChannel (const std::string& address, uint16_t port): RunnableService ("BOB"), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)) { diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 2e6314e2..8b0b31d2 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.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 * @@ -124,7 +124,7 @@ namespace client { public: - BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr localDestination, bool quiet); + BOBI2POutboundTunnel (const std::string& outhost, uint16_t port, std::shared_ptr localDestination, bool quiet); void Start (); void Stop (); @@ -149,19 +149,19 @@ namespace client BOBDestination (std::shared_ptr localDestination, const std::string &nickname, const std::string &inhost, const std::string &outhost, - const int inport, const int outport, const bool quiet); + const uint16_t inport, const uint16_t outport, const bool quiet); ~BOBDestination (); void Start (); void Stop (); void StopTunnels (); - void CreateInboundTunnel (int port, const std::string& inhost); - void CreateOutboundTunnel (const std::string& outhost, int port, bool quiet); + void CreateInboundTunnel (uint16_t port, const std::string& inhost); + void CreateOutboundTunnel (const std::string& outhost, uint16_t port, bool quiet); const std::string& GetNickname() const { return m_Nickname; } const std::string& GetInHost() const { return m_InHost; } const std::string& GetOutHost() const { return m_OutHost; } - int GetInPort() const { return m_InPort; } - int GetOutPort() const { return m_OutPort; } + uint16_t GetInPort() const { return m_InPort; } + uint16_t GetOutPort() const { return m_OutPort; } bool GetQuiet() const { return m_Quiet; } bool IsRunning() const { return m_IsRunning; } const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); }; @@ -175,7 +175,7 @@ namespace client std::string m_Nickname; std::string m_InHost, m_OutHost; - int m_InPort, m_OutPort; + uint16_t m_InPort, m_OutPort; bool m_Quiet; bool m_IsRunning; }; @@ -237,7 +237,7 @@ namespace client boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer; bool m_IsOpen, m_IsQuiet, m_IsActive; std::string m_Nickname, m_InHost, m_OutHost; - int m_InPort, m_OutPort; + uint16_t m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; std::map m_Options; BOBDestination * m_CurrentDestination; @@ -248,7 +248,7 @@ namespace client { public: - BOBCommandChannel (const std::string& address, int port); + BOBCommandChannel (const std::string& address, uint16_t port); ~BOBCommandChannel (); void Start (); diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index afb34c2a..829756a1 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.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 * @@ -577,12 +577,12 @@ namespace client std::string dest; if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) dest = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION); - int port = section.second.get (I2P_CLIENT_TUNNEL_PORT); + uint16_t port = section.second.get (I2P_CLIENT_TUNNEL_PORT); // optional params - bool matchTunnels = section.second.get(I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false); - std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "transient"); - std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); - int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); + bool matchTunnels = section.second.get (I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false); + std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "transient"); + std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); + uint16_t destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); // I2CP @@ -720,22 +720,22 @@ namespace client { // mandatory params std::string host = section.second.get (I2P_SERVER_TUNNEL_HOST); - int port = section.second.get (I2P_SERVER_TUNNEL_PORT); + uint16_t port = section.second.get (I2P_SERVER_TUNNEL_PORT); std::string keys = section.second.get (I2P_SERVER_TUNNEL_KEYS); // optional params - int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); - std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); + uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); + std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); if(accessList == "") - accessList=section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); - std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); + accessList = section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); + std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, false); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, ""); - bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); - bool ssl = section.second.get(I2P_SERVER_TUNNEL_SSL, false); + bool isUniqueLocal = section.second.get (I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); + bool ssl = section.second.get (I2P_SERVER_TUNNEL_SSL, false); // I2CP std::map options; diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 61930876..26b47d8b 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -748,7 +748,7 @@ namespace proxy { Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination): + HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination): TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name), m_OutproxyUrl (outproxy), m_Addresshelper (addresshelper) { diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index 69ed4cef..d819a53c 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.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 * @@ -15,8 +15,8 @@ namespace proxy { { public: - HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); - HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); + HTTPProxy(const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : HTTPProxy(name, address, port, "", true, localDestination) {} ; ~HTTPProxy() {}; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 87f37e5e..2c53e766 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -936,7 +936,7 @@ namespace client } } - I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread): + I2CPServer::I2CPServer (const std::string& interface, uint16_t port, bool isSingleThread): RunnableService ("I2CP"), m_IsSingleThread (isSingleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port)) diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index e38da0ac..f0081ef6 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.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 client { public: - I2CPServer (const std::string& interface, int port, bool isSingleThread); + I2CPServer (const std::string& interface, uint16_t port, bool isSingleThread); ~I2CPServer (); void Start (); diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 2a6fe44e..c30b7c9f 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.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 * @@ -107,7 +107,7 @@ namespace client m_ReadyTimerTriggered = false; } - void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) { + void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, uint16_t port) { assert(streamRequestComplete); auto address = i2p::client::context.GetAddressBook ().GetAddress (dest); if (address) @@ -119,7 +119,7 @@ namespace client } } - void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr address, int port) + void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr address, uint16_t port) { if(m_ConnectTimeout && !m_LocalDestination->IsReady()) { diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index e14f85c1..4f67e19c 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.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 * @@ -59,8 +59,8 @@ namespace client if (dest) dest->Acquire (); m_LocalDestination = dest; } - void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); - void CreateStream(StreamRequestComplete complete, std::shared_ptr address, int port); + void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, uint16_t port = 0); + void CreateStream(StreamRequestComplete complete, std::shared_ptr address, uint16_t port); inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); } virtual void Start () = 0; @@ -155,11 +155,11 @@ namespace client { public: - TCPIPAcceptor (const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + TCPIPAcceptor (const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : I2PService(localDestination), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), m_Timer (GetService ()) {} - TCPIPAcceptor (const std::string& address, int port, i2p::data::SigningKeyType kt) : + TCPIPAcceptor (const std::string& address, uint16_t port, i2p::data::SigningKeyType kt) : I2PService(kt), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), m_Timer (GetService ()) {} diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 1118da24..9a9a4988 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -31,7 +31,7 @@ namespace client } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr leaseSet, int port): + std::shared_ptr leaseSet, uint16_t port): I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { @@ -581,7 +581,7 @@ namespace client { public: I2PClientTunnelHandler (I2PClientTunnel * parent, std::shared_ptr address, - int destinationPort, std::shared_ptr socket): + uint16_t destinationPort, std::shared_ptr socket): I2PServiceHandler(parent), m_Address(address), m_DestinationPort (destinationPort), m_Socket(socket) {}; void Handle(); @@ -589,7 +589,7 @@ namespace client private: void HandleStreamRequestComplete (std::shared_ptr stream); std::shared_ptr m_Address; - int m_DestinationPort; + uint16_t m_DestinationPort; std::shared_ptr m_Socket; }; @@ -630,7 +630,7 @@ namespace client } I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): + const std::string& address, uint16_t port, std::shared_ptr localDestination, uint16_t destinationPort): TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), m_DestinationPort (destinationPort), m_KeepAliveInterval (0) { @@ -705,10 +705,10 @@ namespace client } I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, uint16_t inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - int inPort = (inport ? inport : port); + uint16_t inPort = (inport ? inport : port); m_PortDestination = localDestination->GetStreamingDestination (inPort); if (!m_PortDestination) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); @@ -870,8 +870,8 @@ namespace client } I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& host, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, + const std::string& host, uint16_t inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_Host (host) { @@ -883,8 +883,8 @@ namespace client } I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& webircpass, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, + const std::string& webircpass, uint16_t inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_WebircPass (webircpass) { diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 4c7b2002..b94eb9e4 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.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 * @@ -41,7 +41,7 @@ namespace client public: I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr leaseSet, int port = 0); // to I2P + std::shared_ptr leaseSet, uint16_t port = 0); // to I2P I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream); // to I2P using simplified API I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, @@ -154,7 +154,7 @@ namespace client public: I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort = 0); + const std::string& address, uint16_t port, std::shared_ptr localDestination, uint16_t destinationPort = 0); ~I2PClientTunnel () {} void Start (); @@ -174,7 +174,7 @@ namespace client std::string m_Name, m_Destination; std::shared_ptr m_Address; - int m_DestinationPort; + uint16_t m_DestinationPort; uint32_t m_KeepAliveInterval; std::unique_ptr m_KeepAliveTimer; }; @@ -183,8 +183,8 @@ namespace client { public: - I2PServerTunnel (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, int inport = 0, bool gzip = true); + I2PServerTunnel (const std::string& name, const std::string& address, uint16_t port, + std::shared_ptr localDestination, uint16_t inport = 0, bool gzip = true); void Start (); void Stop (); @@ -200,7 +200,7 @@ namespace client void SetLocalAddress (const std::string& localAddress); const std::string& GetAddress() const { return m_Address; } - int GetPort () const { return m_Port; }; + uint16_t GetPort () const { return m_Port; }; uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); }; const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; } @@ -219,7 +219,7 @@ namespace client bool m_IsUniqueLocal; std::string m_Name, m_Address; - int m_Port; + uint16_t m_Port; boost::asio::ip::tcp::endpoint m_Endpoint; std::shared_ptr m_PortDestination; std::set m_AccessList; @@ -232,9 +232,9 @@ namespace client { public: - I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, + I2PServerTunnelHTTP (const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination, const std::string& host, - int inport = 0, bool gzip = true); + uint16_t inport = 0, bool gzip = true); private: @@ -249,9 +249,9 @@ namespace client { public: - I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, + I2PServerTunnelIRC (const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination, const std::string& webircpass, - int inport = 0, bool gzip = true); + uint16_t inport = 0, bool gzip = true); private: diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 4e19990a..bb9d6a6b 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1217,7 +1217,7 @@ namespace client subsessions.clear (); } - SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, int port): + SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) { if (Type == eSAMSessionTypeStream) @@ -1244,7 +1244,7 @@ namespace client // TODO: implement datagrams } - SAMBridge::SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread): + SAMBridge::SAMBridge (const std::string& address, uint16_t portTCP, uint16_t portUDP, bool singleThread): RunnableService ("SAM"), m_IsSingleThread (singleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), portTCP)), m_DatagramEndpoint (boost::asio::ip::address::from_string(address), (!portUDP) ? portTCP-1 : portUDP), m_DatagramSocket (GetIOService (), m_DatagramEndpoint), diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 97ac0b8e..b4c72754 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -221,9 +221,9 @@ namespace client struct SAMSubSession: public SAMSession { std::shared_ptr masterSession; - int inPort; + uint16_t inPort; - SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, int port); + SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port); // implements SAMSession std::shared_ptr GetLocalDestination (); void StopLocalDestination (); @@ -233,7 +233,7 @@ namespace client { public: - SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread); + SAMBridge (const std::string& address, uint16_t portTCP, uint16_t portUDP, bool singleThread); ~SAMBridge (); void Start (); diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index c40cb479..693c5185 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -837,7 +837,7 @@ namespace proxy shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, + SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, uint16_t port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination) : TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) diff --git a/libi2pd_client/SOCKS.h b/libi2pd_client/SOCKS.h index f41cfd72..bd88d6e6 100644 --- a/libi2pd_client/SOCKS.h +++ b/libi2pd_client/SOCKS.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 * @@ -23,7 +23,7 @@ namespace proxy { public: - SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, + SOCKSServer(const std::string& name, const std::string& address, uint16_t port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination = nullptr); ~SOCKSServer() {}; From a0795d85341b86f56893bb5e49cf1938467cd280 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 05:12:07 +0300 Subject: [PATCH 065/264] set server tunnel inport in ClientContext from port (#1936) Signed-off-by: r4sas --- libi2pd_client/ClientContext.cpp | 2 +- libi2pd_client/I2PTunnel.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 829756a1..d8c0bd2d 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -723,7 +723,7 @@ namespace client uint16_t port = section.second.get (I2P_SERVER_TUNNEL_PORT); std::string keys = section.second.get (I2P_SERVER_TUNNEL_KEYS); // optional params - uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); + uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, port); std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); if(accessList == "") accessList = section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 9a9a4988..ad4e14b8 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -708,10 +708,9 @@ namespace client uint16_t port, std::shared_ptr localDestination, uint16_t inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - uint16_t inPort = (inport ? inport : port); - m_PortDestination = localDestination->GetStreamingDestination (inPort); + m_PortDestination = localDestination->GetStreamingDestination (inport); if (!m_PortDestination) // default destination - m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); + m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } void I2PServerTunnel::Start () From fba23a45286f844710fa5c561ba60430ebc70d5e Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 16:33:21 +0300 Subject: [PATCH 066/264] i18n: update translations Signed-off-by: r4sas --- contrib/i18n/README.md | 9 +++++---- i18n/Chinese.cpp | 2 +- i18n/French.cpp | 18 +++++++++++------- i18n/Russian.cpp | 6 +++++- i18n/Swedish.cpp | 14 +++++++++++++- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/contrib/i18n/README.md b/contrib/i18n/README.md index 1a9bd289..ce775ecb 100644 --- a/contrib/i18n/README.md +++ b/contrib/i18n/README.md @@ -8,6 +8,11 @@ xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client Regex for transforming gettext translations to our format: --- +``` +in: ^(\"|#[:.,]|msgctxt)(.*)$\n +out: +``` + ``` 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 @@ -18,10 +23,6 @@ in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n out: {"$1", "$2"},\n ``` -``` -in: ^#[:.,](.*)$\n -out: -``` ``` in: \n\n diff --git a/i18n/Chinese.cpp b/i18n/Chinese.cpp index cd38fa0f..5ecfe067 100644 --- a/i18n/Chinese.cpp +++ b/i18n/Chinese.cpp @@ -109,6 +109,7 @@ namespace chinese // language namespace {"Local Destination", "本地目标"}, {"Streams", "流"}, {"Close stream", "断开流"}, + {"Such destination is not found", "找不到此目标"}, {"I2CP session not found", "未找到 I2CP 会话"}, {"I2CP is not enabled", "I2CP 未启用"}, {"Invalid", "无效"}, @@ -158,7 +159,6 @@ namespace chinese // language namespace {"Submit", "提交"}, {"Domain can't end with .b32.i2p", "域名不能以 .b32.i2p 结尾"}, {"Domain must end with .i2p", "域名必须以 .i2p 结尾"}, - {"Such destination is not found", "找不到此目标"}, {"Unknown command", "未知指令"}, {"Command accepted", "已接受指令"}, {"Proxy error", "代理错误"}, diff --git a/i18n/French.cpp b/i18n/French.cpp index 0ce044e1..8bec887c 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -69,6 +69,7 @@ namespace french // language namespace {"Stopping in", "Arrêt dans"}, {"Family", "Famille"}, {"Tunnel creation success rate", "Taux de succès de création de tunnels"}, + {"Total tunnel creation success rate", "Taux de réussite de création de tunnel"}, {"Received", "Reçu"}, {"%.2f KiB/s", "%.2f Kio/s"}, {"Sent", "Envoyé"}, @@ -91,10 +92,11 @@ namespace french // language namespace {"Address registration line", "Ligne d'inscription de l'adresse"}, {"Domain", "Domaine"}, {"Generate", "Générer"}, - {"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."}, + {"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"}, + {"Expire LeaseSet", "Expiration du LeaseSet"}, {"Inbound tunnels", "Tunnels entrants"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, @@ -109,6 +111,7 @@ namespace french // language namespace {"Local Destination", "Destination locale"}, {"Streams", "Flux"}, {"Close stream", "Fermer le flux"}, + {"Such destination is not found", "Cette destination est introuvable"}, {"I2CP session not found", "Session I2CP introuvable"}, {"I2CP is not enabled", "I2CP est désactivé"}, {"Invalid", "Invalide"}, @@ -128,7 +131,7 @@ namespace french // language namespace {"Start graceful shutdown", "Démarrer l'arrêt gracieux"}, {"Force shutdown", "Forcer l'arrêt"}, {"Reload external CSS styles", "Rafraîchir les styles CSS externes"}, - {"Note: any action done here are not persistent and not changes your config files.", "Note: Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."}, + {"Note: any action done here are not persistent and not changes your config files.", "Note : Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."}, {"Logging level", "Niveau de journalisation"}, {"Transit tunnels limit", "Limite sur les tunnels transitoires"}, {"Change", "Changer"}, @@ -150,6 +153,8 @@ namespace french // language namespace {"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 %d seconds", "Vous serez redirigé dans %d secondes"}, + {"LeaseSet expiration time updated", "Temps d'expiration du LeaseSet mis à jour"}, + {"LeaseSet is not found or already expired", "Le LeaseSet est introuvable ou a déjà expirée"}, {"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"}, @@ -158,24 +163,23 @@ namespace french // language namespace {"Submit", "Soumettre"}, {"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"}, {"Domain must end with .i2p", "Le domaine doit terminer par .i2p"}, - {"Such destination is not found", "Cette destination est introuvable"}, {"Unknown command", "Commande inconnue"}, {"Command accepted", "Commande acceptée"}, {"Proxy error", "Erreur de proxy"}, {"Proxy info", "Information sur le proxy"}, - {"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"}, + {"Proxy error: Host not found", "Erreur de proxy : Hôte introuvable"}, {"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"}, {"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 %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."}, + {"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."}, + {"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."}, + {"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"}, diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index dbfb13f2..15952710 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -69,6 +69,7 @@ namespace russian // language namespace {"Stopping in", "Остановка через"}, {"Family", "Семейство"}, {"Tunnel creation success rate", "Успешно построенных туннелей"}, + {"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"}, {"Received", "Получено"}, {"%.2f KiB/s", "%.2f КиБ/с"}, {"Sent", "Отправлено"}, @@ -95,6 +96,7 @@ namespace russian // language namespace {"Address", "Адрес"}, {"Type", "Тип"}, {"EncType", "ТипШифр"}, + {"Expire LeaseSet", "Просрочить Лизсет"}, {"Inbound tunnels", "Входящие туннели"}, {"%dms", "%dмс"}, {"Outbound tunnels", "Исходящие туннели"}, @@ -109,6 +111,7 @@ namespace russian // language namespace {"Local Destination", "Локальное назначение"}, {"Streams", "Стримы"}, {"Close stream", "Закрыть стрим"}, + {"Such destination is not found", "Такая точка назначения не найдена"}, {"I2CP session not found", "I2CP сессия не найдена"}, {"I2CP is not enabled", "I2CP не включен"}, {"Invalid", "Некорректный"}, @@ -150,6 +153,8 @@ namespace russian // language namespace {"StreamID can't be null", "StreamID не может быть пустым"}, {"Return to destination page", "Вернуться на страницу точки назначения"}, {"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"}, + {"LeaseSet expiration time updated", "Время действия LeaseSet обновлено"}, + {"LeaseSet is not found or already expired", "Лизсет не найден или время действия уже истекло"}, {"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"}, {"Back to commands list", "Вернуться к списку команд"}, {"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, @@ -158,7 +163,6 @@ namespace russian // language namespace {"Submit", "Отправить"}, {"Domain can't end with .b32.i2p", "Домен не может заканчиваться на .b32.i2p"}, {"Domain must end with .i2p", "Домен должен заканчиваться на .i2p"}, - {"Such destination is not found", "Такая точка назначения не найдена"}, {"Unknown command", "Неизвестная команда"}, {"Command accepted", "Команда принята"}, {"Proxy error", "Ошибка прокси"}, diff --git a/i18n/Swedish.cpp b/i18n/Swedish.cpp index e7f84e69..05ed1e18 100644 --- a/i18n/Swedish.cpp +++ b/i18n/Swedish.cpp @@ -61,6 +61,8 @@ namespace swedish // language namespace {"Clock skew", "Tidsförskjutning"}, {"Offline", "Nedkopplad"}, {"Symmetric NAT", "Symmetrisk NAT"}, + {"Full cone NAT", "Full kon NAT"}, + {"No Descriptors", "Inga Beskrivningar"}, {"Uptime", "Upptid"}, {"Network status", "Nätverkstillstånd"}, {"Network status v6", "Nätverkstillstånd v6"}, @@ -107,6 +109,7 @@ namespace swedish // language namespace {"Local Destination", "Lokal Plats"}, {"Streams", "Strömmar"}, {"Close stream", "Stäng strömmen"}, + {"Such destination is not found", "En sådan plats hittas ej"}, {"I2CP session not found", "I2CP-period hittades inte"}, {"I2CP is not enabled", "I2CP är inte påslaget"}, {"Invalid", "Ogiltig"}, @@ -116,8 +119,10 @@ namespace swedish // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "EndDate"}, + {"floodfill mode is disabled", "Floodfill läget är inaktiverat"}, {"Queue size", "Köstorlek"}, {"Run peer test", "Utför utsiktstest"}, + {"Reload tunnels configuration", "Ladda om tunnelkonfiguration"}, {"Decline transit tunnels", "Avvisa förmedlande tunnlar"}, {"Accept transit tunnels", "Tillåt förmedlande tunnlar"}, {"Cancel graceful shutdown", "Avbryt välvillig avstängning"}, @@ -154,7 +159,6 @@ namespace swedish // language namespace {"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"}, @@ -165,6 +169,14 @@ namespace swedish // language namespace {"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 %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "Värd %s är redan i routerns adressbok. Var försiktig: källan till denna URL kan vara skadlig! Klicka här för att uppdatera registreringen: Fortsätt."}, + {"Addresshelper forced update rejected", "Tvingad uppdatering av adresshjälparen nekad"}, + {"To add host %s in router's addressbook, click here: Continue.", "För att lägga till värd %s i routerns adressbok, klicka här: Fortsätt."}, + {"Addresshelper request", "Adresshjälpare förfrågan"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Värd %s tillagd i routerns adressbok från hjälparen. Klicka här för att fortsätta: Fortsätt."}, + {"Addresshelper adding", "Adresshjälpare tilläggning"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "Värd %s är redan i routerns adressbok. Klicka här för att uppdatera registreringen: Fortsätt."}, + {"Addresshelper update", "Adresshjälpare uppdatering"}, {"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"}, From ca02b5d860d7989c44355f9cbc35bc0e2449638d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 12 Jun 2023 14:45:34 +0000 Subject: [PATCH 067/264] debian: add compat patches for previous releases Signed-off-by: R4SAS --- contrib/debian/README | 7 +++++-- contrib/debian/bionic/compat | 1 + contrib/debian/bionic/control | 18 ++++++++++++++++++ contrib/debian/trusty/compat | 1 + contrib/debian/trusty/control | 18 ++++++++++++++++++ contrib/debian/trusty/patches/01-upnp.patch | 17 +++++++++++++++++ .../debian/trusty/patches/02-service.patch | 19 +++++++++++++++++++ contrib/debian/trusty/patches/series | 2 ++ contrib/debian/trusty/rules | 18 ++++++++++++++++++ contrib/debian/xenial/compat | 1 + contrib/debian/xenial/control | 18 ++++++++++++++++++ contrib/debian/xenial/patches/01-upnp.patch | 17 +++++++++++++++++ .../debian/xenial/patches/02-service.patch | 19 +++++++++++++++++++ contrib/debian/xenial/patches/series | 2 ++ contrib/debian/xenial/rules | 13 +++++++++++++ 15 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 contrib/debian/bionic/compat create mode 100644 contrib/debian/bionic/control create mode 100644 contrib/debian/trusty/compat create mode 100644 contrib/debian/trusty/control create mode 100644 contrib/debian/trusty/patches/01-upnp.patch create mode 100644 contrib/debian/trusty/patches/02-service.patch create mode 100644 contrib/debian/trusty/patches/series create mode 100755 contrib/debian/trusty/rules create mode 100644 contrib/debian/xenial/compat create mode 100644 contrib/debian/xenial/control create mode 100644 contrib/debian/xenial/patches/01-upnp.patch create mode 100644 contrib/debian/xenial/patches/02-service.patch create mode 100644 contrib/debian/xenial/patches/series create mode 100755 contrib/debian/xenial/rules diff --git a/contrib/debian/README b/contrib/debian/README index cccbc4de..7dc3a61f 100644 --- a/contrib/debian/README +++ b/contrib/debian/README @@ -1,2 +1,5 @@ -This forder contain systemd unit files. -To use systemd daemon control, place files from this directory to debian folder before building package. +This forder contain files required for building debian packages. + +The trunk repository is contains the packaging files for the latest stable version of Debian (if we not forgot to update them). + +Files in subdirectories contains fixes to make possible to build package on specific versions of Debian/Ubuntu. They are used when building the release package. diff --git a/contrib/debian/bionic/compat b/contrib/debian/bionic/compat new file mode 100644 index 00000000..b4de3947 --- /dev/null +++ b/contrib/debian/bionic/compat @@ -0,0 +1 @@ +11 diff --git a/contrib/debian/bionic/control b/contrib/debian/bionic/control new file mode 100644 index 00000000..d872881c --- /dev/null +++ b/contrib/debian/bionic/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 11~), 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.2.0 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/trusty/compat b/contrib/debian/trusty/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/contrib/debian/trusty/compat @@ -0,0 +1 @@ +9 diff --git a/contrib/debian/trusty/control b/contrib/debian/trusty/control new file mode 100644 index 00000000..fc618ddc --- /dev/null +++ b/contrib/debian/trusty/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 9), 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 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/trusty/patches/01-upnp.patch b/contrib/debian/trusty/patches/01-upnp.patch new file mode 100644 index 00000000..bec8f2b0 --- /dev/null +++ b/contrib/debian/trusty/patches/01-upnp.patch @@ -0,0 +1,17 @@ +Description: Enable UPnP usage in package +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2022-03-23 + +--- i2pd.orig/Makefile ++++ i2pd/Makefile +@@ -31,7 +31,7 @@ include filelist.mk + + USE_AESNI := $(or $(USE_AESNI),yes) + USE_STATIC := $(or $(USE_STATIC),no) +-USE_UPNP := $(or $(USE_UPNP),no) ++USE_UPNP := $(or $(USE_UPNP),yes) + DEBUG := $(or $(DEBUG),yes) + + # for debugging purposes only, when commit hash needed in trunk builds in i2pd version string diff --git a/contrib/debian/trusty/patches/02-service.patch b/contrib/debian/trusty/patches/02-service.patch new file mode 100644 index 00000000..12b35525 --- /dev/null +++ b/contrib/debian/trusty/patches/02-service.patch @@ -0,0 +1,19 @@ +Description: Disable LogsDirectory and LogsDirectoryMode options in service +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2023-05-17 + +--- a/contrib/i2pd.service ++++ b/contrib/i2pd.service +@@ -8,8 +8,8 @@ User=i2pd + Group=i2pd + RuntimeDirectory=i2pd + RuntimeDirectoryMode=0700 +-LogsDirectory=i2pd +-LogsDirectoryMode=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/contrib/debian/trusty/patches/series b/contrib/debian/trusty/patches/series new file mode 100644 index 00000000..d8caec41 --- /dev/null +++ b/contrib/debian/trusty/patches/series @@ -0,0 +1,2 @@ +01-upnp.patch +02-service.patch diff --git a/contrib/debian/trusty/rules b/contrib/debian/trusty/rules new file mode 100755 index 00000000..97a4e008 --- /dev/null +++ b/contrib/debian/trusty/rules @@ -0,0 +1,18 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 + +export DEB_BUILD_MAINT_OPTIONS=hardening=+all + +include /usr/share/dpkg/architecture.mk + +ifeq ($(DEB_HOST_ARCH),i386) + export DEB_BUILD_OPTIONS=parallel=1 +endif + +export DEB_CXXFLAGS_MAINT_APPEND=-Wall -pedantic +export DEB_LDFLAGS_MAINT_APPEND= + +%: + dh $@ --parallel + +override_dh_auto_install: diff --git a/contrib/debian/xenial/compat b/contrib/debian/xenial/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/contrib/debian/xenial/compat @@ -0,0 +1 @@ +9 diff --git a/contrib/debian/xenial/control b/contrib/debian/xenial/control new file mode 100644 index 00000000..fc618ddc --- /dev/null +++ b/contrib/debian/xenial/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 9), 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 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/xenial/patches/01-upnp.patch b/contrib/debian/xenial/patches/01-upnp.patch new file mode 100644 index 00000000..bec8f2b0 --- /dev/null +++ b/contrib/debian/xenial/patches/01-upnp.patch @@ -0,0 +1,17 @@ +Description: Enable UPnP usage in package +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2022-03-23 + +--- i2pd.orig/Makefile ++++ i2pd/Makefile +@@ -31,7 +31,7 @@ include filelist.mk + + USE_AESNI := $(or $(USE_AESNI),yes) + USE_STATIC := $(or $(USE_STATIC),no) +-USE_UPNP := $(or $(USE_UPNP),no) ++USE_UPNP := $(or $(USE_UPNP),yes) + DEBUG := $(or $(DEBUG),yes) + + # for debugging purposes only, when commit hash needed in trunk builds in i2pd version string diff --git a/contrib/debian/xenial/patches/02-service.patch b/contrib/debian/xenial/patches/02-service.patch new file mode 100644 index 00000000..12b35525 --- /dev/null +++ b/contrib/debian/xenial/patches/02-service.patch @@ -0,0 +1,19 @@ +Description: Disable LogsDirectory and LogsDirectoryMode options in service +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2023-05-17 + +--- a/contrib/i2pd.service ++++ b/contrib/i2pd.service +@@ -8,8 +8,8 @@ User=i2pd + Group=i2pd + RuntimeDirectory=i2pd + RuntimeDirectoryMode=0700 +-LogsDirectory=i2pd +-LogsDirectoryMode=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/contrib/debian/xenial/patches/series b/contrib/debian/xenial/patches/series new file mode 100644 index 00000000..d8caec41 --- /dev/null +++ b/contrib/debian/xenial/patches/series @@ -0,0 +1,2 @@ +01-upnp.patch +02-service.patch diff --git a/contrib/debian/xenial/rules b/contrib/debian/xenial/rules new file mode 100755 index 00000000..11791d9b --- /dev/null +++ b/contrib/debian/xenial/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +include /usr/share/dpkg/architecture.mk + +export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic +export DEB_LDFLAGS_MAINT_APPEND = + +%: + dh $@ --parallel + +override_dh_auto_install: From fee940238a4b8cba86eecb2204aadc445f824c24 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 17 Jun 2023 07:52:06 -0400 Subject: [PATCH 068/264] handle SOCK5 authrosation with empty user/password --- libi2pd_client/SOCKS.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 693c5185..649ad814 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -587,7 +587,10 @@ namespace proxy EnterState(GET5_USER_SIZE); break; case GET5_USER_SIZE: - EnterState(GET5_USER, *sock_buff); + if (*sock_buff) + EnterState(GET5_USER, *sock_buff); + else // empty user + EnterState(GET5_PASSWD_SIZE); break; case GET5_USER: // skip user for now @@ -595,7 +598,13 @@ namespace proxy if (m_parseleft == 0) EnterState(GET5_PASSWD_SIZE); break; case GET5_PASSWD_SIZE: - EnterState(GET5_PASSWD, *sock_buff); + if (*sock_buff) + EnterState(GET5_PASSWD, *sock_buff); + else // empty password + { + Socks5UserPasswdResponse (); + EnterState(GET5_REQUESTV); + } break; case GET5_PASSWD: // skip passwd for now From 07c529173e9833220eb89353c758cae03faf73f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 17 Jun 2023 10:08:04 -0400 Subject: [PATCH 069/264] send current version of the subnegotiation in user/password response --- libi2pd_client/SOCKS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 649ad814..547a2da2 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -332,7 +332,7 @@ namespace proxy void SOCKSHandler::Socks5UserPasswdResponse () { - m_response[0] = 5; // Version + m_response[0] = 1; // Version of the subnegotiation m_response[1] = 0; // Response code LogPrint(eLogDebug, "SOCKS: v5 user/password response"); boost::asio::async_write(*m_sock, boost::asio::const_buffers_1(m_response, 2), From 13f263b7910a30d59c4090a07d8773d0a1c99260 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Jun 2023 11:54:55 -0400 Subject: [PATCH 070/264] correct transport comptibility for OBEP in second attempt --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 3dc0256e..a2168f64 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -522,7 +522,7 @@ namespace tunnel } if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 { - auto hop1 = nextHop (prevHop, true); + auto hop1 = nextHop (prevHop, inbound); if (hop1) hop = hop1; } prevHop = hop; From 5f430269862c710ddaa7d97b8823b68a7fe5f24a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Jul 2023 12:30:33 -0400 Subject: [PATCH 071/264] check if local destination is not null --- libi2pd_client/BOB.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 3e6590f2..498a5460 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -667,6 +667,11 @@ namespace client return; } auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + if (!localDestination) + { + SendReplyError ("No local destination"); + return; + } if (addr->IsIdentHash ()) { // we might have leaseset already From b8f998f76a4acb0f0764e151308f6150a19f076c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Jul 2023 13:08:39 -0400 Subject: [PATCH 072/264] don't delete BOBDestination if used by another BOBSession --- libi2pd_client/BOB.cpp | 24 +++++++++++------------- libi2pd_client/BOB.h | 10 +++++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 498a5460..23c3b72f 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -357,13 +357,13 @@ namespace client os << data << std::endl; } - void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out) + void BOBCommandSession::BuildStatusLine(bool currentTunnel, std::shared_ptr dest, std::string &out) { // helper lambdas const auto issetStr = [](const std::string &str) { return str.empty() ? "not_set" : str; }; // for inhost, outhost const auto issetNum = [&issetStr](const int p) { return issetStr(p == 0 ? "" : std::to_string(p)); }; // for inport, outport const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; }; - const auto destReady = [](const BOBDestination * const dest) { return dest->IsRunning(); }; + const auto destReady = [](const BOBDestination * const dest) { return dest && dest->IsRunning(); }; const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str // tunnel info @@ -373,9 +373,9 @@ namespace client const std::string outhost = issetStr(currentTunnel ? m_OutHost : dest->GetOutHost()); const std::string inport = issetNum(currentTunnel ? m_InPort : dest->GetInPort()); const std::string outport = issetNum(currentTunnel ? m_OutPort : dest->GetOutPort()); - const bool keys = destExists(dest); // key must exist when destination is created - const bool starting = destExists(dest) && !destReady(dest); - const bool running = destExists(dest) && destReady(dest); + const bool keys = destExists(dest.get ()); // key must exist when destination is created + const bool starting = destExists(dest.get ()) && !destReady(dest.get ()); + const bool running = destExists(dest.get ()) && destReady(dest.get ()); const bool stopping = false; // build line @@ -446,7 +446,7 @@ namespace client if (!m_CurrentDestination) { - m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command + m_CurrentDestination = std::make_shared (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); } @@ -666,7 +666,8 @@ namespace client SendReplyError ("Address Not found"); return; } - auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + auto localDestination = (m_CurrentDestination && m_CurrentDestination->IsRunning ()) ? + m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); if (!localDestination) { SendReplyError ("No local destination"); @@ -880,8 +881,6 @@ namespace client { if (IsRunning ()) Stop (); - for (const auto& it: m_Destinations) - delete it.second; } void BOBCommandChannel::Start () @@ -898,9 +897,9 @@ namespace client StopIOService (); } - void BOBCommandChannel::AddDestination (const std::string& name, BOBDestination * dest) + void BOBCommandChannel::AddDestination (const std::string& name, std::shared_ptr dest) { - m_Destinations[name] = dest; + m_Destinations.emplace (name, dest); } void BOBCommandChannel::DeleteDestination (const std::string& name) @@ -909,12 +908,11 @@ namespace client if (it != m_Destinations.end ()) { it->second->Stop (); - delete it->second; m_Destinations.erase (it); } } - BOBDestination * BOBCommandChannel::FindDestination (const std::string& name) + std::shared_ptr BOBCommandChannel::FindDestination (const std::string& name) { auto it = m_Destinations.find (name); if (it != m_Destinations.end ()) diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 8b0b31d2..1f5fda5f 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -228,7 +228,7 @@ namespace client void SendReplyError (const char * msg); void SendRaw (const char * data); - void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out); + void BuildStatusLine(bool currentTunnel, std::shared_ptr destination, std::string &out); private: @@ -240,7 +240,7 @@ namespace client uint16_t m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; std::map m_Options; - BOBDestination * m_CurrentDestination; + std::shared_ptr m_CurrentDestination; }; typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len); @@ -255,9 +255,9 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return GetIOService (); }; - void AddDestination (const std::string& name, BOBDestination * dest); + void AddDestination (const std::string& name, std::shared_ptr dest); void DeleteDestination (const std::string& name); - BOBDestination * FindDestination (const std::string& name); + std::shared_ptr FindDestination (const std::string& name); private: @@ -267,7 +267,7 @@ namespace client private: boost::asio::ip::tcp::acceptor m_Acceptor; - std::map m_Destinations; + std::map > m_Destinations; std::map m_CommandHandlers; std::map m_HelpStrings; From 638e9b4d7ff7366c8e902d45ae1a0d3ae13189d8 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sat, 8 Jul 2023 17:07:04 -0700 Subject: [PATCH 073/264] Fixed division by zero due to thread race condition. --- libi2pd/NetDb.cpp | 4 +++- libi2pd/Transports.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index baf96f74..5134dbe0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1253,7 +1253,9 @@ namespace data uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::unique_lock l(m_RouterInfosMutex); - inds[0] %= m_RouterInfos.size (); + auto count = m_RouterInfos.size (); + if(count == 0) return nullptr; + inds[0] %= count; auto it = m_RouterInfos.begin (); std::advance (it, inds[0]); // try random router diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 8daf56ef..38d6e270 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -861,7 +861,9 @@ namespace transport uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::unique_lock l(m_PeersMutex); - inds[0] %= m_Peers.size (); + auto count = m_Peers.size (); + if(count == 0) return nullptr; + inds[0] %= count; auto it = m_Peers.begin (); std::advance (it, inds[0]); // try random peer From 2bb48b4546a0d174af55b32afac293cbeb8e4302 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 13:12:22 -0700 Subject: [PATCH 074/264] Fixed crash when Base64ToByteStream() is only given '=' characters. --- libi2pd/Base.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 94446e86..8f84728c 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -187,6 +187,9 @@ namespace data else return 0; + if(*InBuffer == P64) + return 0; + ps = (unsigned char *)(InBuffer + InCount - 1); while ( *ps-- == P64 ) outCount--; From 47dc5591b92b5fbf2385f5e25b0726dd5768ec12 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 15:09:17 -0700 Subject: [PATCH 075/264] Eliminate undefined behavior of bit shifting signed int. --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 94446e86..5f8b7e58 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -298,7 +298,7 @@ namespace data size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen) { size_t ret = 0, pos = 1; - int bits = 8, tmp = inBuf[0]; + unsigned int bits = 8, tmp = inBuf[0]; while (ret < outLen && (bits > 0 || pos < len)) { if (bits < 5) From c4be5f7fdb4ff4113b62f5b8f049887a9fcacdf4 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 18:45:30 -0700 Subject: [PATCH 076/264] Use offset from Identity::signingKey instead of Identity::certificate for key. --- libi2pd/Identity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index ca47e797..a4a9f716 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -581,7 +581,7 @@ namespace data if (keyType == SIGNING_KEY_TYPE_DSA_SHA1) m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ()) - m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check + m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check else { // public key is not required From 17c4038c6048a1567eba76b89a8a9e19d7e81d38 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Jul 2023 13:16:35 -0400 Subject: [PATCH 077/264] select router with ipv4 for endpoint --- libi2pd/NetDb.cpp | 19 ++++++++++++------- libi2pd/NetDb.hpp | 4 ++-- libi2pd/Tunnel.cpp | 4 ++-- libi2pd/TunnelPool.cpp | 19 ++++++++----------- libi2pd/TunnelPool.h | 4 ++-- libi2pd_client/MatchedDestination.cpp | 3 ++- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5134dbe0..7bccb2a0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -59,7 +59,7 @@ namespace data { Reseed (); } - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false)) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false)) Reseed (); // we don't have a router we can connect to. Trying to reseed auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); @@ -1199,15 +1199,17 @@ namespace data }); } - std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - router->IsECIES () && !router->IsHighCongestion (false); + router->IsECIES () && !router->IsHighCongestion (false) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); } @@ -1231,17 +1233,20 @@ namespace data }); } - std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES () && !router->IsHighCongestion (true); + router->IsECIES () && !router->IsHighCongestion (true) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) + }); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index adfdcde7..b7d9a5b3 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -84,8 +84,8 @@ namespace data void HandleNTCP2RouterInfoMsg (std::shared_ptr m); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; - std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; + std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; + std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) 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) const; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index db6f74f9..6234ceb4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -709,7 +709,7 @@ namespace tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); CreateTunnel ( @@ -781,7 +781,7 @@ namespace tunnel auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : // should be reachable by us because we send build request directly - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); if (!router) { LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); return; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a2168f64..5b305de1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -470,13 +470,14 @@ namespace tunnel return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); } - std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse) const + std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, + bool reverse, bool endpoint) const { - auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse); + auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint): + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint); if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse); + hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); return hop; } @@ -508,7 +509,7 @@ namespace tunnel for(int i = start; i < numHops; i++ ) { - auto hop = nextHop (prevHop, inbound); + auto hop = nextHop (prevHop, inbound, i == numHops - 1); 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"); @@ -520,11 +521,6 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 - { - auto hop1 = nextHop (prevHop, inbound); - if (hop1) hop = hop1; - } prevHop = hop; path.Add (hop); } @@ -566,7 +562,8 @@ namespace tunnel if (m_CustomPeerSelector) return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound); } - return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2)); + return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index e9dd142e..c1fd19cd 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, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -112,7 +112,7 @@ namespace tunnel std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude = nullptr) const; // for overriding tunnel peer selection - std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; + std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); private: diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 1e2e8275..40752f5b 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -73,7 +73,8 @@ namespace client { auto pool = GetTunnelPool(); if(!pool || !pool->StandardSelectPeers(path, hops, inbound, - std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) + std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3))) return false; // more here for outbound tunnels if(!inbound && m_RemoteLeaseSet) From ea7cf1cf6905257cd668848283ad86dfb5c6eb00 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 15 Jul 2023 18:44:37 +0300 Subject: [PATCH 078/264] fix termination block processing and size check --- libi2pd/NTCP2.cpp | 2 +- libi2pd/SSU2Session.cpp | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5e1cbaf6..364ebe8e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -884,7 +884,7 @@ namespace transport auto size = bufbe16toh (frame + offset); offset += 2; LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "NTCP2: Unexpected block length ", size); break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 49004437..23afd4c3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1486,7 +1486,7 @@ namespace transport auto size = bufbe16toh (buf + offset); offset += 2; LogPrint (eLogDebug, "SSU2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "SSU2: Unexpected block length ", size); break; @@ -1532,16 +1532,21 @@ namespace transport break; case eSSU2BlkTermination: { - uint8_t rsn = buf[11]; // reason - LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); - if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) - RequestTermination (eSSU2TerminationReasonTerminationReceived); - else if (m_State != eSSU2SessionStateTerminated) + if (size >= 9) { - if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) - m_State = eSSU2SessionStateClosingConfirmed; - Done (); + uint8_t rsn = buf[offset + 8]; // reason + LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); + if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) + RequestTermination (eSSU2TerminationReasonTerminationReceived); + else if (m_State != eSSU2SessionStateTerminated) + { + if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) + m_State = eSSU2SessionStateClosingConfirmed; + Done (); + } } + else + LogPrint(eLogWarning, "SSU2: Unexpected termination block size ", size); break; } case eSSU2BlkRelayRequest: From 8e63f8f333d21724bb5143f99f8ee0c471ddd473 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Jul 2023 17:11:56 -0400 Subject: [PATCH 079/264] consider all addresses non published for U and H routers --- libi2pd/RouterInfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 5ba8a5b1..646711c1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -995,6 +995,7 @@ namespace data bool RouterInfo::IsPublished (bool v4) const { + if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published auto addr = GetAddresses (); if (v4) return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || From 940a97db11d2e092273090319b4cf2f148bb0971 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 16 Jul 2023 14:02:30 +0300 Subject: [PATCH 080/264] [gha] fix msvc build Signed-off-by: r4sas --- .github/workflows/build-windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 356bb466..172e0596 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -29,7 +29,7 @@ jobs: - name: Install Boost uses: crazy-max/ghaction-chocolatey@v2 with: - args: install boost-msvc-14.3 + args: install boost-msvc-14.3 --version=1.81.0 - name: Install OpenSSL uses: crazy-max/ghaction-chocolatey@v2 From e7157cf15efddbe50a057c72afee5eb0a3276199 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 17:57:30 -0400 Subject: [PATCH 081/264] don't create paired inbound tunnel if length is different --- libi2pd/TunnelPool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5b305de1..fd31cb09 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -296,10 +296,12 @@ namespace tunnel for (const auto& it : m_InboundTunnels) if (it->IsEstablished ()) num++; } - if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0) + if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0 && + m_NumInboundHops == m_NumOutboundHops) { for (auto it: m_OutboundTunnels) { + // try to create inbound tunnel through the same path as succesive outbound CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; From c620fc1232e4a7823b2ac1558ffeb454c3a9f8b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 18:44:51 -0400 Subject: [PATCH 082/264] clear unreachable flag upon succesive connect --- libi2pd/NetDb.cpp | 9 +++------ libi2pd/Profiling.cpp | 6 +++--- libi2pd/Profiling.h | 2 +- libi2pd/Transports.cpp | 1 + 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 7bccb2a0..112d3cb3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -424,12 +424,9 @@ namespace data if (r) { r->SetUnreachable (unreachable); - if (unreachable) - { - auto profile = r->GetProfile (); - if (profile) - profile->Unreachable (); - } + auto profile = r->GetProfile (); + if (profile) + profile->Unreachable (unreachable); } } diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 47fc15e7..879aea29 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -165,12 +165,12 @@ namespace data } } - void RouterProfile::Unreachable () + void RouterProfile::Unreachable (bool unreachable) { - m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); + m_LastUnreachableTime = unreachable ? i2p::util::GetSecondsSinceEpoch () : 0; UpdateTime (); } - + void RouterProfile::Connected () { m_HasConnected = true; diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 6b814893..c351b41d 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -55,7 +55,7 @@ namespace data void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); - void Unreachable (); + void Unreachable (bool unreachable); void Connected (); boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 38d6e270..01e484f4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -716,6 +716,7 @@ namespace transport if (transport == i2p::data::RouterInfo::eNTCP2V4 || transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real + i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable } it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect From 902899ae2422d82147a5e73dac13d7a7f2297a30 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 19:49:42 -0400 Subject: [PATCH 083/264] don't pick completely unreachable peers --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 112d3cb3..061ccc23 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1203,7 +1203,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && router->IsECIES () && !router->IsHighCongestion (false) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) @@ -1237,7 +1237,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && From 0754255c1f597beba3f9dae5c21f7c99e927918b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 21:08:26 -0400 Subject: [PATCH 084/264] drop incoming session from too old or from future routers --- libi2pd/NTCP2.cpp | 11 +++++++++-- libi2pd/SSU2Session.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 364ebe8e..fa852f92 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,12 +695,19 @@ namespace transport SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { - LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); SendTerminationAndTerminate (eNTCP2Message3Error); return; } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri.GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "NTCP2: RouterInfo is from future for ", (ri.GetTimestamp () - ts)/1000LL, " seconds"); + SendTerminationAndTerminate (eNTCP2Message3Error); + return; + } 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)) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 23afd4c3..51c167ea 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1053,6 +1053,17 @@ namespace transport LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block"); return false; } + auto ts = i2p::util::GetMillisecondsSinceEpoch(); + if (ts > ri->GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is too old for ", (ts - ri->GetTimestamp ())/1000LL, " seconds"); + return false; + } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri->GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is from future for ", (ri->GetTimestamp () - ts)/1000LL, " seconds"); + return false; + } m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); if (!m_Address || memcmp (S, m_Address->s, 32)) { From f13cc0b862646c0d13514d429d1472df1b948883 Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 19 Jul 2023 16:38:04 +0300 Subject: [PATCH 085/264] allow 0 hops with explicitPeers --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index fd31cb09..23cc53e3 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -570,9 +570,9 @@ namespace tunnel bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) { + if (!m_ExplicitPeers->size ()) return false; int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size (); - if (!numHops) return false; for (int i = 0; i < numHops; i++) { auto& ident = (*m_ExplicitPeers)[i]; From 6e9a3422e9e723197c3ad56fbc9357f2656fe1f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 07:59:09 -0400 Subject: [PATCH 086/264] correct min size for keepalive --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 51c167ea..dcc5ad52 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -243,7 +243,7 @@ namespace transport if (IsEstablished ()) { uint8_t payload[20]; - size_t payloadSize = CreatePaddingBlock (payload, 20, 5); + size_t payloadSize = CreatePaddingBlock (payload, 20, 8); SendData (payload, payloadSize); } } From c7efd465fa5bd06d4fccfde0e771a1920c624049 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 18:25:28 -0400 Subject: [PATCH 087/264] padding for path response --- libi2pd/SSU2Session.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index dcc5ad52..4a1395b3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2857,7 +2857,7 @@ namespace transport void SSU2Session::SendPathResponse (const uint8_t * data, size_t len) { - if (len < 8 || len > m_MaxPayloadSize - 3) + if (len > m_MaxPayloadSize - 3) { LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); return; @@ -2866,7 +2866,10 @@ namespace transport payload[0] = eSSU2BlkPathResponse; htobe16buf (payload + 1, len); memcpy (payload + 3, data, len); - SendData (payload, len + 3); + size_t payloadSize = len + 3; + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0); + SendData (payload, payloadSize); } void SSU2Session::SendPathChallenge () @@ -2884,7 +2887,7 @@ namespace transport } len += 3; if (len < m_MaxPayloadSize) - len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len); + len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); SendData (payload, len); } From b8e19bf5f1e3fbcf0f45ccfb85b1923142d96e46 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 08:50:49 -0400 Subject: [PATCH 088/264] reduced peer test interval and added peer test interval variance --- libi2pd/SSU2.cpp | 12 ++++++++---- libi2pd/SSU2.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index a9e04790..6594f6d9 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1078,7 +1078,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1091,7 +1092,8 @@ namespace transport m_IntroducersUpdateTimer.cancel (); i2p::context.ClearSSU2Introducers (true); m_Introducers.clear (); - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1101,7 +1103,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } @@ -1114,7 +1117,8 @@ namespace transport m_IntroducersUpdateTimerV6.cancel (); i2p::context.ClearSSU2Introducers (false); m_IntroducersV6.clear (); - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 2e652786..a1fafc63 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -29,7 +29,8 @@ namespace transport const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes - const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds class SSU2Server: private i2p::util::RunnableServiceWithWork From 413e25f20e16a0a0e1b01ed9cdf1d76e20ba3a5b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 10:13:05 -0400 Subject: [PATCH 089/264] don't pick too old session for introducer --- libi2pd/SSU2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6594f6d9..f3f0542d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1035,10 +1035,13 @@ namespace transport for (const auto& it : sessions) { + uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; introducer.iTag = it->GetRelayTag (); introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); - introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); if (i2p::context.AddSSU2Introducer (introducer, v4)) { From d6834d6a9a205756f77a1ec02488db947a1c4d4d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 15:03:03 -0400 Subject: [PATCH 090/264] keep non-published, but not-expired introducers in the introducers list --- libi2pd/SSU2.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index f3f0542d..959bef54 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -983,7 +983,7 @@ namespace transport void SSU2Server::UpdateIntroducers (bool v4) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - std::list newList; + std::list newList, impliedList; auto& introducers = v4 ? m_Introducers : m_IntroducersV6; std::set excluded; for (const auto& it : introducers) @@ -997,12 +997,17 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - session->SendKeepAlive (); if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else + { + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + { + impliedList.push_back (it); // keep in introducers list, but not publish + session->SendKeepAlive (); + } session = nullptr; + } } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); @@ -1024,10 +1029,7 @@ namespace transport { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) - { - newList.push_back (it); sessions.push_back (session); - } } } } @@ -1075,6 +1077,7 @@ namespace transport } } } + introducers.splice (introducers.end (), impliedList); // insert non-published, but non-expired introducers back } void SSU2Server::ScheduleIntroducersUpdateTimer () From 4aa631c33f7db3e75979a3e21da3597ebd83bc6b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 16:51:19 -0400 Subject: [PATCH 091/264] clear implied list if no more introducers found --- libi2pd/SSU2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 959bef54..c371928c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1019,6 +1019,7 @@ namespace transport { // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); + impliedList.clear (); for (auto& it : introducers) { auto it1 = m_SessionsByRouterHash.find (it); From 2064504ccedc84d16007db4b22f8385c949dec28 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:17:10 -0400 Subject: [PATCH 092/264] fixed send keepalive for existing session --- libi2pd/SSU2.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index c371928c..0832b78c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,17 +997,16 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - { impliedList.push_back (it); // keep in introducers list, but not publish - session->SendKeepAlive (); - } - session = nullptr; - } + else + session = nullptr; + } + if (session) session->SendKeepAlive (); } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From ae5239de435e1dcdff342961af9b506f60a494d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:42:36 -0400 Subject: [PATCH 093/264] remove introducer from RouterInfo after 60 minutes --- libi2pd/SSU2.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 0832b78c..ac42ca7a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,16 +997,19 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) - newList.push_back (it); - else + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + session->SendKeepAlive (); + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + newList.push_back (it); + else + { impliedList.push_back (it); // keep in introducers list, but not publish - else - session = nullptr; + session = nullptr; + } } - if (session) session->SendKeepAlive (); + else + session = nullptr; } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From 68f4961f1aff340f5e0269af7653cf029918d97a Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 30 Jul 2023 15:29:10 +0300 Subject: [PATCH 094/264] separate test status from network status --- Win32/Win32App.cpp | 9 ++++--- daemon/HTTPServer.cpp | 9 ++++--- libi2pd/RouterContext.cpp | 31 ++++++++++++++++++------ libi2pd/RouterContext.h | 14 +++++++---- libi2pd/SSU2.cpp | 4 +-- libi2pd/SSU2Session.cpp | 51 ++++++++++++++++++++++++++++++--------- libi2pd/SSU2Session.h | 2 ++ libi2pd/Transports.cpp | 12 ++++----- 8 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index fc61a8ac..9f750c4c 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -145,18 +145,19 @@ namespace win32 s << bytes << " Bytes\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing) { switch (status) { case eRouterStatusOK: s << "OK"; break; - case eRouterStatusTesting: s << "Test"; break; case eRouterStatusFirewalled: s << "FW"; break; case eRouterStatusUnknown: s << "Unk"; break; case eRouterStatusProxy: s << "Proxy"; break; case eRouterStatusMesh: s << "Mesh"; break; default: s << "Unk"; }; + if (testing) + s << " (Test)"; if (i2p::context.GetError () != eRouterErrorNone) { switch (i2p::context.GetError ()) @@ -179,11 +180,11 @@ namespace win32 { s << "\n"; s << "Status: "; - ShowNetworkStatus (s, i2p::context.GetStatus ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ()); if (i2p::context.SupportsV6 ()) { s << " / "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ()); } s << "; "; s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 50666940..2d6800b4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -222,18 +222,19 @@ namespace http { s << "" << tr("ERROR") << ": " << string << "
\r\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error) { switch (status) { case eRouterStatusOK: s << tr("OK"); break; - case eRouterStatusTesting: s << tr("Testing"); break; case eRouterStatusFirewalled: s << tr("Firewalled"); break; case eRouterStatusUnknown: s << tr("Unknown"); break; case eRouterStatusProxy: s << tr("Proxy"); break; case eRouterStatusMesh: s << tr("Mesh"); break; default: s << tr("Unknown"); } + if (testing) + s << " (" << tr("Testing") << ")"; if (error != eRouterErrorNone) { switch (error) @@ -264,12 +265,12 @@ namespace http { ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; s << "" << tr("Network status") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ()); s << "
\r\n"; if (i2p::context.SupportsV6 ()) { s << "" << tr("Network status v6") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ()); s << "
\r\n"; } #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 3e7d7a2c..fa3ba7bd 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -31,7 +31,8 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), - m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID), + m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), + m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID), m_PublishReplyToken (0), m_IsHiddenMode (false) { } @@ -277,8 +278,29 @@ namespace i2p fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); } + void RouterContext::SetTesting (bool testing) + { + if (testing != m_Testing) + { + m_Testing = testing; + if (m_Testing) + m_Error = eRouterErrorNone; + } + } + + void RouterContext::SetTestingV6 (bool testing) + { + if (testing != m_TestingV6) + { + m_TestingV6 = testing; + if (m_TestingV6) + m_ErrorV6 = eRouterErrorNone; + } + } + void RouterContext::SetStatus (RouterStatus status) { + SetTesting (false); if (status != m_Status) { m_Status = status; @@ -290,9 +312,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (true, false); // ipv4 break; - case eRouterStatusTesting: - m_Error = eRouterErrorNone; - break; default: ; } @@ -301,6 +320,7 @@ namespace i2p void RouterContext::SetStatusV6 (RouterStatus status) { + SetTestingV6 (false); if (status != m_StatusV6) { m_StatusV6 = status; @@ -312,9 +332,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (false, true); // ipv6 break; - case eRouterStatusTesting: - m_ErrorV6 = eRouterErrorNone; - break; default: ; } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index b8183339..d49b5523 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -42,11 +42,10 @@ namespace garlic enum RouterStatus { eRouterStatusOK = 0, - eRouterStatusTesting = 1, - eRouterStatusFirewalled = 2, - eRouterStatusUnknown = 3, - eRouterStatusProxy = 4, - eRouterStatusMesh = 5 + eRouterStatusFirewalled = 1, + eRouterStatusUnknown = 2, + eRouterStatusProxy = 3, + eRouterStatusMesh = 4 }; enum RouterError @@ -121,10 +120,14 @@ namespace garlic uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; }; uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; }; + bool GetTesting () const { return m_Testing; }; + void SetTesting (bool testing); RouterStatus GetStatus () const { return m_Status; }; void SetStatus (RouterStatus status); RouterError GetError () const { return m_Error; }; void SetError (RouterError error) { m_Error = error; }; + bool GetTestingV6 () const { return m_TestingV6; }; + void SetTestingV6 (bool testing); RouterStatus GetStatusV6 () const { return m_StatusV6; }; void SetStatusV6 (RouterStatus status); RouterError GetErrorV6 () const { return m_ErrorV6; }; @@ -231,6 +234,7 @@ namespace garlic int m_ShareRatio; RouterStatus m_Status, m_StatusV6; RouterError m_Error, m_ErrorV6; + bool m_Testing, m_TestingV6; int m_NetID; std::unique_ptr m_NTCP2Keys; std::unique_ptr m_SSU2Keys; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index ac42ca7a..53ef8db7 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1140,7 +1140,7 @@ namespace transport // timeout expired if (v4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetTesting ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimer (); @@ -1163,7 +1163,7 @@ namespace transport } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimerV6 (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4a1395b3..54add930 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1651,8 +1651,8 @@ namespace transport break; case eSSU2SessionStateSessionCreatedReceived: case eSSU2SessionStateTokenReceived: - if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) || - (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting)) + if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetTesting ()) || + (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetTestingV6 ())) { if (m_Server.IsSyncClockFromPeers ()) { @@ -1750,14 +1750,14 @@ 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.GetTesting ()) i2p::context.SetError (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetError (eRouterErrorFullConeNAT); } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetErrorV6 (eRouterErrorFullConeNAT); @@ -2230,7 +2230,7 @@ namespace transport if (buf[1] == eSSU2PeerTestCodeAccept) { if (GetRouterStatus () == eRouterStatusUnknown) - SetRouterStatus (eRouterStatusTesting); + SetTestingState (true); auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie if (r && it->second.first) { @@ -2256,13 +2256,17 @@ namespace transport } else { - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) { - SetRouterStatus (eRouterStatusFirewalled); - if (m_Address->IsV4 ()) - m_Server.RescheduleIntroducersUpdateTimer (); - else - m_Server.RescheduleIntroducersUpdateTimerV6 (); + SetTestingState (false); + if (GetRouterStatus () != eRouterStatusFirewalled) + { + SetRouterStatus (eRouterStatusFirewalled); + if (m_Address->IsV4 ()) + m_Server.RescheduleIntroducersUpdateTimer (); + else + m_Server.RescheduleIntroducersUpdateTimerV6 (); + } } } LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), @@ -2291,7 +2295,7 @@ namespace transport { LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ", i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3))); - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) SetRouterStatus (eRouterStatusUnknown); it->second.first->Done (); } @@ -2445,6 +2449,29 @@ namespace transport } } + bool SSU2Session::GetTestingState () const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + return i2p::context.GetTesting (); + if (m_Address->IsV6 ()) + return i2p::context.GetTestingV6 (); + } + return false; + } + + void SSU2Session::SetTestingState (bool testing) const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + i2p::context.SetTesting (testing); + else if (m_Address->IsV6 ()) + i2p::context.SetTestingV6 (testing); + } + } + size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) { if (len < 9) return 0; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 304efdab..14d76971 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -308,6 +308,8 @@ namespace transport void AdjustMaxPayloadSize (); RouterStatus GetRouterStatus () const; void SetRouterStatus (RouterStatus status) const; + bool GetTestingState () const; + void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); void CreateNonce (uint64_t seqn, uint8_t * nonce); bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 01e484f4..b452c05e 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -650,8 +650,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 if (router) { - if (i2p::context.GetStatus () != eRouterStatusTesting) - i2p::context.SetStatus (eRouterStatusTesting); + if (!i2p::context.GetTesting ()) + i2p::context.SetTesting (true); m_SSU2Server->StartPeerTest (router, true); excluded.insert (router->GetIdentHash ()); } @@ -669,8 +669,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 if (router) { - if (i2p::context.GetStatusV6 () != eRouterStatusTesting) - i2p::context.SetStatusV6 (eRouterStatusTesting); + if (!i2p::context.GetTestingV6 ()) + i2p::context.SetTestingV6 (true); m_SSU2Server->StartPeerTest (router, false); excluded.insert (router->GetIdentHash ()); } @@ -832,8 +832,8 @@ namespace transport ++it; } } - bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting; - bool ipv6Testing = i2p::context.GetStatusV6 () == eRouterStatusTesting; + bool ipv4Testing = i2p::context.GetTesting (); + bool ipv6Testing = i2p::context.GetTestingV6 (); // if still testing, repeat peer test if (ipv4Testing || ipv6Testing) PeerTest (ipv4Testing, ipv6Testing); From 38795a41cbbb21a756ecb4fd13f045e6f5f5811f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 08:55:06 -0400 Subject: [PATCH 095/264] don't publish introducers with zero iTag --- libi2pd/SSU2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 53ef8db7..5d0e7d22 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1028,7 +1028,7 @@ namespace transport if (it1 != m_SessionsByRouterHash.end ()) { auto session = it1->second; - if (session->IsEstablished ()) + if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) @@ -1040,11 +1040,12 @@ namespace transport for (const auto& it : sessions) { + uint32_t tag = it->GetRelayTag (); uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; - if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; - introducer.iTag = it->GetRelayTag (); + introducer.iTag = tag; introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); From 9bac680f2a3181bb861beb2dbf739d92a5ab6597 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 5 Aug 2023 17:49:22 +0300 Subject: [PATCH 096/264] improve transport session logging --- libi2pd/NTCP2.cpp | 23 ++++++++++++++++++----- libi2pd/SSU2Session.cpp | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fa852f92..bbd93435 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -375,7 +375,16 @@ namespace transport m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); m_SendQueueSize = 0; - LogPrint (eLogDebug, "NTCP2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -691,11 +700,13 @@ namespace transport i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag if (ri.IsUnreachable ()) { - LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ()); SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - auto ts = i2p::util::GetMillisecondsSinceEpoch (); + LogPrint(eLogDebug, "NTCP2: SessionConfirmed from ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (ri.GetIdentHash ()), ")"); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); @@ -1409,7 +1420,8 @@ namespace transport LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); return; } - LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); GetService ().post([this, conn]() { if (this->AddNTCP2Session (conn)) @@ -1465,7 +1477,8 @@ namespace transport } else { - LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); conn->ClientLogin (); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 54add930..f0e539c7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -114,6 +114,8 @@ namespace transport { if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived) { + LogPrint(eLogDebug, "SSU2: Connecting to ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ")"); ScheduleConnectTimer (); auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint); if (token) @@ -269,7 +271,16 @@ namespace transport m_ReceivedI2NPMsgIDs.clear (); m_Server.RemoveSession (m_SourceConnID); transports.PeerDisconnected (shared_from_this ()); - LogPrint (eLogDebug, "SSU2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -298,6 +309,8 @@ namespace transport m_OnEstablished (); m_OnEstablished = nullptr; } + LogPrint(eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") established"); } void SSU2Session::Done () From 8447822c3596cadadfa6c7bd7ab0643ddd814b34 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 15:25:16 -0400 Subject: [PATCH 097/264] don't publish intrducers with zero tag --- libi2pd/RouterInfo.cpp | 3 +++ libi2pd/SSU2.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 646711c1..399e26a1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1321,6 +1321,7 @@ namespace data int i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; if (introducer.iExp) // expiration is specified { WriteString ("iexp" + boost::lexical_cast(i), properties); @@ -1333,6 +1334,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("ih" + boost::lexical_cast(i), properties); properties << '='; char value[64]; @@ -1345,6 +1347,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("itag" + boost::lexical_cast(i), properties); properties << '='; WriteString (boost::lexical_cast(introducer.iTag), properties); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5d0e7d22..7099ba0c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -995,7 +995,7 @@ namespace transport session = it1->second; excluded.insert (it); } - if (session && session->IsEstablished ()) + if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) // still session with introducer? { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { From 7bcc905f05b1356bb2f02cdc2abfe5a6a516207c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 7 Aug 2023 21:28:13 -0400 Subject: [PATCH 098/264] exclude SSU1 introducers --- libi2pd/RouterInfo.cpp | 2 +- libi2pd/RouterInfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 399e26a1..63cb79ef 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -579,7 +579,7 @@ namespace data int numValid = 0; for (auto& it: address->ssu->introducers) { - if (it.iTag && ts < it.iExp) + if (it.iTag && ts < it.iExp && !it.iH.IsZero ()) numValid++; else it.iTag = 0; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 47ee1dae..9aff2240 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -125,7 +125,7 @@ namespace data struct Introducer { - Introducer (): iTag (0), iExp (0) {}; + Introducer (): iTag (0), iExp (0) { iH.Fill(0); }; IdentHash iH; uint32_t iTag; uint32_t iExp; From 627b8dca8334ad036f948013bc564abcee8c291b Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 13 Aug 2023 17:08:14 -0700 Subject: [PATCH 099/264] Fixed buf offset EVP_EncryptFinal_ex() to include outlen. --- libi2pd/Crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4a78f2b1..12087443 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -991,7 +991,7 @@ namespace crypto EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen); EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen); - EVP_EncryptFinal_ex(ctx, buf, &outlen); + EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen); } else From 662a59d0fda3f763a2f67654dd50cc2cf38a8178 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Mon, 14 Aug 2023 19:21:30 -0700 Subject: [PATCH 100/264] Eliminate additional undefined behavior of bit shifting signed int. --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 0e69b663..e979c5b4 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -272,7 +272,7 @@ namespace data size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) { - int tmp = 0, bits = 0; + unsigned int tmp = 0, bits = 0; size_t ret = 0; for (size_t i = 0; i < len; i++) { From c112276eea649c3b406953e3400573d78a049f20 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Aug 2023 10:57:05 -0400 Subject: [PATCH 101/264] memory poll for RouterProfile --- libi2pd/NetDb.cpp | 1 + libi2pd/NetDb.hpp | 2 ++ libi2pd/Profiling.cpp | 3 ++- libi2pd/Profiling.h | 3 +-- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 061ccc23..02d4dfd8 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -175,6 +175,7 @@ namespace data if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { + m_RouterProfilesPool.CleanUpMt (); if (m_PersistProfiles) PersistProfiles (); DeleteObsoleteProfiles (); lastProfilesCleanup = ts; diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b7d9a5b3..44dff3b8 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -128,6 +128,7 @@ namespace data }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); }; + std::shared_ptr NewRouterProfile () { return m_RouterProfilesPool.AcquireSharedMt (); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; @@ -185,6 +186,7 @@ namespace data i2p::util::MemoryPoolMt m_RouterInfoAddressVectorsPool; i2p::util::MemoryPoolMt m_LeasesPool; i2p::util::MemoryPoolMt m_IdentitiesPool; + i2p::util::MemoryPoolMt m_RouterProfilesPool; }; extern NetDb netdb; diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 879aea29..2031fa39 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -16,6 +16,7 @@ #include "FS.h" #include "Log.h" #include "Timestamp.h" +#include "NetDb.hpp" #include "Profiling.h" namespace i2p @@ -237,7 +238,7 @@ namespace data if (it != g_Profiles.end ()) return it->second; } - auto profile = std::make_shared (); + auto profile = netdb.NewRouterProfile (); profile->Load (identHash); // if possible std::unique_lock l(g_ProfilesMutex); g_Profiles.emplace (identHash, profile); diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index c351b41d..6531e060 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -31,7 +31,7 @@ namespace data const char PEER_PROFILE_USAGE_CONNECTED[] = "connected"; 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_TIMEOUT = 3 * 3600; // in seconds (3 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) @@ -43,7 +43,6 @@ namespace data public: RouterProfile (); - RouterProfile& operator= (const RouterProfile& ) = default; void Save (const IdentHash& identHash); void Load (const IdentHash& identHash); From 32c5ff23a62b8b8f200b4717244524bb3ab68638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=B0=9C=E0=B0=BF=E0=B0=82=E0=B0=A6=E0=B0=82=20=E0=B0=B5?= =?UTF-8?q?=E0=B0=BE=E0=B0=90=E0=B0=BF?= <109575325+jindam-vani@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:51:21 +0000 Subject: [PATCH 102/264] Differentiate cryptocurrency & its associated address (#1951) --- README.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d0481ed9..e7fb7318 100644 --- a/README.md +++ b/README.md @@ -99,13 +99,23 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http Donations --------- -BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f -LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG -XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH +**E-Mail**: ```i2porignal at yandex.ru``` + +**BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f``` + +**LTC**: ```LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59``` + +**ETH**: ```0x9e5bac70d20d1079ceaa111127f4fb3bccce379d``` + +**GST**: ```GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG``` + +**DASH**: ```Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF``` + +**ZEC**: ```t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ``` + +**ANC**: ```AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z``` + +**XMR**: ```497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH``` License ------- From 7b6aa41ca8dc3ca2a0c9d01ff9870794ad98e403 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 31 Aug 2023 16:52:51 +0000 Subject: [PATCH 103/264] CPU: remove AVX code, switch to __builtin for AES detection (#1959) * [cpu] remove avx detect and code blocks, try to switch to __builtin * [cpu] use __builtin_* only on x86 systems * [cpu] perform check in separate function * [cpu] set AES definition on MSVC * update x86 and aes support checks at compile time * [cmake] update comment about AES on MSVC --- .editorconfig | 3 + build/CMakeLists.txt | 11 +- contrib/i2pd.conf | 2 - daemon/Daemon.cpp | 3 +- libi2pd/CPU.cpp | 60 ++++---- libi2pd/CPU.h | 5 +- libi2pd/Config.cpp | 4 +- libi2pd/Crypto.cpp | 332 ++++++++++++++++++++++--------------------- libi2pd/Crypto.h | 2 +- libi2pd/Identity.cpp | 29 +--- libi2pd/api.cpp | 3 +- 11 files changed, 222 insertions(+), 232 deletions(-) diff --git a/.editorconfig b/.editorconfig index e1f1243a..0f57a84a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -34,3 +34,6 @@ trim_trailing_whitespace = false [*.yml] indent_style = space indent_size = 2 + +[*.patch] +trim_trailing_whitespace = false diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index f5d01a0b..3185ffab 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -197,14 +197,11 @@ endif() # Note: AES-NI and AVX is available on x86-based CPU's. # Here also ARM64 implementation, but currently we don't support it. -# MSVC is not supported. -if(MSVC) - message(STATUS "AES-NI is not supported on MSVC, option was disabled") - set(WITH_AESNI OFF) -endif() - +# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code. if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + endif() add_definitions(-D__AES__) endif() diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 5facbbd5..545973a3 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -280,8 +280,6 @@ verify = true [cpuext] ## Use CPU AES-NI instructions set when work with cryptography when available (default: true) # aesni = true -## Use CPU AVX instructions set when work with cryptography when available (default: true) -# avx = true ## Force usage of CPU instructions set, even if they not found (default: false) ## DO NOT TOUCH that option if you really don't know what are you doing! # force = false diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 8e9721db..f04236fe 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -150,12 +150,11 @@ namespace util bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); - bool avx; i2p::config::GetOption("cpuext.avx", avx); bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); bool ssu; i2p::config::GetOption("ssu", ssu); if (!ssu && i2p::config::IsDefault ("precomputation.elgamal")) precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly - i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); + i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt); i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 0804e2ac..d42f1ddd 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.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 * @@ -7,52 +7,52 @@ */ #include "CPU.h" -#if defined(__x86_64__) || defined(__i386__) -#include -#endif #include "Log.h" -#ifndef bit_AES -#define bit_AES (1 << 25) -#endif -#ifndef bit_AVX -#define bit_AVX (1 << 28) -#endif +#if defined(_MSC_VER) +#include +#ifndef bit_AES + #define bit_AES (1 << 25) +#endif +#endif namespace i2p { namespace cpu { bool aesni = false; - bool avx = false; - void Detect(bool AesSwitch, bool AvxSwitch, bool force) + inline bool cpu_support_aes() { -#if defined(__x86_64__) || defined(__i386__) - int info[4]; - __cpuid(0, info[0], info[1], info[2], info[3]); - if (info[0] >= 0x00000001) { - __cpuid(0x00000001, info[0], info[1], info[2], info[3]); -#if defined (_WIN32) && (WINVER == 0x0501) // WinXP - if (AesSwitch && force) { // only if forced -#else - if ((info[2] & bit_AES && AesSwitch) || (AesSwitch && force)) { +#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) +#if defined(_MSC_VER) + int cpu_info[4]; + __cpuid(cpu_info, 1); + return ((cpu_info[2] & bit_AES) != 0); +#elif defined(__clang__) +#if __clang_major__ >= 6 + __builtin_cpu_init(); #endif - aesni = true; - } -#if defined (_WIN32) && (WINVER == 0x0501) // WinXP - if (AvxSwitch && force) { // only if forced + return __builtin_cpu_supports("aes"); +#elif defined(__GNUC__) + __builtin_cpu_init(); + return __builtin_cpu_supports("aes"); #else - if ((info[2] & bit_AVX && AvxSwitch) || (AvxSwitch && force)) { + return false; #endif - avx = true; - } +#else + return false; +#endif + } + + void Detect(bool AesSwitch, bool force) + { + if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) { + aesni = true; } -#endif // defined(__x86_64__) || defined(__i386__) LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled")); - LogPrint(eLogInfo, "AVX ", (avx ? "enabled" : "disabled")); } } } diff --git a/libi2pd/CPU.h b/libi2pd/CPU.h index f021bccb..a0695884 100644 --- a/libi2pd/CPU.h +++ b/libi2pd/CPU.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 * @@ -14,9 +14,8 @@ namespace i2p namespace cpu { extern bool aesni; - extern bool avx; - void Detect(bool AesSwitch, bool AvxSwitch, bool force); + void Detect(bool AesSwitch, bool force); } } diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 6b515ef9..5551b010 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -193,7 +193,7 @@ namespace config { options_description precomputation("Precomputation options"); precomputation.add_options() ("precomputation.elgamal", -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) value()->default_value(false), #else value()->default_value(true), @@ -308,7 +308,7 @@ namespace config { options_description cpuext("CPU encryption extensions options"); cpuext.add_options() ("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used") - ("cpuext.avx", bool_switch()->default_value(true), "Use auto detection for AVX CPU extensions. If false, AVX will be not used") + ("cpuext.avx", bool_switch()->default_value(false), "Deprecated option") ("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines") ; diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 12087443..b5bc33d1 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.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 * @@ -28,6 +28,12 @@ #include "I2PEndian.h" #include "Log.h" +#if defined(__AES__) && !defined(_MSC_VER) && ((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) + #define SUPPORTS_AES 1 +#else + #define SUPPORTS_AES 0 +#endif + namespace i2p { namespace crypto @@ -361,7 +367,7 @@ namespace crypto BIGNUM * b1 = BN_CTX_get (ctx); BIGNUM * b = BN_CTX_get (ctx); // select random k -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits @@ -428,7 +434,7 @@ namespace crypto void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) { -#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) +#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) || defined(_MSC_VER) RAND_bytes (priv, 256); #else // lower 226 bits (28 bytes and 2 bits) only. short exponent @@ -555,7 +561,7 @@ namespace crypto } // AES -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +586,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +627,7 @@ namespace crypto #endif -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,16 +648,18 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[in]), %%xmm0 \n" - EncryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" - ); + ( + "movups (%[in]), %%xmm0 \n" + EncryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + : + : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) + : "%xmm0", "memory" + ); } else #endif @@ -660,7 +668,7 @@ namespace crypto } } -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,16 +689,18 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[in]), %%xmm0 \n" - DecryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" - ); + ( + "movups (%[in]), %%xmm0 \n" + DecryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + : + : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) + : "%xmm0", "memory" + ); } else #endif @@ -699,7 +709,7 @@ namespace crypto } } -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +718,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,28 +732,30 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first // then invert it using aesimc __asm__ - ( - CallAESIMC(16) - CallAESIMC(32) - CallAESIMC(48) - CallAESIMC(64) - CallAESIMC(80) - CallAESIMC(96) - CallAESIMC(112) - CallAESIMC(128) - CallAESIMC(144) - CallAESIMC(160) - CallAESIMC(176) - CallAESIMC(192) - CallAESIMC(208) - : : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory" - ); + ( + CallAESIMC(16) + CallAESIMC(32) + CallAESIMC(48) + CallAESIMC(64) + CallAESIMC(80) + CallAESIMC(96) + CallAESIMC(112) + CallAESIMC(128) + CallAESIMC(144) + CallAESIMC(160) + CallAESIMC(176) + CallAESIMC(192) + CallAESIMC(208) + : + : [shed]"r"(GetKeySchedule ()) + : "%xmm0", "memory" + ); } else #endif @@ -754,28 +766,28 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) - : "%xmm0", "%xmm1", "cc", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) + : "%xmm0", "%xmm1", "cc", "memory" + ); } else #endif @@ -799,22 +811,22 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - "movups %%xmm0, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out) - : "%xmm0", "%xmm1", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); } else #endif @@ -823,29 +835,29 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" - "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - "movaps %%xmm2, %%xmm1 \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) - : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256(sched) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + "movaps %%xmm2, %%xmm1 \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); } else #endif @@ -869,22 +881,22 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "movups (%[in]), %%xmm0 \n" - "movups %%xmm0, (%[iv]) \n" - DecryptAES256(sched) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out) - : "%xmm0", "%xmm1", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "movups %%xmm0, (%[iv]) \n" + DecryptAES256(sched) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); } else #endif @@ -893,34 +905,34 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - // encrypt IV - "movups (%[in]), %%xmm0 \n" - EncryptAES256(sched_iv) - "movaps %%xmm0, %%xmm1 \n" - // double IV encryption - EncryptAES256(sched_iv) - "movups %%xmm0, (%[out]) \n" - // encrypt data, IV is xmm1 - "1: \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched_l) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes - : "%xmm0", "%xmm1", "cc", "memory" - ); + ( + // encrypt IV + "movups (%[in]), %%xmm0 \n" + EncryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + EncryptAES256(sched_iv) + "movups %%xmm0, (%[out]) \n" + // encrypt data, IV is xmm1 + "1: \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched_l) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "cc", "memory" + ); } else #endif @@ -934,35 +946,35 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - // decrypt IV - "movups (%[in]), %%xmm0 \n" - DecryptAES256(sched_iv) - "movaps %%xmm0, %%xmm1 \n" - // double IV encryption - DecryptAES256(sched_iv) - "movups %%xmm0, (%[out]) \n" - // decrypt data, IV is xmm1 - "1: \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "movups (%[in]), %%xmm0 \n" - "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched_l) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - "movaps %%xmm2, %%xmm1 \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes - : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" - ); + ( + // decrypt IV + "movups (%[in]), %%xmm0 \n" + DecryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + DecryptAES256(sched_iv) + "movups %%xmm0, (%[out]) \n" + // decrypt data, IV is xmm1 + "1: \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "movups (%[in]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256(sched_l) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + "movaps %%xmm2, %%xmm1 \n" + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); } else #endif @@ -1285,9 +1297,9 @@ namespace crypto } }*/ - void InitCrypto (bool precomputation, bool aesni, bool avx, bool force) + void InitCrypto (bool precomputation, bool aesni, bool force) { - i2p::cpu::Detect (aesni, avx, force); + i2p::cpu::Detect (aesni, force); #if LEGACY_OPENSSL SSL_library_init (); #endif @@ -1297,7 +1309,7 @@ namespace crypto CRYPTO_set_locking_callback (OpensslLockingCallback);*/ if (precomputation) { -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); #else @@ -1312,7 +1324,7 @@ namespace crypto if (g_ElggTable) { DestroyElggTable (g_ElggTable, -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) ELGAMAL_FULL_EXPONENT_NUM_BYTES #else ELGAMAL_SHORT_EXPONENT_NUM_BYTES diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index d4cbda97..1419293b 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -307,7 +307,7 @@ namespace crypto void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) // init and terminate - void InitCrypto (bool precomputation, bool aesni, bool avx, bool force); + void InitCrypto (bool precomputation, bool aesni, bool force); void TerminateCrypto (); } } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index a4a9f716..3a659c11 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -803,29 +803,12 @@ namespace data XORMetric operator^(const IdentHash& key1, const IdentHash& key2) { XORMetric m; -#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600) - if(i2p::cpu::avx) - { - __asm__ - ( - "vmovups %1, %%ymm0 \n" - "vmovups %2, %%ymm1 \n" - "vxorps %%ymm0, %%ymm1, %%ymm1 \n" - "vmovups %%ymm1, %0 \n" - : "=m"(*m.metric) - : "m"(*key1), "m"(*key2) - : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler - ); - } - else -#endif - { - const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); - m.metric_ll[0] = hash1[0] ^ hash2[0]; - m.metric_ll[1] = hash1[1] ^ hash2[1]; - m.metric_ll[2] = hash1[2] ^ hash2[2]; - m.metric_ll[3] = hash1[3] ^ hash2[3]; - } + + const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); + m.metric_ll[0] = hash1[0] ^ hash2[0]; + m.metric_ll[1] = hash1[1] ^ hash2[1]; + m.metric_ll[2] = hash1[2] ^ hash2[2]; + m.metric_ll[3] = hash1[3] ^ hash2[3]; return m; } diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 3bfb801c..ad24519f 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -38,9 +38,8 @@ namespace api bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); - bool avx; i2p::config::GetOption("cpuext.avx", avx); bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); - i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); + i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt); int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); From c53ad2012ceb9c7489c97378e86500332d8edbac Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 6 Sep 2023 20:26:46 +0000 Subject: [PATCH 104/264] [cpu] use cpuid on gcc < 5 Signed-off-by: r4sas --- libi2pd/CPU.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index d42f1ddd..14ce3788 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -9,12 +9,16 @@ #include "CPU.h" #include "Log.h" -#if defined(_MSC_VER) -#include - #ifndef bit_AES #define bit_AES (1 << 25) #endif + +#if (defined(__GNUC__) && __GNUC__ < 5) + #include +#endif + +#ifdef _MSC_VER + #include #endif namespace i2p @@ -26,18 +30,18 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -#if defined(_MSC_VER) - int cpu_info[4]; - __cpuid(cpu_info, 1); - return ((cpu_info[2] & bit_AES) != 0); +#if (defined(__GNUC__) && __GNUC__ > 4) + __builtin_cpu_init(); + return __builtin_cpu_supports("aes"); #elif defined(__clang__) #if __clang_major__ >= 6 __builtin_cpu_init(); #endif return __builtin_cpu_supports("aes"); -#elif defined(__GNUC__) - __builtin_cpu_init(); - return __builtin_cpu_supports("aes"); +#elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) + int cpu_info[4]; + __cpuid(cpu_info, 1); + return ((cpu_info[2] & bit_AES) != 0); #else return false; #endif From 4a5e16b99405182c6daa5862088a9b9247e1c6b4 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 7 Sep 2023 16:56:53 +0000 Subject: [PATCH 105/264] [cpu] tests with preprocessor Signed-off-by: r4sas --- libi2pd/CPU.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 14ce3788..53771ff0 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -30,21 +30,26 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -#if (defined(__GNUC__) && __GNUC__ > 4) +# if (defined(__GNUC__) && __GNUC__ > 4) +# warning("CPU: IN GCC!!!") __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -#elif defined(__clang__) -#if __clang_major__ >= 6 +# elif (defined(__clang__) && !defined(__GNUC__)) +# warning("CPU: IN CLANG!!!") +# warning(__clang__) +# if (__clang_major__ >= 6) __builtin_cpu_init(); -#endif +# endif return __builtin_cpu_supports("aes"); -#elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) +# elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) +# warning("CPU: IN MSVC!!!") int cpu_info[4]; __cpuid(cpu_info, 1); return ((cpu_info[2] & bit_AES) != 0); -#else +# else +# warning("CPU: FALSE") return false; -#endif +# endif #else return false; #endif From 4ed19c05f68e58a15c57f2791b1b0e1d863dda55 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 7 Sep 2023 21:20:52 +0000 Subject: [PATCH 106/264] [cpu] split AES detect for GNU C < 5 Signed-off-by: r4sas --- libi2pd/CPU.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 53771ff0..106882eb 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -30,29 +30,30 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -# if (defined(__GNUC__) && __GNUC__ > 4) -# warning("CPU: IN GCC!!!") +#if defined(__clang__) +# if (__clang_major__ >= 6) + __builtin_cpu_init(); +# endif + return __builtin_cpu_supports("aes"); +#elif (defined(__GNUC__) && __GNUC__ >= 5) __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -# elif (defined(__clang__) && !defined(__GNUC__)) -# warning("CPU: IN CLANG!!!") -# warning(__clang__) -# if (__clang_major__ >= 6) - __builtin_cpu_init(); -# endif - return __builtin_cpu_supports("aes"); -# elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) -# warning("CPU: IN MSVC!!!") +#elif (defined(__GNUC__) && __GNUC__ < 5) + int cpu_info[4]; + bool flag = false; + __cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); + if (cpu_info[0] >= 0x00000001) { + __cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); + flag = ((cpu_info[2] & bit_AES) != 0); + } + return flag; +#elif defined(_MSC_VER) int cpu_info[4]; __cpuid(cpu_info, 1); return ((cpu_info[2] & bit_AES) != 0); -# else -# warning("CPU: FALSE") - return false; -# endif -#else - return false; #endif +#endif + return false; } void Detect(bool AesSwitch, bool force) From 70829ee79e971f325ea4f3b753d0f8b02bce9fce Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 10 Sep 2023 13:02:52 +0300 Subject: [PATCH 107/264] [rpm] add Fedora ELN support Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 68 +++++++++++++++----------------------- contrib/rpm/i2pd.spec | 69 ++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 82 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 62a28631..ff46bc0f 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -11,9 +11,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz %if 0%{?rhel} == 7 -BuildRequires: cmake3 + BuildRequires: cmake3 %else -BuildRequires: cmake + BuildRequires: cmake %endif BuildRequires: chrpath @@ -28,9 +28,11 @@ Requires: logrotate Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + %description C++ implementation of I2P. + %prep %setup -q -n i2pd-openssl @@ -38,72 +40,56 @@ C++ implementation of I2P. %build cd build %if 0%{?rhel} == 7 -%cmake3 \ + %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF %else -%cmake \ + %cmake \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -%if 0%{?fedora} > 29 + %if 0%{?fedora} > 29 -DBUILD_SHARED_LIBS:BOOL=OFF \ . -%else + %else -DBUILD_SHARED_LIBS:BOOL=OFF -%endif + %endif %endif - -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} > 7 -pushd build + %if 0%{?mageia} > 7 + pushd build + %endif %endif make %{?_smp_mflags} -%if 0%{?rhel} == 9 -popd +%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 + popd %endif -%if 0%{?fedora} >= 33 -popd -%endif - -%if 0%{?mageia} > 7 -popd -%endif %install pushd build -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} -pushd build + %if 0%{?mageia} + pushd build + %endif %endif chrpath -d i2pd diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 19825237..5d1adfb7 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.48.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -9,9 +9,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz %if 0%{?rhel} == 7 -BuildRequires: cmake3 + BuildRequires: cmake3 %else -BuildRequires: cmake + BuildRequires: cmake %endif BuildRequires: chrpath @@ -26,9 +26,11 @@ Requires: logrotate Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + %description C++ implementation of I2P. + %prep %setup -q @@ -36,71 +38,56 @@ C++ implementation of I2P. %build cd build %if 0%{?rhel} == 7 -%cmake3 \ + %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF %else -%cmake \ + %cmake \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -%if 0%{?fedora} > 29 + %if 0%{?fedora} > 29 -DBUILD_SHARED_LIBS:BOOL=OFF \ . -%else + %else -DBUILD_SHARED_LIBS:BOOL=OFF -%endif + %endif %endif -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} > 7 -pushd build + %if 0%{?mageia} > 7 + pushd build + %endif %endif make %{?_smp_mflags} -%if 0%{?rhel} == 9 -popd +%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 + popd %endif -%if 0%{?fedora} >= 33 -popd -%endif - -%if 0%{?mageia} > 7 -popd -%endif %install pushd build -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} -pushd build + %if 0%{?mageia} + pushd build + %endif %endif chrpath -d i2pd From 1e7feae0df17eb26cd4d843fcbf1afb26bae95f7 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 10 Sep 2023 13:08:00 +0300 Subject: [PATCH 108/264] [rpm] remove BuildRequires tabulation Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 4 ++-- contrib/rpm/i2pd.spec | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index ff46bc0f..cebc15a4 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -11,9 +11,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz %if 0%{?rhel} == 7 - BuildRequires: cmake3 +BuildRequires: cmake3 %else - BuildRequires: cmake +BuildRequires: cmake %endif BuildRequires: chrpath diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5d1adfb7..cc826928 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -9,9 +9,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz %if 0%{?rhel} == 7 - BuildRequires: cmake3 +BuildRequires: cmake3 %else - BuildRequires: cmake +BuildRequires: cmake %endif BuildRequires: chrpath From 918aa556ef93272464ca396ae485b30b24b42b36 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 15 Sep 2023 11:37:45 -0400 Subject: [PATCH 109/264] fixed non-x86 build --- libi2pd/CPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 106882eb..5d5fc6b3 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if (defined(__GNUC__) && __GNUC__ < 5) +#if (defined(__GNUC__) && __GNUC__ < 5 && (defined(__x86_64__) || defined(__i386__))) #include #endif From df6bb6d9b8b33d9a7db81386fd8771c5b7b8bc57 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Sep 2023 10:19:57 -0400 Subject: [PATCH 110/264] 2.49.0 --- ChangeLog | 27 +++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 881e05d7..17ec98d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,33 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.49.0] - 2023-09-18 +### Added +- Handle SOCK5 authrozation with empty user/password +- Drop incoming transport sessions from too old or from future routers +- Memory pool for router profiles +- Allow 0 hops in explicitPeers +### Changed +- Separate network and testing status +- Remove AVX code +- Improve NTCP2 transport session logging +- Select router with ipv4 for tunnel endpoint +- Consider all addresses non-published for U and H routers even if they have host/port +- Don't pick completely unreachable routers for tunnels +- Exclude SSU1 introducers from SSU2 addresses +- Don't create paired inbound tunnel if length is different +- Remove introducer from RouterInfo after 60 minutes +- Reduce SSU2 keep alive interval and add peer test interval variance +- Don't pick too old sessions for introducer +### Fixed +- Version of the subnegotiation in user/password SOCKS5 response +- Send keepalive for existing session with introducer +- Buffer offset for EVP_EncryptFinal_ex() to include outlen +- Termination block size processing for transport sessions +- Crash if deleted BOB destination was shared between few BOB sessions +- Introducers with zero tag +- Padding for SSU2 path response + ## [2.48.0] - 2023-06-12 ### Added - Allow user/password authentication method for SOCK5 proxy diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index cebc15a4..c745e05f 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.48.0 +Version: 2.49.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 18 2023 orignal - 2.49.0 +- update to 2.49.0 + * Mon Jun 12 2023 orignal - 2.48.0 - update to 2.48.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index cc826928..b88f21b2 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.48.0 +Version: 2.49.0 Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 18 2023 orignal - 2.49.0 +- update to 2.49.0 + * Mon Jun 12 2023 orignal - 2.48.0 - update to 2.48.0 diff --git a/debian/changelog b/debian/changelog index 91b0abdf..613bc7c9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.49.0-1) unstable; urgency=high + + * updated to version 2.49.0/0.9.60 + + -- orignal Mon, 18 Sep 2023 16:00:00 +0000 + i2pd (2.48.0-1) unstable; urgency=high * updated to version 2.48.0/0.9.59 diff --git a/libi2pd/version.h b/libi2pd/version.h index 903ceebc..9854995e 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 48 +#define I2PD_VERSION_MINOR 49 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 59 +#define I2P_VERSION_MICRO 60 #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 3a4238729a103baef76ab677d555ae55a4833a9b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Sep 2023 10:41:31 -0400 Subject: [PATCH 111/264] 2.49.0 --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17ec98d7..69d5c4c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ ## [2.49.0] - 2023-09-18 ### Added -- Handle SOCK5 authrozation with empty user/password +- Handle SOCK5 authorization with empty user/password - Drop incoming transport sessions from too old or from future routers - Memory pool for router profiles - Allow 0 hops in explicitPeers @@ -17,7 +17,7 @@ - Exclude SSU1 introducers from SSU2 addresses - Don't create paired inbound tunnel if length is different - Remove introducer from RouterInfo after 60 minutes -- Reduce SSU2 keep alive interval and add peer test interval variance +- Reduce SSU2 keep alive interval and add keep alive interval variance - Don't pick too old sessions for introducer ### Fixed - Version of the subnegotiation in user/password SOCKS5 response From 4d573f6655c37cc13022157c1e2d043debca7512 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 15:36:15 +0000 Subject: [PATCH 112/264] 2.49.0 Signed-off-by: r4sas --- ChangeLog | 16 ++++++++-------- Win32/mask.bmp | Bin 25818 -> 0 bytes contrib/rpm/i2pd.spec | 2 +- debian/changelog | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 Win32/mask.bmp diff --git a/ChangeLog b/ChangeLog index 69d5c4c9..4dd49a24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,20 +4,20 @@ ## [2.49.0] - 2023-09-18 ### Added - Handle SOCK5 authorization with empty user/password -- Drop incoming transport sessions from too old or from future routers -- Memory pool for router profiles +- Drop incoming transport sessions from too old or from future routers +- Memory pool for router profiles - Allow 0 hops in explicitPeers ### Changed - Separate network and testing status - Remove AVX code -- Improve NTCP2 transport session logging -- Select router with ipv4 for tunnel endpoint +- Improve NTCP2 transport session logging +- Select router with ipv4 for tunnel endpoint - Consider all addresses non-published for U and H routers even if they have host/port - Don't pick completely unreachable routers for tunnels -- Exclude SSU1 introducers from SSU2 addresses +- Exclude SSU1 introducers from SSU2 addresses - Don't create paired inbound tunnel if length is different -- Remove introducer from RouterInfo after 60 minutes -- Reduce SSU2 keep alive interval and add keep alive interval variance +- Remove introducer from RouterInfo after 60 minutes +- Reduce SSU2 keep alive interval and add keep alive interval variance - Don't pick too old sessions for introducer ### Fixed - Version of the subnegotiation in user/password SOCKS5 response @@ -26,7 +26,7 @@ - Termination block size processing for transport sessions - Crash if deleted BOB destination was shared between few BOB sessions - Introducers with zero tag -- Padding for SSU2 path response +- Padding for SSU2 path response ## [2.48.0] - 2023-06-12 ### Added diff --git a/Win32/mask.bmp b/Win32/mask.bmp deleted file mode 100644 index cc2aeda75c6139ef81b479bb01f726996e756050..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25818 zcmeHPcUV(d7I**Holl+FZ)cRENUT(c0qHF?=@v#o1*5{yl8}(lLJd7gCv+kfK#^WV zDHae0>{1kz8O8283JR!L#x}brJm;AS9S1~t?|aF2bKkk`_shBWoO5rYx8|z-jQ&d* z-X-Cc3NJNy{bPnOyd&4rA7;$pzW%)aH_fhh@80!2d-lg4e@wG+e@VmT)YN`kce1qM zI_r;84v;%>;)K*jf{FyVOEr7{QMFf1!37%^K znHJ&gZNH4NrHaC0X8{S4ki@mC9iuFQiA^v9zumj*1jlteHw(FwsbXMl;*RO|yVpnWD5D2&by3OD&@`+u)eMhAHNIn+G;lpK; zK7uw9)!n^u@eI+JC~5*YAA>f`qPV#9b4XLt8OY(Kj*f3QnGwg14_X$>oOlFUFSOc= zdLcAM(~<^K1UYspI*1>>3yWJ@Tc13A3RLq_1WjFP zyJS1x(+kHoUqV(}9bo3ZBP=1K=g){vN>mI&AiRThdgkm|zTRag=LeX?@MU5j$B4j% z%k2$~Ef<N;ItzdJh4%WTso!6gu4K}kRp+_;Odl(Vd6EXk#+csuy+H zIK3BWG)nD+gz=6Z6R$jWR5VFIjHi@DWquKF2alE4zzm%1y^}W+OaHA1ba!{>W$v|6 z(jxLufpUT*OqVJGb-?Rn)(_GF^!4&ZZ2ynOkxG{1l#qf8axy6U{QrHC}%=O~b-6LQ*Qg{l4`71g!DKqlm@jJu{x z-t*&9WnTHBoqN!cr?Peefpm$Go>2sQ&{9}pya>Re2j+iLcqBno3Y}evLXs+*!+|dC z&~viO71x-W{bXTjB(Owfy&s~AD$Y50n>eb_d)lGkfxY{o3t$+P=9W1v2mos~${`sl zA8)^~a$`jRz`k|s7GsNzy?_`HqOG{bi1Sc`Su4C^l@h%`!C{BGYoY2UZ=BFV4WGkY zRgC#nopE6OA~{4AA@W^)kn6f^D+#j&816hF_d7zuGYM0i=~kd-Tk_5Dvk&$jRRCZ0Z+$Q1d8T8FNL2ma9t7 zha4?dle8swnuY09hgnM$mI4}onzM``;_QWsLkOfVW?gQ*{OJZX&X)Ou6yvOBl8g2B z_7lq&54$*_dt78gV4DfWo{9_B za614j^=n|KZp204P~D?Ug_;dHa2q7vQFh9LdxbR{&#Yb5o!}BtRAMIDNyU{~~ntzxN;rs!xpwW@p#KorfyHvl&qm6Zk6vuFuQVRQSSZT%|{cOK1VHu8evx>ul=OJ`)A7U1++|G5sCTotCs58DA=cgCjlOYpcEcRo&C+f7weNC*7kwP9o^>QRH)h4C>&<#q51&% zFbfN-qS)8i2!1Q)`V38`=CP|r4>+I-Tv!;LC$20c0xJrL3?|k+bJ4w+feYNJq?9pi$GnaVvghQ9&Vux`7|$g0Ij0 z`}gzrWd~V1*e(76>>iqi;V*5Mc$>!3LnDx1f8wjss&#RklAN-p#wIx9G?XkL?Xhw- zD51?fDNsNC_#0eK{AyHPi|_&UsxE~Z-c{gRz$3VUG~MtPRksrG7*PU2UUxME+zW@f zVw;4;?Bq2mT1HN4dbZ;7)^nF4r{0M3q|yReuqQoKH?aHx2t0rOqVQM^y5TVcnV9Uz6l*Tgh~e9 zupQ!QYTkC?BA@bq=mD1cCS5;LUL|+M#D*Jp_IrJOlG5EQ8u+UO!4`YC3=t z?o=Y~f~PR4A_Rh>LPCYQ-yrF(vHYrm?7`&eu5Eg}yb=u2kLo2>csK;AD=M7?#1Z(n z%$L>)YlI0CHY6a(tWqW1rw=h3WlA<|Awu|6)Ay*R zUo~MqR}8(0!V*CiTN{qmjOb?!*SSye>~lM-4gk}&O;F&Sg(S62UGyT_v;ymOSxx#1 zYia!iA_Dqq8$cDo)`2LSR`4lJW(}g2kg2`a6DCsF(|4FJDNGU&5B2au*0H;H@6vHdOqI=v*bO{n$0hMOe%mA! zAQ%H$*LHhee8QH;Bz{#@9b0^0 zVn#C!YlT=FQ2~!A71%UPA_d~52o8{NlK1J?F81y??qN~j%5Uu^UR8u5IT;_$kpj;U zP-{7Ru{`&1USe@pcwPo8XJ1r)UTX1?lIqr$ww|7zwksXgO)alpVP4|j@^u5qcf}?k z@h>L<35K;Du!PnOPg5Bg$P5Xa#7KVUg9mWto0mp=8P%coC!hx8LhHm5e>VbGuUxSf z;riob0dapv3M`C#Ez}=9f$ZkSxFw^HAW%(O_LrYlggLtbSEvA%m@EWf7NzQQy*@ZW z8toSV#>c>xpY=VXNe6){23ke(K5c7mAuV}-loV=k5D+WbpUW$Nr6(Q%U@VwSg9!B2 z#WH321;c0&+nEE_i90@+&tY%B*h-fAa5&#ibUF6dLKDv$(gM)+=GB|z&~SpV7>nu( zCdlwDpF7dWSQz6Z!36u0Px9`q+cXtDbZxYgRt5*3Pv*1!I3>^10D);Wb&HSGI{f6& zarNpj>W5+vR*tJ?5M@Eo_3PKsOf&(T^?{Z)h*bn+I_s{&eyWXvGcgGuZF^DackHyI zr}=-RJ4}NmnFkrTn9}^gJvtycEqFV*|JO1=W}rQpZ`K{AX6(_p5P+4iv#V<~8i-a8 z=WJ-QfvI6b{`?batF5SVT($yK5uyY+>ATUgSYm1*02J+t%!(u>4&R-dH*QeW^&yaB zi(7vC_U++?v8R)cK-;BD#&%vKp5_2&-;ZDmTlPLyHe*utNgvQOY_PDd{+}n$JC{|A z$P6rx2>~IS1(w2}Ym6v74UznGL+zVg6&8WZD=w)&fzdb`#HOT7 jeqH_7=~>Zb Date: Sun, 17 Sep 2023 15:59:11 +0000 Subject: [PATCH 113/264] [i18n] update translations Signed-off-by: r4sas --- i18n/French.cpp | 6 +++--- i18n/Italian.cpp | 6 +++++- i18n/Portuguese.cpp | 6 +++++- i18n/Ukrainian.cpp | 6 +++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/i18n/French.cpp b/i18n/French.cpp index 8bec887c..0a5b147e 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -96,7 +96,7 @@ namespace french // language namespace {"Address", "Adresse"}, {"Type", "Type"}, {"EncType", "EncType"}, - {"Expire LeaseSet", "Expiration du LeaseSet"}, + {"Expire LeaseSet", "Expirer le jeu de baux"}, {"Inbound tunnels", "Tunnels entrants"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, @@ -153,8 +153,8 @@ namespace french // language namespace {"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 %d seconds", "Vous serez redirigé dans %d secondes"}, - {"LeaseSet expiration time updated", "Temps d'expiration du LeaseSet mis à jour"}, - {"LeaseSet is not found or already expired", "Le LeaseSet est introuvable ou a déjà expirée"}, + {"LeaseSet expiration time updated", "Temps d'expiration du jeu de baux mis à jour"}, + {"LeaseSet is not found or already expired", "Le jeu de baux est introuvable ou a déjà expiré"}, {"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"}, diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index 386372d5..2dcaab5e 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -69,6 +69,7 @@ namespace italian // language namespace {"Stopping in", "Arresto in"}, {"Family", "Famiglia"}, {"Tunnel creation success rate", "Percentuale di tunnel creati con successo"}, + {"Total tunnel creation success rate", "Percentuale di successo totale nella creazione del tunnel"}, {"Received", "Ricevuti"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Inviati"}, @@ -95,6 +96,7 @@ namespace italian // language namespace {"Address", "Indirizzo"}, {"Type", "Tipologia"}, {"EncType", "Tipo di crittografia"}, + {"Expire LeaseSet", "Scadenza LeaseSet"}, {"Inbound tunnels", "Tunnel in entrata"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnel in uscita"}, @@ -109,6 +111,7 @@ namespace italian // language namespace {"Local Destination", "Destinazione locale"}, {"Streams", "Flussi"}, {"Close stream", "Interrompi il flusso"}, + {"Such destination is not found", "Questa destinazione non è stata trovata"}, {"I2CP session not found", "Sessione I2CP non trovata"}, {"I2CP is not enabled", "I2CP non è abilitato"}, {"Invalid", "Invalido"}, @@ -150,6 +153,8 @@ namespace italian // language namespace {"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 %d seconds", "Sarai reindirizzato tra %d secondi"}, + {"LeaseSet expiration time updated", "Tempo di scadenza LeaseSet aggiornato"}, + {"LeaseSet is not found or already expired", "LeaseSet non trovato o già scaduto"}, {"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"}, @@ -158,7 +163,6 @@ namespace italian // language namespace {"Submit", "Invia"}, {"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"}, {"Domain must end with .i2p", "I domini devono terminare con .i2p"}, - {"Such destination is not found", "Questa destinazione non è stata trovata"}, {"Unknown command", "Comando sconosciuto"}, {"Command accepted", "Comando accettato"}, {"Proxy error", "Errore del proxy"}, diff --git a/i18n/Portuguese.cpp b/i18n/Portuguese.cpp index 8ba7f0cd..4c6d749f 100644 --- a/i18n/Portuguese.cpp +++ b/i18n/Portuguese.cpp @@ -69,6 +69,7 @@ namespace portuguese // language namespace {"Stopping in", "Parando em"}, {"Family", "Família"}, {"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"}, + {"Total tunnel creation success rate", "Taxa total de sucesso na criação de túneis"}, {"Received", "Recebido"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Enviado"}, @@ -95,6 +96,7 @@ namespace portuguese // language namespace {"Address", "Endereço"}, {"Type", "Tipo"}, {"EncType", "Tipo de Criptografia"}, + {"Expire LeaseSet", "Expirar LeaseSet"}, {"Inbound tunnels", "Túneis de Entrada"}, {"%dms", "%dms"}, {"Outbound tunnels", "Túneis de Saída"}, @@ -109,6 +111,7 @@ namespace portuguese // language namespace {"Local Destination", "Destinos Locais"}, {"Streams", "Fluxos"}, {"Close stream", "Fechar fluxo"}, + {"Such destination is not found", "Tal destino não foi encontrado"}, {"I2CP session not found", "Sessão do I2CP não encontrada"}, {"I2CP is not enabled", "I2CP não está ativado"}, {"Invalid", "Inválido"}, @@ -150,6 +153,8 @@ namespace portuguese // language namespace {"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"}, + {"LeaseSet expiration time updated", "Tempo de validade do LeaseSet atualizado"}, + {"LeaseSet is not found or already expired", "LeaseSet não foi encontrado ou já expirou"}, {"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"}, @@ -158,7 +163,6 @@ namespace portuguese // language namespace {"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"}, diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index c1e222ea..d089c142 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -69,6 +69,7 @@ namespace ukrainian // language namespace {"Stopping in", "Зупинка через"}, {"Family", "Сімейство"}, {"Tunnel creation success rate", "Успішно побудованих тунелів"}, + {"Total tunnel creation success rate", "Загальна кількість створених тунелів"}, {"Received", "Отримано"}, {"%.2f KiB/s", "%.2f КіБ/с"}, {"Sent", "Відправлено"}, @@ -95,6 +96,7 @@ namespace ukrainian // language namespace {"Address", "Адреса"}, {"Type", "Тип"}, {"EncType", "ТипШифр"}, + {"Expire LeaseSet", "Завершити LeaseSet"}, {"Inbound tunnels", "Вхідні тунелі"}, {"%dms", "%dмс"}, {"Outbound tunnels", "Вихідні тунелі"}, @@ -109,6 +111,7 @@ namespace ukrainian // language namespace {"Local Destination", "Локальні Призначення"}, {"Streams", "Потоки"}, {"Close stream", "Закрити потік"}, + {"Such destination is not found", "Така точка призначення не знайдена"}, {"I2CP session not found", "I2CP сесія не знайдена"}, {"I2CP is not enabled", "I2CP не увікнуто"}, {"Invalid", "Некоректний"}, @@ -150,6 +153,8 @@ namespace ukrainian // language namespace {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, {"Return to destination page", "Повернутися на сторінку точки призначення"}, {"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"}, + {"LeaseSet expiration time updated", "Час закінчення LeaseSet оновлено"}, + {"LeaseSet is not found or already expired", "LeaseSet не знайдено або вже закінчився"}, {"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"}, {"Back to commands list", "Повернутися до списку команд"}, {"Register at reg.i2p", "Зареєструвати на reg.i2p"}, @@ -158,7 +163,6 @@ namespace ukrainian // language namespace {"Submit", "Надіслати"}, {"Domain can't end with .b32.i2p", "Домен не може закінчуватися на .b32.i2p"}, {"Domain must end with .i2p", "Домен повинен закінчуватися на .i2p"}, - {"Such destination is not found", "Така точка призначення не знайдена"}, {"Unknown command", "Невідома команда"}, {"Command accepted", "Команда прийнята"}, {"Proxy error", "Помилка проксі"}, From 9c25a88707294f93843c2fead9cd4768776d6078 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 16:21:36 +0000 Subject: [PATCH 114/264] [i18n] update translations Signed-off-by: r4sas --- i18n/Uzbek.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/i18n/Uzbek.cpp b/i18n/Uzbek.cpp index 9d798be4..cf94a489 100644 --- a/i18n/Uzbek.cpp +++ b/i18n/Uzbek.cpp @@ -69,6 +69,7 @@ namespace uzbek // language namespace {"Stopping in", "Ichida to'xtatish"}, {"Family", "Oila"}, {"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"}, + {"Total tunnel creation success rate", "Tunnel yaratishning umumiy muvaffaqiyat darajasi"}, {"Received", "Qabul qilindi"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Yuborilgan"}, @@ -95,6 +96,7 @@ namespace uzbek // language namespace {"Address", "Manzil"}, {"Type", "Turi"}, {"EncType", "ShifrlashTuri"}, + {"Expire LeaseSet", "LeaseSet muddati tugaydi"}, {"Inbound tunnels", "Kirish tunnellari"}, {"%dms", "%dms"}, {"Outbound tunnels", "Chiquvchi tunnellar"}, @@ -109,6 +111,7 @@ namespace uzbek // language namespace {"Local Destination", "Mahalliy joylanish"}, {"Streams", "Strim"}, {"Close stream", "Strimni o'chirish"}, + {"Such destination is not found", "Bunday yo'nalish topilmadi"}, {"I2CP session not found", "I2CP sessiyasi topilmadi"}, {"I2CP is not enabled", "I2CP yoqilmagan"}, {"Invalid", "Noto'g'ri"}, @@ -150,6 +153,8 @@ namespace uzbek // language namespace {"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"}, {"Return to destination page", "Manzilgoh sahifasiga qaytish"}, {"You will be redirected in %d seconds", "Siz %d soniyadan so‘ng boshqa yo‘nalishga yo‘naltirilasiz"}, + {"LeaseSet expiration time updated", "LeaseSet amal qilish muddati yangilandi"}, + {"LeaseSet is not found or already expired", "LeaseSet topilmadi yoki muddati tugagan"}, {"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"}, @@ -158,7 +163,6 @@ namespace uzbek // language namespace {"Submit", "Yuborish"}, {"Domain can't end with .b32.i2p", "Domen .b32.i2p bilan tugashi mumkin emas"}, {"Domain must end with .i2p", "Domen .i2p bilan tugashi kerak"}, - {"Such destination is not found", "Bunday yo'nalish topilmadi"}, {"Unknown command", "Noma'lum buyruq"}, {"Command accepted", "Buyruq qabul qilindi"}, {"Proxy error", "Proksi xatosi"}, From 1857f14be86aa360c90f7baab0d7013f10f22632 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 18:33:42 +0000 Subject: [PATCH 115/264] [cpu] use short defines instead of long checks Signed-off-by: r4sas --- libi2pd/CPU.cpp | 4 ++-- libi2pd/CPU.h | 18 ++++++++++++++++++ libi2pd/Crypto.cpp | 15 +++++---------- libi2pd/Crypto.h | 8 ++++---- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 5d5fc6b3..4c522987 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if (defined(__GNUC__) && __GNUC__ < 5 && (defined(__x86_64__) || defined(__i386__))) +#if defined(__GNUC__) && __GNUC__ < 5 && IS_X86 #include #endif @@ -29,7 +29,7 @@ namespace cpu inline bool cpu_support_aes() { -#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) +#if IS_X86 #if defined(__clang__) # if (__clang_major__ >= 6) __builtin_cpu_init(); diff --git a/libi2pd/CPU.h b/libi2pd/CPU.h index a0695884..1c30db48 100644 --- a/libi2pd/CPU.h +++ b/libi2pd/CPU.h @@ -9,6 +9,24 @@ #ifndef LIBI2PD_CPU_H #define LIBI2PD_CPU_H +#if defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__) +# define IS_X86 1 +# if defined(_M_AMD64) || defined(__x86_64__) +# define IS_X86_64 1 +# else +# define IS_X86_64 0 +# endif +#else +# define IS_X86 0 +# define IS_X86_64 0 +#endif + +#if defined(__AES__) && !defined(_MSC_VER) && IS_X86 +# define SUPPORTS_AES 1 +#else +# define SUPPORTS_AES 0 +#endif + namespace i2p { namespace cpu diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index b5bc33d1..3e5bdd35 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -28,11 +28,6 @@ #include "I2PEndian.h" #include "Log.h" -#if defined(__AES__) && !defined(_MSC_VER) && ((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) - #define SUPPORTS_AES 1 -#else - #define SUPPORTS_AES 0 -#endif namespace i2p { @@ -165,7 +160,7 @@ namespace crypto // DH/ElGamal -#if !defined(__x86_64__) +#if !IS_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 @@ -367,7 +362,7 @@ namespace crypto BIGNUM * b1 = BN_CTX_get (ctx); BIGNUM * b = BN_CTX_get (ctx); // select random k -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits @@ -434,7 +429,7 @@ namespace crypto void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) { -#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) || defined(_MSC_VER) +#if IS_X86 || defined(_MSC_VER) RAND_bytes (priv, 256); #else // lower 226 bits (28 bytes and 2 bits) only. short exponent @@ -1309,7 +1304,7 @@ namespace crypto CRYPTO_set_locking_callback (OpensslLockingCallback);*/ if (precomputation) { -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); #else @@ -1324,7 +1319,7 @@ namespace crypto if (g_ElggTable) { DestroyElggTable (g_ElggTable, -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 ELGAMAL_FULL_EXPONENT_NUM_BYTES #else ELGAMAL_SHORT_EXPONENT_NUM_BYTES diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 1419293b..816d79fd 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.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 * @@ -150,7 +150,7 @@ namespace crypto }; -#ifdef __AES__ +#if SUPPORTS_AES class ECBCryptoAESNI { public: @@ -167,7 +167,7 @@ namespace crypto }; #endif -#ifdef __AES__ +#if SUPPORTS_AES class ECBEncryption: public ECBCryptoAESNI #else class ECBEncryption @@ -183,7 +183,7 @@ namespace crypto AES_KEY m_Key; }; -#ifdef __AES__ +#if SUPPORTS_AES class ECBDecryption: public ECBCryptoAESNI #else class ECBDecryption From 3da50614264f2bb93bc7bad9425772d92b01a973 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Sep 2023 17:11:45 +0000 Subject: [PATCH 116/264] [cpu] Increase GCC version for use of builtin CPU extensions checker Signed-off-by: r4sas --- libi2pd/CPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 4c522987..e434dd57 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if defined(__GNUC__) && __GNUC__ < 5 && IS_X86 +#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86 #include #endif From fb420bb563a3ebf8803faaa390ba6b2bb840d872 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Sep 2023 18:12:26 +0000 Subject: [PATCH 117/264] [cpu] more builtin version check changes Signed-off-by: r4sas --- libi2pd/CPU.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index e434dd57..77820c88 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -35,10 +35,10 @@ namespace cpu __builtin_cpu_init(); # endif return __builtin_cpu_supports("aes"); -#elif (defined(__GNUC__) && __GNUC__ >= 5) +#elif (defined(__GNUC__) && __GNUC__ >= 6) __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -#elif (defined(__GNUC__) && __GNUC__ < 5) +#elif (defined(__GNUC__) && __GNUC__ < 6) int cpu_info[4]; bool flag = false; __cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); From 0cf656cd7687fce461f644820066afc36be312b3 Mon Sep 17 00:00:00 2001 From: hfsfox Date: Thu, 28 Sep 2023 22:30:38 +0300 Subject: [PATCH 118/264] Add Haiku OS support (#1970) --- Makefile | 3 +++ Makefile.haiku | 10 ++++++++++ build/CMakeLists.txt | 4 ++++ libi2pd/FS.cpp | 8 ++++++++ libi2pd/I2PEndian.h | 2 +- libi2pd/util.cpp | 11 +++++++++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 Makefile.haiku diff --git a/Makefile b/Makefile index 0861ec0b..86ea0aa8 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,9 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS))) else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp include Makefile.bsd +else ifneq (, $(findstring haiku, $(SYS))) + DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp + include Makefile.haiku else # not supported $(error Not supported platform) endif diff --git a/Makefile.haiku b/Makefile.haiku new file mode 100644 index 00000000..85c2835d --- /dev/null +++ b/Makefile.haiku @@ -0,0 +1,10 @@ +CXX = g++ +CXXFLAGS := -Wall -std=c++11 +INCFLAGS = -I/system/develop/headers +DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE +LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + +ifeq ($(USE_UPNP),yes) + DEFINES += -DUSE_UPNP + LDLIBS += -lminiupnpc +endif diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 3185ffab..abfadfca 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -139,6 +139,10 @@ if(APPLE) add_definitions(-DMAC_OSX) endif() +if(HAIKU) + add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE) +endif() + if(MSVC) add_definitions(-DWINVER=0x0600) add_definitions(-D_WIN32_WINNT=0x0600) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 7334550f..d38bcc2f 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -136,6 +136,14 @@ namespace fs { dataDir = (home != NULL && strlen(home) > 0) ? home : ""; dataDir += "/Library/Application Support/" + appName; return; +#elif defined(__HAIKU__) + char *home = getenv("HOME"); + if (home != NULL && strlen(home) > 0) { + dataDir = std::string(home) + "/config/settings/" + appName; + } else { + dataDir = "/tmp/" + appName; + } + return; #else /* other unix */ #if defined(ANDROID) const char * ext = getenv("EXTERNAL_STORAGE"); diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index 06abf29a..681a4999 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -14,7 +14,7 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) #include -#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) +#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) || defined(__HAIKU__) #include #elif defined(__APPLE__) && defined(__MACH__) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 088a7af5..a7afdce8 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -27,6 +27,17 @@ # include #endif +#if defined(__HAIKU__) +#include +#include +#include +#include +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#include +#endif +#endif + #ifdef _WIN32 #include #include From 1e6edf06a29a0af8ac09f12c227f6b9ed76d75df Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Sep 2023 16:05:13 -0400 Subject: [PATCH 119/264] send already accepting error response --- libi2pd_client/SAM.cpp | 49 ++++++++++++++++++++++++++++-------------- libi2pd_client/SAM.h | 5 +++-- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index bb9d6a6b..1a281c57 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -360,7 +360,7 @@ namespace client if (type == eSAMSessionTypeUnknown) { // unknown style - SendI2PError("Unknown STYLE"); + SendSessionI2PError("Unknown STYLE"); return; } @@ -375,14 +375,14 @@ namespace client if (e) { // not an ip address - SendI2PError("Invalid IP Address in HOST"); + SendSessionI2PError("Invalid IP Address in HOST"); return; } auto port = std::stoi(params[SAM_PARAM_PORT]); if (port == -1) { - SendI2PError("Invalid port"); + SendSessionI2PError("Invalid port"); return; } forward = std::make_shared(addr, port); @@ -484,7 +484,7 @@ namespace client LogPrint (eLogDebug, "SAM: Stream connect: ", buf); if ( m_SocketType != eSAMSocketTypeUnknown) { - SendI2PError ("Socket already in use"); + SendSessionI2PError ("Socket already in use"); return; } std::map params; @@ -582,7 +582,7 @@ namespace client LogPrint (eLogDebug, "SAM: Stream accept: ", buf); if ( m_SocketType != eSAMSocketTypeUnknown) { - SendI2PError ("Socket already in use"); + SendSessionI2PError ("Socket already in use"); return; } std::map params; @@ -598,9 +598,15 @@ namespace client if (!session->GetLocalDestination ()->IsAcceptingStreams ()) { m_IsAccepting = true; + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + else // already accepting + { + // TODO: implement queue + LogPrint (eLogInfo, "SAM: Session ", m_ID, " is already accepting"); + SendStreamI2PError ("Already accepting"); + } } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -620,26 +626,26 @@ namespace client } if (session->GetLocalDestination ()->IsAcceptingStreams ()) { - SendI2PError ("Already accepting"); + SendSessionI2PError ("Already accepting"); return; } auto it = params.find (SAM_PARAM_PORT); if (it == params.end ()) { - SendI2PError ("PORT is missing"); + SendSessionI2PError ("PORT is missing"); return; } auto port = std::stoi (it->second); if (port <= 0 || port >= 0xFFFF) { - SendI2PError ("Invalid PORT"); + SendSessionI2PError ("Invalid PORT"); return; } boost::system::error_code ec; auto ep = m_Socket.remote_endpoint (ec); if (ec) { - SendI2PError ("Socket error"); + SendSessionI2PError ("Socket error"); return; } ep.port (port); @@ -791,13 +797,13 @@ namespace client if (type == eSAMSessionTypeUnknown) { // unknown style - SendI2PError("Unsupported STYLE"); + SendSessionI2PError("Unsupported STYLE"); return; } auto fromPort = std::stoi(params[SAM_PARAM_FROM_PORT]); if (fromPort == -1) { - SendI2PError("Invalid from port"); + SendSessionI2PError("Invalid from port"); return; } auto subsession = std::make_shared(masterSession, id, type, fromPort); @@ -810,7 +816,7 @@ namespace client SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); } else - SendI2PError ("Wrong session type"); + SendSessionI2PError ("Wrong session type"); } void SAMSocket::ProcessSessionRemove (char * buf, size_t len) @@ -832,12 +838,12 @@ namespace client SendSessionCreateReplyOk (); } else - SendI2PError ("Wrong session type"); + SendSessionI2PError ("Wrong session type"); } - void SAMSocket::SendI2PError(const std::string & msg) + void SAMSocket::SendSessionI2PError(const std::string & msg) { - LogPrint (eLogError, "SAM: I2P error: ", msg); + LogPrint (eLogError, "SAM: Session I2P error: ", msg); #ifdef _MSC_VER size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); #else @@ -846,6 +852,17 @@ namespace client SendMessageReply (m_Buffer, len, true); } + void SAMSocket::SendStreamI2PError(const std::string & msg) + { + LogPrint (eLogError, "SAM: Stream I2P error: ", msg); +#ifdef _MSC_VER + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); +#else + size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); +#endif + SendMessageReply (m_Buffer, len, true); + } + void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { if (leaseSet) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index b4c72754..736c0945 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -49,7 +49,7 @@ namespace client const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n"; const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n"; - const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n"; + const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; const char SAM_STREAM_FORWARD[] = "STREAM FORWARD"; const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND"; @@ -141,7 +141,8 @@ namespace client void ProcessNamingLookup (char * buf, size_t len); void ProcessSessionAdd (char * buf, size_t len); void ProcessSessionRemove (char * buf, size_t len); - void SendI2PError(const std::string & msg); + void SendSessionI2PError(const std::string & msg); + void SendStreamI2PError(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ExtractParams (char * buf, std::map& params); From efdbe267554bfa03bcb51097f8e19e9d335e3a9f Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Sep 2023 18:40:51 -0400 Subject: [PATCH 120/264] try peer test again if Unknown --- libi2pd/Transports.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b452c05e..45284e24 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -833,8 +833,12 @@ namespace transport } } bool ipv4Testing = i2p::context.GetTesting (); + if (!ipv4Testing) + ipv4Testing = i2p::context.GetRouterInfo ().IsSSU2V4 () && (i2p::context.GetStatus() == eRouterStatusUnknown); bool ipv6Testing = i2p::context.GetTestingV6 (); - // if still testing, repeat peer test + if (!ipv6Testing) + ipv6Testing = i2p::context.GetRouterInfo ().IsSSU2V6 () && (i2p::context.GetStatusV6() == eRouterStatusUnknown); + // if still testing or unknown, repeat peer test if (ipv4Testing || ipv6Testing) PeerTest (ipv4Testing, ipv6Testing); m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT)); From 9980bfa0e7f03a3849eca4e2e771593cc64419a5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Sep 2023 14:10:45 -0400 Subject: [PATCH 121/264] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7fb7318..ce25c8f2 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http Donations --------- -**E-Mail**: ```i2porignal at yandex.ru``` +**E-Mail**: ```i2porignal at yandex.com``` **BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f``` From e926b0392f3458a1c8af15a4baba0185a56eea09 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Oct 2023 14:22:53 -0400 Subject: [PATCH 122/264] reseed.is.prestium.org reseed added --- .../reheatedburger_at_protonmail.com.crt | 34 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt diff --git a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt new file mode 100644 index 00000000..d14c5fe1 --- /dev/null +++ b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw +fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM +HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX +DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD +VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL +EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6 +MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI +Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt +4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5 +UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k +P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t +3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5 +zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r +Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ +lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1 +sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz +euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW +MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf +BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC +AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj +tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6 +ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf +xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD +UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM +XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE +Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p +Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq +NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr +QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9 +0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY= +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 5551b010..0f101e64 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -221,7 +221,8 @@ namespace config { "https://reseed-pl.i2pd.xyz/," "https://www2.mk16.de/," "https://i2p.ghativega.in/," - "https://i2p.novg.net/" + "https://i2p.novg.net/," + "https://reseed.is.prestium.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From 606e35eec1efd02480f85bac9b8d47706aca8dbe Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Oct 2023 12:59:40 -0400 Subject: [PATCH 123/264] reseed.us.prestium.org reseed added --- .../reseed/null_at_i2pmail.org.crt | 33 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/null_at_i2pmail.org.crt diff --git a/contrib/certificates/reseed/null_at_i2pmail.org.crt b/contrib/certificates/reseed/null_at_i2pmail.org.crt new file mode 100644 index 00000000..d736a95e --- /dev/null +++ b/contrib/certificates/reseed/null_at_i2pmail.org.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw +cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM +EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2 +WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD +VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE +AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0 +XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE +ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA +1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp +gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp +486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR +gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW +DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn +KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX +kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV +bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G +A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD +VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG +9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss +q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj +EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39 +gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV +La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH +xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6 +a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8 +NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK +heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO +j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU +vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw= +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 0f101e64..cd78727f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -222,7 +222,8 @@ namespace config { "https://www2.mk16.de/," "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.is.prestium.org/" + "https://reseed.is.prestium.org/," + "https://reseed.us.prestium.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From 0cc91dd2d2225b7e4690fc4fb7a39106d018ebf8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 15 Oct 2023 08:31:55 -0400 Subject: [PATCH 124/264] don't pick too active peer --- libi2pd/NTCP2.cpp | 20 +++++++------- libi2pd/RouterContext.cpp | 14 +++++----- libi2pd/RouterInfo.h | 8 ++++-- libi2pd/SSU2Session.cpp | 18 ++++++------- libi2pd/TransportSession.h | 55 +++++++++++++++++++++++++++++++++----- libi2pd/Transports.cpp | 2 +- 6 files changed, 80 insertions(+), 37 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index bbd93435..0a23f07e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -374,7 +374,7 @@ namespace transport transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); - m_SendQueueSize = 0; + SetSendQueueSize (0); auto remoteIdentity = GetRemoteIdentity (); if (remoteIdentity) { @@ -433,7 +433,7 @@ namespace transport void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts) { if (m_NextReceivedBuffer && !m_IsReceiving && - ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) + ts > GetLastActivityTimestamp () + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) { delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; @@ -789,7 +789,7 @@ namespace transport void NTCP2Session::ServerLogin () { SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + SetLastActivityTimestamp (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 (), @@ -872,9 +872,8 @@ namespace transport } else { - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumReceivedBytes += bytes_transferred + 2; // + length - i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); + UpdateNumReceivedBytes (bytes_transferred + 2); + i2p::transport::transports.UpdateReceivedBytes (bytes_transferred + 2); uint8_t nonce[12]; CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++; if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false)) @@ -1095,11 +1094,10 @@ namespace transport } else { - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumSentBytes += bytes_transferred; + UpdateNumSentBytes (bytes_transferred); i2p::transport::transports.UpdateSentBytes (bytes_transferred); LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); - if (m_LastActivityTimestamp > m_NextRouterInfoResendTime) + if (GetLastActivityTimestamp () > m_NextRouterInfoResendTime) { m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL + rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; @@ -1108,7 +1106,7 @@ namespace transport else { SendQueue (); - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } } } @@ -1231,7 +1229,7 @@ namespace transport GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); Terminate (); } - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } void NTCP2Session::SendLocalRouterInfo (bool update) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index fa3ba7bd..f21c0592 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -594,15 +594,15 @@ namespace i2p /* detect parameters */ switch (L) { - case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; - case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = 48; type = low; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break; - case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break; + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48 + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 + case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s default: - limit = 48; type = low; + limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; // 48 } /* update caps & flags in RI */ auto caps = m_RouterInfo.GetCaps (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 9aff2240..a95119ed 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -42,8 +42,12 @@ namespace data const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */ const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */ const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ - const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ - const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ + const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */ + const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */ + // bandwidth limits in kBps + const uint32_t LOW_BANDWIDTH_LIMIT = 48; + const uint32_t HIGH_BANDWIDTH_LIMIT = 256; + const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048; // congesion flags const char CAPS_FLAG_MEDIUM_CONGESTION = 'D'; const char CAPS_FLAG_HIGH_CONGESTION = 'E'; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index f0e539c7..487d5549 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -263,7 +263,7 @@ namespace transport m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); m_SendQueue.clear (); - m_SendQueueSize = 0; + SetSendQueueSize (0); m_SentPackets.clear (); m_IncompleteMessages.clear (); m_RelaySessions.clear (); @@ -364,7 +364,7 @@ namespace transport RequestTermination (eSSU2TerminationReasonTimeout); } } - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } bool SSU2Session::SendQueue () @@ -524,7 +524,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; + SetSendQueueSize (0); RequestTermination (eSSU2TerminationReasonTimeout); return resentPackets.size (); } @@ -1452,8 +1452,7 @@ namespace transport header.ll[1] ^= CreateHeaderMask (m_KeyDataSend + 32, payload + (len + 4)); m_Server.Send (header.buf, 16, payload, len + 16, m_RemoteEndpoint); m_SendPacketNum++; - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumSentBytes += len + 32; + UpdateNumSentBytes (len + 32); return m_SendPacketNum - 1; } @@ -1494,8 +1493,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: Data AEAD verification failed "); return; } - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumReceivedBytes += len; + UpdateNumReceivedBytes (len); if (!packetNum || UpdateReceivePacketNum (packetNum)) HandlePayload (payload, payloadSize); } @@ -2357,7 +2355,7 @@ namespace transport if (!msg->IsExpired ()) { // m_LastActivityTimestamp is updated in ProcessData before - if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second) + if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)GetLastActivityTimestamp ()).second) m_Handler.PutNextMessage (std::move (msg)); else LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); @@ -2943,7 +2941,7 @@ namespace transport else ++it; } - if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > m_LastActivityTimestamp + SSU2_DECAY_INTERVAL) + if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > GetLastActivityTimestamp () + SSU2_DECAY_INTERVAL) // decay m_ReceivedI2NPMsgIDs.clear (); else @@ -3015,7 +3013,7 @@ namespace transport { bool sent = SendQueue (); // if we have something to send if (sent) - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); if (m_IsDataReceived) { if (!sent) SendQuickAck (); diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 7d2f2653..e298fdb2 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -71,15 +71,17 @@ namespace transport const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds + const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds class TransportSession { public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0), - m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), - m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), - m_HandshakeInterval (0) + m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_HandshakeInterval (0), + m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0), + m_LastBandWidthUpdateNumSentBytes (0), m_LastBandWidthUpdateNumReceivedBytes (0), + m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), + m_LastBandwidthUpdateTimestamp (m_LastActivityTimestamp), m_InBandwidth (0), m_OutBandwidth (0) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -103,11 +105,29 @@ namespace transport } size_t GetNumSentBytes () const { return m_NumSentBytes; }; + void UpdateNumSentBytes (size_t len) + { + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + m_NumSentBytes += len; + UpdateBandwidth (); + } size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; + void UpdateNumReceivedBytes (size_t len) + { + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + m_NumReceivedBytes += len; + UpdateBandwidth (); + } size_t GetSendQueueSize () const { return m_SendQueueSize; }; + void SetSendQueueSize (size_t s) { m_SendQueueSize = s; }; bool IsOutgoing () const { return m_IsOutgoing; }; bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD && m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; }; + bool IsBandwidthExceeded (bool isHighBandwidth) const + { + auto limit = isHighBandwidth ? i2p::data::HIGH_BANDWIDTH_LIMIT*1024 : i2p::data::LOW_BANDWIDTH_LIMIT*1024; // convert to bytes + return std::max (m_InBandwidth, m_OutBandwidth) > limit; + } int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; @@ -120,21 +140,44 @@ namespace transport uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers + uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; }; + void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; }; + virtual uint32_t GetRelayTag () const { return 0; }; virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; virtual bool IsEstablished () const = 0; + private: + + void UpdateBandwidth () + { + uint64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; + if (interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) + { + m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval; + m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; + m_InBandwidth = (m_NumReceivedBytes - m_LastBandWidthUpdateNumReceivedBytes)/interval; + m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes; + m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp; + } + } + protected: std::shared_ptr m_RemoteIdentity; mutable std::mutex m_RemoteIdentityMutex; - size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize; bool m_IsOutgoing; int m_TerminationTimeout; - uint64_t m_LastActivityTimestamp; uint32_t m_CreationTime; // seconds since epoch int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed + + private: + + size_t m_SendQueueSize, m_NumSentBytes, m_NumReceivedBytes, + m_LastBandWidthUpdateNumSentBytes, m_LastBandWidthUpdateNumReceivedBytes; + uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp; + uint32_t m_InBandwidth, m_OutBandwidth; }; // SOCKS5 proxy diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 45284e24..53a13410 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -951,7 +951,7 @@ namespace transport // connected, not overloaded and not slow return !peer.router && !peer.sessions.empty () && peer.isReachable && peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && - !peer.sessions.front ()->IsSlow () && + !peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) && (!isHighBandwidth || peer.isHighBandwidth); }); } From 0a519d8072423c978a6ea1a788c20976580a5d2c Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 15 Oct 2023 18:08:15 +0300 Subject: [PATCH 125/264] Fix MSVC compilation for std::max --- build/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index abfadfca..6a2aa99b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -121,7 +121,7 @@ if(WIN32) ) file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX") endif() From 04adc14b769da541b07dfddb6a6a0c7b269f15e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Oct 2023 18:46:59 -0400 Subject: [PATCH 126/264] ls@mail.i2p yggdrasil reseed added --- .../certificates/reseed/ls_at_mail.i2p.crt | 32 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/ls_at_mail.i2p.crt diff --git a/contrib/certificates/reseed/ls_at_mail.i2p.crt b/contrib/certificates/reseed/ls_at_mail.i2p.crt new file mode 100644 index 00000000..8e0902d7 --- /dev/null +++ b/contrib/certificates/reseed/ls_at_mail.i2p.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFdTCCA12gAwIBAgIEQ5vCxzANBgkqhkiG9w0BAQ0FADBrMQswCQYDVQQGEwJY +WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt +b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAw +HhcNMjMxMDE2MjAwNTA5WhcNMzMxMDEzMjAwNTA5WjBrMQswCQYDVQQGEwJYWDEL +MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnltb3Vz +IE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPcbKRtf4PzrDa0iRit0XrwnmA +2c1fJhkBipdPor7gMOAlkR82H1lkZSizR7kTZnr7vYqjDrOQr7bl5Dy3qo8/YCbZ +jsnUCTIIgIJQUxUlR40RjaSXphqzUEiXKHR6b0RahhFisQ3hlbbgzSch5YgSLKws +hOLi+eDSXw+HlwHlWFlT1XOKxSTJ/F3Bv40gxqZVC2pbxiPOeRZHQ6Ojw75lxTSF +gww2WzgztiWt4X9BO1yepnVqhAVRPmTfGUMfKzq9jkMzZKeQFV4uZSP9nCqzEpYd +WNDUfpTWiAQ9F+BwFXGusXXA3tGVwS7s6IEoiJFM5fsoJYfRoWGh3/1eirhBXW7U +M6oubMSTADyrvfjLfJBMmMnc2hNblRlKr0ZKUjMfv8cnyT4kQxlXLAHHXY2P89TM +TEVODkU48gnv6tC4t1JCb1/Da+3yVMjNX6rCzQfUwnLFrWthrwiI0NivAKFtiZjq +w1/ZQcYke2YyeqcfXMn+NTUA22Sm2mJoMo7jUf+rbM9Pi27/DncJgRGj5qwY0D3S +gc7829EjuZNPttGBmae1EmO7WQMB32cqdmItnV2FXpMhnn9h0u5H52kYqwn+mdtc +dTJRcbfKG1RTr3UjFISaTwL8qigMIkVXIzcpnr/R/sSeEs8xCqfsJ6rb4dCyFx+M +hqQcOCL5tumyd4W/LQIDAQABoyEwHzAdBgNVHQ4EFgQUgfaOG5HCnlW82wZ5BahL +GRO06igwDQYJKoZIhvcNAQENBQADggIBAKdVpqS9qF7gGotgXaVA1iP5YNsWlTvG +daGqeA/87//U21W6gpq82FhzsmsvUtXZfIeVIlDPI7WNDzS+A3K/KKrwM7dLgSie +r9eMl3D8WYPU95QF4mAlRyl7PCCsYoVjyvfro0iq3/iudIA5476rjfLdTXRi5hAT +qemPj0S+6sRjKEldRtGXrQATFlvLIWVYpgHijdDDx5M2hAz2y0mFxlDZTlA4BhL4 +DwtGlVKmbc2x5MvIQM4UhbQqkxYS4gXnzf5Qx9QIytHfTr/hmbrkhKR1GCO31BSk +x9LhZxdI8LlwKSo6YgwXEB9E0M/tplaK9iZJFv4HPYLZrVJpb4IklMumyLMrgW5P +fR0dgKn+R9lk0emJ1Cu+qyyzf1vsLycYBwaEztINn4VK+/HfDFpnVCvJOyNuDmj5 +KBLIoGdGoVfylmnc+e8zAXe+DY41fgniHMISOO78P8Bx9vTB+rhqnOUr9MzlUxPB +sKGjbXy2YynEqiGb+9g344v/+ukTSDenqTPHVzJ5uOi0iedy+3ASzUNN6GJocovP +167VOhwaETM0FwiKe0VdZRLLbbZ79CtJC0tmgcgPQPRa9Ldr6KN7u1J3D6lUp6zl +byPom10ueKONRb36t7ai79l2SEUZRSMkx6AXIU0JJ1SMtQtav7b5LkpYJfdL7+vO +dDx2/Za0VmdD +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index cd78727f..3d3c5c2a 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -230,7 +230,8 @@ namespace config { "http://[301:65b9:c7cd:9a36::1]:18801/," "http://[320:8936:ec1a:31f1::216]/," "http://[306:3834:97b9:a00a::1]/," - "http://[316:f9e0:f22e:a74f::216]/" + "http://[316:f9e0:f22e:a74f::216]/," + "http://[300:e097:2621:79e3::add1]:7170" ), "Reseed URLs through the Yggdrasil, separated by comma") ; From d04b19d77ce03a973f4e83668fa3e79be574bcdb Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Oct 2023 18:09:41 -0400 Subject: [PATCH 127/264] don't recalculate badwidth if clock was adjusted too much --- libi2pd/TransportSession.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index e298fdb2..f4668116 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -152,8 +152,16 @@ namespace transport void UpdateBandwidth () { - uint64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; - if (interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) + int64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; + if (interval < 0 || interval > 60*10) // 10 minutes + { + // clock was adjusted, copy new values + m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; + m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes; + m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp; + return; + } + if ((uint64_t)interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) { m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval; m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; From 0ef9c083264ba00227383b921a2f4459a8afa290 Mon Sep 17 00:00:00 2001 From: Dex Date: Fri, 27 Oct 2023 15:06:24 +1100 Subject: [PATCH 128/264] fix manpage typo for ipv4 flag --- debian/i2pd.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/i2pd.1 b/debian/i2pd.1 index 5145321f..42c282d9 100644 --- a/debian/i2pd.1 +++ b/debian/i2pd.1 @@ -64,7 +64,7 @@ The network interface to bind to for IPv4 connections The network interface to bind to for IPv6 connections .TP \fB\-\-ipv4=\fR -Enable communication through ipv6 (\fIenabled\fR by default) +Enable communication through ipv4 (\fIenabled\fR by default) .TP \fB\-\-ipv6\fR Enable communication through ipv6 (\fIdisabled\fR by default) From e090b9052a15c57ab6bf2aebfbdd43a845bb97f8 Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Sun, 29 Oct 2023 11:57:14 +0300 Subject: [PATCH 129/264] Yggdrasil reseed address replaced by address for 4.X+ version --- contrib/i2pd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 545973a3..be4a6719 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -225,7 +225,7 @@ verify = true ## Default: "mainline" I2P Network reseeds # urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/ ## Reseed URLs through the Yggdrasil, separated by comma -# yggurls = http://[324:9de3:fea4:f6ac::ace]:7070/ +# yggurls = http://[324:71e:281a:9ed3::ace]:7070/ ## Path to local reseed data file (.su3) for manual reseeding # file = /path/to/i2pseeds.su3 ## or HTTPS URL to reseed from From 3286bdb4a771fb1cb8bd33bb03a4d4ff695ac39a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Oct 2023 22:11:38 -0400 Subject: [PATCH 130/264] verify jump link for valid characters --- libi2pd/Base.cpp | 12 ++++++++++- libi2pd/Base.h | 4 +++- libi2pd_client/AddressBook.cpp | 20 +++++++++++++----- libi2pd_client/HTTPProxy.cpp | 37 ++++++++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index e979c5b4..02ad5f9f 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.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 * @@ -28,6 +28,11 @@ namespace data return T32; } + bool IsBase32 (char ch) + { + return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7'); + } + static void iT64Build(void); /* @@ -55,6 +60,11 @@ namespace data return T64; } + bool IsBase64 (char ch) + { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '~'; + } + /* * Reverse Substitution Table (built in run time) */ diff --git a/libi2pd/Base.h b/libi2pd/Base.h index 79152e02..a163435c 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.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 * @@ -19,9 +19,11 @@ namespace data { size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len ); const char * GetBase32SubstitutionTable (); const char * GetBase64SubstitutionTable (); + bool IsBase64 (char ch); size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); + bool IsBase32 (char ch); /** * Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 055311a9..8f2117a7 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.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 * @@ -403,10 +403,20 @@ namespace client if (!addr) return false; - i2p::data::IdentityEx ident; - if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash) - return true; - + auto pos = jump.find(".b32.i2p"); + if (pos != std::string::npos) + { + i2p::data::IdentHash identHash; + if (identHash.FromBase32(jump.substr (0, pos)) && identHash == addr->identHash) + return true; + } + else + { + i2p::data::IdentityEx ident; + if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash) + return true; + } + return false; } diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 26b47d8b..76d37a1e 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -75,8 +75,9 @@ namespace proxy { void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); - bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm); - void SanitizeHTTPRequest(i2p::http::HTTPReq & req); + static bool ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm); + static bool VerifyAddressHelper (const std::string& jump); + static void SanitizeHTTPRequest(i2p::http::HTTPReq& req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); /* error helpers */ @@ -221,7 +222,7 @@ namespace proxy { std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) + bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm) { confirm = false; const char *param = "i2paddresshelper="; @@ -237,8 +238,13 @@ namespace proxy { std::string value = params["i2paddresshelper"]; len += value.length(); - b64 = i2p::http::UrlDecode(value); - + jump = i2p::http::UrlDecode(value); + if (!VerifyAddressHelper (jump)) + { + LogPrint (eLogError, "HTTPProxy: Malformed jump link ", jump); + return false; + } + // if we need update exists, request formed with update param if (params["update"] == "true") { @@ -269,7 +275,26 @@ namespace proxy { return true; } - void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) + bool HTTPReqHandler::VerifyAddressHelper (const std::string& jump) + { + auto pos = jump.find(".b32.i2p"); + if (pos != std::string::npos) + { + auto b32 = jump.substr (0, pos); + for (auto& ch: b32) + if (!i2p::data::IsBase32(ch)) return false; + return true; + } + else + { + for (auto& ch: jump) + if (!i2p::data::IsBase64(ch)) return false; + return true; + } + return false; + } + + void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq& req) { /* drop common headers */ req.RemoveHeader("Via"); From e1b4feb618ecd7ab9fc81c462646182224384e8c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 08:10:17 -0400 Subject: [PATCH 131/264] correct base64 check --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 02ad5f9f..b8de571b 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -62,7 +62,7 @@ namespace data bool IsBase64 (char ch) { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '~'; + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~'; } /* From 69b0bef206c23046e3ace953db5ecf8af35ebff6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 10:09:47 -0400 Subject: [PATCH 132/264] fixed possible invalid pointer when send error response --- libi2pd_client/HTTPProxy.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 76d37a1e..88de602b 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -109,7 +109,7 @@ namespace proxy { std::shared_ptr m_sock; std::shared_ptr m_proxysock; boost::asio::ip::tcp::resolver m_proxy_resolver; - std::string m_OutproxyUrl; + std::string m_OutproxyUrl, m_Response; bool m_Addresshelper; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; @@ -206,8 +206,8 @@ namespace proxy { << "" << content << "\r\n" << "\r\n"; res.body = ss.str(); - std::string response = res.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), + m_Response = res.to_string(); + boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } @@ -217,8 +217,8 @@ namespace proxy { res.code = 302; res.add_header("Location", address); res.add_header("Connection", "close"); - std::string response = res.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), + m_Response = res.to_string(); + boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } From 575268d36093928d48491cf85e007504732bbf2d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 20:02:48 -0400 Subject: [PATCH 133/264] reduce expiration time for low bandwidth and far routers --- libi2pd/NetDb.cpp | 11 +++++++++-- libi2pd/NetDb.hpp | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 02d4dfd8..12817ad1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -654,13 +654,20 @@ namespace data // find & mark expired routers if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport 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 (checkForExpiration) + { + uint64_t t = expirationTimeout; + if (total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth () && // low bandwidth router + ((it.second->GetIdentHash()[0] & 0xFE) != (i2p::context.GetIdentHash ()[0] & 0xFE))) // different first 7 bits + t >>= 1; // reduce expiration time by 2 times + if (ts > it.second->GetTimestamp () + t) + it.second->SetUnreachable (true); + } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 44dff3b8..8edc94d6 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -39,6 +39,7 @@ namespace data const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; + const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours From a6ee1e648e0724d7798986d1f490c22b80105dd9 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 Oct 2023 09:10:56 -0400 Subject: [PATCH 134/264] recognize trailing padding as part of base64 address --- libi2pd_client/HTTPProxy.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 88de602b..a0fc8f07 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -287,8 +287,17 @@ namespace proxy { } else { + bool padding = false; for (auto& ch: jump) - if (!i2p::data::IsBase64(ch)) return false; + { + if (ch == '=') + padding = true; + else + { + if (padding) return false; // other chars after padding + if (!i2p::data::IsBase64(ch)) return false; + } + } return true; } return false; From a3f62e1d7150cd6d1b5195019a8f3a0caf201548 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 Oct 2023 13:20:04 -0400 Subject: [PATCH 135/264] check actual distance with router to reduce expiration time --- libi2pd/NetDb.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 12817ad1..54b7b7c1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -661,12 +661,13 @@ namespace data } else if (checkForExpiration) { - uint64_t t = expirationTimeout; - if (total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth () && // low bandwidth router - ((it.second->GetIdentHash()[0] & 0xFE) != (i2p::context.GetIdentHash ()[0] & 0xFE))) // different first 7 bits - t >>= 1; // reduce expiration time by 2 times - if (ts > it.second->GetTimestamp () + t) + if (ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); + else if ((ts > it.second->GetTimestamp () + expirationTimeout/2) && // more than half of expiration + total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth() && // low bandwidth + !it.second->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill + (CreateRoutingKey (it.second->GetIdentHash ()) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits + it.second->SetUnreachable (true); } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router From 379be2a29e3d9298cb46e0adba1abc27f36732c1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 31 Oct 2023 22:33:12 +0300 Subject: [PATCH 136/264] [gha] Update FreeBSD build action --- .github/workflows/build-freebsd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml index 76b496ad..b4decc49 100644 --- a/.github/workflows/build-freebsd.yml +++ b/.github/workflows/build-freebsd.yml @@ -13,7 +13,7 @@ jobs: - name: Test in FreeBSD id: test - uses: vmactions/freebsd-vm@v0.3.0 + uses: vmactions/freebsd-vm@v0.3.1 with: usesh: true mem: 2048 From 0021501d750250ad0da604cc4593b5a28b442b05 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 31 Oct 2023 22:39:51 +0300 Subject: [PATCH 137/264] [gha] disable FreeBSD build Additional info: https://github.com/vmactions/freebsd-vm/issues/74 --- .../workflows/{build-freebsd.yml => build-freebsd.yml-disabled} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{build-freebsd.yml => build-freebsd.yml-disabled} (100%) diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml-disabled similarity index 100% rename from .github/workflows/build-freebsd.yml rename to .github/workflows/build-freebsd.yml-disabled From 083034fa35bfdc4924294e57c08313a739cc02f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Nov 2023 21:56:32 -0500 Subject: [PATCH 138/264] send peer tests with random delays --- libi2pd/Transports.cpp | 44 +++++++++++++++++++++++++++++++++++++++--- libi2pd/Transports.h | 2 ++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 53a13410..b6e2e261 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -645,14 +645,33 @@ namespace transport LogPrint (eLogInfo, "Transports: Started peer test IPv4"); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router + int testDelay = 0; for (int i = 0; i < 5; i++) { auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 if (router) { if (!i2p::context.GetTesting ()) + { i2p::context.SetTesting (true); - m_SSU2Server->StartPeerTest (router, true); + // send first peer test immediately + m_SSU2Server->StartPeerTest (router, true); + } + else + { + testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; + if (m_Service) + { + auto delayTimer = std::make_shared(*m_Service); + delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); + delayTimer->async_wait ( + [this, router, delayTimer](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + m_SSU2Server->StartPeerTest (router, true); + }); + } + } excluded.insert (router->GetIdentHash ()); } } @@ -664,14 +683,33 @@ namespace transport LogPrint (eLogInfo, "Transports: Started peer test IPv6"); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router + int testDelay = 0; for (int i = 0; i < 5; i++) { auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 if (router) { if (!i2p::context.GetTestingV6 ()) - i2p::context.SetTestingV6 (true); - m_SSU2Server->StartPeerTest (router, false); + { + i2p::context.SetTestingV6 (true); + // send first peer test immediately + m_SSU2Server->StartPeerTest (router, false); + } + else + { + testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; + if (m_Service) + { + auto delayTimer = std::make_shared(*m_Service); + delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); + delayTimer->async_wait ( + [this, router, delayTimer](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + m_SSU2Server->StartPeerTest (router, false); + }); + } + } excluded.insert (router->GetIdentHash ()); } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index a8f2a16a..cb63ca91 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -105,6 +105,8 @@ namespace transport const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds const int PEER_TEST_INTERVAL = 71; // in minutes + const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds + const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds const int MAX_NUM_DELAYED_MESSAGES = 150; const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after class Transports From 6b33250c599f138d8834fb00bfe9f936bc9d8894 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sat, 4 Nov 2023 12:24:33 +0100 Subject: [PATCH 139/264] build/CMakeLists.txt: enable C language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detection of libatomic is broken since version 2.47.0 and https://github.com/PurpleI2P/i2pd/commit/b7f0d87dafa8957131b496c38fbe65d8cb378a9d because C language is not enabled anymore: -- Looking for __atomic_fetch_add_4 in atomic -- Looking for __atomic_fetch_add_4 in atomic - not found CMake Error at cmake_modules/CheckAtomic.cmake:59 (message): Host compiler appears to require libatomic, but cannot find it. Call Stack (most recent call first): CMakeLists.txt:54 (include) Indeed if C language is not enabled, the test will be run with the C++ compiler resulting in the following error: Building CXX object CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o /home/fabrice/buildroot/output/host/bin/x86_64-linux-g++ --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4 -DNDEBUG -o CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-NApnv9/CheckFunctionExists.cxx : error: new declaration ‘char __atomic_fetch_add_4()’ ambiguates built-in declaration ‘unsigned int __atomic_fetch_add_4(volatile void*, unsigned int, int)’ [-fpermissive] whereas with a C compiler, we'll get: Building C object CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o /home/fabrice/buildroot/output/host/bin/x86_64-linux-gcc --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4 -DNDEBUG -o CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-e0zFMG/CheckFunctionExists.c : warning: conflicting types for built-in function ‘__atomic_fetch_add_4’; expected ‘unsigned int(volatile void *, unsigned int, int)’ [-Wbuiltin-declaration-mismatch] Fix #1908 Signed-off-by: Fabrice Fontaine --- build/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 6a2aa99b..232e427f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -25,7 +25,7 @@ project( i2pd VERSION ${PROJECT_VERSION} HOMEPAGE_URL "https://i2pd.website/" - LANGUAGES CXX + LANGUAGES C CXX ) # configurable options From 1a02819187ea306d64e6090d7a3536bacfc76982 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Fri, 21 Jul 2023 21:43:40 +0300 Subject: [PATCH 140/264] Remove deprecated bind_at_load from macOS --- Makefile.osx | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.osx b/Makefile.osx index e069aaff..467c9fdd 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -5,7 +5,6 @@ DEFINES := -DMAC_OSX LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib LDFLAGS += -Wl,-dead_strip LDFLAGS += -Wl,-dead_strip_dylibs -LDFLAGS += -Wl,-bind_at_load ifeq ($(USE_STATIC),yes) LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread From 9632e7ba03533533ff056ad89546bdc3441269b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Nov 2023 18:32:57 -0500 Subject: [PATCH 141/264] exclude NAT64 ipv6 addresses --- libi2pd/util.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index a7afdce8..d1ed9992 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.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 * @@ -665,6 +665,7 @@ namespace net if (host.is_v6()) { static const std::vector< std::pair > reservedIPv6Ranges { + address_pair_v6("64:ff9b::", "64:ff9b:ffff:ffff:ffff:ffff:ffff:ffff"), // NAT64 address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), From 8d6eb5b6b2c8f69627cefaa5b6eb4f1010c11631 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Nov 2023 19:12:07 -0500 Subject: [PATCH 142/264] don't lock mutex in AsyncSend --- libi2pd/Streaming.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c2cf3a0a..a7f932f5 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -532,14 +532,18 @@ namespace stream void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler) { + std::shared_ptr buffer; if (len > 0 && buf) - { - std::unique_lock l(m_SendBufferMutex); - m_SendBuffer.Add (buf, len, handler); - } + buffer = std::make_shared(buf, len, handler); else if (handler) handler(boost::system::error_code ()); - m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ())); + auto s = shared_from_this (); + m_Service.post ([s, buffer]() + { + if (buffer) + s->m_SendBuffer.Add (buffer); + s->SendBuffer (); + }); } void Stream::SendBuffer () From 21259204b1f55e1014d088d5d7a2b1cf11048ea6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Nov 2023 09:39:36 -0500 Subject: [PATCH 143/264] eliminate send buffer mutex completely --- libi2pd/Streaming.cpp | 171 ++++++++++++++++++++---------------------- libi2pd/Streaming.h | 2 - 2 files changed, 80 insertions(+), 93 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a7f932f5..629039ab 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -19,11 +19,6 @@ namespace i2p { namespace stream { - void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler) - { - Add (std::make_shared(buf, len, handler)); - } - void SendBufferQueue::Add (std::shared_ptr buf) { if (buf) @@ -115,10 +110,7 @@ namespace stream void Stream::CleanUp () { - { - std::unique_lock l(m_SendBufferMutex); - m_SendBuffer.CleanUp (); - } + m_SendBuffer.CleanUp (); while (!m_ReceiveQueue.empty ()) { auto packet = m_ReceiveQueue.front (); @@ -553,91 +545,88 @@ namespace stream bool isNoAck = m_LastReceivedSequenceNumber < 0; // first packet std::vector packets; + while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0)) { - std::unique_lock l(m_SendBufferMutex); - while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0)) + Packet * p = m_LocalDestination.NewPacket (); + uint8_t * packet = p->GetBuffer (); + // TODO: implement setters + size_t size = 0; + htobe32buf (packet + size, m_SendStreamID); + size += 4; // sendStreamID + htobe32buf (packet + size, m_RecvStreamID); + size += 4; // receiveStreamID + htobe32buf (packet + size, m_SequenceNumber++); + size += 4; // sequenceNum + if (isNoAck) + htobuf32 (packet + size, 0); + else + htobe32buf (packet + size, m_LastReceivedSequenceNumber); + size += 4; // ack Through + if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) { - Packet * p = m_LocalDestination.NewPacket (); - uint8_t * packet = p->GetBuffer (); - // TODO: implement setters - size_t size = 0; - htobe32buf (packet + size, m_SendStreamID); - size += 4; // sendStreamID - htobe32buf (packet + size, m_RecvStreamID); - size += 4; // receiveStreamID - htobe32buf (packet + size, m_SequenceNumber++); - size += 4; // sequenceNum - if (isNoAck) - htobuf32 (packet + size, 0); - else - htobe32buf (packet + size, m_LastReceivedSequenceNumber); - size += 4; // ack Through - if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) - { - // first SYN packet - packet[size] = 8; - size++; // NACK count - memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); - size += 32; - } - else - { - packet[size] = 0; - size++; // NACK count - } - packet[size] = m_RTO/1000; - size++; // resend delay - if (m_Status == eStreamStatusNew) - { - // initial packet - m_Status = eStreamStatusOpen; - if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; - if (m_RemoteLeaseSet) - { - m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); - m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU; - } - uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | - PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; - if (isNoAck) flags |= PACKET_FLAG_NO_ACK; - bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); - if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; - htobe16buf (packet + size, flags); - size += 2; // flags - size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); - size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); - uint8_t * optionsSize = packet + size; // set options size later - size += 2; // options size - m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); - size += identityLen; // from - htobe16buf (packet + size, m_MTU); - size += 2; // max packet size - if (isOfflineSignature) - { - const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); - memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); - size += offlineSignature.size (); // offline signature - } - uint8_t * signature = packet + size; // set it later - memset (signature, 0, signatureLen); // zeroes for now - size += signatureLen; // signature - htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size - size += m_SendBuffer.Get (packet + size, m_MTU); // payload - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); - } - else - { - // follow on packet - htobuf16 (packet + size, 0); - size += 2; // flags - htobuf16 (packet + size, 0); // no options - size += 2; // options size - size += m_SendBuffer.Get(packet + size, m_MTU); // payload - } - p->len = size; - packets.push_back (p); - numMsgs--; + // first SYN packet + packet[size] = 8; + size++; // NACK count + memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); + size += 32; } + else + { + packet[size] = 0; + size++; // NACK count + } + packet[size] = m_RTO/1000; + size++; // resend delay + if (m_Status == eStreamStatusNew) + { + // initial packet + m_Status = eStreamStatusOpen; + if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; + if (m_RemoteLeaseSet) + { + m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); + m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU; + } + uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | + PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; + if (isNoAck) flags |= PACKET_FLAG_NO_ACK; + bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); + if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; + htobe16buf (packet + size, flags); + size += 2; // flags + size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); + size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); + uint8_t * optionsSize = packet + size; // set options size later + size += 2; // options size + m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); + size += identityLen; // from + htobe16buf (packet + size, m_MTU); + size += 2; // max packet size + if (isOfflineSignature) + { + const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); + memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); + size += offlineSignature.size (); // offline signature + } + uint8_t * signature = packet + size; // set it later + memset (signature, 0, signatureLen); // zeroes for now + size += signatureLen; // signature + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + size += m_SendBuffer.Get (packet + size, m_MTU); // payload + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + } + else + { + // follow on packet + htobuf16 (packet + size, 0); + size += 2; // flags + htobuf16 (packet + size, 0); // no options + size += 2; // options size + size += m_SendBuffer.Get(packet + size, m_MTU); // payload + } + p->len = size; + packets.push_back (p); + numMsgs--; } if (packets.size () > 0) { diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 3609df92..1db59118 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -135,7 +135,6 @@ namespace stream SendBufferQueue (): m_Size (0) {}; ~SendBufferQueue () { CleanUp (); }; - void Add (const uint8_t * buf, size_t len, SendHandler handler); void Add (std::shared_ptr buf); size_t Get (uint8_t * buf, size_t len); size_t GetSize () const { return m_Size; }; @@ -251,7 +250,6 @@ namespace stream size_t m_NumSentBytes, m_NumReceivedBytes; uint16_t m_Port; - std::mutex m_SendBufferMutex; SendBufferQueue m_SendBuffer; int m_WindowSize, m_RTT, m_RTO, m_AckDelay; uint64_t m_LastWindowSizeIncreaseTime; From 94255ebaf40236f224bcd45be89c18d0747ce591 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Nov 2023 13:44:30 -0500 Subject: [PATCH 144/264] STREAM ACCEPT queue --- libi2pd_client/SAM.cpp | 29 +++++++++++++++++------------ libi2pd_client/SAM.h | 5 ++++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1a281c57..54da4654 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -601,10 +601,15 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - else // already accepting + else if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) + { + // already accepting, queue up + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + session->acceptQueue.push_back (shared_from_this()); + } + else { - // TODO: implement queue - LogPrint (eLogInfo, "SAM: Session ", m_ID, " is already accepting"); + LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); SendStreamI2PError ("Already accepting"); } } @@ -1057,16 +1062,16 @@ namespace client m_Stream = stream; context.GetAddressBook ().InsertFullAddress (stream->GetRemoteIdentity ()); auto session = m_Owner.FindSession (m_ID); - if (session) + if (session && !session->acceptQueue.empty ()) { - // find more pending acceptors - for (auto & it: m_Owner.ListSockets (m_ID)) - if (it->m_SocketType == eSAMSocketTypeAcceptor) - { - it->m_IsAccepting = true; - session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, it, std::placeholders::_1)); - break; - } + // pending acceptors + auto socket = session->acceptQueue.front (); + session->acceptQueue.pop_front (); + if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) + { + socket->m_IsAccepting = true; + session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + } } if (!m_IsSilent) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 736c0945..2841afb9 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -31,6 +31,8 @@ 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 = 3; // in seconds + const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 64; + 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"; @@ -189,7 +191,8 @@ namespace client std::string Name; SAMSessionType Type; std::shared_ptr UDPEndpoint; // TODO: move - + std::list > acceptQueue; + SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); virtual ~SAMSession () {}; From d327533b56d5a7f88d9d5004670fa5274d333dfc Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Nov 2023 18:50:52 -0500 Subject: [PATCH 145/264] close unclaimed acceptors after 3 seconds --- libi2pd_client/SAM.cpp | 52 ++++++++++++++++++++++++++++++------------ libi2pd_client/SAM.h | 5 ++-- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 54da4654..ffdeb5ac 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -601,16 +601,27 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - else if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) - { - // already accepting, queue up - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); - session->acceptQueue.push_back (shared_from_this()); - } - else + else { - LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); - SendStreamI2PError ("Already accepting"); + auto ts = i2p::util::GetSecondsSinceEpoch (); + while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket) + m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); + } + if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) + { + // already accepting, queue up + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts)); + } + else + { + LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); + SendStreamI2PError ("Already accepting"); + } } } else @@ -1065,12 +1076,23 @@ namespace client if (session && !session->acceptQueue.empty ()) { // pending acceptors - auto socket = session->acceptQueue.front (); - session->acceptQueue.pop_front (); - if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) - { - socket->m_IsAccepting = true; - session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + auto ts = i2p::util::GetSecondsSinceEpoch (); + while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket) + m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); + } + if (!session->acceptQueue.empty ()) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) + { + socket->m_IsAccepting = true; + session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + } } } if (!m_IsSilent) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 2841afb9..34af5a62 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -31,7 +31,8 @@ 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 = 3; // in seconds - const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 64; + const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 50; + const size_t SAM_SESSION_MAX_ACCEPT_INTERVAL = 3; // in seconds const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; @@ -191,7 +192,7 @@ namespace client std::string Name; SAMSessionType Type; std::shared_ptr UDPEndpoint; // TODO: move - std::list > acceptQueue; + std::list, uint64_t> > acceptQueue; // socket, receive time in seconds SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); virtual ~SAMSession () {}; From c215f2e8d19f07b95163fdfecd974fa5eec2dce1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Nov 2023 13:06:50 -0500 Subject: [PATCH 146/264] check router for null pointer --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 54b7b7c1..07f0f341 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -628,7 +628,7 @@ namespace data auto own = i2p::context.GetSharedRouterInfo (); for (auto& it: m_RouterInfos) { - if (it.second == own) continue; // skip own + if (!it.second || it.second == own) continue; // skip own std::string ident = it.second->GetIdentHashBase64(); if (it.second->IsUpdated ()) { @@ -698,7 +698,7 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { - if (it->second->IsUnreachable ()) + if (!it->second || it->second->IsUnreachable ()) it = m_RouterInfos.erase (it); else { From c802c2deb0eac4e8b012939f0da6128d40bf6b8c Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 5 Dec 2023 15:48:26 -0500 Subject: [PATCH 147/264] update yggdrasil ressed address --- libi2pd/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3d3c5c2a..4deb59ac 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -231,7 +231,7 @@ namespace config { "http://[320:8936:ec1a:31f1::216]/," "http://[306:3834:97b9:a00a::1]/," "http://[316:f9e0:f22e:a74f::216]/," - "http://[300:e097:2621:79e3::add1]:7170" + "http://[300:eaff:7fab:181b::e621]:7170" ), "Reseed URLs through the Yggdrasil, separated by comma") ; From 9b82265cd87e8bd4b329733713b50c6c7f85b6ba Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Dec 2023 11:07:10 -0500 Subject: [PATCH 148/264] 2.50.0 --- ChangeLog | 15 +++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4dd49a24..1e5156f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.0] - 2023-12-18 +### Added +- Support of concurrent ACCEPTs on SAM 3.1 +- Haiku OS support +- Low bandwidth and far routers can expire before 1 hour +### Changed +- Don't pick too active peer for first hop +- Try peer test again if status is Unknown +- Send peer tests with random delay +- Reseeds list +### Fixed +- XSS vulnerability in addresshelper +- Publishing NAT64 ipv6 addresses +- Deadlock in AsyncSend callback + ## [2.49.0] - 2023-09-18 ### Added - Handle SOCK5 authorization with empty user/password diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index c745e05f..f0344a34 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.49.0 +Version: 2.50.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Dec 18 2023 orignal - 2.50.0 +- update to 2.50.0 + * Mon Sep 18 2023 orignal - 2.49.0 - update to 2.49.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 56a7f6e1..9b662f6e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.49.0 +Version: 2.50.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Dec 18 2023 orignal - 2.50.0 +- update to 2.50.0 + * Mon Sep 18 2023 orignal - 2.49.0 - update to 2.49.0 diff --git a/debian/changelog b/debian/changelog index 4c8ed6bb..55566573 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.0-1) unstable; urgency=medium + + * updated to version 2.50.0/0.9.61 + + -- orignal Mon, 18 Dec 2023 16:00:00 +0000 + i2pd (2.49.0-1) unstable; urgency=medium * updated to version 2.49.0/0.9.60 diff --git a/libi2pd/version.h b/libi2pd/version.h index 9854995e..03d6b963 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 49 +#define I2PD_VERSION_MINOR 50 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 60 +#define I2P_VERSION_MICRO 61 #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 c2d71331749ac3500d20d19038c29d7d8d4d2eed Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Dec 2023 19:30:55 +0000 Subject: [PATCH 149/264] [make] fix windows msys2 build Signed-off-by: r4sas --- Makefile | 2 +- Makefile.mingw | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 86ea0aa8..3998beb0 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ obj/%.o: %.cpp | mk_obj_dir -include $(DEPS) $(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) - $(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS) + $(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(SHLIB): $(LIB_OBJS) ifneq ($(USE_STATIC),yes) diff --git a/Makefile.mingw b/Makefile.mingw index 6cd19080..157f49c1 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -5,14 +5,11 @@ WINDRES = windres CXXFLAGS := $(CXX_DEBUG) -fPIC -msse INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32 -LDFLAGS := ${LD_DEBUG} -static +LDFLAGS := ${LD_DEBUG} -static -fPIC -msse NEEDED_CXXFLAGS += -std=c++17 DEFINES += -DWIN32_LEAN_AND_MEAN -# Boost libraries suffix -BOOST_SUFFIX = -mt - # UPNP Support ifeq ($(USE_UPNP),yes) DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB @@ -20,20 +17,20 @@ ifeq ($(USE_UPNP),yes) endif LDLIBS += \ - -lboost_system$(BOOST_SUFFIX) \ - -lboost_date_time$(BOOST_SUFFIX) \ - -lboost_filesystem$(BOOST_SUFFIX) \ - -lboost_program_options$(BOOST_SUFFIX) \ - -lssl \ - -lcrypto \ - -lz \ + $(MINGW_PREFIX)/lib/libboost_system-mt.a \ + $(MINGW_PREFIX)/lib/libboost_date_time-mt.a \ + $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ + $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ + $(MINGW_PREFIX)/lib/libssl.a \ + $(MINGW_PREFIX)/lib/libcrypto.a \ + $(MINGW_PREFIX)/lib/libz.a \ -lwsock32 \ -lws2_32 \ - -lgdi32 \ -liphlpapi \ + -lcrypt32 \ + -lgdi32 \ -lole32 \ - -luuid \ - -lpthread + -luuid ifeq ($(USE_WIN32_APP), yes) DEFINES += -DWIN32_APP @@ -48,6 +45,7 @@ endif ifeq ($(USE_AESNI),yes) NEEDED_CXXFLAGS += -maes + LDFLAGS += -maes DEFINES += -D__AES__ endif From 53c6b10177b85f510dd0e67a9d6dbb5ccaa0bbcf Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Dec 2023 19:41:28 +0000 Subject: [PATCH 150/264] [make] get the mistakenly deleted pthread back Signed-off-by: r4sas --- Makefile.mingw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.mingw b/Makefile.mingw index 157f49c1..38da225a 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -30,7 +30,8 @@ LDLIBS += \ -lcrypt32 \ -lgdi32 \ -lole32 \ - -luuid + -luuid \ + -lpthread ifeq ($(USE_WIN32_APP), yes) DEFINES += -DWIN32_APP From c3429bb1a935f8c637cae422a2b85d0f3508d1aa Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 09:38:08 +0000 Subject: [PATCH 151/264] [gha] return freebsd build back Signed-off-by: r4sas --- .github/workflows/build-freebsd.yml | 32 +++++++++++++++++++++++++++++ ChangeLog | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-freebsd.yml diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml new file mode 100644 index 00000000..6dc46a39 --- /dev/null +++ b/.github/workflows/build-freebsd.yml @@ -0,0 +1,32 @@ +name: Build on FreeBSD + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + name: with UPnP + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Test in FreeBSD + id: test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + mem: 2048 + sync: rsync + copyback: true + prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc + run: | + cd build + cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . + gmake -j2 + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: i2pd-freebsd + path: build/i2pd diff --git a/ChangeLog b/ChangeLog index 1e5156f9..31e8718b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,7 +9,7 @@ ### Changed - Don't pick too active peer for first hop - Try peer test again if status is Unknown -- Send peer tests with random delay +- Send peer tests with random delay - Reseeds list ### Fixed - XSS vulnerability in addresshelper From 05eda2bc9eed9a816f6668c9b06a62d7a42d98d5 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 09:55:10 +0000 Subject: [PATCH 152/264] [gha] build docker containers only on specific paths changes Signed-off-by: r4sas --- .github/workflows/build-freebsd.yml-disabled | 32 -------------------- .github/workflows/docker.yml | 10 ++++++ 2 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/build-freebsd.yml-disabled diff --git a/.github/workflows/build-freebsd.yml-disabled b/.github/workflows/build-freebsd.yml-disabled deleted file mode 100644 index b4decc49..00000000 --- a/.github/workflows/build-freebsd.yml-disabled +++ /dev/null @@ -1,32 +0,0 @@ -name: Build on FreeBSD - -on: [push, pull_request] - -jobs: - build: - runs-on: macos-12 - name: with UPnP - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Test in FreeBSD - id: test - uses: vmactions/freebsd-vm@v0.3.1 - with: - usesh: true - mem: 2048 - sync: rsync - copyback: true - prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc - run: | - cd build - cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . - gmake -j2 - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: i2pd-freebsd - path: build/i2pd diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 28e4e8b0..41fe859e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -5,6 +5,16 @@ on: branches: - openssl - docker + paths: + - .github/workflows/docker.yml + - contrib/docker/** + - contrib/certificates/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.linux tags: - '*' From beffdb9fe175a93164bd88ee0fafe1a22595ed15 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 10:06:49 +0000 Subject: [PATCH 153/264] [apparmor] add profile for docker container Author: corona@mail.i2p Signed-off-by: r4sas --- contrib/apparmor/docker-i2pd | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 contrib/apparmor/docker-i2pd diff --git a/contrib/apparmor/docker-i2pd b/contrib/apparmor/docker-i2pd new file mode 100644 index 00000000..8e34298a --- /dev/null +++ b/contrib/apparmor/docker-i2pd @@ -0,0 +1,42 @@ +# _________________________________________ +# / Copy this file to the right location \ +# | then load with: | +# | | +# | apparmor_parser -r -W | +# | /etc/apparmor.d/docker-i2pd | +# | | +# | docker run --security-opt | +# | "apparmor=docker-i2pd" ... | +# | purplei2p/i2pd | +# | | +# \ And "aa-status" to verify it's loaded. / +# ----------------------------------------- +# \ ^__^ +# \ (oo)\_______ +# (__)\ )\/\ +# ||----w | +# || || + +#include + +profile docker-i2pd flags=(attach_disconnected,mediate_deleted) { + #include + #include + #include + + /bin/busybox ix, + /usr/local/bin/i2pd ix, + /entrypoint.sh ixr, + + /i2pd_certificates/** r, + + /home/i2pd/data/** rw, + + /home/i2pd/data/i2pd.pid k, + + deny /home/i2pd/data/i2pd.conf w, + deny /home/i2pd/data/tunnels.conf w, + deny /home/i2pd/data/tunnels.d/** w, + deny /home/i2pd/data/certificates/** w, + deny /home/i2pd/data/i2pd.log r, +} From 0e98dd5c7049d79bdcdba341357c504e562eb61f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Dec 2023 07:40:40 -0500 Subject: [PATCH 154/264] use fallback EdDSA implementation with openssl 3.2.0 due to regression in EVP_DigestSign (#23075) --- libi2pd/Crypto.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 816d79fd..5b31cdd4 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -39,7 +39,9 @@ # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # define OPENSSL_HKDF 1 -# define OPENSSL_EDDSA 1 +# if (OPENSSL_VERSION_NUMBER < 0x030200000) // 3.2.0, regression in EVP_DigestSign +# define OPENSSL_EDDSA 1 +# endif # define OPENSSL_X25519 1 # if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash # define OPENSSL_SIPHASH 1 From 8ffc1486a4cbacb774fd5b8834f9a6022ed2044b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Dec 2023 09:32:12 -0500 Subject: [PATCH 155/264] test-eddsa added --- tests/CMakeLists.txt | 7 +++++ tests/Makefile | 6 +++- tests/test-eddsa.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/test-eddsa.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 21daadd9..de319f5d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -65,6 +65,10 @@ SET(test-elligator_SRCS test-elligator.cpp ) +set(test-eddsa_SRCS + test-eddsa.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}) @@ -77,6 +81,7 @@ 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}) +add_executable(test-eddsa ${test-eddsa_SRCS}) set(LIBS libi2pd @@ -101,6 +106,7 @@ target_link_libraries(test-x25519 ${LIBS}) target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) target_link_libraries(test-blinding ${LIBS}) target_link_libraries(test-elligator ${LIBS}) +target_link_libraries(test-eddsa ${LIBS}) add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked) add_test(test-http-req ${TEST_PATH}/test-http-req) @@ -114,3 +120,4 @@ 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) +add_test(test-eddsa ${TEST_PATH}/test-eddsa) diff --git a/tests/Makefile b/tests/Makefile index 9c5711e2..7c44e467 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -7,7 +7,8 @@ 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 + test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding \ + test-elligator test-eddsa ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) CXXFLAGS += -DWIN32_LEAN_AND_MEAN @@ -55,6 +56,9 @@ test-blinding: test-blinding.cpp $(LIBI2PD) test-elligator: test-elligator.cpp $(LIBI2PD) $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) +test-eddsa: test-eddsa.cpp $(LIBI2PD) + $(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-eddsa.cpp b/tests/test-eddsa.cpp new file mode 100644 index 00000000..b3895e2b --- /dev/null +++ b/tests/test-eddsa.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +#include "Signature.h" + +// TEST 1024 from RFC-8032 + +int main () +{ + uint8_t key[32], pub[32], msg[1024], sig[64]; + BIGNUM * input = BN_new(); + BN_hex2bn(&input, "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5"); + BN_bn2bin(input, key); + BN_hex2bn(&input, + "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8" + "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d" + "658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc" + "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4fe" + "ba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e" + "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbef" + "efd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7" + "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed1" + "85ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2" + "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24" + "554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270" + "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc" + "2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07" + "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128ba" + "b27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a" + "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429e" + "c96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7" + "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c" + "42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8" + "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34df" + "f7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08" + "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649" + "de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4" + "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a3" + "2ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e" + "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5f" + "b93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5" + "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1" + "369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d" + "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c" + "0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0" + ); + BN_bn2bin(input, msg); + BN_hex2bn(&input, + "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350" + "aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03"); + BN_bn2bin(input, sig); + BN_hex2bn(&input, + "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"); + BN_bn2bin(input, pub); + + uint8_t s[64]; + i2p::crypto::EDDSA25519Signer signer (key); + signer.Sign (msg, 1023, s); +#if OPENSSL_EDDSA + assert(memcmp (s, sig, 64) == 0); +#endif + + i2p::crypto::EDDSA25519Verifier verifier; + verifier.SetPublicKey (pub); + assert(verifier.Verify (msg, 1023, s)); +} From 43e130ee347c9aea7a840ebfa242ec897f906886 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 19 Dec 2023 19:29:08 -0500 Subject: [PATCH 156/264] reinitialize context before each Sign/Verify call to make it working with openssl 3.2 --- libi2pd/Crypto.h | 4 +--- libi2pd/Signature.cpp | 27 ++++++++++++++------------- libi2pd/Signature.h | 4 +++- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 5b31cdd4..816d79fd 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -39,9 +39,7 @@ # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # define OPENSSL_HKDF 1 -# if (OPENSSL_VERSION_NUMBER < 0x030200000) // 3.2.0, regression in EVP_DigestSign -# define OPENSSL_EDDSA 1 -# endif +# define OPENSSL_EDDSA 1 # define OPENSSL_X25519 1 # if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash # define OPENSSL_SIPHASH 1 diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index ebc188a9..60cdbec2 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.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 * @@ -15,7 +15,8 @@ namespace i2p namespace crypto { #if OPENSSL_EDDSA - EDDSA25519Verifier::EDDSA25519Verifier () + EDDSA25519Verifier::EDDSA25519Verifier (): + m_Pkey (nullptr) { m_MDCtx = EVP_MD_CTX_create (); } @@ -23,17 +24,18 @@ namespace crypto EDDSA25519Verifier::~EDDSA25519Verifier () { EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); } void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) { - EVP_PKEY * pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); - EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, pkey); - EVP_PKEY_free (pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); + m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); } bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { + EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); } @@ -99,29 +101,26 @@ namespace crypto #if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): - m_MDCtx (nullptr), m_Fallback (nullptr) + m_MDCtx (nullptr), m_Pkey (nullptr), m_Fallback (nullptr) { - EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); + m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; size_t len = EDDSA25519_PUBLIC_KEY_LENGTH; - EVP_PKEY_get_raw_public_key (pkey, publicKey, &len); + EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len); if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH)) { LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback"); m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey); } else - { m_MDCtx = EVP_MD_CTX_create (); - EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, pkey); - } - EVP_PKEY_free (pkey); } EDDSA25519Signer::~EDDSA25519Signer () { if (m_Fallback) delete m_Fallback; EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); } void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const @@ -131,7 +130,9 @@ namespace crypto { size_t l = 64; uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232 - EVP_DigestSign (m_MDCtx, sig, &l, buf, len); + EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); + if (!EVP_DigestSign (m_MDCtx, sig, &l, buf, len)) + LogPrint (eLogError, "EdDSA signing failed"); memcpy (signature, sig, 64); } } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index e153e66d..671ebfb7 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.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 * @@ -305,6 +305,7 @@ namespace crypto #if OPENSSL_EDDSA EVP_MD_CTX * m_MDCtx; + EVP_PKEY * m_Pkey; #else EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; @@ -342,6 +343,7 @@ namespace crypto private: EVP_MD_CTX * m_MDCtx; + EVP_PKEY * m_Pkey; EDDSA25519SignerCompat * m_Fallback; }; #else From 816a58f292228fb72ca9383023cba817acfad56d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 23 Dec 2023 18:13:31 +0000 Subject: [PATCH 157/264] 2.50.1 Signed-off-by: r4sas --- ChangeLog | 4 ++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 31e8718b..87329bf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.0] - 2023-12-23 +###Fixed +- Support for new EdDSA usage behavior in OpenSSL 3.2.0 + ## [2.50.0] - 2023-12-18 ### Added - Support of concurrent ACCEPTs on SAM 3.1 diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index f0344a34..ab5b4190 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.50.0 +Version: 2.50.1 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Dec 23 2023 r4sas - 2.50.1 +- update to 2.50.1 + * Mon Dec 18 2023 orignal - 2.50.0 - update to 2.50.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 9b662f6e..74cc826d 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.50.0 +Version: 2.50.1 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Dec 23 2023 r4sas - 2.50.1 +- update to 2.50.1 + * Mon Dec 18 2023 orignal - 2.50.0 - update to 2.50.0 diff --git a/debian/changelog b/debian/changelog index 55566573..5484fd92 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.1-1) unstable; urgency=medium + + * updated to version 2.50.1/0.9.61 + + -- r4sas Sat, 23 Dec 2023 18:30:00 +0000 + i2pd (2.50.0-1) unstable; urgency=medium * updated to version 2.50.0/0.9.61 diff --git a/libi2pd/version.h b/libi2pd/version.h index 03d6b963..c79e3a2b 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -19,7 +19,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 50 -#define I2PD_VERSION_MICRO 0 +#define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) From 69ee6112b3b134c40e4446999ede613d985a9122 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 23 Dec 2023 19:53:39 +0000 Subject: [PATCH 158/264] [changelog] fix version Signed-off-by: r4sas --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 87329bf8..0778cd70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog -## [2.50.0] - 2023-12-23 +## [2.50.1] - 2023-12-23 ###Fixed - Support for new EdDSA usage behavior in OpenSSL 3.2.0 From 302af823a3509e5faa0e5cfcacdef2e480250d88 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 15:55:53 -0500 Subject: [PATCH 159/264] fixed race condition with openssl 3.2.0 --- libi2pd/Signature.cpp | 38 +++++++++++++++++++++++++------------- libi2pd/Signature.h | 2 -- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 60cdbec2..342b6d03 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -18,12 +18,10 @@ namespace crypto EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) { - m_MDCtx = EVP_MD_CTX_create (); } EDDSA25519Verifier::~EDDSA25519Verifier () { - EVP_MD_CTX_destroy (m_MDCtx); EVP_PKEY_free (m_Pkey); } @@ -35,8 +33,17 @@ namespace crypto bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); + if (m_Pkey) + { + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, m_Pkey); + auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len); + EVP_MD_CTX_destroy (ctx); + return ret; + } + else + LogPrint (eLogError, "EdDSA verification key is not set"); + return false; } #else @@ -101,7 +108,7 @@ namespace crypto #if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): - m_MDCtx (nullptr), m_Pkey (nullptr), m_Fallback (nullptr) + m_Pkey (nullptr), m_Fallback (nullptr) { m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; @@ -111,30 +118,35 @@ namespace crypto { LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback"); m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey); + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; } - else - m_MDCtx = EVP_MD_CTX_create (); } EDDSA25519Signer::~EDDSA25519Signer () { if (m_Fallback) delete m_Fallback; - EVP_MD_CTX_destroy (m_MDCtx); - EVP_PKEY_free (m_Pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); } void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { - if (m_Fallback) return m_Fallback->Sign (buf, len, signature); - else + if (m_Fallback) + return m_Fallback->Sign (buf, len, signature); + else if (m_Pkey) { + + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); size_t l = 64; uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232 - EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - if (!EVP_DigestSign (m_MDCtx, sig, &l, buf, len)) + EVP_DigestSignInit (ctx, NULL, NULL, NULL, m_Pkey); + if (!EVP_DigestSign (ctx, sig, &l, buf, len)) LogPrint (eLogError, "EdDSA signing failed"); memcpy (signature, sig, 64); + EVP_MD_CTX_destroy (ctx); } + else + LogPrint (eLogError, "EdDSA signing key is not set"); } #endif } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 671ebfb7..8bd94357 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -304,7 +304,6 @@ namespace crypto private: #if OPENSSL_EDDSA - EVP_MD_CTX * m_MDCtx; EVP_PKEY * m_Pkey; #else EDDSAPoint m_PublicKey; @@ -342,7 +341,6 @@ namespace crypto private: - EVP_MD_CTX * m_MDCtx; EVP_PKEY * m_Pkey; EDDSA25519SignerCompat * m_Fallback; }; From d4c47d90cb308c9845888fcc746b30dcb1c96fdd Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 17:16:28 -0500 Subject: [PATCH 160/264] adjust time offset after second time discrepancy --- libi2pd/SSU2.cpp | 21 ++++++++++++++++++++- libi2pd/SSU2.h | 2 ++ libi2pd/SSU2Session.cpp | 7 +++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 7099ba0c..4448c1df 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -24,7 +24,8 @@ namespace transport m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()), m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), - m_IsPublished (true), m_IsSyncClockFromPeers (true), m_IsThroughProxy (false) + m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0), + m_IsThroughProxy (false) { } @@ -209,6 +210,24 @@ namespace transport return ep.port (); } + void SSU2Server::AdjustTimeOffset (int64_t offset) + { + if (offset) + { + if (m_PendingTimeOffset) // one more + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); + i2p::util::AdjustTimeOffset (-offset); + m_PendingTimeOffset = 0; + } + else + m_PendingTimeOffset = offset; // first + } + else + m_PendingTimeOffset = 0; // reset + } + boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) { boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4; diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index a1fafc63..03e22245 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -66,6 +66,7 @@ namespace transport bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; + void AdjustTimeOffset (int64_t offset); void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); @@ -161,6 +162,7 @@ namespace transport std::shared_ptr m_LastSession; bool m_IsPublished; // if we maintain introducers bool m_IsSyncClockFromPeers; + int64_t m_PendingTimeOffset; // during peer test // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 487d5549..bab9f2bb 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1668,10 +1668,7 @@ namespace transport if (m_Server.IsSyncClockFromPeers ()) { if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) - { - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); - i2p::util::AdjustTimeOffset (-offset); - } + m_Server.AdjustTimeOffset (-offset); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { @@ -2481,6 +2478,8 @@ namespace transport else if (m_Address->IsV6 ()) i2p::context.SetTestingV6 (testing); } + if (!testing) + m_Server.AdjustTimeOffset (0); // reset time offset when testing is over } size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) From 8319dd6b25b62b085d3f9b2867e438cd204ed7fb Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 19:49:16 -0500 Subject: [PATCH 161/264] drop exploratory and leaseset lookups for non-floodfill router --- libi2pd/NetDb.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 07f0f341..9f186659 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1019,6 +1019,11 @@ namespace data std::shared_ptr replyMsg; if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) { + if (!context.IsFloodfill ()) + { + LogPrint (eLogWarning, "NetDb: Exploratory lookup to non-floodfill dropped"); + return; + } LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded"); std::set excludedRouters; const uint8_t * excluded_ident = excluded; @@ -1044,6 +1049,7 @@ namespace data if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) { + // try to find router auto router = FindRouter (ident); if (router && !router->IsUnreachable ()) { @@ -1056,17 +1062,26 @@ namespace data if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { - auto leaseSet = FindLeaseSet (ident); - if (!leaseSet) + // try to find leaseset + if (context.IsFloodfill ()) + { + auto leaseSet = FindLeaseSet (ident); + if (!leaseSet) + { + // no leaseset found + LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32()); + } + else if (!leaseSet->IsExpired ()) // we don't send back expired leasesets + { + LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found"); + replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); + } + } + else if (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP) { - // no lease set found - LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32()); - } - else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets - { - LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found"); - replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); - } + LogPrint (eLogWarning, "NetDb: Explicit LeaseSet lookup to non-floodfill dropped"); + return; + } } if (!replyMsg) From 21f41a2b2a39461a480b8539beb2f1c141bb8fe7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Dec 2023 10:14:24 -0500 Subject: [PATCH 162/264] correct time offset direction --- libi2pd/SSU2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 4448c1df..55eb0567 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -217,8 +217,8 @@ namespace transport if (m_PendingTimeOffset) // one more { offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); - i2p::util::AdjustTimeOffset (-offset); + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); m_PendingTimeOffset = 0; } else From b855c7189111a30ed5acdffe8d2d584c35b2fc61 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Dec 2023 14:39:59 -0500 Subject: [PATCH 163/264] don't adjust clock if time offsets are too different --- libi2pd/SSU2.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 55eb0567..6a8615d5 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -216,9 +216,14 @@ namespace transport { if (m_PendingTimeOffset) // one more { - offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); - i2p::util::AdjustTimeOffset (offset); + if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); + } + else + LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); m_PendingTimeOffset = 0; } else From c5cab05a6b8690f3fd2442054c1475e06dc43640 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 2 Jan 2024 19:42:49 -0500 Subject: [PATCH 164/264] reset peding time offset if correct time was received --- libi2pd/SSU2Session.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bab9f2bb..e5261622 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1668,7 +1668,12 @@ namespace transport if (m_Server.IsSyncClockFromPeers ()) { if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) + { + LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint); m_Server.AdjustTimeOffset (-offset); + } + else + m_Server.AdjustTimeOffset (0); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { From 577c71b930dddcc0ca74dcb4368aa2aea07486da Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Thu, 4 Jan 2024 21:35:25 +0200 Subject: [PATCH 165/264] Fix typos --- libi2pd/Datagram.h | 2 +- libi2pd/NTCP2.cpp | 2 +- libi2pd/RouterInfo.cpp | 2 +- libi2pd/TunnelPool.cpp | 2 +- libi2pd_client/UDPTunnel.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 8f3d5ceb..e6d1f7b6 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -150,7 +150,7 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ + /** find a receiver by port, if none by port is found try default receiver, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); private: diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0a23f07e..f1a5e241 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1234,7 +1234,7 @@ namespace transport void NTCP2Session::SendLocalRouterInfo (bool update) { - if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session + if (update || !IsOutgoing ()) // we send it in SessionConfirmed for outgoing session m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ())); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 63cb79ef..60f9a518 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -995,7 +995,7 @@ namespace data bool RouterInfo::IsPublished (bool v4) const { - if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published + if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addresses are not published auto addr = GetAddresses (); if (v4) return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 23cc53e3..5339c9be 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -301,7 +301,7 @@ namespace tunnel { for (auto it: m_OutboundTunnels) { - // try to create inbound tunnel through the same path as succesive outbound + // try to create inbound tunnel through the same path as successive outbound CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 862ce216..3233c3f0 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -72,7 +72,7 @@ namespace client boost::asio::ip::udp::endpoint LocalEndpoint; /** client's udp endpoint */ boost::asio::ip::udp::endpoint RemoteEndpoint; - /** how long has this converstation been idle in ms */ + /** how long has this conversation been idle in ms */ uint64_t idle; }; From 5cf1961fa4910ad7b5bd1298bfe723af50b5ccb5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 11:31:01 -0500 Subject: [PATCH 166/264] drop updated routers from future --- libi2pd/NetDb.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9f186659..6e023c45 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -247,9 +247,10 @@ namespace data m_Requests.RequestComplete (ident, r); return r; } - if (r->IsUnreachable ()) + if (r->IsUnreachable () || + i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < r->GetTimestamp ()) { - // delete router as invalid after update + // delete router as invalid or from future after update m_RouterInfos.erase (ident); if (wasFloodfill) { From a8135b8d1820281d18d96cf2fa87e65c55350356 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 14:51:42 -0500 Subject: [PATCH 167/264] 2.50.2 --- libi2pd/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/version.h b/libi2pd/version.h index c79e3a2b..7b9e20c8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,7 +19,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 50 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MICRO 2 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) From 3b97feb89fdc310ab43cc9336e1817f5b17f4b82 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 15:07:51 -0500 Subject: [PATCH 168/264] 2.50.2 --- ChangeLog | 5 +++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0778cd70..6534a9b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.2] - 2024-01-06 +###Fixed +- Crash with OpenSSL 3.2.0 +- False positive clock skew detection + ## [2.50.1] - 2023-12-23 ###Fixed - Support for new EdDSA usage behavior in OpenSSL 3.2.0 diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index ab5b4190..0bc46eab 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.50.1 +Version: 2.50.2 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 06 2024 orignal - 2.50.2 +- update to 2.50.2 + * Sat Dec 23 2023 r4sas - 2.50.1 - update to 2.50.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 74cc826d..1de4076e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.50.1 +Version: 2.50.2 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 06 2024 orignal - 2.50.2 +- update to 2.50.2 + * Sat Dec 23 2023 r4sas - 2.50.1 - update to 2.50.1 diff --git a/debian/changelog b/debian/changelog index 5484fd92..56ab7c16 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.2) unstable; urgency=medium + + * updated to version 2.50.2/0.9.61 + +-- orignal Sat, 06 Jan 2024 16:00:00 +0000 + i2pd (2.50.1-1) unstable; urgency=medium * updated to version 2.50.1/0.9.61 From 8bc58daa5a63a12f88b3fb454ee297e37e1ec48a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Jan 2024 18:42:34 -0500 Subject: [PATCH 169/264] fixed #2004. Check supported crypto --- libi2pd_client/SAM.cpp | 56 +++++++++++++++++++++++++----------------- libi2pd_client/SAM.h | 6 +++-- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index ffdeb5ac..775b9411 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -550,17 +550,22 @@ namespace client if (!session) session = m_Owner.FindSession(m_ID); if (session) { - m_SocketType = eSAMSocketTypeStream; - m_Stream = session->GetLocalDestination ()->CreateStream (remote); - if (m_Stream) - { - m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send - m_BufferOffset = 0; - I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ())) + { + m_SocketType = eSAMSocketTypeStream; + m_Stream = session->GetLocalDestination ()->CreateStream (remote); + if (m_Stream) + { + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; + I2PReceive (); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } + else + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendStreamCantReachPeer ("Incompatible crypto"); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -573,7 +578,7 @@ namespace client else { LogPrint (eLogError, "SAM: Destination to connect not found"); - SendMessageReply (SAM_STREAM_STATUS_CANT_REACH_PEER, strlen(SAM_STREAM_STATUS_CANT_REACH_PEER), true); + SendStreamCantReachPeer ("LeaseSet not found"); } } @@ -857,27 +862,32 @@ namespace client SendSessionI2PError ("Wrong session type"); } + void SAMSocket::SendReplyWithMessage (const char * reply, const std::string & msg) + { +#ifdef _MSC_VER + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); +#else + size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); +#endif + SendMessageReply (m_Buffer, len, true); + } + void SAMSocket::SendSessionI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Session I2P error: ", msg); -#ifdef _MSC_VER - size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); -#else - size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); -#endif - SendMessageReply (m_Buffer, len, true); + SendReplyWithMessage (SAM_SESSION_STATUS_I2P_ERROR, msg); } void SAMSocket::SendStreamI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Stream I2P error: ", msg); -#ifdef _MSC_VER - size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); -#else - size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); -#endif - SendMessageReply (m_Buffer, len, true); + SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); } + + void SAMSocket::SendStreamCantReachPeer(const std::string & msg) + { + SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); + } void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 34af5a62..3ed8f00c 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -51,7 +51,7 @@ namespace client const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n"; const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n"; - const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n"; + const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"%s\"\n"; const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; const char SAM_STREAM_FORWARD[] = "STREAM FORWARD"; @@ -144,8 +144,10 @@ namespace client void ProcessNamingLookup (char * buf, size_t len); void ProcessSessionAdd (char * buf, size_t len); void ProcessSessionRemove (char * buf, size_t len); + void SendReplyWithMessage (const char * reply, const std::string & msg); void SendSessionI2PError(const std::string & msg); void SendStreamI2PError(const std::string & msg); + void SendStreamCantReachPeer(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ExtractParams (char * buf, std::map& params); From 1e9bcd6b8b228aeed713f1d1714809409e97633a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 8 Jan 2024 16:36:14 +0300 Subject: [PATCH 170/264] [gha] MSVC: Switch to direct Boost and OpenSSL installation --- .github/workflows/build-windows-msvc.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 172e0596..a077d626 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -26,15 +26,27 @@ jobs: ./install_zlib.bat del install_zlib.bat + #- name: Install Boost + # uses: crazy-max/ghaction-chocolatey@v2 + # with: + # args: install boost-msvc-14.3 --version=1.81.0 + + #- name: Install OpenSSL + # uses: crazy-max/ghaction-chocolatey@v2 + # with: + # args: install openssl + - name: Install Boost - uses: crazy-max/ghaction-chocolatey@v2 - with: - args: install boost-msvc-14.3 --version=1.81.0 + run: | + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" + ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT + del boost_1_84_0-msvc-14.3-64.exe - name: Install OpenSSL - uses: crazy-max/ghaction-chocolatey@v2 - with: - args: install openssl + run: | + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" + ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + del Win64OpenSSL-3_2_0.exe - name: Configure working-directory: build From dfe8b25e5ec2d0533584bf03cf0d1289bc1ca71d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 8 Jan 2024 17:05:36 +0300 Subject: [PATCH 171/264] [gha] MSVC: remove deletion of installation files --- .github/workflows/build-windows-msvc.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index a077d626..5af526e2 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -40,13 +40,11 @@ jobs: run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT - del boost_1_84_0-msvc-14.3-64.exe - name: Install OpenSSL run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - del Win64OpenSSL-3_2_0.exe - name: Configure working-directory: build From cd087568b55161767c6094f86054d4976e137209 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 9 Jan 2024 21:02:11 -0500 Subject: [PATCH 172/264] reply with CANT_REACH_PEER if connect to outselves --- libi2pd_client/SAM.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 775b9411..1a3afb58 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -523,15 +523,20 @@ namespace client { if (addr->IsIdentHash ()) { - auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); - if (leaseSet) - Connect(leaseSet, session); - else - { - session->GetLocalDestination ()->RequestDestination(addr->identHash, - std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, - shared_from_this(), std::placeholders::_1)); + if (session->GetLocalDestination ()->GetIdentHash () != addr->identHash) + { + auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); + if (leaseSet) + Connect(leaseSet, session); + else + { + session->GetLocalDestination ()->RequestDestination(addr->identHash, + std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, + shared_from_this(), std::placeholders::_1)); + } } + else + SendStreamCantReachPeer ("Can't connect to myself"); } else // B33 session->GetLocalDestination ()->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey, From 2ad26dd4c9def4cf05e144f65793323187a2b830 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Jan 2024 14:09:08 -0500 Subject: [PATCH 173/264] fixed race condition in ECIESx25519 tags table --- libi2pd/RouterContext.cpp | 22 +++++++++++++++++++++- libi2pd/RouterContext.h | 1 + libi2pd/Tunnel.cpp | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index f21c0592..10d33bf5 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1199,7 +1199,27 @@ namespace i2p else i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); } - + + void RouterContext::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag) + { + if (m_Service) + { + struct + { + uint8_t k[32]; + uint64_t t; + } data; + memcpy (data.k, key, 32); + data.t = tag; + m_Service->GetService ().post ([this,data](void) + { + AddECIESx25519Key (data.k, data.t); + }); + } + else + LogPrint (eLogError, "Router: service is NULL"); + } + void RouterContext::CleanupDestination () { if (m_Service) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index d49b5523..91a553ba 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -136,6 +136,7 @@ namespace garlic void SetNetID (int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data); bool DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data); + void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag); void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU2 or Daemon diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6234ceb4..b8e17920 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -116,7 +116,7 @@ namespace tunnel if (m_Pool && m_Pool->GetLocalDestination ()) m_Pool->GetLocalDestination ()->SubmitECIESx25519Key (key, tag); else - i2p::context.AddECIESx25519Key (key, tag); + i2p::context.SubmitECIESx25519Key (key, tag); } i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); } From ca9782dd0d4ad8116035352f22524b4f3ee77633 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Jan 2024 15:39:42 -0500 Subject: [PATCH 174/264] handle 'reservedrange' param properly --- daemon/Daemon.cpp | 4 +--- libi2pd/NTCP2.cpp | 4 ++-- libi2pd/Reseed.cpp | 24 +++++++++++------------- libi2pd/RouterInfo.cpp | 5 +++-- libi2pd/SSU2.cpp | 8 ++++---- libi2pd/SSU2Session.cpp | 4 ++-- libi2pd/Transports.cpp | 13 ++++++++++--- libi2pd/Transports.h | 5 +++-- 8 files changed, 36 insertions(+), 31 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index f04236fe..308daa4c 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -298,12 +298,10 @@ namespace util bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); LogPrint(eLogInfo, "Daemon: Starting Transports"); if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled"); if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled"); - i2p::transport::transports.SetCheckReserved(checkInReserved); i2p::transport::transports.Start(ntcp2, ssu2); if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2()) LogPrint(eLogInfo, "Daemon: Transports started"); diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f1a5e241..efc317c2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1490,7 +1490,7 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ())) + if (!i2p::transport::transports.IsInReservedRange(ep.address ())) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { @@ -1537,7 +1537,7 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ()) || + if (!i2p::transport::transports.IsInReservedRange(ep.address ()) || i2p::util::net::IsYggdrasilAddress (ep.address ())) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 28e4db24..5fdc2fae 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -687,18 +687,16 @@ namespace data while (it != end) { boost::asio::ip::tcp::endpoint ep = *it; - if ( - ( - !i2p::util::net::IsInReservedRange(ep.address ()) && ( - (ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || - (ep.address ().is_v6 () && i2p::context.SupportsV6 ()) - ) - ) || - ( - i2p::util::net::IsYggdrasilAddress (ep.address ()) && - i2p::context.SupportsMesh () - ) - ) + bool supported = false; + if (!ep.address ().is_unspecified ()) + { + if (ep.address ().is_v4 ()) + supported = i2p::context.SupportsV4 (); + else if (ep.address ().is_v6 ()) + supported = i2p::util::net::IsYggdrasilAddress (ep.address ()) ? + i2p::context.SupportsMesh () : i2p::context.SupportsV6 (); + } + if (supported) { s.lowest_layer().connect (ep, ecode); if (!ecode) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 60f9a518..7cde7c33 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -21,6 +21,7 @@ #include "Base.h" #include "Timestamp.h" #include "Log.h" +#include "Transports.h" #include "NetDb.hpp" #include "RouterContext.h" #include "RouterInfo.h" @@ -253,7 +254,7 @@ namespace data address->host = boost::asio::ip::address::from_string (value, ecode); if (!ecode && !address->host.is_unspecified ()) { - if (!i2p::util::net::IsInReservedRange (address->host) || + if (!i2p::transport::transports.IsInReservedRange (address->host) || i2p::util::net::IsYggdrasilAddress (address->host)) isHost = true; else diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6a8615d5..1503b404 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -566,7 +566,7 @@ namespace transport else it1->second->ProcessRetry (buf, len); } - else if (!i2p::util::net::IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ()) + else if (!i2p::transport::transports.IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ()) { // assume new incoming session auto session = std::make_shared (*this); @@ -666,7 +666,7 @@ namespace transport bool isValidEndpoint = !address->host.is_unspecified () && address->port; if (isValidEndpoint) { - if (i2p::util::net::IsInReservedRange(address->host)) return false; + if (i2p::transport::transports.IsInReservedRange(address->host)) return false; auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port)); if (s) { @@ -753,7 +753,7 @@ namespace transport if (addr) { bool isValidEndpoint = !addr->host.is_unspecified () && addr->port && - !i2p::util::net::IsInReservedRange(addr->host); + !i2p::transport::transports.IsInReservedRange(addr->host); if (isValidEndpoint) { auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (addr->host, addr->port)); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index e5261622..8cb39102 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1471,7 +1471,7 @@ namespace transport ResendHandshakePacket (); // assume we receive return; } - if (from != m_RemoteEndpoint && !i2p::util::net::IsInReservedRange (from.address ())) + if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ())) { LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from); m_RemoteEndpoint = from; @@ -1753,7 +1753,7 @@ namespace transport if (ExtractEndpoint (buf, len, ep)) { LogPrint (eLogInfo, "SSU2: Our external address is ", ep); - if (!i2p::util::net::IsInReservedRange (ep.address ())) + if (!i2p::transport::transports.IsInReservedRange (ep.address ())) { i2p::context.UpdateAddress (ep.address ()); // check our port diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b6e2e261..318d410f 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -505,7 +505,7 @@ namespace transport if (!m_NTCP2Server) continue; std::shared_ptr address = (tr == i2p::data::RouterInfo::eNTCP2V6) ? peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); - if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + if (address && IsInReservedRange(address->host)) address = nullptr; if (address) { @@ -524,7 +524,7 @@ namespace transport if (!m_SSU2Server) continue; std::shared_ptr address = (tr == i2p::data::RouterInfo::eSSU2V6) ? peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); - if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + if (address && IsInReservedRange(address->host)) address = nullptr; if (address && address->IsReachableSSU ()) { @@ -1084,6 +1084,11 @@ namespace transport } } + bool Transports::IsInReservedRange (const boost::asio::ip::address& host) const + { + return IsCheckReserved () && i2p::util::net::IsInReservedRange (host); + } + void InitAddressFromIface () { bool ipv6; i2p::config::GetOption("ipv6", ipv6); @@ -1196,6 +1201,8 @@ namespace transport i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish } + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + transports.SetCheckReserved (checkReserved); } } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index cb63ca91..7ef7f9b2 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -167,7 +167,8 @@ namespace transport void PeerTest (bool ipv4 = true, bool ipv6 = true); void SetCheckReserved (bool check) { m_CheckReserved = check; }; - bool IsCheckReserved () { return m_CheckReserved; }; + bool IsCheckReserved () const { return m_CheckReserved; }; + bool IsInReservedRange (const boost::asio::ip::address& host) const; private: From 34d75b08ddac5a3655dab2f89793528562af30d2 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 12 Jan 2024 17:13:07 +0200 Subject: [PATCH 175/264] handle 'reservedrange' param properly --- daemon/Daemon.cpp | 4 ++++ libi2pd/Transports.cpp | 3 --- libi2pd/api.cpp | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 308daa4c..17d17f72 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -160,6 +160,10 @@ namespace util int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); + + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + i2p::transport::transports.SetCheckReserved(checkReserved); + i2p::context.Init (); i2p::transport::InitTransports (); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 318d410f..0bd17104 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1200,9 +1200,6 @@ namespace transport else i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish } - - bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); - transports.SetCheckReserved (checkReserved); } } } diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index ad24519f..05f962f3 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -44,6 +44,9 @@ namespace api int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + i2p::transport::transports.SetCheckReserved(checkReserved); + i2p::context.Init (); } From d8f6c4a93dc1722463754eb5c1670a4bab2f2304 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 14 Jan 2024 17:16:31 -0500 Subject: [PATCH 176/264] correct encryption and path for follow on lookup request --- libi2pd/NetDb.cpp | 42 +++-------------- libi2pd/NetDbRequests.cpp | 94 +++++++++++++++++++++++++-------------- libi2pd/NetDbRequests.h | 24 ++++++---- 3 files changed, 83 insertions(+), 77 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 6e023c45..8eb5d653 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -721,7 +721,7 @@ namespace data void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { - auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory + auto dest = m_Requests.CreateRequest (destination, false, direct, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already"); @@ -761,10 +761,10 @@ namespace data } } - void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete) + void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploratory, RequestedDestination::RequestComplete requestComplete) { - auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory + auto dest = m_Requests.CreateRequest (destination, exploratory, true, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already"); @@ -919,39 +919,9 @@ namespace data auto dest = m_Requests.FindRequest (ident); if (dest) { - bool deleteDest = true; if (num > 0) - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; - auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr; - if (!dest->IsExploratory ()) - { - // reply to our destination. Try other floodfills - if (outbound && inbound) - { - auto count = dest->GetExcludedPeers ().size (); - if (count < 7) - { - auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); - if (nextFloodfill) - { - // request destination - LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); - outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, - dest->CreateRequestMessage (nextFloodfill, inbound)); - deleteDest = false; - } - } - else - LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills"); - } - } - - if (deleteDest) - // no more requests for the destinationation. delete it - m_Requests.RequestComplete (ident, nullptr); - } + // try to send next requests + m_Requests.SendNextRequest (dest); else // no more requests for destination possible. delete it m_Requests.RequestComplete (ident, nullptr); @@ -1156,7 +1126,7 @@ namespace data for (int i = 0; i < numDestinations; i++) { RAND_bytes (randomHash, 32); - auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory + auto dest = m_Requests.CreateRequest (randomHash, true, !throughTunnels); // exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Exploratory destination is requested already"); diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 4011b8aa..2cb578e2 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,6 +11,7 @@ #include "Transports.h" #include "NetDb.hpp" #include "NetDbRequests.h" +#include "ECIESX25519AEADRatchetSession.h" namespace i2p { @@ -74,14 +75,15 @@ namespace data } - std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete) + std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, + bool isExploratory, bool direct, RequestedDestination::RequestComplete requestComplete) { // request RouterInfo directly - auto dest = std::make_shared (destination, isExploratory); + auto dest = std::make_shared (destination, isExploratory, direct); dest->SetRequestComplete (requestComplete); { - std::unique_lock l(m_RequestedDestinationsMutex); - if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted + std::unique_lock l(m_RequestedDestinationsMutex); + if (!m_RequestedDestinations.emplace (destination, dest).second) // not inserted return nullptr; } return dest; @@ -125,35 +127,10 @@ namespace data { auto& dest = it->second; bool done = false; - if (ts < dest->GetCreationTime () + 60) // request is worthless after 1 minute + if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) // request becomes worthless { - if (ts > dest->GetCreationTime () + 5) // no response for 5 seconds - { - auto count = dest->GetExcludedPeers ().size (); - if (!dest->IsExploratory () && count < 7) - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool->GetNextOutboundTunnel (); - auto inbound = pool->GetNextInboundTunnel (); - auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); - if (nextFloodfill && outbound && inbound) - outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, - dest->CreateRequestMessage (nextFloodfill, inbound)); - else - { - done = true; - if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels"); - if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); - if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); - } - } - else - { - if (!dest->IsExploratory ()) - LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); - done = true; - } - } + if (ts > dest->GetCreationTime () + MIN_REQUEST_TIME) // retry in no response after min interval + done = !SendNextRequest (dest); } else // delete obsolete request done = true; @@ -164,5 +141,56 @@ namespace data ++it; } } + + bool NetDbRequests::SendNextRequest (std::shared_ptr dest) + { + if (!dest) return false; + bool ret = true; + auto count = dest->GetExcludedPeers ().size (); + if (!dest->IsExploratory () && count < MAX_NUM_REQUEST_ATTEMPTS) + { + auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); + if (nextFloodfill) + { + bool direct = dest->IsDirect (); + if (direct && !nextFloodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) && + !i2p::transport::transports.IsConnected (nextFloodfill->GetIdentHash ())) + direct = false; // floodfill can't be reached directly + if (direct) + i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), dest->CreateRequestMessage (nextFloodfill->GetIdentHash ())); + else + { + auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = pool->GetNextOutboundTunnel (); + auto inbound = pool->GetNextInboundTunnel (); + if (nextFloodfill && outbound && inbound) + { + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); + auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); + outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, nextFloodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } + else + { + ret = false; + if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels"); + if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); + } + } + } + else + { + ret = false; + if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); + } + } + else + { + if (!dest->IsExploratory ()) + LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); + ret = false; + } + return ret; + } } } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index cf2f0915..a4d1cf21 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -9,9 +9,10 @@ #ifndef NETDB_REQUESTS_H__ #define NETDB_REQUESTS_H__ +#include #include #include -#include +#include #include "Identity.h" #include "RouterInfo.h" @@ -19,14 +20,18 @@ namespace i2p { namespace data { + const size_t MAX_NUM_REQUEST_ATTEMPTS = 7; + const uint64_t MIN_REQUEST_TIME = 5; // in seconds + const uint64_t MAX_REQUEST_TIME = 60; // in seconds + class RequestedDestination { public: typedef std::function)> RequestComplete; - RequestedDestination (const IdentHash& destination, bool isExploratory = false): - m_Destination (destination), m_IsExploratory (isExploratory), m_CreationTime (0) {}; + RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true): + m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_CreationTime (0) {}; ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; const IdentHash& GetDestination () const { return m_Destination; }; @@ -34,6 +39,7 @@ namespace data const std::set& GetExcludedPeers () { return m_ExcludedPeers; }; void ClearExcludedPeers (); bool IsExploratory () const { return m_IsExploratory; }; + bool IsDirect () const { return m_IsDirect; }; bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); }; uint64_t GetCreationTime () const { return m_CreationTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); @@ -47,7 +53,7 @@ namespace data private: IdentHash m_Destination; - bool m_IsExploratory; + bool m_IsExploratory, m_IsDirect; std::set m_ExcludedPeers; uint64_t m_CreationTime; RequestComplete m_RequestComplete; @@ -60,15 +66,17 @@ namespace data void Start (); void Stop (); - std::shared_ptr CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr); + std::shared_ptr CreateRequest (const IdentHash& destination, bool isExploratory, + bool direct = false, RequestedDestination::RequestComplete requestComplete = nullptr); void RequestComplete (const IdentHash& ident, std::shared_ptr r); std::shared_ptr FindRequest (const IdentHash& ident) const; void ManageRequests (); - + bool SendNextRequest (std::shared_ptr dest); + private: mutable std::mutex m_RequestedDestinationsMutex; - std::map > m_RequestedDestinations; + std::unordered_map > m_RequestedDestinations; }; } } From 4afdca090d33ba2d2bb390e46637ba42aa42fc5d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 14 Jan 2024 18:54:21 -0500 Subject: [PATCH 177/264] support multiple RouterInfo request callbacks --- libi2pd/NetDbRequests.cpp | 20 +++++++++++++++++++- libi2pd/NetDbRequests.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 2cb578e2..167095d7 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -83,8 +83,26 @@ namespace data dest->SetRequestComplete (requestComplete); { std::unique_lock l(m_RequestedDestinationsMutex); - if (!m_RequestedDestinations.emplace (destination, dest).second) // not inserted + auto ret = m_RequestedDestinations.emplace (destination, dest); + if (!ret.second) // not inserted + { + dest->SetRequestComplete (nullptr); // don't call requestComplete in destructor + if (requestComplete) + { + auto prev = ret.first->second->GetRequestComplete (); + if (prev) // if already set + ret.first->second->SetRequestComplete ( + [requestComplete, prev](std::shared_ptr r) + { + prev (r); // call previous + requestComplete (r); // then new + }); + else + ret.first->second->SetRequestComplete (requestComplete); + } + return nullptr; + } } return dest; } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index a4d1cf21..001b0f07 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -46,6 +46,7 @@ namespace data std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; }; + RequestComplete GetRequestComplete () const { return m_RequestComplete; }; bool IsRequestComplete () const { return m_RequestComplete != nullptr; }; void Success (std::shared_ptr r); void Fail (); From 49f4dc53adf1c3d464f4d9baaae3c49dfe6ae8af Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 15 Jan 2024 19:32:17 -0500 Subject: [PATCH 178/264] try next floodfill for router request on demand --- libi2pd/NetDbRequests.cpp | 21 +++++++++++++++++---- libi2pd/NetDbRequests.h | 8 ++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 167095d7..92e5a7b8 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -17,6 +17,17 @@ namespace i2p { namespace data { + RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct): + m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), + m_CreationTime (i2p::util::GetSecondsSinceEpoch ()), m_LastRequestTime (0) + { + } + + RequestedDestination::~RequestedDestination () + { + if (m_RequestComplete) m_RequestComplete (nullptr); + } + std::shared_ptr RequestedDestination::CreateRequestMessage (std::shared_ptr router, std::shared_ptr replyTunnel) { @@ -29,7 +40,7 @@ namespace data msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); if(router) m_ExcludedPeers.insert (router->GetIdentHash ()); - m_CreationTime = i2p::util::GetSecondsSinceEpoch (); + m_LastRequestTime = i2p::util::GetSecondsSinceEpoch (); return msg; } @@ -38,7 +49,7 @@ namespace data auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers); m_ExcludedPeers.insert (floodfill); - m_CreationTime = i2p::util::GetSecondsSinceEpoch (); + m_LastRequestTime = i2p::util::GetSecondsSinceEpoch (); return msg; } @@ -100,7 +111,9 @@ namespace data else ret.first->second->SetRequestComplete (requestComplete); } - + if (i2p::util::GetSecondsSinceEpoch () > ret.first->second->GetLastRequestTime () + MIN_REQUEST_TIME) + if (!SendNextRequest (ret.first->second)) // try next floodfill + m_RequestedDestinations.erase (ret.first); // delete request if failed return nullptr; } } @@ -147,7 +160,7 @@ namespace data bool done = false; if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) // request becomes worthless { - if (ts > dest->GetCreationTime () + MIN_REQUEST_TIME) // retry in no response after min interval + if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval done = !SendNextRequest (dest); } else // delete obsolete request diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index 001b0f07..47a5d481 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -30,9 +30,8 @@ namespace data typedef std::function)> RequestComplete; - RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true): - m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_CreationTime (0) {}; - ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; + RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true); + ~RequestedDestination (); const IdentHash& GetDestination () const { return m_Destination; }; int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); }; @@ -42,6 +41,7 @@ namespace data bool IsDirect () const { return m_IsDirect; }; bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); }; uint64_t GetCreationTime () const { return m_CreationTime; }; + uint64_t GetLastRequestTime () const { return m_LastRequestTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); @@ -56,7 +56,7 @@ namespace data IdentHash m_Destination; bool m_IsExploratory, m_IsDirect; std::set m_ExcludedPeers; - uint64_t m_CreationTime; + uint64_t m_CreationTime, m_LastRequestTime; // in seconds RequestComplete m_RequestComplete; }; From 7cfcb12c7b0f3e9c3f6408c404b22e0a3e3e53bf Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 16 Jan 2024 14:33:36 -0500 Subject: [PATCH 179/264] don't create peer for unreachable router --- libi2pd/Transports.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0bd17104..eb836354 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -436,6 +436,10 @@ namespace transport auto it = m_Peers.find (ident); if (it == m_Peers.end ()) { + // check if not known as unreachable + auto profile = i2p::data::GetRouterProfile (ident); + if (profile && profile->IsUnreachable ()) return; // don't create peer to unreachable router + // try to connect bool connected = false; try { From 39e378a03dda77cb380182c1c0c192478caa44e9 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 17 Jan 2024 18:15:49 -0500 Subject: [PATCH 180/264] check received data size --- libi2pd/NTCP2.cpp | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index efc317c2..c52c5cc2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -809,10 +809,15 @@ namespace transport void NTCP2Session::HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode) + if (ecode || bytes_transferred != 2) { if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); + { + if (ecode) + LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); + else if (bytes_transferred != 2) + LogPrint (eLogError, "NTCP2: Receive length of ", bytes_transferred, " bytes"); + } Terminate (); } else @@ -833,14 +838,19 @@ namespace transport CreateNextReceivedBuffer (m_NextReceivedLen); boost::system::error_code ec; size_t moreBytes = m_Socket.available(ec); - if (!ec && moreBytes >= m_NextReceivedLen) - { - // read and process message immediately if available - moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec); - HandleReceived (ec, moreBytes); - } + if (!ec) + { + if (moreBytes >= m_NextReceivedLen) + { + // read and process message immediately if available + moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec); + HandleReceived (ec, moreBytes); + } + else + Receive (); + } else - Receive (); + LogPrint (eLogWarning, "NTCP2: Socket error: ", ec.message ()); } else { @@ -864,10 +874,15 @@ namespace transport void NTCP2Session::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode) + if (ecode || bytes_transferred != m_NextReceivedLen) { - if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); + else if (bytes_transferred != m_NextReceivedLen) + LogPrint (eLogError, "NTCP2: Received ", bytes_transferred, " bytes. Instead ", m_NextReceivedLen); + } Terminate (); } else From 1e5604ed4373dcea18a8353df188451d592bd864 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 18 Jan 2024 19:18:51 -0500 Subject: [PATCH 181/264] check if peer is connected before trying to connect --- libi2pd/Transports.cpp | 15 ++++++++------- libi2pd/Transports.h | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index eb836354..5d3027a9 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -458,7 +458,7 @@ namespace transport } if (!connected) return; } - if (!it->second.sessions.empty ()) + if (it->second.IsConnected ()) it->second.sessions.front ()->SendI2NPMessages (msgs); else { @@ -616,7 +616,8 @@ namespace transport { LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect"); it->second.SetRouter (r); - ConnectToPeer (ident, it->second); + if (!it->second.IsConnected ()) + ConnectToPeer (ident, it->second); } else { @@ -810,13 +811,13 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { - auto before = it->second.sessions.size (); + bool wasConnected = it->second.IsConnected (); it->second.sessions.remove (session); - if (it->second.sessions.empty ()) + if (!it->second.IsConnected ()) { if (it->second.delayedMessages.size () > 0) { - if (before > 0) // we had an active session before + if (wasConnected) // we had an active session before it->second.numAttempts = 0; // start over ConnectToPeer (ident, it->second); } @@ -849,7 +850,7 @@ namespace transport { return !session || !session->IsEstablished (); }); - if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) + if (!it->second.IsConnected () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); /* if (!it->second.router) @@ -991,7 +992,7 @@ namespace transport [isHighBandwidth](const Peer& peer)->bool { // connected, not overloaded and not slow - return !peer.router && !peer.sessions.empty () && peer.isReachable && + return !peer.router && peer.IsConnected () && peer.isReachable && peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && !peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) && (!isHighBandwidth || peer.isHighBandwidth); diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 7ef7f9b2..0e5518b1 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -101,6 +101,8 @@ namespace transport isReachable = (bool)router->GetCompatibleTransports (true); } } + + bool IsConnected () const { return !sessions.empty (); } }; const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds From b4484c8e8f7615b6beeab872515c3f9ff1dc3bc9 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 19 Jan 2024 21:54:10 +0300 Subject: [PATCH 182/264] [gha] msvc: switch back to boost 1.81.0 --- .github/workflows/build-windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 5af526e2..dea64644 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -38,7 +38,7 @@ jobs: - name: Install Boost run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT - name: Install OpenSSL From 140146e433a83eb9137d668baedc13282a5a03c0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 19 Jan 2024 14:09:48 -0500 Subject: [PATCH 183/264] limit mininal received packet size to 40 bytes --- libi2pd/SSU2.cpp | 9 ++++++++- libi2pd/SSU2.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1503b404..1fb10927 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -283,8 +283,15 @@ namespace transport // but better to find out which host were sent it and mark that router as unreachable { i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); + if (bytes_transferred < SSU2_MIN_RECEIVED_PACKET_SIZE) + { + // drop too short packets + m_PacketsPool.ReleaseMt (packet); + Receive (socket); + return; + } packet->len = bytes_transferred; - + boost::system::error_code ec; size_t moreBytes = socket.available (ec); if (!ec && moreBytes) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 03e22245..6d07f7fa 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -27,6 +27,7 @@ namespace transport const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K const size_t SSU2_MAX_NUM_INTRODUCERS = 3; + const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds From 0b47f65b069e47187efed3707c90866d0b036f39 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 19 Jan 2024 18:29:17 -0500 Subject: [PATCH 184/264] don't remove another NTCP2 session with same address --- libi2pd/NTCP2.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index c52c5cc2..a58ab0a2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1415,7 +1415,11 @@ namespace transport void NTCP2Server::RemoveNTCP2Session (std::shared_ptr session) { if (session && session->GetRemoteIdentity ()) - m_NTCP2Sessions.erase (session->GetRemoteIdentity ()->GetIdentHash ()); + { + auto it = m_NTCP2Sessions.find (session->GetRemoteIdentity ()->GetIdentHash ()); + if (it != m_NTCP2Sessions.end () && it->second == session) + m_NTCP2Sessions.erase (it); + } } std::shared_ptr NTCP2Server::FindNTCP2Session (const i2p::data::IdentHash& ident) From 5e19e361e7ececd3008615a623e48f7f2f351e8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 20 Jan 2024 17:33:28 -0500 Subject: [PATCH 185/264] check max frame sizebefore sending --- libi2pd/NTCP2.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a58ab0a2..45968f7d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -809,15 +809,10 @@ namespace transport void NTCP2Session::HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode || bytes_transferred != 2) + if (ecode) { if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); - else if (bytes_transferred != 2) - LogPrint (eLogError, "NTCP2: Receive length of ", bytes_transferred, " bytes"); - } + LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); Terminate (); } else @@ -874,15 +869,10 @@ namespace transport void NTCP2Session::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode || bytes_transferred != m_NextReceivedLen) + if (ecode) { if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); - else if (bytes_transferred != m_NextReceivedLen) - LogPrint (eLogError, "NTCP2: Received ", bytes_transferred, " bytes. Instead ", m_NextReceivedLen); - } + LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); Terminate (); } else @@ -1061,6 +1051,11 @@ namespace transport macBuf = m_NextSendBuffer + paddingLen; totalLen += paddingLen; } + if (totalLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + LogPrint (eLogError, "NTCP2: Frame to send is too long ", totalLen); + return; + } uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers @@ -1085,6 +1080,12 @@ namespace transport delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; return; } + if (payloadLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + LogPrint (eLogError, "NTCP2: Buffer to send is too long ", payloadLen); + delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; + return; + } // encrypt uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; @@ -1160,7 +1161,12 @@ namespace transport len -= 3; if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; - if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + ssize_t l = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + if (l <= 0) return 0; + paddingSize = l; + } if (paddingSize > len) paddingSize = len; if (paddingSize) { @@ -1169,7 +1175,7 @@ namespace transport RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes)); m_NextPaddingSize = 0; } - paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize; + paddingSize = m_PaddingSizes[m_NextPaddingSize++] % (paddingSize + 1); } buf[0] = eNTCP2BlkPadding; // blk htobe16buf (buf + 1, paddingSize); // size From 9f217f8a117089e7a4e3d9eeb732f7a741f11edf Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2024 18:59:04 -0500 Subject: [PATCH 186/264] don't send expired I2NP messages --- libi2pd/I2NPProtocol.cpp | 10 +++++++--- libi2pd/I2NPProtocol.h | 3 ++- libi2pd/NTCP2.cpp | 7 +++++++ libi2pd/SSU2Session.cpp | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index b8147555..ebd5f8d6 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -72,11 +72,15 @@ namespace i2p SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); } - bool I2NPMessage::IsExpired () const + bool I2NPMessage::IsExpired (uint64_t ts) const { - auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto exp = GetExpiration (); return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future + } + + bool I2NPMessage::IsExpired () const + { + return IsExpired (i2p::util::GetMillisecondsSinceEpoch ()); } std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 6c64f2ab..e86f4f32 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -252,6 +252,7 @@ namespace tunnel void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0, bool checksum = true); void RenewI2NPMessageHeader (); bool IsExpired () const; + bool IsExpired (uint64_t ts) const; // in milliseconds }; template diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 45968f7d..925c89dd 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1132,10 +1132,17 @@ namespace transport if (!m_SendQueue.empty ()) { std::vector > msgs; + auto ts = i2p::util::GetMillisecondsSinceEpoch (); size_t s = 0; while (!m_SendQueue.empty ()) { auto msg = m_SendQueue.front (); + if (!msg || msg->IsExpired (ts)) + { + // drop null or expired message + m_SendQueue.pop_front (); + continue; + } size_t len = msg->GetNTCP2Length (); if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header { diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 8cb39102..3ea07629 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -379,8 +379,9 @@ namespace transport while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize) { auto msg = m_SendQueue.front (); - if (!msg) + if (!msg || msg->IsExpired (ts)) { + // drop null or expired message m_SendQueue.pop_front (); continue; } From a2249f0a82ca29215b039e15e7755be9f6012735 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 13:52:13 -0500 Subject: [PATCH 187/264] identify server tunnel session but from ant to ports --- libi2pd_client/UDPTunnel.cpp | 57 +++++++++++++++++++++++++----------- libi2pd_client/UDPTunnel.h | 7 +++-- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 1e4b3d7c..3fcf8b35 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -27,8 +27,17 @@ namespace client m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } - void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t, uint16_t, const uint8_t * buf, size_t len) + void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { + if (m_LastSession && (fromPort != m_LastSession->RemotePort || toPort != m_LastSession->LocalPort)) + { + std::lock_guard lock(m_SessionsMutex); + auto it = m_Sessions.find (GetSessionIndex (fromPort, toPort)); + if (it != m_Sessions.end ()) + m_LastSession = it->second; + else + m_LastSession = nullptr; + } if (m_LastSession) { m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); @@ -41,11 +50,12 @@ namespace client std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); - while(itr != m_Sessions.end()) { - if(now - (*itr)->LastActivity >= delta ) + while(itr != m_Sessions.end()) + { + if(now - itr->second->LastActivity >= delta ) itr = m_Sessions.erase(itr); else - ++itr; + itr++; } } @@ -66,15 +76,25 @@ namespace client UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) { auto ih = from.GetIdentHash(); - for (auto & s : m_Sessions ) + auto idx = GetSessionIndex (remotePort, localPort); { - if (s->Identity.GetLL()[0] == ih.GetLL()[0] && remotePort == s->RemotePort) + std::lock_guard lock(m_SessionsMutex); + auto it = m_Sessions.find (idx); + if (it != m_Sessions.end ()) { - /** found existing session */ - LogPrint(eLogDebug, "UDPServer: Found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); - return s; - } - } + if (it->second->Identity.GetLL()[0] == ih.GetLL()[0]) + { + LogPrint(eLogDebug, "UDPServer: Found session ", it->second->IPSocket.local_endpoint(), " ", ih.ToBase32()); + return it->second; + } + else + { + LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed"); + m_Sessions.erase (it); + } + } + } + boost::asio::ip::address addr; /** create new udp session */ if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) @@ -84,10 +104,12 @@ namespace client } else addr = m_LocalAddress; - boost::asio::ip::udp::endpoint ep(addr, 0); - m_Sessions.push_back(std::make_shared(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort)); - auto & back = m_Sessions.back(); - return back; + + auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), + m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort); + std::lock_guard lock(m_SessionsMutex); + m_Sessions.emplace (idx, s); + return s; } UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, @@ -175,8 +197,9 @@ namespace client std::vector > sessions; std::lock_guard lock (m_SessionsMutex); - for (UDPSessionPtr s: m_Sessions) + for (auto it: m_Sessions) { + auto s = it.second; if (!s->m_Destination) continue; auto info = s->m_Destination->GetInfoForRemote (s->Identity); if (!info) continue; diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 3233c3f0..6dff41ea 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -104,7 +104,8 @@ namespace client void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); - + uint32_t GetSessionIndex (uint16_t fromPort, uint16_t toPort) const { return ((uint32_t)fromPort << 16) + toPort; } + private: bool m_IsUniqueLocal; @@ -112,7 +113,7 @@ namespace client boost::asio::ip::address m_LocalAddress; boost::asio::ip::udp::endpoint m_RemoteEndpoint; std::mutex m_SessionsMutex; - std::vector m_Sessions; + std::unordered_map m_Sessions; // (from port, to port)->session std::shared_ptr m_LocalDest; UDPSessionPtr m_LastSession; bool m_Gzip; From c5a18065281e45469518d6db032264971252199b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 13:58:42 -0500 Subject: [PATCH 188/264] fixed possible deadlock --- libi2pd_client/UDPTunnel.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 3fcf8b35..0bf3202f 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -19,10 +19,7 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0] || fromPort != m_LastSession->RemotePort) - { - std::lock_guard lock(m_SessionsMutex); m_LastSession = ObtainUDPSession(from, toPort, fromPort); - } m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } From 70639f11396ad514d3bf358b8dccdd9aee7aff80 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 19:05:38 -0500 Subject: [PATCH 189/264] don't adjust clock if offsets came from same router --- libi2pd/SSU2.cpp | 29 +++++++++++++++++++++-------- libi2pd/SSU2.h | 3 ++- libi2pd/SSU2Session.cpp | 6 +++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1fb10927..0ebeab6d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -210,27 +210,40 @@ namespace transport return ep.port (); } - void SSU2Server::AdjustTimeOffset (int64_t offset) + void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr from) { if (offset) { if (m_PendingTimeOffset) // one more { - if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + if (m_PendingTimeOffsetFrom && from && + m_PendingTimeOffsetFrom->GetIdentHash ().GetLL()[0] != from->GetIdentHash ().GetLL()[0]) // from different routers { - offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); - i2p::util::AdjustTimeOffset (offset); - } + if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); + } + else + LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); + m_PendingTimeOffset = 0; + m_PendingTimeOffsetFrom = nullptr; + } else - LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); - m_PendingTimeOffset = 0; + LogPrint (eLogWarning, "SSU2: Time offsets from same router. Clock not adjusted"); } else + { m_PendingTimeOffset = offset; // first + m_PendingTimeOffsetFrom = from; + } } else + { m_PendingTimeOffset = 0; // reset + m_PendingTimeOffsetFrom = nullptr; + } } boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 6d07f7fa..da682746 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -67,7 +67,7 @@ namespace transport bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; - void AdjustTimeOffset (int64_t offset); + void AdjustTimeOffset (int64_t offset, std::shared_ptr from); void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); @@ -164,6 +164,7 @@ namespace transport bool m_IsPublished; // if we maintain introducers bool m_IsSyncClockFromPeers; int64_t m_PendingTimeOffset; // during peer test + std::shared_ptr m_PendingTimeOffsetFrom; // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 3ea07629..5c951391 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1671,10 +1671,10 @@ namespace transport if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) { LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint); - m_Server.AdjustTimeOffset (-offset); + m_Server.AdjustTimeOffset (-offset, GetRemoteIdentity ()); } else - m_Server.AdjustTimeOffset (0); + m_Server.AdjustTimeOffset (0, nullptr); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { @@ -2485,7 +2485,7 @@ namespace transport i2p::context.SetTestingV6 (testing); } if (!testing) - m_Server.AdjustTimeOffset (0); // reset time offset when testing is over + m_Server.AdjustTimeOffset (0, nullptr); // reset time offset when testing is over } size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) From 5b93558bd0d7b46bf004a198f15282d217e5c7d8 Mon Sep 17 00:00:00 2001 From: weko Date: Thu, 25 Jan 2024 01:05:58 +0000 Subject: [PATCH 190/264] Add support for multiple udp server tunnels on one destionation --- libi2pd/Datagram.cpp | 68 ++++++++++++++++++++++++++++++-- libi2pd/Datagram.h | 28 +++++++------ libi2pd_client/ClientContext.cpp | 2 +- libi2pd_client/SAM.cpp | 53 ++++++++++++++----------- libi2pd_client/UDPTunnel.cpp | 46 ++++++++++++++------- libi2pd_client/UDPTunnel.h | 3 +- 6 files changed, 143 insertions(+), 57 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 64738ebe..c99db584 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -19,7 +19,7 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner, bool gzip): - m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip) + m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip) { if (m_Gzip) m_Deflator.reset (new i2p::data::GzipDeflator); @@ -119,19 +119,79 @@ namespace datagram void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - if (m_RawReceiver) - m_RawReceiver (fromPort, toPort, buf, len); + auto r = FindRawReceiver(toPort); + + if (r) + r (fromPort, toPort, buf, len); else LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram"); } + void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port) + { + std::lock_guard lock(m_ReceiversMutex); + m_ReceiversByPorts[port] = receiver; + if (!m_DefaultReceiver) { + m_DefaultReceiver = receiver; + m_DefaultReceiverPort = port; + } + } + + void DatagramDestination::ResetReceiver (uint16_t port) + { + std::lock_guard lock(m_ReceiversMutex); + m_ReceiversByPorts.erase (port); + if (m_DefaultReceiverPort == port) { + m_DefaultReceiver = nullptr; + m_DefaultReceiverPort = 0; + } + } + + + void DatagramDestination::SetRawReceiver (const RawReceiver& receiver, uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + m_RawReceiversByPorts[port] = receiver; + if (!m_DefaultRawReceiver) { + m_DefaultRawReceiver = receiver; + m_DefaultRawReceiverPort = port; + } + }; + + void DatagramDestination::ResetRawReceiver (uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + m_RawReceiversByPorts.erase (port); + if (m_DefaultRawReceiverPort == port) { + m_DefaultRawReceiver = nullptr; + m_DefaultRawReceiverPort = 0; + } + } + + DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) { std::lock_guard lock(m_ReceiversMutex); - Receiver r = m_Receiver; + Receiver r = nullptr; auto itr = m_ReceiversByPorts.find(port); if (itr != m_ReceiversByPorts.end()) r = itr->second; + else { + r = m_DefaultReceiver; + } + return r; + } + + DatagramDestination::RawReceiver DatagramDestination::FindRawReceiver(uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + RawReceiver r = nullptr; + auto itr = m_RawReceiversByPorts.find(port); + if (itr != m_RawReceiversByPorts.end()) + r = itr->second; + else { + r = m_DefaultRawReceiver; + } return r; } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index e6d1f7b6..fd6af909 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -126,14 +126,12 @@ namespace datagram void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); - void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; - void ResetReceiver () { m_Receiver = nullptr; }; - void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; }; - void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; + void SetReceiver (const Receiver& receiver, uint16_t port); + void ResetReceiver (uint16_t port); - void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; }; - void ResetRawReceiver () { m_RawReceiver = nullptr; }; + void SetRawReceiver (const RawReceiver& receiver, uint16_t port); + void ResetRawReceiver (uint16_t port); std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); @@ -150,20 +148,26 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - /** find a receiver by port, if none by port is found try default receiver, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); + RawReceiver FindRawReceiver(uint16_t port); private: std::shared_ptr m_Owner; - Receiver m_Receiver; // default - RawReceiver m_RawReceiver; // default - bool m_Gzip; // gzip compression of data messages + std::mutex m_SessionsMutex; std::map m_Sessions; - std::mutex m_ReceiversMutex; - std::map m_ReceiversByPorts; + Receiver m_DefaultReceiver; + RawReceiver m_DefaultRawReceiver; + uint16_t m_DefaultReceiverPort; + uint16_t m_DefaultRawReceiverPort; + std::mutex m_ReceiversMutex; + std::mutex m_RawReceiversMutex; + std::unordered_map m_ReceiversByPorts; + std::unordered_map m_RawReceiversByPorts; + + bool m_Gzip; // gzip compression of data messages i2p::data::GzipInflator m_Inflator; std::unique_ptr m_Deflator; std::vector m_From, m_Signature; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d8c0bd2d..4efe252d 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -775,7 +775,7 @@ namespace client address = "127.0.0.1"; } auto localAddress = boost::asio::ip::address::from_string(address); - auto serverTunnel = std::make_shared(name, localDestination, localAddress, endpoint, port, gzip); + auto serverTunnel = std::make_shared(name, localDestination, localAddress, endpoint, inPort, gzip); if(!isUniqueLocal) { LogPrint(eLogInfo, "Clients: Disabling loopback address mapping"); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1a3afb58..e4cbae8a 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -415,12 +415,17 @@ namespace client { session->UDPEndpoint = forward; auto dest = session->GetLocalDestination ()->CreateDatagramDestination (); + auto port = std::stoi(params[SAM_PARAM_PORT]); if (type == eSAMSessionTypeDatagram) dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + port + ); else // raw dest->SetRawReceiver (std::bind (&SAMSocket::HandleI2PRawDatagramReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + port + ); } if (session->GetLocalDestination ()->IsReady ()) @@ -524,7 +529,7 @@ namespace client if (addr->IsIdentHash ()) { if (session->GetLocalDestination ()->GetIdentHash () != addr->identHash) - { + { auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); if (leaseSet) Connect(leaseSet, session); @@ -556,7 +561,7 @@ namespace client if (session) { if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ())) - { + { m_SocketType = eSAMSocketTypeStream; m_Stream = session->GetLocalDestination ()->CreateStream (remote); if (m_Stream) @@ -570,7 +575,7 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } else - SendStreamCantReachPeer ("Incompatible crypto"); + SendStreamCantReachPeer ("Incompatible crypto"); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -583,7 +588,7 @@ namespace client else { LogPrint (eLogError, "SAM: Destination to connect not found"); - SendStreamCantReachPeer ("LeaseSet not found"); + SendStreamCantReachPeer ("LeaseSet not found"); } } @@ -612,27 +617,27 @@ namespace client session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } else - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket) m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); - } + } if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) { // already accepting, queue up SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts)); - } - else - { + } + else + { LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); SendStreamI2PError ("Already accepting"); - } - } + } + } } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -875,8 +880,8 @@ namespace client size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); #endif SendMessageReply (m_Buffer, len, true); - } - + } + void SAMSocket::SendSessionI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Session I2P error: ", msg); @@ -886,14 +891,14 @@ namespace client void SAMSocket::SendStreamI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Stream I2P error: ", msg); - SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); + SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); } void SAMSocket::SendStreamCantReachPeer(const std::string & msg) { - SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); - } - + SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); + } + void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { if (leaseSet) @@ -1093,14 +1098,14 @@ namespace client // pending acceptors auto ts = i2p::util::GetSecondsSinceEpoch (); while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket) m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); - } + } if (!session->acceptQueue.empty ()) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) @@ -1108,7 +1113,7 @@ namespace client socket->m_IsAccepting = true; session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); } - } + } } if (!m_IsSilent) { diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 0bf3202f..cd17bbf0 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -32,7 +32,7 @@ namespace client auto it = m_Sessions.find (GetSessionIndex (fromPort, toPort)); if (it != m_Sessions.end ()) m_LastSession = it->second; - else + else m_LastSession = nullptr; } if (m_LastSession) @@ -47,7 +47,7 @@ namespace client std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); - while(itr != m_Sessions.end()) + while(itr != m_Sessions.end()) { if(now - itr->second->LastActivity >= delta ) itr = m_Sessions.erase(itr); @@ -88,10 +88,10 @@ namespace client { LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed"); m_Sessions.erase (it); - } - } - } - + } + } + } + boost::asio::ip::address addr; /** create new udp session */ if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) @@ -102,7 +102,7 @@ namespace client else addr = m_LocalAddress; - auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), + auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort); std::lock_guard lock(m_SessionsMutex); m_Sessions.emplace (idx, s); @@ -163,9 +163,9 @@ namespace client } I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr localDestination, - const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t port, bool gzip) : + const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t inPort, bool gzip) : m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), - m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_Gzip (gzip) + m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_inPort(inPort), m_Gzip (gzip) { } @@ -179,14 +179,23 @@ namespace client m_LocalDest->Start (); auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip); - dgram->SetReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - dgram->SetRawReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + dgram->SetReceiver ( + std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + m_inPort + ); + dgram->SetRawReceiver ( + std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + m_inPort + ); } void I2PUDPServerTunnel::Stop () { auto dgram = m_LocalDest->GetDatagramDestination (); - if (dgram) dgram->ResetReceiver (); + if (dgram) { + dgram->ResetReceiver (m_inPort); + dgram->ResetRawReceiver (m_inPort); + } } std::vector > I2PUDPServerTunnel::GetSessions () @@ -240,9 +249,13 @@ namespace client dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); + std::placeholders::_5), + RemotePort + ); dgram->SetRawReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + RemotePort + ); m_LocalDest->Start (); if (m_ResolveThread == nullptr) @@ -253,7 +266,10 @@ namespace client void I2PUDPClientTunnel::Stop () { auto dgram = m_LocalDest->GetDatagramDestination (); - if (dgram) dgram->ResetReceiver (); + if (dgram) { + dgram->ResetReceiver (RemotePort); + dgram->ResetRawReceiver (RemotePort); + } m_cancel_resolve = true; m_Sessions.clear(); diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 6dff41ea..5650124c 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -105,7 +105,7 @@ namespace client void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); uint32_t GetSessionIndex (uint16_t fromPort, uint16_t toPort) const { return ((uint32_t)fromPort << 16) + toPort; } - + private: bool m_IsUniqueLocal; @@ -116,6 +116,7 @@ namespace client std::unordered_map m_Sessions; // (from port, to port)->session std::shared_ptr m_LocalDest; UDPSessionPtr m_LastSession; + uint16_t m_inPort; bool m_Gzip; public: From 4b167fdbafe577bca8b745e64ed0b15140c90b34 Mon Sep 17 00:00:00 2001 From: weko Date: Thu, 25 Jan 2024 01:57:24 +0000 Subject: [PATCH 191/264] Update copyright year --- libi2pd/Datagram.cpp | 2 +- libi2pd/Datagram.h | 2 +- libi2pd_client/ClientContext.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index c99db584..717e3312 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index fd6af909..45edecab 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 4efe252d..c27ce625 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * From 67c4d4bcaafbe67ee5dd7bbd4fda44eb1d91a6e4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2024 09:09:44 -0500 Subject: [PATCH 192/264] fixed VS build error --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 925c89dd..fff2fdc7 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1170,7 +1170,7 @@ namespace transport size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) { - ssize_t l = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + int l = (int)NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; if (l <= 0) return 0; paddingSize = l; } From 75c2cb751f493c4bf96249e1b1e800868806943c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2024 18:51:46 -0500 Subject: [PATCH 193/264] lock mutex before deleting RouterInfo's buffer --- libi2pd/NetDb.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 8eb5d653..f1be7520 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -240,7 +240,7 @@ namespace data { bool wasFloodfill = r->IsFloodfill (); { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); if (!r->Update (buf, len)) { updated = false; @@ -254,7 +254,7 @@ namespace data m_RouterInfos.erase (ident); if (wasFloodfill) { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Remove (r->GetIdentHash ()); } m_Requests.RequestComplete (ident, nullptr); @@ -265,7 +265,7 @@ namespace data if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated { LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) @@ -291,7 +291,7 @@ namespace data { bool inserted = false; { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); inserted = m_RouterInfos.insert ({r->GetIdentHash (), r}).second; } if (inserted) @@ -302,7 +302,7 @@ namespace data if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Insert (r); } else @@ -325,7 +325,7 @@ namespace data bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len) { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); bool updated = false; auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end () && it->second->GetStoreType () == i2p::data::NETDB_STORE_TYPE_LEASESET) @@ -366,7 +366,7 @@ namespace data 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); + std::lock_guard lock(m_LeaseSetsMutex); auto it = m_LeaseSets.find(ident); if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType || leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ()) @@ -393,7 +393,7 @@ namespace data std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); auto it = m_RouterInfos.find (ident); if (it != m_RouterInfos.end ()) return it->second; @@ -403,7 +403,7 @@ namespace data std::shared_ptr NetDb::FindLeaseSet (const IdentHash& destination) const { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); auto it = m_LeaseSets.find (destination); if (it != m_LeaseSets.end ()) return it->second; @@ -437,7 +437,7 @@ namespace data auto r = FindRouter (ident); if (r) { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); r->ExcludeReachableTransports (transports); } } @@ -527,7 +527,7 @@ namespace data void NetDb::VisitLeaseSets(LeaseSetVisitor v) { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); for ( auto & entry : m_LeaseSets) v(entry.first, entry.second); } @@ -543,7 +543,7 @@ namespace data void NetDb::VisitRouterInfos(RouterInfoVisitor v) { - std::unique_lock lock(m_RouterInfosMutex); + std::lock_guard lock(m_RouterInfosMutex); for ( const auto & item : m_RouterInfos ) v(item.second); } @@ -555,7 +555,7 @@ namespace data size_t iters = max_iters_per_cyle; while(n > 0) { - std::unique_lock lock(m_RouterInfosMutex); + std::lock_guard lock(m_RouterInfosMutex); uint32_t idx = rand () % m_RouterInfos.size (); uint32_t i = 0; for (const auto & it : m_RouterInfos) { @@ -638,6 +638,7 @@ namespace data // we have something to save it.second->SaveToFile (m_Storage.Path(ident)); it.second->SetUnreachable (false); + std::lock_guard l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update it.second->DeleteBuffer (); } it.second->SetUpdated (false); @@ -696,7 +697,7 @@ namespace data LogPrint (eLogInfo, "NetDb: Deleting ", deletedCount, " unreachable routers"); // clean up RouterInfos table { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { if (!it->second || it->second->IsUnreachable ()) @@ -710,7 +711,7 @@ namespace data } // clean up expired floodfills or not floodfills anymore { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Cleanup ([](const std::shared_ptr& r)->bool { return r && r->IsFloodfill () && !r->IsUnreachable (); @@ -1249,7 +1250,7 @@ namespace data return 0; uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); auto count = m_RouterInfos.size (); if(count == 0) return nullptr; inds[0] %= count; @@ -1311,7 +1312,7 @@ namespace data const std::set& excluded) const { IdentHash destKey = CreateRoutingKey (destination); - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); return m_Floodfills.FindClosest (destKey, [&excluded](const std::shared_ptr& r)->bool { return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && @@ -1326,7 +1327,7 @@ namespace data IdentHash destKey = CreateRoutingKey (destination); std::vector > v; { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); v = m_Floodfills.FindClosest (destKey, num, [&excluded](const std::shared_ptr& r)->bool { return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && @@ -1381,7 +1382,7 @@ namespace data { auto ts = i2p::util::GetSecondsSinceEpoch (); { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); for (auto& it: m_RouterInfos) it.second->UpdateIntroducers (ts); } From 530c353b00f73dcc497cf13206d50051b0748615 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 27 Jan 2024 12:17:59 -0500 Subject: [PATCH 194/264] don't send Ack with NACK immediately but after 2 milliseconds --- libi2pd/Streaming.cpp | 37 ++++++++++++++++--------------------- libi2pd/Streaming.h | 3 ++- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 629039ab..c43f99ad 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -179,13 +179,9 @@ namespace stream { if (!m_IsAckSendScheduled) { - m_IsAckSendScheduled = true; auto ackTimeout = m_RTT/10; if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; - else if (ackTimeout < MIN_SEND_ACK_TIMEOUT) ackTimeout = MIN_SEND_ACK_TIMEOUT; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout)); - m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, - shared_from_this (), std::placeholders::_1)); + ScheduleAck (ackTimeout); } } else if (packet->IsSYN ()) @@ -207,23 +203,11 @@ namespace stream // save message and wait for missing message again SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) - { - // send NACKs for missing messages ASAP - if (m_IsAckSendScheduled) - { - m_IsAckSendScheduled = false; - m_AckSendTimer.cancel (); - } - SendQuickAck (); - } + // send NACKs for missing messages with minimal timeout + ScheduleAck (MIN_SEND_ACK_TIMEOUT); else - { // wait for SYN - m_IsAckSendScheduled = true; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT)); - m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, - shared_from_this (), std::placeholders::_1)); - } + ScheduleAck (SYN_TIMEOUT); } } } @@ -1029,6 +1013,17 @@ namespace stream } } + void Stream::ScheduleAck (int timeout) + { + if (m_IsAckSendScheduled) + m_AckSendTimer.cancel (); + m_IsAckSendScheduled = true; + if (timeout < MIN_SEND_ACK_TIMEOUT) timeout = MIN_SEND_ACK_TIMEOUT; + m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(timeout)); + m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, + shared_from_this (), std::placeholders::_1)); + } + void Stream::HandleAckSendTimer (const boost::system::error_code& ecode) { if (m_IsAckSendScheduled) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 1db59118..ed79edc9 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -227,6 +227,7 @@ namespace stream void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); + void ScheduleAck (int timeout); void HandleAckSendTimer (const boost::system::error_code& ecode); private: From a3246cd9dc92f91219801e6ef8c6fa22f0056616 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 27 Jan 2024 17:57:50 -0500 Subject: [PATCH 195/264] doen't send Ack packet too often if missing packets --- libi2pd/Streaming.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c43f99ad..a4604892 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -203,8 +203,11 @@ namespace stream // save message and wait for missing message again SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) - // send NACKs for missing messages with minimal timeout - ScheduleAck (MIN_SEND_ACK_TIMEOUT); + { + if (!m_IsAckSendScheduled) + // send NACKs for missing messages + ScheduleAck (MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size ()); + } else // wait for SYN ScheduleAck (SYN_TIMEOUT); From 81015a52285651e0c6fe2a8bf33d7dd0b2c96b83 Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 28 Jan 2024 15:37:14 +0200 Subject: [PATCH 196/264] log changes of network status --- libi2pd/RouterContext.cpp | 4 ++++ libi2pd/RouterContext.h | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 10d33bf5..b3c51ca6 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -303,6 +303,8 @@ namespace i2p SetTesting (false); if (status != m_Status) { + LogPrint(eLogInfo, "Router: network status v4 changed ", + ROUTER_STATUS_NAMES[m_Status], " -> ", ROUTER_STATUS_NAMES[status]); m_Status = status; switch (m_Status) { @@ -323,6 +325,8 @@ namespace i2p SetTestingV6 (false); if (status != m_StatusV6) { + LogPrint(eLogInfo, "Router: network status v6 changed ", + ROUTER_STATUS_NAMES[m_StatusV6], " -> ", ROUTER_STATUS_NAMES[status]); m_StatusV6 = status; switch (m_StatusV6) { diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 91a553ba..ddfc65de 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -48,6 +48,15 @@ namespace garlic eRouterStatusMesh = 4 }; + const char* const ROUTER_STATUS_NAMES[] = + { + "OK", // 0 + "Firewalled", // 1 + "Unknown", // 2 + "Proxy", // 3 + "Mesh" // 4 + }; + enum RouterError { eRouterErrorNone = 0, From 822cb35efe35b95c269329275b1d00f3b7f3b7c8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 28 Jan 2024 18:12:40 -0500 Subject: [PATCH 197/264] limit send Ack timeout by Ack delay interval --- libi2pd/Streaming.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a4604892..74fb3d97 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -205,8 +205,12 @@ namespace stream if (m_LastReceivedSequenceNumber >= 0) { if (!m_IsAckSendScheduled) + { // send NACKs for missing messages - ScheduleAck (MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size ()); + int ackTimeout = MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size (); + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; + ScheduleAck (ackTimeout); + } } else // wait for SYN From d926a310645d9778848f8fadb710a70dc66ebd34 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jan 2024 18:01:41 -0500 Subject: [PATCH 198/264] fixed warning --- libi2pd/Datagram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 717e3312..f87f9653 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -156,7 +156,7 @@ namespace datagram m_DefaultRawReceiver = receiver; m_DefaultRawReceiverPort = port; } - }; + } void DatagramDestination::ResetRawReceiver (uint16_t port) { From f0084785059b8e78acef3301e1fd818ec6b0c73b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jan 2024 19:54:43 -0500 Subject: [PATCH 199/264] handle I2NP messages drops --- libi2pd/I2NPProtocol.h | 7 +++++-- libi2pd/NTCP2.cpp | 1 + libi2pd/NetDb.cpp | 6 +++++- libi2pd/NetDbRequests.cpp | 6 +++++- libi2pd/SSU2Session.cpp | 1 + libi2pd/Transports.h | 7 +++++++ 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index e86f4f32..a2877a08 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "Crypto.h" #include "I2PEndian.h" #include "Identity.h" @@ -149,7 +150,8 @@ namespace tunnel uint8_t * buf; size_t len, offset, maxLen; std::shared_ptr from; - + std::function onDrop; + I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header @@ -241,7 +243,6 @@ namespace tunnel SetSize (len - offset - I2NP_HEADER_SIZE); SetChks (0); } - void ToNTCP2 () { uint8_t * ntcp2 = GetNTCP2Header (); @@ -253,6 +254,8 @@ namespace tunnel void RenewI2NPMessageHeader (); bool IsExpired () const; bool IsExpired (uint64_t ts) const; // in milliseconds + + void Drop () { if (onDrop) { onDrop (); onDrop = nullptr; }; } }; template diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fff2fdc7..ad8ef51d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1140,6 +1140,7 @@ namespace transport if (!msg || msg->IsExpired (ts)) { // drop null or expired message + if (msg) msg->Drop (); m_SendQueue.pop_front (); continue; } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f1be7520..0bf7af9d 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -736,7 +736,11 @@ namespace data !i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) direct = false; // floodfill can't be reached directly if (direct) - transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + { + auto msg = dest->CreateRequestMessage (floodfill->GetIdentHash ()); + msg->onDrop = [this, dest]() { this->m_Requests.SendNextRequest (dest); }; + transports.SendMessage (floodfill->GetIdentHash (), msg); + } else { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 92e5a7b8..4099f921 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -188,7 +188,11 @@ namespace data !i2p::transport::transports.IsConnected (nextFloodfill->GetIdentHash ())) direct = false; // floodfill can't be reached directly if (direct) - i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), dest->CreateRequestMessage (nextFloodfill->GetIdentHash ())); + { + auto msg = dest->CreateRequestMessage (nextFloodfill->GetIdentHash ()); + msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; + i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), msg); + } else { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 5c951391..fa6d9eca 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -382,6 +382,7 @@ namespace transport if (!msg || msg->IsExpired (ts)) { // drop null or expired message + if (msg) msg->Drop (); m_SendQueue.pop_front (); continue; } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 0e5518b1..c78a8bd0 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -86,6 +86,13 @@ namespace transport } } + ~Peer () + { + // drop not sent delayed messages + for (auto& it: delayedMessages) + it->Drop (); + } + void Done () { for (auto& it: sessions) From 85f5f5b91e669d626adb1daaa98a35fbc0321245 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 10:04:19 -0500 Subject: [PATCH 200/264] fixed potential deadlock --- libi2pd/Transports.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index c78a8bd0..540bafb4 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -85,18 +85,14 @@ namespace transport isReachable = (bool)router->GetCompatibleTransports (true); } } - - ~Peer () - { - // drop not sent delayed messages - for (auto& it: delayedMessages) - it->Drop (); - } void Done () { for (auto& it: sessions) it->Done (); + // drop not sent delayed messages + for (auto& it: delayedMessages) + it->Drop (); } void SetRouter (std::shared_ptr r) From e40b656ecf8ea4bdbb92c2c5f5c996ffae7aa2d2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 15:41:57 -0500 Subject: [PATCH 201/264] Drop for tunnel and encrypted messages --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 10 ++++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 4 ++-- libi2pd/NetDb.cpp | 1 + libi2pd/NetDbRequests.cpp | 1 + libi2pd/TunnelGateway.cpp | 11 +++++++++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 3b3ed485..6f56f2e5 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1171,7 +1171,7 @@ namespace garlic return m; } - std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey) + std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey) { // Noise_N, we are Alice, routerPublicKey is Bob's i2p::crypto::NoiseSymmetricState noiseState; @@ -1205,6 +1205,12 @@ namespace garlic htobe32buf (m->GetPayload (), offset); m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); + if (msg->onDrop) + { + // move onDrop to the wrapping I2NP messages + m->onDrop = msg->onDrop; + msg->onDrop = nullptr; + } return m; } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 301f597a..517833e8 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -246,7 +246,7 @@ namespace garlic }; std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); - std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); + std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0bf7af9d..bedb19f6 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -749,6 +749,7 @@ namespace data if (outbound && inbound) { auto msg = dest->CreateRequestMessage (floodfill, inbound); + msg->onDrop = [this, dest]() { this->m_Requests.SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); } diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 4099f921..3b5f41b6 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -202,6 +202,7 @@ namespace data { LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); + msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, nextFloodfill->GetIdentity ()->GetEncryptionPublicKey ())); } diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index 12e7652f..85ff224e 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -35,6 +35,13 @@ namespace tunnel if (!m_CurrentTunnelDataMsg) { CreateCurrentTunnelDataMessage (); + if (block.data && block.data->onDrop) + { + // onDrop is called for the first fragment in tunnel message + // that's usually true for short TBMs or lookups + m_CurrentTunnelDataMsg->onDrop = block.data->onDrop; + block.data->onDrop = nullptr; + } messageCreated = true; } @@ -155,7 +162,6 @@ namespace tunnel void TunnelGatewayBuffer::CreateCurrentTunnelDataMessage () { - m_CurrentTunnelDataMsg = nullptr; m_CurrentTunnelDataMsg = NewI2NPTunnelMessage (true); // tunnel endpoint is at least of two tunnel messages size // we reserve space for padding m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; @@ -223,6 +229,7 @@ namespace tunnel m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ()); newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + if (tunnelMsg->onDrop) newMsg->onDrop = tunnelMsg->onDrop; newTunnelMsgs.push_back (newMsg); m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; } From 0ca782ed717bc8ad631efd4bf252c1b78894b72b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 18:02:14 -0500 Subject: [PATCH 202/264] drop unsent messages if session disconnects --- libi2pd/NTCP2.cpp | 2 ++ libi2pd/SSU2Session.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index ad8ef51d..6fe88509 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -373,6 +373,8 @@ namespace transport m_Socket.close (); transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); + for (auto& it: m_SendQueue) + it->Drop (); m_SendQueue.clear (); SetSendQueueSize (0); auto remoteIdentity = GetRemoteIdentity (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index fa6d9eca..9180ccc8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -262,6 +262,8 @@ namespace transport m_SentHandshakePacket.reset (nullptr); m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); + for (auto& it: m_SendQueue) + it->Drop (); m_SendQueue.clear (); SetSendQueueSize (0); m_SentPackets.clear (); From 2e9f2d4a3b1513797a73f94b1b661d4f9b76bb9b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 21:52:18 -0500 Subject: [PATCH 203/264] Drop for LeaseSet request --- libi2pd/Destination.cpp | 67 ++++++++++++++++++++++++----------------- libi2pd/Destination.h | 3 +- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index b9555abe..9b173f24 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -502,38 +502,43 @@ namespace client if (it != m_LeaseSetRequests.end ()) { auto request = it->second; - bool found = false; - if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) + for (int i = 0; i < num; i++) { - for (int i = 0; i < num; i++) + i2p::data::IdentHash peerHash (buf + 33 + i*32); + if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) { - i2p::data::IdentHash peerHash (buf + 33 + i*32); - if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) - { - LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); - i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory - } - } - - auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); - if (floodfill) - { - LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); - if (SendLeaseSetRequest (key, floodfill, request)) - found = true; + LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); + i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory } } - if (!found) - { - LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); - request->Complete (nullptr); - m_LeaseSetRequests.erase (key); - } + SendNextLeaseSetRequest (key, request); } else LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); } + void LeaseSetDestination::SendNextLeaseSetRequest (const i2p::data::IdentHash& key, + std::shared_ptr request) + { + bool found = false; + if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) + { + auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); + if (floodfill) + { + LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); + if (SendLeaseSetRequest (key, floodfill, request)) + found = true; + } + } + if (!found) + { + LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); + request->Complete (nullptr); + m_LeaseSetRequests.erase (key); + } + } + void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID) { if (msgID == m_PublishReplyToken) @@ -822,14 +827,22 @@ namespace client AddECIESx25519Key (replyKey, replyTag); else AddSessionKey (replyKey, replyTag); - auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, - request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); + auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES); + auto s = shared_from_this (); + msg->onDrop = [s, dest, request]() + { + s->GetService ().post([s, dest, request]() + { + s->SendNextLeaseSetRequest (dest, request); + }); + }; + auto encryptedMsg = WrapMessageForRouter (nextFloodfill, msg); request->outboundTunnel->SendTunnelDataMsgs ( { i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeRouter, - nextFloodfill->GetIdentHash (), 0, msg + nextFloodfill->GetIdentHash (), 0, encryptedMsg } }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 3b395f4d..a066c64c 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -176,6 +176,7 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr requestedBlindedKey = nullptr); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); + void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); From ffdd5935e90e65300da10164ca72a0de64a52b4a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 31 Jan 2024 11:46:01 -0500 Subject: [PATCH 204/264] Handle drop of own RouterInfo publishing message --- libi2pd/RouterContext.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b3c51ca6..40949891 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1378,10 +1378,19 @@ namespace i2p uint32_t replyToken; RAND_bytes ((uint8_t *)&replyToken, 4); LogPrint (eLogInfo, "Router: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); + auto onDrop = [this]() + { + if (m_Service) + m_Service->GetService ().post ([this]() { HandlePublishResendTimer (boost::system::error_code ()); }); + }; if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? + { // send directly - i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken); + msg->onDrop = onDrop; + i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), msg); + } else { // otherwise through exploratory @@ -1392,6 +1401,7 @@ namespace i2p { // encrypt for floodfill auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound); + msg->onDrop = onDrop; outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); } From 83cb3a1820802a5ddf01fb3de1f0654f9f56e237 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 31 Jan 2024 15:41:21 -0500 Subject: [PATCH 205/264] reduce router unreachable interval --- libi2pd/Profiling.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 6531e060..ed23fb12 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -35,7 +35,7 @@ namespace data const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) - const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes) const int PEER_PROFILE_USEFUL_THRESHOLD = 3; class RouterProfile From 96cf6ca531289328aeda9c8ea7f6eae06b338c57 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 18:14:45 -0500 Subject: [PATCH 206/264] drop earlier if outgoing queue is semi-full --- libi2pd/NTCP2.cpp | 7 ++++++- libi2pd/SSU2Session.cpp | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 6fe88509..76f3a940 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1250,8 +1250,13 @@ namespace transport void NTCP2Session::PostI2NPMessages (std::vector > msgs) { if (m_IsTerminated) return; + bool isSemiFull = m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE/2; for (auto it: msgs) - m_SendQueue.push_back (std::move (it)); + if (isSemiFull && it->onDrop) + it->Drop (); // drop earlier because we can handle it + else + m_SendQueue.push_back (std::move (it)); + if (!m_IsSending) SendQueue (); else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9180ccc8..12671f4f 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -351,8 +351,12 @@ namespace transport void SSU2Session::PostI2NPMessages (std::vector > msgs) { if (m_State == eSSU2SessionStateTerminated) return; + bool isSemiFull = m_SendQueue.size () > SSU2_MAX_OUTGOING_QUEUE_SIZE/2; for (auto it: msgs) - m_SendQueue.push_back (std::move (it)); + if (isSemiFull && it->onDrop) + it->Drop (); // drop earlier because we can handle it + else + m_SendQueue.push_back (std::move (it)); SendQueue (); if (m_SendQueue.size () > 0) // windows is full From 8f28cee32fa76c87d8b2930a6197732a21f84852 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 18:55:10 -0500 Subject: [PATCH 207/264] drop earlier if delayed queue is semi-full --- libi2pd/Transports.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 5d3027a9..a70e77b4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -477,7 +477,10 @@ namespace transport } } for (auto& it1: msgs) - it->second.delayedMessages.push_back (it1); + if (sz > MAX_NUM_DELAYED_MESSAGES/2 && it1->onDrop) + it1->Drop (); // drop earlier because we can handle it + else + it->second.delayedMessages.push_back (it1); } else { From 47578b69c621a6d8b6a812530b8a6da31bbd9a9a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 19:38:12 -0500 Subject: [PATCH 208/264] handle drop of tunnel test message --- libi2pd/TunnelPool.cpp | 74 +++++++++++++++++++++++++++--------------- libi2pd/TunnelPool.h | 4 +-- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5339c9be..93df99be 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -360,36 +360,58 @@ namespace tunnel } // new tests - std::unique_lock l1(m_OutboundTunnelsMutex); - auto it1 = m_OutboundTunnels.begin (); - std::unique_lock l2(m_InboundTunnelsMutex); - auto it2 = m_InboundTunnels.begin (); - while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) + std::vector, std::shared_ptr > > newTests; { - bool failed = false; - if ((*it1)->IsFailed ()) + std::unique_lock l1(m_OutboundTunnelsMutex); + auto it1 = m_OutboundTunnels.begin (); + std::unique_lock l2(m_InboundTunnelsMutex); + auto it2 = m_InboundTunnels.begin (); + while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - uint32_t msgID; - RAND_bytes ((uint8_t *)&msgID, 4); + bool failed = false; + if ((*it1)->IsFailed ()) { - std::unique_lock l(m_TestsMutex); - m_Tests[msgID] = std::make_pair (*it1, *it2); + failed = true; + ++it1; + } + if ((*it2)->IsFailed ()) + { + failed = true; + ++it2; + } + if (!failed) + { + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; } - (*it1)->SendTunnelDataMsgTo ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), - CreateDeliveryStatusMsg (msgID)); - ++it1; ++it2; } - } + } + for (auto& it: newTests) + { + uint32_t msgID; + RAND_bytes ((uint8_t *)&msgID, 4); + { + std::unique_lock l(m_TestsMutex); + m_Tests[msgID] = it; + } + auto msg = CreateDeliveryStatusMsg (msgID); + auto outbound = it.first; + auto s = shared_from_this (); + msg->onDrop = [msgID, outbound, s]() + { + // if test msg dropped locally it's outbound tunnel to blame + outbound->SetState (eTunnelStateFailed); + { + std::unique_lock l(s->m_TestsMutex); + s->m_Tests.erase (msgID); + } + { + std::unique_lock l(s->m_OutboundTunnelsMutex); + s->m_OutboundTunnels.erase (outbound); + } + }; + outbound->SendTunnelDataMsgTo (it.second->GetNextIdentHash (), it.second->GetNextTunnelID (), msg); + } } void TunnelPool::ManageTunnels (uint64_t ts) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index c1fd19cd..7cb1f5c9 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -30,7 +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; + const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 3; class Tunnel; class InboundTunnel; From 7b776666a3dcec3e7237a064c2ce97139e7a86ea Mon Sep 17 00:00:00 2001 From: StormyCloudInc <64628149+WaxySteelWorm@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:21:19 -0600 Subject: [PATCH 209/264] Add files via upload --- .../reseed/admin_at_stormycloud.org.crt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 contrib/certificates/reseed/admin_at_stormycloud.org.crt diff --git a/contrib/certificates/reseed/admin_at_stormycloud.org.crt b/contrib/certificates/reseed/admin_at_stormycloud.org.crt new file mode 100644 index 00000000..ae44521b --- /dev/null +++ b/contrib/certificates/reseed/admin_at_stormycloud.org.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF1zCCA7+gAwIBAgIRAMDqFR09Xuj8ZUu+oetSvAEwDQYJKoZIhvcNAQELBQAw +dTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxHjAcBgNVBAMM +FWFkbWluQHN0b3JteWNsb3VkLm9yZzAeFw0yNDAxMjUxNDE1MzBaFw0zNDAxMjUx +NDE1MzBaMHUxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx +HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR4w +HAYDVQQDDBVhZG1pbkBzdG9ybXljbG91ZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDbGX+GikPzQXr9zvkrhfO9g0l49KHLNQhUKYqd6T+PfnGo +Fm0d3ZZVVQZ045vWgroOXDGGZZWxUIlb2inRaR2DF1TxN3pPYt59RgY9ZQ9+TL7o +isY91krCRygY8EcAmHIjlfZQ9dBVcL7CfyT0MYZA5Efee9+NDHSewTfQP9T2faIE +83Fcyd93a2mIHYjKUbJnojng/wgsy8srbsEuuTok4MIQmDj+B5nz+za2FgI0/ydh +srlMt4aGJF4/DIem9z9d0zBCOkwrmtFIzjNF1mOSA8ES4m5YnKA/y9rZlRidLPGu +prbXhPVnqHeOnHMz2QCw1wbVo504kl0bMqyEz2tVWsO9ep7iZoQs2xkFAEaegYNT +QLUpwVGlyuq3wXXwopFRffOSimGSazICwWI6j+K0pOtgefNJaWrqKYvtkj1SbK2L +LBNUIENz6VnB7KPRckuX6zxC8PpOiBK9BcftfO+xAz/wC6qq3riBPw30KKSym0nC +Zp5KciDn4Phtw9PGq8Bkl8SyWl0jtFnfTB1tzJkisf2qKcNHaFTEe2JW763YLbh/ +AU+8X8evFu40qLgvOgKoyy5DLy6i8zetX+3t9K0Fxt9+Vzzq6lm5V/RS8iIPPn+M +q1/3Z5kD0KQBG9h/Gl8BH+lB71ZxPAOZ3SMu8DJZcxBLVmDWqQPCr5CKnoz0swID +AQABo2IwYDAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG +AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHgYDVR0OBBcEFWFkbWluQHN0b3JteWNs +b3VkLm9yZzANBgkqhkiG9w0BAQsFAAOCAgEARWOJ69vTHMneSXYscha+4Ytjg0RM +faewJNEGj8qy/Qvh9si2bWYNPRK6BlbHFS7pRYBLAnhaeLBGVv1CCR6GUMMe74zQ +UuMeAoWU6qMDmB3GfYoZJh8sIxpwHqyJeTdeccRbZ4sX4F6u3IHPXYiU/AgbYqH7 +pYXQg2lCjXZYaDFAlEf5SlYUDOhhXe5kR8Edhlrsu32/JzA1DQK0JjxKCBp+DQmA +ltdOpQtAg03fHP4ssdj7VvjIDl28iIlATwBvHrdNm7T0tYWn6TWhvxbRqvfTxfaH +MvxnPdIJwNP4/9TyQkwjwHb1h+ucho3CnxI/AxspdOvT1ElMhP6Ce6rcS9pk11Rl +x0ChsqpWwDg7KYpg0qZFSKCTBp4zBq9xoMJ6BQcgMfyl736WbsCzFTEyfifp8beg +NxUa/Qk7w7cuSPGyMIKNOmOR7FLlFbtocy8sXVsUQdqnp/edelufdNe39U9uNtY6 +yoXI9//Tc6NgOwy2Oyia0slZ5qHRkB7e4USXMRzJ3p4q9eCVKjAJs81Utp7O2U+9 +vhbhwWP8CAnNTT1E5WS6EKtfrdqF7wjkV+noPGLDGmrXi01J1fSMAjMfVO+7/LOL +UN+G4ybKWnEhhOO27yidN8Xx6UrCS23DBlPPQAeA74dTsTExiOxf1o1EXzcQiMyO +LAj3/Ojbi1xkWhI= +-----END CERTIFICATE----- From de2b0f6e0986c16d394e1d9b34dcd10266d96e2f Mon Sep 17 00:00:00 2001 From: StormyCloudInc <64628149+WaxySteelWorm@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:24:11 -0600 Subject: [PATCH 210/264] Update Config.cpp --- libi2pd/Config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 4deb59ac..18cc69ee 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -223,7 +223,8 @@ namespace config { "https://i2p.ghativega.in/," "https://i2p.novg.net/," "https://reseed.is.prestium.org/," - "https://reseed.us.prestium.org/" + "https://reseed.us.prestium.org/", + "https://reseed.stormycloud.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From ce356378667fac05b192ec5e9ae1e4c7fbf7bc31 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Feb 2024 15:45:22 -0500 Subject: [PATCH 211/264] handle drop of tunnel build message --- libi2pd/Tunnel.cpp | 14 ++++++++++---- libi2pd/Tunnel.h | 14 +++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index b8e17920..b578217f 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -90,7 +90,13 @@ namespace tunnel hop = hop->prev; } msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild); - + auto s = shared_from_this (); + msg->onDrop = [s]() + { + LogPrint (eLogInfo, "I2NP: Tunnel ", s->GetTunnelID (), " request was not sent"); + s->SetState (i2p::tunnel::eTunnelStateBuildFailed); + }; + // send message if (outboundTunnel) { @@ -246,7 +252,7 @@ namespace tunnel { if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive EncryptTunnelMsg (msg, msg); - msg->from = shared_from_this (); + msg->from = GetSharedFromThis (); m_Endpoint.HandleDecryptedTunnelDataMsg (msg); } @@ -261,7 +267,7 @@ namespace tunnel if (msg) { m_NumReceivedBytes += msg->GetLength (); - msg->from = shared_from_this (); + msg->from = GetSharedFromThis (); HandleI2NPMessage (msg); } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index e6e3c3a5..47ff0465 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -65,7 +65,8 @@ namespace tunnel class OutboundTunnel; class InboundTunnel; - class Tunnel: public TunnelBase + class Tunnel: public TunnelBase, + public std::enable_shared_from_this { struct TunnelHop { @@ -155,7 +156,7 @@ namespace tunnel i2p::data::IdentHash m_EndpointIdentHash; }; - class InboundTunnel: public Tunnel, public std::enable_shared_from_this + class InboundTunnel: public Tunnel { public: @@ -167,6 +168,13 @@ namespace tunnel // override TunnelBase void Cleanup () override { m_Endpoint.Cleanup (); }; + protected: + + std::shared_ptr GetSharedFromThis () + { + return std::static_pointer_cast(shared_from_this ()); + } + private: TunnelEndpoint m_Endpoint; From be815804e66c878c81cb802193b589204d66005b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Feb 2024 15:44:17 -0500 Subject: [PATCH 212/264] expire transit tunnel is not sent further --- libi2pd/I2NPProtocol.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index ebd5f8d6..70cefbdc 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -584,13 +584,14 @@ namespace i2p memcpy (ivKey, noiseState.m_CK , 32); // check if we accept this tunnel + std::shared_ptr transitTunnel; uint8_t retCode = 0; if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) retCode = 30; if (!retCode) { // create new transit tunnel - auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( + transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), @@ -624,11 +625,22 @@ namespace i2p reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; } // send reply + auto onDrop = [transitTunnel]() + { + if (transitTunnel) + { + auto t = transitTunnel->GetCreationTime (); + if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT) + // make transit tunnel expired + transitTunnel->SetCreationTime (t - i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT); + } + }; if (isEndpoint) { auto replyMsg = NewI2NPShortMessage (); replyMsg->Concat (buf, len); replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); + if (transitTunnel) replyMsg->onDrop = onDrop; if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local? { @@ -652,9 +664,12 @@ namespace i2p } } else - transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, - bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + { + auto msg = CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, + bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); + if (transitTunnel) msg->onDrop = onDrop; + transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, msg); + } return; } record += SHORT_TUNNEL_BUILD_RECORD_SIZE; @@ -714,7 +729,11 @@ namespace i2p return msg; } else - return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + { + auto newMsg = CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + if (msg->onDrop) newMsg->onDrop = msg->onDrop; + return newMsg; + } } std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, From f64b136f5a8426c304e38946c5cf8cfa62de5281 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Feb 2024 13:37:08 -0500 Subject: [PATCH 213/264] remove prestium reseeds --- .../reseed/null_at_i2pmail.org.crt | 33 ------------------ .../reheatedburger_at_protonmail.com.crt | 34 ------------------- libi2pd/Config.cpp | 4 +-- 3 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 contrib/certificates/reseed/null_at_i2pmail.org.crt delete mode 100644 contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt diff --git a/contrib/certificates/reseed/null_at_i2pmail.org.crt b/contrib/certificates/reseed/null_at_i2pmail.org.crt deleted file mode 100644 index d736a95e..00000000 --- a/contrib/certificates/reseed/null_at_i2pmail.org.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw -cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE -ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM -EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2 -WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD -VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE -AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0 -XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE -ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA -1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp -gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp -486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR -gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW -DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn -KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX -kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV -bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G -A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD -VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG -9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss -q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj -EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39 -gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV -La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH -xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6 -a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8 -NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK -heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO -j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU -vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw= ------END CERTIFICATE----- diff --git a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt deleted file mode 100644 index d14c5fe1..00000000 --- a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw -fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE -ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM -HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX -DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD -VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL -EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6 -MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI -Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt -4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5 -UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k -P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t -3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5 -zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r -Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ -lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1 -sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz -euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW -MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf -BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC -AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj -tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6 -ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf -xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD -UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM -XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE -Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p -Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq -NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr -QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9 -0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY= ------END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 18cc69ee..b2ad7a17 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -222,8 +222,6 @@ namespace config { "https://www2.mk16.de/," "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.is.prestium.org/," - "https://reseed.us.prestium.org/", "https://reseed.stormycloud.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( From c01fd3299ffb23f0497957ac6f10d8564a4fd7e4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Feb 2024 18:51:59 -0500 Subject: [PATCH 214/264] handle drop of destination publish msg --- libi2pd/Destination.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9b173f24..ef0d5db3 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -626,6 +626,15 @@ namespace client LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); auto msg = WrapMessageForRouter (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound)); + auto s = shared_from_this (); + msg->onDrop = [s]() + { + s->GetService ().post([s]() + { + s->m_PublishConfirmationTimer.cancel (); + s->HandlePublishConfirmationTimer (boost::system::error_code()); + }); + }; m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, shared_from_this (), std::placeholders::_1)); @@ -642,7 +651,7 @@ namespace client m_PublishReplyToken = 0; if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds or failed. will try again"); Publish (); } else @@ -827,7 +836,9 @@ namespace client AddECIESx25519Key (replyKey, replyTag); else AddSessionKey (replyKey, replyTag); - auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES); + + auto msg = WrapMessageForRouter (nextFloodfill, + CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); auto s = shared_from_this (); msg->onDrop = [s, dest, request]() { @@ -836,13 +847,12 @@ namespace client s->SendNextLeaseSetRequest (dest, request); }); }; - auto encryptedMsg = WrapMessageForRouter (nextFloodfill, msg); request->outboundTunnel->SendTunnelDataMsgs ( { i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeRouter, - nextFloodfill->GetIdentHash (), 0, encryptedMsg + nextFloodfill->GetIdentHash (), 0, msg } }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); From c158bbe90a7c502b9a5fc23d6a8218bf7372b3d3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 Feb 2024 19:43:29 -0500 Subject: [PATCH 215/264] send frame when it exceeds 16K --- libi2pd/NTCP2.cpp | 3 +++ libi2pd/NTCP2.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 76f3a940..0dbccbca 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1152,10 +1152,13 @@ namespace transport msgs.push_back (msg); s += (len + 3); m_SendQueue.pop_front (); + if (s >= NTCP2_SEND_AFTER_FRAME_SIZE) + break; // send frame right a way } else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) { LogPrint (eLogError, "NTCP2: I2NP message of size ", len, " can't be sent. Dropped"); + msg->Drop (); m_SendQueue.pop_front (); } else diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index ba1380c3..1eac23f0 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,6 +28,7 @@ namespace transport { const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519; + const size_t NTCP2_SEND_AFTER_FRAME_SIZE = 16386; // send frame when exceeds this size const size_t NTCP2_SESSION_REQUEST_MAX_SIZE = 287; const size_t NTCP2_SESSION_CREATED_MAX_SIZE = 287; const int NTCP2_MAX_PADDING_RATIO = 6; // in % From 586695673b6b6e8fc9e6d3a17d963da196e98b71 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 18:48:10 -0500 Subject: [PATCH 216/264] correct log message for next netdb request --- libi2pd/NetDbRequests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 3b5f41b6..4893fa1b 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -189,6 +189,7 @@ namespace data direct = false; // floodfill can't be reached directly if (direct) { + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " directly"); auto msg = dest->CreateRequestMessage (nextFloodfill->GetIdentHash ()); msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), msg); @@ -200,7 +201,7 @@ namespace data auto inbound = pool->GetNextInboundTunnel (); if (nextFloodfill && outbound && inbound) { - LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " through tunnels"); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, From f98027755281c4d168bd4843b1850ce7ceb2cfc6 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 19:55:54 -0500 Subject: [PATCH 217/264] don't flood failed router --- libi2pd/NetDb.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index bedb19f6..f2166bf0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -226,7 +226,8 @@ namespace data bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { bool updated; - AddRouterInfo (ident, buf, len, updated); + if (!AddRouterInfo (ident, buf, len, updated)) + updated = false; return updated; } @@ -874,7 +875,7 @@ namespace data } else // RouterInfo { - LogPrint (eLogDebug, "NetDb: Store request: RouterInfo"); + LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); size_t size = bufbe16toh (buf + offset); offset += 2; if (size > MAX_RI_BUFFER_SIZE || size > len - offset) From 1b23aa2d7b7e4696713f7ce0a4d90e1a92baee85 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:44:12 -0500 Subject: [PATCH 218/264] increase request timeout --- libi2pd/NetDb.cpp | 2 +- libi2pd/NetDbRequests.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f2166bf0..f3822997 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -149,7 +149,7 @@ namespace data if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastManageRequest >= 15 || ts + 15 < lastManageRequest) // manage requests every 15 seconds + if (ts - lastManageRequest >= MANAGE_REQUESTS_INTERVAL || ts + MANAGE_REQUESTS_INTERVAL < lastManageRequest) // manage requests every 15 seconds { m_Requests.ManageRequests (); lastManageRequest = ts; diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index 47a5d481..25c102de 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -21,8 +21,9 @@ namespace i2p namespace data { const size_t MAX_NUM_REQUEST_ATTEMPTS = 7; + const uint64_t MANAGE_REQUESTS_INTERVAL = 15; // in seconds const uint64_t MIN_REQUEST_TIME = 5; // in seconds - const uint64_t MAX_REQUEST_TIME = 60; // in seconds + const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS*MANAGE_REQUESTS_INTERVAL; class RequestedDestination { From 7dd9a7a0afc0acfad81421ba681fc889ea08a8ce Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:45:57 -0500 Subject: [PATCH 219/264] added CheckLogLevel --- libi2pd/Log.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 1ec0c5fe..0164ea4f 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -87,8 +87,8 @@ namespace log { Log (); ~Log (); - LogType GetLogType () { return m_Destination; }; - LogLevel GetLogLevel () { return m_MinLevel; }; + LogType GetLogType () const { return m_Destination; }; + LogLevel GetLogLevel () const { return m_MinLevel; }; void Start (); void Stop (); @@ -160,6 +160,11 @@ namespace log { } // log } // i2p +inline bool CheckLogLevel (LogLevel level) noexcept +{ + return level <= i2p::log::Logger().GetLogLevel (); +} + /** internal usage only -- folding args array to single string */ template void LogPrint (std::stringstream& s, TValue&& arg) noexcept @@ -185,9 +190,7 @@ void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept template void LogPrint (LogLevel level, TArgs&&... args) noexcept { - i2p::log::Log &log = i2p::log::Logger(); - if (level > log.GetLogLevel ()) - return; + if (!CheckLogLevel (level)) return; // fold message to single string std::stringstream ss; @@ -200,7 +203,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept auto msg = std::make_shared(level, std::time(nullptr), std::move(ss).str()); msg->tid = std::this_thread::get_id(); - log.Append(msg); + i2p::log::Logger().Append(msg); } /** From 592d6ae4f47c7f1647e3b61862d28674fac882ad Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:56:25 -0500 Subject: [PATCH 220/264] check log level before calculating base32 or base64 of ident --- libi2pd/NetDb.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f3822997..026ae53e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -262,10 +262,12 @@ namespace data return nullptr; } } - LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated { - LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); std::lock_guard l(m_FloodfillsMutex); if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); @@ -280,7 +282,8 @@ namespace data } else { - LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); updated = false; } } @@ -297,7 +300,8 @@ namespace data } if (inserted) { - LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || @@ -338,10 +342,11 @@ namespace data if(it->second->GetExpirationTime() < expires) { it->second->Update (buf, len, false); // signature is verified already - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } - else + else if (CheckLogLevel (eLogDebug)) LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else @@ -352,7 +357,8 @@ namespace data auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { - LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); m_LeaseSets[ident] = leaseSet; updated = true; } @@ -376,7 +382,8 @@ namespace data i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ()) { // TODO: implement actual update - LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); m_LeaseSets[ident] = leaseSet; return true; } @@ -863,19 +870,22 @@ namespace data { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 { - LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32()); updated = AddLeaseSet (ident, buf + offset, len - offset); } else // all others are considered as LeaseSet2 { - LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", int(storeType), " for ", ident.ToBase32()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", int(storeType), " for ", ident.ToBase32()); updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType); } } } else // RouterInfo { - LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); size_t size = bufbe16toh (buf + offset); offset += 2; if (size > MAX_RI_BUFFER_SIZE || size > len - offset) From d96803a2909a966bad9cc0599a46191c982dce84 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Feb 2024 15:24:48 -0500 Subject: [PATCH 221/264] always request through tunnels in case of restricted routes --- libi2pd/NetDb.cpp | 1 + libi2pd/Transports.cpp | 25 ++++++++++++++++--------- libi2pd/Transports.h | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 026ae53e..e8c92658 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -730,6 +730,7 @@ namespace data void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { + if (direct && i2p::transport::transports.RoutesRestricted ()) direct = false; // always use tunnels for restricted routes auto dest = m_Requests.CreateRequest (destination, false, direct, requestComplete); // non-exploratory if (!dest) { diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index a70e77b4..0afe47a1 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1015,18 +1015,25 @@ namespace transport } } - void Transports::RestrictRoutesToRouters(std::set routers) + void Transports::RestrictRoutesToRouters(const std::set& routers) { - std::unique_lock lock(m_TrustedRoutersMutex); + std::lock_guard lock(m_TrustedRoutersMutex); m_TrustedRouters.clear(); for (const auto & ri : routers ) m_TrustedRouters.push_back(ri); } - bool Transports::RoutesRestricted() const { - std::unique_lock famlock(m_FamilyMutex); - std::unique_lock routerslock(m_TrustedRoutersMutex); - return m_TrustedFamilies.size() > 0 || m_TrustedRouters.size() > 0; + bool Transports::RoutesRestricted() const + { + { + std::lock_guard routerslock(m_TrustedRoutersMutex); + if (!m_TrustedRouters.empty ()) return true; + } + { + std::lock_guard famlock(m_FamilyMutex); + if (!m_TrustedFamilies.empty ()) return true; + } + return false; } /** XXX: if routes are not restricted this dies */ @@ -1050,7 +1057,7 @@ namespace transport return i2p::data::netdb.GetRandomRouterInFamily(fam); } { - std::unique_lock l(m_TrustedRoutersMutex); + std::lock_guard l(m_TrustedRoutersMutex); auto sz = m_TrustedRouters.size(); if (sz) { @@ -1067,12 +1074,12 @@ namespace transport bool Transports::IsRestrictedPeer(const i2p::data::IdentHash & ih) const { { - std::unique_lock l(m_TrustedRoutersMutex); + std::lock_guard l(m_TrustedRoutersMutex); for (const auto & r : m_TrustedRouters ) if ( r == ih ) return true; } { - std::unique_lock l(m_FamilyMutex); + std::lock_guard l(m_FamilyMutex); auto ri = i2p::data::netdb.FindRouter(ih); for (const auto & fam : m_TrustedFamilies) if(ri->IsFamily(fam)) return true; diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 540bafb4..206b0256 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -165,7 +165,7 @@ namespace transport /** restrict routes to use only these router families for first hops */ void RestrictRoutesToFamilies(const std::set& families); /** restrict routes to use only these routers for first hops */ - void RestrictRoutesToRouters(std::set routers); + void RestrictRoutesToRouters(const std::set& routers); bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; From 36dbc15bca1a41f7f764a15e2c272394aa06154d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Feb 2024 18:08:51 -0500 Subject: [PATCH 222/264] keep SSU2 socket open even if failed to bind --- libi2pd/SSU2.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 0ebeab6d..3e0583ea 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -258,13 +258,22 @@ namespace transport socket.set_option (boost::asio::ip::v6_only (true)); socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU2_SOCKET_RECEIVE_BUFFER_SIZE)); socket.set_option (boost::asio::socket_base::send_buffer_size (SSU2_SOCKET_SEND_BUFFER_SIZE)); + } + catch (std::exception& ex ) + { + LogPrint (eLogCritical, "SSU2: Failed to open socket on ", localEndpoint.address (), ": ", ex.what()); + ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint.address (), ": ", ex.what ()); + return socket; + } + try + { socket.bind (localEndpoint); LogPrint (eLogInfo, "SSU2: Start listening on ", localEndpoint); } catch (std::exception& ex ) { - LogPrint (eLogCritical, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what()); - ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint, ": ", ex.what ()); + LogPrint (eLogWarning, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what(), ". Actual endpoint is ", socket.local_endpoint ()); + // we can continue without binding being firewalled } return socket; } From adba3987f84f67f6ab8b2be8762f51ff29154a71 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 10 Feb 2024 17:10:21 +0200 Subject: [PATCH 223/264] logging fixes --- libi2pd/NTCP2.cpp | 2 +- libi2pd/RouterInfo.cpp | 2 +- libi2pd/SSU2Session.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0dbccbca..19609b0b 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -381,7 +381,7 @@ namespace transport if (remoteIdentity) { LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), - " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); } else { diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7cde7c33..a034691a 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -131,7 +131,7 @@ namespace data m_BufferLen = s.tellg (); if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) { - LogPrint(eLogError, "RouterInfo: File", fullPath, " is malformed"); + LogPrint(eLogError, "RouterInfo: File ", fullPath, " is malformed"); return false; } s.seekg(0, std::ios::beg); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 12671f4f..4015dcac 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -277,7 +277,7 @@ namespace transport if (remoteIdentity) { LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), - " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); } else { From 158160f5c0256bd91bb68c5550d5fe97150dcda2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Feb 2024 20:03:36 -0500 Subject: [PATCH 224/264] common code for SOCKS5 proxy connectivity --- libi2pd/NTCP2.cpp | 119 ++++------------------------ libi2pd/NTCP2.h | 3 +- libi2pd/SSU2.h | 1 + libi2pd/Socks5.h | 154 +++++++++++++++++++++++++++++++++++++ libi2pd/TransportSession.h | 11 +-- 5 files changed, 170 insertions(+), 118 deletions(-) create mode 100644 libi2pd/Socks5.h diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 19609b0b..58a1c539 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -19,9 +19,10 @@ #include "RouterContext.h" #include "Transports.h" #include "NetDb.hpp" -#include "NTCP2.h" #include "HTTP.h" #include "util.h" +#include "Socks5.h" +#include "NTCP2.h" #if defined(__linux__) && !defined(_NETINET_IN_H) #include @@ -1728,47 +1729,18 @@ namespace transport case eSocksProxy: { // TODO: support username/password auth etc - static const uint8_t buff[3] = {SOCKS5_VER, 0x01, 0x00}; - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), - [] (const boost::system::error_code & ec, std::size_t transferred) - { - (void) transferred; - if(ec) - { - LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message()); - } - }); - auto readbuff = std::make_shared >(2); - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), - [this, readbuff, timer, conn](const boost::system::error_code & ec, std::size_t transferred) - { - if(ec) - { - LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - return; - } - else if(transferred == 2) - { - if((*readbuff)[1] == 0x00) - { - AfterSocksHandshake(conn, timer); - return; - } - else if ((*readbuff)[1] == 0xff) - { - LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication"); - timer->cancel(); - conn->Terminate(); - return; - } - LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]); - } - LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response"); + Socks5Handshake (conn->GetSocket(), conn->GetRemoteEndpoint (), + [conn, timer](const boost::system::error_code& ec) + { timer->cancel(); - conn->Terminate(); - }); + if (!ec) + conn->ClientLogin(); + else + { + LogPrint(eLogError, "NTCP2: SOCKS proxy handshake error ", ec.message()); + conn->Terminate(); + } + }); break; } case eHTTPProxy: @@ -1836,71 +1808,6 @@ namespace transport } } - void NTCP2Server::AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer) - { - // build request - size_t sz = 6; // header + port - auto buff = std::make_shared >(256); - auto readbuff = std::make_shared >(256); - (*buff)[0] = SOCKS5_VER; - (*buff)[1] = SOCKS5_CMD_CONNECT; - (*buff)[2] = 0x00; - - auto& ep = conn->GetRemoteEndpoint (); - if(ep.address ().is_v4 ()) - { - (*buff)[3] = SOCKS5_ATYP_IPV4; - auto addrbytes = ep.address ().to_v4().to_bytes(); - sz += 4; - memcpy(buff->data () + 4, addrbytes.data(), 4); - } - else if (ep.address ().is_v6 ()) - { - (*buff)[3] = SOCKS5_ATYP_IPV6; - auto addrbytes = ep.address ().to_v6().to_bytes(); - sz += 16; - memcpy(buff->data () + 4, addrbytes.data(), 16); - } - else - { - // We mustn't really fall here because all connections are made to IP addresses - LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy"); - return; - } - htobe16buf(buff->data () + sz - 2, ep.port ()); - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(), - [buff](const boost::system::error_code & ec, std::size_t written) - { - if(ec) - { - LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message()); - return; - } - }); - - 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, 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); - 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(); - conn->ClientLogin(); - return; - } - else - LogPrint(eLogError, "NTCP2: Proxy reply error ", (int)(*readbuff)[1]); - timer->cancel(); - conn->Terminate(); - }); - } - void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) { auto addr = std::make_shared(boost::asio::ip::tcp::endpoint(localAddress, 0)); diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 1eac23f0..a566b38d 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -267,8 +267,7 @@ namespace transport void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); - void AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer); - + // timer void ScheduleTermination (); void HandleTerminationTimer (const boost::system::error_code& ecode); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index da682746..da5ca317 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -13,6 +13,7 @@ #include #include "util.h" #include "SSU2Session.h" +#include "Socks5.h" namespace i2p { diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h new file mode 100644 index 00000000..84a23997 --- /dev/null +++ b/libi2pd/Socks5.h @@ -0,0 +1,154 @@ +/* +* Copyright (c) 2024, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#ifndef SOCKS5_H__ +#define SOCKS5_H__ + +#include +#include +#include +#include "I2PEndian.h" + +namespace i2p +{ +namespace transport +{ + // SOCKS5 constants + const uint8_t SOCKS5_VER = 0x05; + const uint8_t SOCKS5_CMD_CONNECT = 0x01; + const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03; + const uint8_t SOCKS5_ATYP_IPV4 = 0x01; + const uint8_t SOCKS5_ATYP_IPV6 = 0x04; + const uint8_t SOCKS5_ATYP_NAME = 0x03; + const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; + const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; + + // SOCKS5 handshake + template + void Socks5Connect (Socket& s, Handler handler, std::shared_ptr > buff, uint16_t port) + { + if (buff && buff->size () >= 6) + { + (*buff)[0] = SOCKS5_VER; + (*buff)[1] = SOCKS5_CMD_CONNECT; + (*buff)[2] = 0x00; + htobe16buf(buff->data () + buff->size () - 2, port); + boost::asio::async_write(s, boost::asio::buffer(*buff), boost::asio::transfer_all(), + [buff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + (void) transferred; + if (!ec) + { + auto readbuff = std::make_shared >(262); // max possible + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if (!(*readbuff)[1]) // succeeded + { + boost::system::error_code ec; + size_t moreBytes = s.available(ec); + if (!ec && moreBytes) // read remaining portion of reply + boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); + if (!ec) + handler (boost::system::error_code ()); + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); + } + else + handler (ec); + }); + } + else + handler (ec); + }); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::no_buffer_space)); + } + + template + void Socks5Connect (Socket& s, const boost::asio::ip::tcp::endpoint& ep, Handler handler) + { + std::shared_ptr > buff; + if(ep.address ().is_v4 ()) + { + buff = std::make_shared >(10); + (*buff)[3] = SOCKS5_ATYP_IPV4; + auto addrbytes = ep.address ().to_v4().to_bytes(); + memcpy(buff->data () + 4, addrbytes.data(), 4); + } + else if (ep.address ().is_v6 ()) + { + buff = std::make_shared >(22); + (*buff)[3] = SOCKS5_ATYP_IPV6; + auto addrbytes = ep.address ().to_v6().to_bytes(); + memcpy(buff->data () + 4, addrbytes.data(), 16); + } + if (buff) + Socks5Connect (s, handler, buff, ep.port ()); + else + handler (boost::asio::error::make_error_code (boost::asio::error::fault)); + } + + template + void Socks5Connect (Socket& s, const std::pair& ep, Handler handler) + { + auto& addr = ep.first; + if (addr.length () <= 255) + { + auto buff = std::make_shared >(addr.length () + 7); + (*buff)[3] = SOCKS5_ATYP_NAME; + (*buff)[4] = addr.length (); + memcpy (buff->data () + 5, addr.c_str (), addr.length ()); + Socks5Connect (s, handler, buff, ep.second); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::name_too_long)); + } + + + template + void Socks5Handshake (Socket& s, Endpoint ep, Handler handler) + { + static const uint8_t methodSelection[3] = { SOCKS5_VER, 0x01, 0x00 }; // 1 method, no auth + boost::asio::async_write(s, boost::asio::buffer(methodSelection, 3), boost::asio::transfer_all(), + [&s, ep, handler] (const boost::system::error_code& ec, std::size_t transferred) + { + (void) transferred; + if (!ec) + { + auto readbuff = std::make_shared >(2); + boost::asio::async_read(s, boost::asio::buffer(*readbuff), boost::asio::transfer_all(), + [&s, ep, handler, readbuff] (const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if (transferred == 2 && (*readbuff)[1] == 0x00) // no auth + Socks5Connect (s, ep, handler); + else + handler (boost::asio::error::make_error_code (boost::asio::error::invalid_argument)); + } + else + handler (ec); + }); + } + else + handler (ec); + }); + } + +} +} + +#endif diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index f4668116..c6bf0de3 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -187,15 +187,6 @@ namespace transport uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp; uint32_t m_InBandwidth, m_OutBandwidth; }; - - // SOCKS5 proxy - const uint8_t SOCKS5_VER = 0x05; - const uint8_t SOCKS5_CMD_CONNECT = 0x01; - const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03; - const uint8_t SOCKS5_ATYP_IPV4 = 0x01; - const uint8_t SOCKS5_ATYP_IPV6 = 0x04; - const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; - const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; } } From 0ae7931a6f4d0299f64f95bea8249b8d6fd7b17d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 11:23:37 -0500 Subject: [PATCH 225/264] replaced SOCKS4 outproxy by SOCKS5 --- libi2pd_client/HTTPProxy.cpp | 71 ++++++++++-------------------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index a0fc8f07..5f9ee1de 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -29,6 +29,7 @@ #include "Config.h" #include "HTTP.h" #include "I18N.h" +#include "Socks5.h" namespace i2p { namespace proxy { @@ -93,9 +94,6 @@ namespace proxy { void HTTPConnect(const std::string & host, uint16_t port); void HandleHTTPConnectStreamRequestComplete(std::shared_ptr stream); - void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered); - void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered); - typedef std::function ProxyResolvedHandler; void HandleUpstreamProxyResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr, ProxyResolvedHandler handler); @@ -612,43 +610,30 @@ namespace proxy { void HTTPReqHandler::HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec) { - if(!ec) { - if(m_RequestURL.host.size() > 255) { + if(!ec) + { + if(m_RequestURL.host.size() > 255) + { GenericProxyError(tr("Hostname is too long"), m_RequestURL.host); return; } uint16_t port = m_RequestURL.port; if(!port) port = 80; LogPrint(eLogDebug, "HTTPProxy: Connected to SOCKS upstream"); - std::string host = m_RequestURL.host; - std::size_t reqsize = 0; - m_socks_buf[0] = '\x04'; - m_socks_buf[1] = 1; - htobe16buf(m_socks_buf+2, port); - m_socks_buf[4] = 0; - m_socks_buf[5] = 0; - m_socks_buf[6] = 0; - m_socks_buf[7] = 1; - // user id - m_socks_buf[8] = 'i'; - m_socks_buf[9] = '2'; - m_socks_buf[10] = 'p'; - m_socks_buf[11] = 'd'; - m_socks_buf[12] = 0; - reqsize += 13; - memcpy(m_socks_buf+ reqsize, host.c_str(), host.size()); - reqsize += host.size(); - m_socks_buf[++reqsize] = 0; - boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2)); - } else GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message()); - } - - void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred) - { - LogPrint(eLogDebug, "HTTPProxy: Upstream SOCKS handshake sent"); - if(ec) GenericProxyError(tr("Cannot negotiate with SOCKS proxy"), ec.message()); - else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2)); + auto s = shared_from_this (); + i2p::transport::Socks5Handshake (*m_proxysock, std::make_pair(host, port), + [s](const boost::system::error_code& ec) + { + if (!ec) + s->SocksProxySuccess(); + else + s->GenericProxyError(tr("SOCKS proxy error"), ec.message ()); + }); + + } + else + GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message()); } void HTTPReqHandler::HandoverToUpstreamProxy() @@ -714,24 +699,6 @@ namespace proxy { } } - void HTTPReqHandler::HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transferred) - { - if(!ec) - { - if(m_socks_buf[1] == 90) { - // success - SocksProxySuccess(); - } else { - std::stringstream ss; - ss << "error code: "; - ss << (int) m_socks_buf[1]; - std::string msg = ss.str(); - GenericProxyError(tr("SOCKS proxy error"), msg); - } - } - else GenericProxyError(tr("No reply from SOCKS proxy"), ec.message()); - } - void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec) { if(!ec) { From b07530a8a17f49745fbee0b6df6ddd6644779796 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 11:44:15 -0500 Subject: [PATCH 226/264] don't print error message if operation cancelled --- libi2pd_client/I2PService.cpp | 88 ++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index c30b7c9f..9b0b8028 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -240,54 +240,68 @@ namespace client void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Downstream read error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Downstream read error:" , ecode.message()); Terminate(); - } else { - if (bytes_transfered > 0 ) - memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); - UpstreamWrite(bytes_transfered); - } + } + else + { + if (bytes_transfered > 0 ) + memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); + UpstreamWrite(bytes_transfered); + } + } } - void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Downstream write error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Downstream write error:" , ecode.message()); Terminate(); - } - else - AsyncReceiveUpstream(); + } + else + AsyncReceiveUpstream(); + } } - void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Upstream write error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Upstream write error:" , ecode.message()); Terminate(); - } - else - AsyncReceiveDownstream(); + } + else + AsyncReceiveDownstream(); + } } void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Upstream read error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Upstream read error:" , ecode.message()); Terminate(); - } else { - if (bytes_transfered > 0 ) - memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); - DownstreamWrite(bytes_transfered); - } + } + else + { + if (bytes_transfered > 0 ) + memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); + DownstreamWrite(bytes_transfered); + } + } } void TCPIPAcceptor::Start () From 075f80aea23eab9b81c925c352291b73c4b34946 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 15:33:37 -0500 Subject: [PATCH 227/264] use SOCK5 proxy for upstream --- libi2pd_client/SOCKS.cpp | 121 ++++++--------------------------------- 1 file changed, 18 insertions(+), 103 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 547a2da2..49a04b81 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,6 +19,7 @@ #include "I2PTunnel.h" #include "I2PService.h" #include "util.h" +#include "Socks5.h" namespace i2p { @@ -27,10 +28,6 @@ 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_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; - struct SOCKSDnsAddress { uint8_t size; @@ -132,7 +129,6 @@ namespace proxy boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method); boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port); boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); - boost::asio::const_buffers_1 GenerateUpstreamRequest(); bool Socks5ChooseAuth(); void Socks5UserPasswdResponse (); void SocksRequestFailed(errTypes error); @@ -146,9 +142,6 @@ namespace proxy void SocksUpstreamSuccess(); void AsyncUpstreamSockRead(); void SendUpstreamRequest(); - void HandleUpstreamData(uint8_t * buff, std::size_t len); - void HandleUpstreamSockSend(const boost::system::error_code & ecode, std::size_t bytes_transfered); - void HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, @@ -161,9 +154,6 @@ namespace proxy uint8_t *m_remaining_data; //Data left to be sent uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded uint8_t m_response[7+max_socks_hostname_size]; - uint8_t m_upstream_response[SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE]; - uint8_t m_upstream_request[14+max_socks_hostname_size]; - std::size_t m_upstream_response_len; address m_address; //Address std::size_t m_remaining_data_len; //Size of the data left to be sent uint32_t m_4aip; //Used in 4a requests @@ -280,37 +270,6 @@ namespace proxy return boost::asio::const_buffers_1(m_response, size); } - boost::asio::const_buffers_1 SOCKSHandler::GenerateUpstreamRequest() - { - size_t upstreamRequestSize = 0; - // TODO: negotiate with upstream - // SOCKS 4a - m_upstream_request[0] = '\x04'; //version - m_upstream_request[1] = m_cmd; - htobe16buf(m_upstream_request + 2, m_port); - m_upstream_request[4] = 0; - m_upstream_request[5] = 0; - m_upstream_request[6] = 0; - m_upstream_request[7] = 1; - // user id - m_upstream_request[8] = 'i'; - m_upstream_request[9] = '2'; - m_upstream_request[10] = 'p'; - m_upstream_request[11] = 'd'; - m_upstream_request[12] = 0; - upstreamRequestSize += 13; - if (m_address.dns.size <= max_socks_hostname_size - ( upstreamRequestSize + 1) ) { - // bounds check okay - memcpy(m_upstream_request + upstreamRequestSize, m_address.dns.value, m_address.dns.size); - upstreamRequestSize += m_address.dns.size; - // null terminate - m_upstream_request[++upstreamRequestSize] = 0; - } else { - LogPrint(eLogError, "SOCKS: BUG!!! m_addr.dns.sizs > max_socks_hostname - ( upstreamRequestSize + 1 ) )"); - } - return boost::asio::const_buffers_1(m_upstream_request, upstreamRequestSize); - } - bool SOCKSHandler::Socks5ChooseAuth() { m_response[0] = '\x05'; // Version @@ -724,32 +683,6 @@ namespace proxy std::placeholders::_1, std::placeholders::_2)); } - void SOCKSHandler::AsyncUpstreamSockRead() - { - LogPrint(eLogDebug, "SOCKS: Async upstream sock read"); - if (m_upstreamSock) { - m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE), - std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); - } else { - LogPrint(eLogError, "SOCKS: No upstream socket for read"); - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } - - void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode) { - if (m_state == UPSTREAM_HANDSHAKE ) { - // we are trying to handshake but it failed - SocksRequestFailed(SOCKS5_NET_UNREACH); - } else { - LogPrint(eLogError, "SOCKS: Bad state when reading from upstream: ", (int) m_state); - } - return; - } - HandleUpstreamData(m_upstream_response, bytes_transfered); - } - void SOCKSHandler::SocksUpstreamSuccess() { LogPrint(eLogInfo, "SOCKS: Upstream success"); @@ -776,46 +709,28 @@ namespace proxy } - void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len) - { - if (m_state == UPSTREAM_HANDSHAKE) { - m_upstream_response_len += len; - // handle handshake data - if (m_upstream_response_len < SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { - // too small, continue reading - AsyncUpstreamSockRead(); - } else if (len == SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { - // just right - uint8_t resp = m_upstream_response[1]; - if (resp == SOCKS4_OK) { - // we have connected ! - SocksUpstreamSuccess(); - } else { - // upstream failure - LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", (int) resp); - // TODO: runtime error? - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } else { - // too big - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } else { - // invalid state - LogPrint(eLogError, "SOCKS: Invalid state reading from upstream: ", (int) m_state); - } - } void SOCKSHandler::SendUpstreamRequest() { LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy"); EnterState(UPSTREAM_HANDSHAKE); - if (m_upstreamSock) { - boost::asio::write(*m_upstreamSock, GenerateUpstreamRequest()); - AsyncUpstreamSockRead(); - } else { + if (m_upstreamSock) + { + auto s = shared_from_this (); + i2p::transport::Socks5Handshake (*m_upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), + [s](const boost::system::error_code& ec) + { + if (!ec) + s->SocksUpstreamSuccess(); + else + { + s->SocksRequestFailed(SOCKS5_NET_UNREACH); + LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", ec.message ()); + } + }); + } + else LogPrint(eLogError, "SOCKS: No upstream socket to send handshake to"); - } } void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) From d9b6262a6e903507697f323926ba9c5f321a234a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 12:10:29 -0500 Subject: [PATCH 228/264] removed unused field --- libi2pd_client/HTTPProxy.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 5f9ee1de..8f9f8ada 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -111,7 +111,6 @@ namespace proxy { bool m_Addresshelper; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; - uint8_t m_socks_buf[255+8]; // for socks request/response int m_req_len; i2p::http::URL m_ClientRequestURL; i2p::http::HTTPReq m_ClientRequest; From 7691a5b4a92acd72cb2b676bf921928f978cdf3b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 13:22:26 -0500 Subject: [PATCH 229/264] use common SOCK5 code for reseed --- libi2pd/Reseed.cpp | 66 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 5fdc2fae..f8307a56 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -26,6 +26,7 @@ #include "HTTP.h" #include "util.h" #include "Config.h" +#include "Socks5.h" namespace i2p { @@ -615,62 +616,21 @@ namespace data { // assume socks if not http, is checked before this for other types // TODO: support username/password auth etc - uint8_t hs_writebuf[3] = {0x05, 0x01, 0x00}; - uint8_t hs_readbuf[2]; - boost::asio::write(sock, boost::asio::buffer(hs_writebuf, 3), boost::asio::transfer_all(), ecode); - if(ecode) + bool success = false; + i2p::transport::Socks5Handshake (sock, std::make_pair(url.host, url.port), + [&success](const boost::system::error_code& ec) + { + if (!ec) + success = true; + else + LogPrint (eLogError, "Reseed: SOCKS handshake failed: ", ec.message()); + }); + service.run (); // execute all async operations + if (!success) { sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake write failed: ", ecode.message()); return ""; - } - boost::asio::read(sock, boost::asio::buffer(hs_readbuf, 2), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake read failed: ", ecode.message()); - return ""; - } - size_t sz = 0; - uint8_t buf[256]; - - buf[0] = 0x05; - buf[1] = 0x01; - buf[2] = 0x00; - buf[3] = 0x03; - sz += 4; - size_t hostsz = url.host.size(); - if(1 + 2 + hostsz + sz > sizeof(buf)) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed, hostname too big: ", url.host); - return ""; - } - buf[4] = (uint8_t) hostsz; - memcpy(buf+5, url.host.c_str(), hostsz); - sz += hostsz + 1; - htobe16buf(buf+sz, url.port); - sz += 2; - boost::asio::write(sock, boost::asio::buffer(buf, sz), boost::asio::transfer_all(), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed writing: ", ecode.message()); - return ""; - } - boost::asio::read(sock, boost::asio::buffer(buf, 10), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed reading: ", ecode.message()); - return ""; - } - if(buf[1] != 0x00) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake bad reply code: ", std::to_string(buf[1])); - return ""; - } + } } } } From 967627e58a3730d143aa0b15693a54bb93f0d0e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 21:55:30 -0500 Subject: [PATCH 230/264] read correct reply length and handle reply codes --- libi2pd/Socks5.h | 106 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h index 84a23997..d611bff3 100644 --- a/libi2pd/Socks5.h +++ b/libi2pd/Socks5.h @@ -29,7 +29,87 @@ namespace transport const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; + const uint8_t SOCKS5_REPLY_SUCCESS = 0x00; + const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01; + const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02; + const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03; + const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04; + const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05; + const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06; + const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07; + const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; + // SOCKS5 handshake + template + void Socks5ReadReply (Socket& s, Handler handler) + { + auto readbuff = std::make_shared >(258); // max possible + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS) + { + size_t len = 0; + switch ((*readbuff)[3]) // ATYP + { + case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes + case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes + case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length + default: ; + } + if (len) + { + len += 2; // port + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + handler (boost::system::error_code ()); // success + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + }); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type + } + else + switch ((*readbuff)[1]) // REP + { + case SOCKS5_REPLY_SERVER_FAILURE: + handler (boost::asio::error::make_error_code (boost::asio::error::access_denied )); + break; + case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_permission)); + break; + case SOCKS5_REPLY_HOST_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable)); + break; + case SOCKS5_REPLY_NETWORK_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable)); + break; + case SOCKS5_REPLY_CONNECTION_REFUSED: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); + break; + case SOCKS5_REPLY_TTL_EXPIRED: + handler (boost::asio::error::make_error_code (boost::asio::error::timed_out)); + break; + case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported)); + break; + case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option)); + break; + default: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + } + } + else + handler (ec); + }); + } + template void Socks5Connect (Socket& s, Handler handler, std::shared_ptr > buff, uint16_t port) { @@ -44,31 +124,7 @@ namespace transport { (void) transferred; if (!ec) - { - auto readbuff = std::make_shared >(262); // max possible - boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size - [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) - { - if (!ec) - { - if (!(*readbuff)[1]) // succeeded - { - boost::system::error_code ec; - size_t moreBytes = s.available(ec); - if (!ec && moreBytes) // read remaining portion of reply - boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); - if (!ec) - handler (boost::system::error_code ()); - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); - } - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); - } - else - handler (ec); - }); - } + Socks5ReadReply (s, handler); else handler (ec); }); From a9ad6fc31e3b733d285dcdad61dfa42bc262c13c Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Feb 2024 18:52:18 -0500 Subject: [PATCH 231/264] renamed TCPIPPipe to SocketsPipe --- libi2pd_client/HTTPProxy.cpp | 2 +- libi2pd_client/I2PService.cpp | 52 +++++++++++++++++------------------ libi2pd_client/I2PService.h | 28 ++++++++++++------- libi2pd_client/SOCKS.cpp | 3 +- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 8f9f8ada..01678f4a 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -638,7 +638,7 @@ namespace proxy { void HTTPReqHandler::HandoverToUpstreamProxy() { LogPrint(eLogDebug, "HTTPProxy: Handover to SOCKS proxy"); - auto connection = std::make_shared(GetOwner(), m_proxysock, m_sock); + auto connection = CreateSocketsPipe (GetOwner(), m_proxysock, m_sock); m_sock = nullptr; m_proxysock = nullptr; GetOwner()->AddHandler(connection); diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 9b0b8028..27e34b69 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -148,25 +148,25 @@ namespace client } } - TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) + SocketsPipe::SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) { - boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE); + boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); upstream->set_option(option); downstream->set_option(option); } - TCPIPPipe::~TCPIPPipe() + SocketsPipe::~SocketsPipe() { Terminate(); } - void TCPIPPipe::Start() + void SocketsPipe::Start() { AsyncReceiveUpstream(); AsyncReceiveDownstream(); } - void TCPIPPipe::Terminate() + void SocketsPipe::Terminate() { if(Kill()) return; if (m_up) @@ -184,52 +184,52 @@ namespace client Done(shared_from_this()); } - void TCPIPPipe::AsyncReceiveUpstream() + void SocketsPipe::AsyncReceiveUpstream() { if (m_up) { - m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), + m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE), + std::bind(&SocketsPipe::HandleUpstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else - LogPrint(eLogError, "TCPIPPipe: Upstream receive: No socket"); + LogPrint(eLogError, "SocketsPipe: Upstream receive: No socket"); } - void TCPIPPipe::AsyncReceiveDownstream() + void SocketsPipe::AsyncReceiveDownstream() { if (m_down) { - m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), + m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE), + std::bind(&SocketsPipe::HandleDownstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else - LogPrint(eLogError, "TCPIPPipe: Downstream receive: No socket"); + LogPrint(eLogError, "SocketsPipe: Downstream receive: No socket"); } - void TCPIPPipe::UpstreamWrite(size_t len) + void SocketsPipe::UpstreamWrite(size_t len) { if (m_up) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream: ", (int) len, " bytes written"); + LogPrint(eLogDebug, "SocketsPipe: Upstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleUpstreamWrite, + std::bind(&SocketsPipe::HandleUpstreamWrite, shared_from_this(), std::placeholders::_1)); } else - LogPrint(eLogError, "TCPIPPipe: Upstream write: no socket"); + LogPrint(eLogError, "SocketsPipe: Upstream write: no socket"); } - void TCPIPPipe::DownstreamWrite(size_t len) + void SocketsPipe::DownstreamWrite(size_t len) { if (m_down) { LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleDownstreamWrite, + std::bind(&SocketsPipe::HandleDownstreamWrite, shared_from_this(), std::placeholders::_1)); } @@ -238,7 +238,7 @@ namespace client } - void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) + void SocketsPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode != boost::asio::error::operation_aborted) { @@ -257,7 +257,7 @@ namespace client } } - void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) + void SocketsPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { if (ecode != boost::asio::error::operation_aborted) { @@ -271,13 +271,13 @@ namespace client } } - void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) + void SocketsPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { if (ecode != boost::asio::error::operation_aborted) { if (ecode) { - LogPrint(eLogWarning, "TCPIPPipe: Upstream write error:" , ecode.message()); + LogPrint(eLogWarning, "SocketsPipe: Upstream write error:" , ecode.message()); Terminate(); } else @@ -285,14 +285,14 @@ namespace client } } - void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) + void SocketsPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode != boost::asio::error::operation_aborted) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); + LogPrint(eLogDebug, "SocketsPipe: Upstream ", (int)bytes_transfered, " bytes received"); if (ecode) { - LogPrint(eLogWarning, "TCPIPPipe: Upstream read error:" , ecode.message()); + LogPrint(eLogWarning, "SocketsPipe: Upstream read error:" , ecode.message()); Terminate(); } else diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 4f67e19c..4be7f2ca 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -99,6 +99,7 @@ namespace client virtual ~I2PServiceHandler() { } //If you override this make sure you call it from the children virtual void Handle() {}; //Start handling the socket + virtual void Start () {}; void Terminate () { Kill (); }; @@ -119,16 +120,16 @@ namespace client std::atomic m_Dead; //To avoid cleaning up multiple times }; - const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8; + const size_t SOCKETS_PIPE_BUFFER_SIZE = 8192 * 8; - // bidirectional pipe for 2 tcp/ip sockets - class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this + // bidirectional pipe for 2 stream sockets + class SocketsPipe: public I2PServiceHandler, public std::enable_shared_from_this { public: - TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); - ~TCPIPPipe(); - void Start(); + SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); + ~SocketsPipe(); + void Start() override; protected: @@ -144,11 +145,18 @@ namespace client private: - uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; - uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; - std::shared_ptr m_up, m_down; + uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; + uint8_t m_upstream_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_buf[SOCKETS_PIPE_BUFFER_SIZE]; + std::shared_ptr m_up; + std::shared_ptr m_down; }; + template + std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) + { + return std::make_shared(owner, upstream, downstream); + } + /* TODO: support IPv6 too */ //This is a service that listens for connections on the IP network and interacts with I2P class TCPIPAcceptor: public I2PService diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 49a04b81..65bad1cf 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -700,13 +700,12 @@ namespace proxy break; } m_sock->send(response); - auto forwarder = std::make_shared(GetOwner(), m_sock, m_upstreamSock); + auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, m_upstreamSock); m_upstreamSock = nullptr; m_sock = nullptr; GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); - } From 710b27688ba03dc580839fb7b4270ecfd4943014 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 15:35:47 -0500 Subject: [PATCH 232/264] generic SocketsPipe for different socket types --- libi2pd_client/I2PService.cpp | 156 ---------------------------------- libi2pd_client/I2PService.h | 99 ++++++++++++++++----- 2 files changed, 76 insertions(+), 179 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 27e34b69..5604f950 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -148,162 +148,6 @@ namespace client } } - SocketsPipe::SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) - { - boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); - upstream->set_option(option); - downstream->set_option(option); - } - - SocketsPipe::~SocketsPipe() - { - Terminate(); - } - - void SocketsPipe::Start() - { - AsyncReceiveUpstream(); - AsyncReceiveDownstream(); - } - - void SocketsPipe::Terminate() - { - if(Kill()) return; - if (m_up) - { - if (m_up->is_open()) - m_up->close(); - m_up = nullptr; - } - if (m_down) - { - if (m_down->is_open()) - m_down->close(); - m_down = nullptr; - } - Done(shared_from_this()); - } - - void SocketsPipe::AsyncReceiveUpstream() - { - if (m_up) - { - m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE), - std::bind(&SocketsPipe::HandleUpstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } - else - LogPrint(eLogError, "SocketsPipe: Upstream receive: No socket"); - } - - void SocketsPipe::AsyncReceiveDownstream() - { - if (m_down) { - m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE), - std::bind(&SocketsPipe::HandleDownstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } - else - LogPrint(eLogError, "SocketsPipe: Downstream receive: No socket"); - } - - void SocketsPipe::UpstreamWrite(size_t len) - { - if (m_up) - { - LogPrint(eLogDebug, "SocketsPipe: Upstream: ", (int) len, " bytes written"); - boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), - boost::asio::transfer_all(), - std::bind(&SocketsPipe::HandleUpstreamWrite, - shared_from_this(), - std::placeholders::_1)); - } - else - LogPrint(eLogError, "SocketsPipe: Upstream write: no socket"); - } - - void SocketsPipe::DownstreamWrite(size_t len) - { - if (m_down) - { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written"); - boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), - boost::asio::transfer_all(), - std::bind(&SocketsPipe::HandleDownstreamWrite, - shared_from_this(), - std::placeholders::_1)); - } - else - LogPrint(eLogError, "TCPIPPipe: Downstream write: No socket"); - } - - - void SocketsPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogWarning, "TCPIPPipe: Downstream read error:" , ecode.message()); - Terminate(); - } - else - { - if (bytes_transfered > 0 ) - memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); - UpstreamWrite(bytes_transfered); - } - } - } - - void SocketsPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - { - LogPrint(eLogWarning, "TCPIPPipe: Downstream write error:" , ecode.message()); - Terminate(); - } - else - AsyncReceiveUpstream(); - } - } - - void SocketsPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - { - LogPrint(eLogWarning, "SocketsPipe: Upstream write error:" , ecode.message()); - Terminate(); - } - else - AsyncReceiveDownstream(); - } - } - - void SocketsPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint(eLogDebug, "SocketsPipe: Upstream ", (int)bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogWarning, "SocketsPipe: Upstream read error:" , ecode.message()); - Terminate(); - } - else - { - if (bytes_transfered > 0 ) - memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); - DownstreamWrite(bytes_transfered); - } - } - } - void TCPIPAcceptor::Start () { m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 4be7f2ca..b8973f9d 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -123,38 +123,91 @@ namespace client const size_t SOCKETS_PIPE_BUFFER_SIZE = 8192 * 8; // bidirectional pipe for 2 stream sockets - class SocketsPipe: public I2PServiceHandler, public std::enable_shared_from_this + template + class SocketsPipe: public I2PServiceHandler, + public std::enable_shared_from_this > { public: - SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); - ~SocketsPipe(); - void Start() override; - - protected: - - void Terminate(); - void AsyncReceiveUpstream(); - void AsyncReceiveDownstream(); - void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleUpstreamWrite(const boost::system::error_code & ecode); - void HandleDownstreamWrite(const boost::system::error_code & ecode); - void UpstreamWrite(size_t len); - void DownstreamWrite(size_t len); + SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream): + I2PServiceHandler(owner), m_up(upstream), m_down(downstream) + { + boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); + upstream->set_option(option); + downstream->set_option(option); + } + ~SocketsPipe() { Terminate(); } + + void Start() override + { + Transfer (m_up, m_down, m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream + Transfer (m_down, m_up, m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream + } private: - uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; - uint8_t m_upstream_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_buf[SOCKETS_PIPE_BUFFER_SIZE]; - std::shared_ptr m_up; - std::shared_ptr m_down; + void Terminate() + { + if(Kill()) return; + if (m_up) + { + if (m_up->is_open()) + m_up->close(); + m_up = nullptr; + } + if (m_down) + { + if (m_down->is_open()) + m_down->close(); + m_down = nullptr; + } + Done(SocketsPipe::shared_from_this()); + } + + template + void Transfer (std::shared_ptr from, std::shared_ptr to, uint8_t * buf, size_t len) + { + if (!from || !to || !buf) return; + auto s = SocketsPipe::shared_from_this (); + from->async_read_some(boost::asio::buffer(buf, len), + [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred) + { + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + { + boost::asio::async_write(*to, boost::asio::buffer(buf, transferred), boost::asio::transfer_all(), + [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred) + { + (void) transferred; + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + s->Transfer (from, to, buf, len); + else + { + LogPrint(eLogWarning, "SocketsPipe: Write error:" , ecode.message()); + s->Terminate(); + } + }); + } + else + { + LogPrint(eLogWarning, "SocketsPipe: Read error:" , ecode.message()); + s->Terminate(); + } + }); + } + + private: + + uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; + std::shared_ptr m_up; + std::shared_ptr m_down; }; - template - std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) + template + std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) { - return std::make_shared(owner, upstream, downstream); + return std::make_shared >(owner, upstream, downstream); } /* TODO: support IPv6 too */ From 0e502c49b5c8274e8c2e6d8b1b226e1002ef02de Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 18:53:28 -0500 Subject: [PATCH 233/264] show correct tunnel status. restore tunnel if delivery status or data for inbound tunnel received --- daemon/HTTPServer.cpp | 18 +++++++----------- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelPool.cpp | 4 ++-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 2d6800b4..862d6e4a 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -133,23 +133,19 @@ namespace http { static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) { std::string state, stateText; - switch (eState) { + switch (eState) + { case i2p::tunnel::eTunnelStateBuildReplyReceived : case i2p::tunnel::eTunnelStatePending : state = "building"; break; - case i2p::tunnel::eTunnelStateBuildFailed : - case i2p::tunnel::eTunnelStateTestFailed : + case i2p::tunnel::eTunnelStateBuildFailed : state = "failed"; stateText = "declined"; break; + case i2p::tunnel::eTunnelStateTestFailed : state = "failed"; stateText = "test failed"; break; case i2p::tunnel::eTunnelStateFailed : state = "failed"; break; case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break; case i2p::tunnel::eTunnelStateEstablished : state = "established"; break; default: state = "unknown"; break; } - - if (state == "building") stateText = tr("building"); - else if (state == "failed") stateText = tr("failed"); - else if (state == "expiring") stateText = tr("expiring"); - else if (state == "established") stateText = tr("established"); - else stateText = tr("unknown"); - + if (stateText.empty ()) stateText = tr(state); + s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; ShowTraffic(s, bytes); s << "\r\n"; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index b578217f..d46da5b9 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -250,7 +250,7 @@ namespace tunnel void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr&& msg) { - if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive + if (GetState () != eTunnelStateExpiring) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive EncryptTunnelMsg (msg, msg); msg->from = GetSharedFromThis (); m_Endpoint.HandleDecryptedTunnelDataMsg (msg); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 93df99be..dc43a025 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -461,7 +461,7 @@ namespace tunnel // restore from test failed state if any if (test.first) { - if (test.first->GetState () == eTunnelStateTestFailed) + if (test.first->GetState () != eTunnelStateExpiring) test.first->SetState (eTunnelStateEstablished); // update latency uint64_t latency = 0; @@ -471,7 +471,7 @@ namespace tunnel } if (test.second) { - if (test.second->GetState () == eTunnelStateTestFailed) + if (test.second->GetState () != eTunnelStateExpiring) test.second->SetState (eTunnelStateEstablished); // update latency uint64_t latency = 0; From 56619caa71bdf306dbd480445d6e2835a5ec603d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 20:16:36 -0500 Subject: [PATCH 234/264] random shuffle of tunnels for peer test pairs --- libi2pd/TunnelPool.cpp | 56 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index dc43a025..2e306ba3 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -361,31 +361,43 @@ namespace tunnel // new tests std::vector, std::shared_ptr > > newTests; + std::random_device rd; + std::mt19937 rnd(rd()); + std::vector > outboundTunnels; { - std::unique_lock l1(m_OutboundTunnelsMutex); - auto it1 = m_OutboundTunnels.begin (); - std::unique_lock l2(m_InboundTunnelsMutex); - auto it2 = m_InboundTunnels.begin (); - while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) + std::unique_lock l(m_OutboundTunnelsMutex); + for (auto& it: m_OutboundTunnels) + outboundTunnels.push_back (it); + } + std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), rnd); + std::vector > inboundTunnels; + { + std::unique_lock l(m_InboundTunnelsMutex); + for (auto& it: m_InboundTunnels) + inboundTunnels.push_back (it); + } + std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), rnd); + auto it1 = outboundTunnels.begin (); + auto it2 = inboundTunnels.begin (); + while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) + { + bool failed = false; + if ((*it1)->IsFailed ()) { - bool failed = false; - if ((*it1)->IsFailed ()) - { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - newTests.push_back(std::make_pair (*it1, *it2)); - ++it1; ++it2; - } + failed = true; + ++it1; } - } + if ((*it2)->IsFailed ()) + { + failed = true; + ++it2; + } + if (!failed) + { + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; + } + } for (auto& it: newTests) { uint32_t msgID; From dddbca6ffbd316cb4195181e955a804d17dfd2ff Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 21:35:41 -0500 Subject: [PATCH 235/264] common rng for random shuffle --- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelPool.cpp | 9 +++------ libi2pd/TunnelPool.h | 6 ++++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index d46da5b9..ac0418d7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -52,7 +52,7 @@ namespace tunnel // shuffle records std::vector recordIndicies; for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i); - std::shuffle (recordIndicies.begin(), recordIndicies.end(), std::mt19937(std::random_device()())); + std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()())); // create real records uint8_t * records = msg->GetPayload () + 1; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 2e306ba3..550a75c5 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -7,7 +7,6 @@ */ #include -#include #include "I2PEndian.h" #include "Crypto.h" #include "Tunnel.h" @@ -45,7 +44,7 @@ namespace tunnel m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance), - m_IsActive (true), m_CustomPeerSelector(nullptr) + m_IsActive (true), m_CustomPeerSelector(nullptr), m_Rng(m_Rd()) { if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY; @@ -361,22 +360,20 @@ namespace tunnel // new tests std::vector, std::shared_ptr > > newTests; - std::random_device rd; - std::mt19937 rnd(rd()); std::vector > outboundTunnels; { std::unique_lock l(m_OutboundTunnelsMutex); for (auto& it: m_OutboundTunnels) outboundTunnels.push_back (it); } - std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), rnd); + std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), m_Rng); std::vector > inboundTunnels; { std::unique_lock l(m_InboundTunnelsMutex); for (auto& it: m_InboundTunnels) inboundTunnels.push_back (it); } - std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), rnd); + std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), m_Rng); auto it1 = outboundTunnels.begin (); auto it2 = inboundTunnels.begin (); while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 7cb1f5c9..3d3d4e33 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "Identity.h" #include "LeaseSet.h" #include "RouterInfo.h" @@ -115,6 +116,8 @@ namespace tunnel std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); + std::mt19937& GetRng () { return m_Rng; } + private: void TestTunnels (); @@ -148,6 +151,9 @@ namespace tunnel uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms + std::random_device m_Rd; + std::mt19937 m_Rng; + public: // for HTTP only From d8be5b8ce1876f28615e051b683c840481c1b00f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 21:58:03 -0500 Subject: [PATCH 236/264] fixed warning --- libi2pd/Socks5.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h index d611bff3..8db8939b 100644 --- a/libi2pd/Socks5.h +++ b/libi2pd/Socks5.h @@ -63,7 +63,7 @@ namespace transport { len += 2; // port boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), - [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + [readbuff, handler](const boost::system::error_code& ec, std::size_t transferred) { if (!ec) handler (boost::system::error_code ()); // success From def404b61aceaf02ff247392f56984430b90aa6b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 22:19:07 -0500 Subject: [PATCH 237/264] skip failed and expiring tunnels for peer tests --- libi2pd/TunnelPool.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 550a75c5..5b472232 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -364,36 +364,24 @@ namespace tunnel { std::unique_lock l(m_OutboundTunnelsMutex); for (auto& it: m_OutboundTunnels) - outboundTunnels.push_back (it); + if (it->IsEstablished () || it->GetState () == eTunnelStateTestFailed) + outboundTunnels.push_back (it); } std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), m_Rng); std::vector > inboundTunnels; { std::unique_lock l(m_InboundTunnelsMutex); for (auto& it: m_InboundTunnels) - inboundTunnels.push_back (it); + if (it->IsEstablished () || it->GetState () == eTunnelStateTestFailed) + inboundTunnels.push_back (it); } std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), m_Rng); auto it1 = outboundTunnels.begin (); auto it2 = inboundTunnels.begin (); while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) { - bool failed = false; - if ((*it1)->IsFailed ()) - { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - newTests.push_back(std::make_pair (*it1, *it2)); - ++it1; ++it2; - } + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; } for (auto& it: newTests) { From 6439e227f67d88cb9bc6ac95c04b397faa148727 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Feb 2024 19:29:33 -0500 Subject: [PATCH 238/264] consider test failed state as established. Delete failed tunnels sooner --- libi2pd/Tunnel.cpp | 9 +++++---- libi2pd/Tunnel.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index ac0418d7..3e10ef1b 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -679,9 +679,10 @@ namespace tunnel for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();) { auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed"); auto pool = tunnel->GetTunnelPool (); if (pool) pool->TunnelExpired (tunnel); @@ -730,10 +731,10 @@ namespace tunnel for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) { auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed"); auto pool = tunnel->GetTunnelPool (); if (pool) pool->TunnelExpired (tunnel); diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 47ff0465..a0815cba 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -91,7 +91,7 @@ namespace tunnel i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; }; TunnelState GetState () const { return m_State; }; void SetState (TunnelState state); - bool IsEstablished () const { return m_State == eTunnelStateEstablished; }; + bool IsEstablished () const { return m_State == eTunnelStateEstablished || m_State == eTunnelStateTestFailed; }; bool IsFailed () const { return m_State == eTunnelStateFailed; }; bool IsRecreated () const { return m_IsRecreated; }; void SetRecreated (bool recreated) { m_IsRecreated = recreated; }; From 441e847de8278d3cc9703ec9bbefec836296ff8f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 14:49:12 -0500 Subject: [PATCH 239/264] don't try to decrypt dulpicate message --- libi2pd/Garlic.cpp | 18 +++++++++++++++--- libi2pd/Garlic.h | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3f885186..7157052c 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -588,11 +588,17 @@ namespace garlic auto it = m_ECIESx25519Tags.find (tag); if (it != m_ECIESx25519Tags.end ()) { - if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + if (!it->second.tagset) return true; // duplicate + if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + { m_LastTagset = it->second.tagset; + it->second.tagset = nullptr; // mark as used + } else + { LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); - m_ECIESx25519Tags.erase (it); + m_ECIESx25519Tags.erase (it); + } return true; } return false; @@ -879,6 +885,12 @@ namespace garlic numExpiredTags = 0; for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) { + if (!it->second.tagset) + { + // delete used tag + it = m_ECIESx25519Tags.erase (it); + continue; + } if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) { it->second.tagset->DeleteSymmKey (it->second.index); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index b926abda..83e3b050 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -221,7 +221,7 @@ namespace garlic struct ECIESX25519AEADRatchetIndexTagset { int index; - ReceiveRatchetTagSetPtr tagset; + ReceiveRatchetTagSetPtr tagset; // null if used }; class GarlicDestination: public i2p::data::LocalDestination From 900153765abbe87101a586f9648d21ee97d7a1b3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 18:56:04 -0500 Subject: [PATCH 240/264] move router's tags cleanup to router's thread --- libi2pd/NetDb.cpp | 9 +-------- libi2pd/RouterContext.cpp | 39 ++++++++++++++++++++++++++------------- libi2pd/RouterContext.h | 8 +++++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index e8c92658..0adeb2e7 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -106,7 +106,7 @@ namespace data { i2p::util::SetThreadName("NetDB"); - uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; + uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0; uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch (); int16_t profilesCleanupVariance = 0; @@ -165,13 +165,6 @@ namespace data lastManage = ts; } - if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT || - ts + i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT < lastDestinationCleanup) - { - i2p::context.CleanupDestination (); - lastDestinationCleanup = ts; - } - if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 40949891..02ebf22c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -61,9 +61,11 @@ namespace i2p { m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); ScheduleInitialPublish (); - m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); - ScheduleCongestionUpdate (); } + m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); + ScheduleCongestionUpdate (); + m_CleanupTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); + ScheduleCleanupTimer (); } } @@ -1223,17 +1225,6 @@ namespace i2p else LogPrint (eLogError, "Router: service is NULL"); } - - void RouterContext::CleanupDestination () - { - if (m_Service) - m_Service->GetService ().post ([this]() - { - this->i2p::garlic::GarlicDestination::CleanupExpiredTags (); - }); - else - LogPrint (eLogError, "Router: service is NULL"); - } uint32_t RouterContext::GetUptime () const { @@ -1465,4 +1456,26 @@ namespace i2p ScheduleCongestionUpdate (); } } + + void RouterContext::ScheduleCleanupTimer () + { + if (m_CleanupTimer) + { + m_CleanupTimer->cancel (); + m_CleanupTimer->expires_from_now (boost::posix_time::minutes(ROUTER_INFO_CLEANUP_INTERVAL)); + m_CleanupTimer->async_wait (std::bind (&RouterContext::HandleCleanupTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Cleanup timer is NULL"); + } + + void RouterContext::HandleCleanupTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + CleanupExpiredTags (); + ScheduleCleanupTimer (); + } + } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index ddfc65de..d85ef282 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -38,6 +38,7 @@ namespace garlic const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds + const int ROUTER_INFO_CLEANUP_INTERVAL = 5; // in minutes enum RouterStatus { @@ -181,7 +182,6 @@ namespace garlic void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove void UpdateStats (); void UpdateTimestamp (uint64_t ts); // in seconds, called from NetDb before publishing - void CleanupDestination (); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; @@ -230,6 +230,8 @@ namespace garlic void HandlePublishResendTimer (const boost::system::error_code& ecode); void ScheduleCongestionUpdate (); void HandleCongestionUpdateTimer (const boost::system::error_code& ecode); + void ScheduleCleanupTimer (); + void HandleCleanupTimer (const boost::system::error_code& ecode); private: @@ -253,7 +255,7 @@ namespace garlic i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; // publish std::unique_ptr m_Service; - std::unique_ptr m_PublishTimer, m_CongestionUpdateTimer; + std::unique_ptr m_PublishTimer, m_CongestionUpdateTimer, m_CleanupTimer; std::set m_PublishExcluded; uint32_t m_PublishReplyToken; bool m_IsHiddenMode; // not publish From 2b6a95cbee8c5216beafbac6116ade4c5230cfc2 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 21:30:40 -0500 Subject: [PATCH 241/264] don't check session for symmetric key tagset. re-create tags hash if too many used tags --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 6 +++ libi2pd/ECIESX25519AEADRatchetSession.h | 10 ++-- libi2pd/Garlic.cpp | 56 +++++++++++++++-------- libi2pd/Garlic.h | 3 +- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 6f56f2e5..3513b7ac 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -117,6 +117,12 @@ namespace garlic return session->HandleNextMessage (buf, len, shared_from_this (), index); } + bool ReceiveRatchetTagSet::IsSessionTerminated () const + { + return !m_Session || m_Session->IsTerminated (); + } + + SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key): ReceiveRatchetTagSet (nullptr), m_Destination (destination) { diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 517833e8..030e2c45 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -86,7 +86,8 @@ namespace garlic virtual bool IsIndexExpired (int index) const; virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + virtual bool IsSessionTerminated () const; + private: int m_TrimBehindIndex = 0; @@ -101,9 +102,10 @@ namespace garlic SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key); - bool IsIndexExpired (int index) const { return false; }; - bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + bool IsIndexExpired (int index) const override { return false; }; + bool HandleNextMessage (uint8_t * buf, size_t len, int index) override; + bool IsSessionTerminated () const override { return false; } + private: GarlicDestination * m_Destination; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 7157052c..ba35995f 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -431,7 +431,8 @@ namespace garlic } GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default - m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0) // 0 means standard + m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0), // 0 means standard + m_NumUsedECIESx25519Tags (0) { } @@ -599,6 +600,7 @@ namespace garlic LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it); } + m_NumUsedECIESx25519Tags++; return true; } return false; @@ -883,24 +885,41 @@ namespace garlic } numExpiredTags = 0; - for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) + if (m_NumUsedECIESx25519Tags > ECIESX25519_TAGSET_MAX_NUM_TAGS) // too many used tags { - if (!it->second.tagset) + std::unordered_map oldTags; + std::swap (m_ECIESx25519Tags, oldTags); // re-create + for (auto& it: oldTags) + if (it.second.tagset) + { + if (it.second.tagset->IsExpired (ts) || it.second.tagset->IsIndexExpired (it.second.index)) + { + it.second.tagset->DeleteSymmKey (it.second.index); + numExpiredTags++; + } + else if (it.second.tagset->IsSessionTerminated()) + numExpiredTags++; + else + m_ECIESx25519Tags.emplace (it); + } + } + else + { + for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) { - // delete used tag - it = m_ECIESx25519Tags.erase (it); - continue; - } - if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) - { - it->second.tagset->DeleteSymmKey (it->second.index); - it = m_ECIESx25519Tags.erase (it); - numExpiredTags++; - } - else - { - auto session = it->second.tagset->GetSession (); - if (!session || session->IsTerminated()) + if (!it->second.tagset) + { + // delete used tag + it = m_ECIESx25519Tags.erase (it); + continue; + } + if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) + { + it->second.tagset->DeleteSymmKey (it->second.index); + it = m_ECIESx25519Tags.erase (it); + numExpiredTags++; + } + else if (it->second.tagset->IsSessionTerminated()) { it = m_ECIESx25519Tags.erase (it); numExpiredTags++; @@ -908,7 +927,8 @@ namespace garlic else ++it; } - } + } + m_NumUsedECIESx25519Tags = 0; if (numExpiredTags > 0) LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ()); if (m_LastTagset && m_LastTagset->IsExpired (ts)) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 83e3b050..0386752b 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -291,6 +291,7 @@ namespace garlic std::unordered_map, std::hash > > m_Tags; std::unordered_map m_ECIESx25519Tags; // session tag -> session ReceiveRatchetTagSetPtr m_LastTagset; // tagset last message came for + int m_NumUsedECIESx25519Tags; // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session @@ -299,7 +300,7 @@ namespace garlic // for HTTP only size_t GetNumIncomingTags () const { return m_Tags.size (); } - size_t GetNumIncomingECIESx25519Tags () const { return m_ECIESx25519Tags.size (); } + size_t GetNumIncomingECIESx25519Tags () const { return m_ECIESx25519Tags.size () - m_NumUsedECIESx25519Tags; } const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; const decltype(m_ECIESx25519Sessions)& GetECIESx25519Sessions () const { return m_ECIESx25519Sessions; } }; From 7e3157b162b644e8624aaea1057fb712052c4761 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Feb 2024 21:28:06 -0500 Subject: [PATCH 242/264] don't process packet in terminated stream --- libi2pd/Streaming.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 74fb3d97..fa809c19 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -129,6 +129,11 @@ namespace stream void Stream::HandleNextPacket (Packet * packet) { + if (m_Status == eStreamStatusTerminated) + { + m_LocalDestination.DeletePacket (packet); + return; + } m_NumReceivedBytes += packet->GetLength (); if (!m_SendStreamID) { @@ -159,7 +164,8 @@ namespace stream { // we have received next in sequence message ProcessPacket (packet); - + if (m_Status == eStreamStatusTerminated) return; + // we should also try stored messages if any for (auto it = m_SavedPackets.begin (); it != m_SavedPackets.end ();) { @@ -169,6 +175,7 @@ namespace stream m_SavedPackets.erase (it++); ProcessPacket (savedPacket); + if (m_Status == eStreamStatusTerminated) return; } else break; From d677d67676eed2d84384797a6b662758878446bb Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 18 Feb 2024 22:54:43 +0200 Subject: [PATCH 243/264] implement medium congestion indication --- libi2pd/I2NPProtocol.cpp | 4 +- libi2pd/RouterContext.cpp | 25 +++++++---- libi2pd/RouterContext.h | 2 +- libi2pd/Transports.cpp | 87 ++++++++++++++++++++++++--------------- libi2pd/Transports.h | 26 ++++++++---- libi2pd/Tunnel.h | 2 +- 6 files changed, 92 insertions(+), 54 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 70cefbdc..78493df2 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -376,7 +376,7 @@ namespace i2p if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; uint8_t retCode = 0; // replace record to reply - if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ()) + if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < 100) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), @@ -586,7 +586,7 @@ namespace i2p // check if we accept this tunnel std::shared_ptr transitTunnel; uint8_t retCode = 0; - if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) + if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= 100) retCode = 30; if (!retCode) { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 02ebf22c..64dd43e4 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1137,13 +1137,14 @@ namespace i2p return i2p::tunnel::tunnels.GetExploratoryPool (); } - bool RouterContext::IsHighCongestion () const + int RouterContext::GetCongestionLevel (bool longTerm) const { - return i2p::tunnel::tunnels.IsTooManyTransitTunnels () || - i2p::transport::transports.IsBandwidthExceeded () || - i2p::transport::transports.IsTransitBandwidthExceeded (); - } - + return std::max ( + i2p::tunnel::tunnels.GetCongestionLevel (), + i2p::transport::transports.GetCongestionLevel (longTerm) + ); + } + void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len) { i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); @@ -1447,10 +1448,16 @@ namespace i2p if (ecode != boost::asio::error::operation_aborted) { auto c = i2p::data::RouterInfo::eLowCongestion; - if (!AcceptsTunnels ()) + if (!AcceptsTunnels () || m_ShareRatio == 0) c = i2p::data::RouterInfo::eRejectAll; - else if (IsHighCongestion ()) - c = i2p::data::RouterInfo::eHighCongestion; + else + { + int congestionLevel = GetCongestionLevel (true); + if (congestionLevel > 90) + c = i2p::data::RouterInfo::eHighCongestion; + else if (congestionLevel > 70) + c = i2p::data::RouterInfo::eMediumCongestion; + } if (m_RouterInfo.UpdateCongestion (c)) UpdateRouterInfo (); ScheduleCongestionUpdate (); diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index d85ef282..062c187d 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -167,7 +167,7 @@ namespace garlic void SetShareRatio (int percents); // 0 - 100 bool AcceptsTunnels () const { return m_AcceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; - bool IsHighCongestion () const; + int GetCongestionLevel (bool longTerm) const; bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; bool SupportsV4 () const { return m_RouterInfo.IsV4 (); }; bool SupportsMesh () const { return m_RouterInfo.IsMesh (); }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0afe47a1..a3914d7c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -140,10 +140,8 @@ namespace transport m_X25519KeysPairSupplier (15), // 15 pre-generated keys m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0), - m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), m_LastTransitBandwidthUpdateBytes (0), m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0), - m_LastInBandwidth15sUpdateBytes (0), m_LastOutBandwidth15sUpdateBytes (0), m_LastTransitBandwidth15sUpdateBytes (0), - m_LastBandwidth15sUpdateTime (0) + m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0) { } @@ -306,6 +304,16 @@ namespace transport m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); + for (int i = 0; i < TRAFFIC_SAMPLE_COUNT; i++) + { + m_TrafficSamples[i].Timestamp = ts - (TRAFFIC_SAMPLE_COUNT - i - 1) * 1000; + m_TrafficSamples[i].TotalReceivedBytes = 0; + m_TrafficSamples[i].TotalSentBytes = 0; + m_TrafficSamples[i].TotalTransitTransmittedBytes = 0; + } + m_TrafficSamplePtr = TRAFFIC_SAMPLE_COUNT - 1; + m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); @@ -364,51 +372,62 @@ namespace transport } } + void Transports::UpdateBandwidthValues(int interval, uint32_t& in, uint32_t& out, uint32_t& transit) + { + TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr]; + TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT]; + auto delta = sample1.Timestamp - sample2.Timestamp; + in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta; + out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta; + transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta; + } + void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { - uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); + m_TrafficSamplePtr++; + if (m_TrafficSamplePtr == TRAFFIC_SAMPLE_COUNT) + m_TrafficSamplePtr = 0; - // updated every second - m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes; - m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes; - m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes; + TrafficSample& sample = m_TrafficSamples[m_TrafficSamplePtr]; + sample.Timestamp = i2p::util::GetMillisecondsSinceEpoch(); + sample.TotalReceivedBytes = m_TotalReceivedBytes; + sample.TotalSentBytes = m_TotalSentBytes; + sample.TotalTransitTransmittedBytes = m_TotalTransitTransmittedBytes; - m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes; - m_LastOutBandwidthUpdateBytes = m_TotalSentBytes; - m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes; - - // updated every 15 seconds - auto delta = ts - m_LastBandwidth15sUpdateTime; - if (delta > 15 * 1000) - { - m_InBandwidth15s = (m_TotalReceivedBytes - m_LastInBandwidth15sUpdateBytes) * 1000 / delta; - m_OutBandwidth15s = (m_TotalSentBytes - m_LastOutBandwidth15sUpdateBytes) * 1000 / delta; - m_TransitBandwidth15s = (m_TotalTransitTransmittedBytes - m_LastTransitBandwidth15sUpdateBytes) * 1000 / delta; - - m_LastBandwidth15sUpdateTime = ts; - m_LastInBandwidth15sUpdateBytes = m_TotalReceivedBytes; - m_LastOutBandwidth15sUpdateBytes = m_TotalSentBytes; - m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes; - } + UpdateBandwidthValues (1, m_InBandwidth, m_OutBandwidth, m_TransitBandwidth); + UpdateBandwidthValues (15, m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s); + UpdateBandwidthValues (300, m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m); m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); } } - bool Transports::IsBandwidthExceeded () const + int Transports::GetCongestionLevel (bool longTerm) const { - auto limit = i2p::context.GetBandwidthLimit() * 1024; // convert to bytes - auto bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); - return bw > limit; - } + auto bwLimit = i2p::context.GetBandwidthLimit () * 1024; // convert to bytes + auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes - bool Transports::IsTransitBandwidthExceeded () const - { - auto limit = i2p::context.GetTransitBandwidthLimit() * 1024; // convert to bytes - return m_TransitBandwidth > limit; + if (tbwLimit == 0 || bwLimit == 0) + return 100; + + uint32_t bw; + uint32_t tbw; + if (longTerm) + { + bw = std::max (m_InBandwidth5m, m_OutBandwidth5m); + tbw = m_TransitBandwidth5m; + } + else + { + bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); + tbw = m_TransitBandwidth; + } + auto bwCongestionLevel = 100 * bw / bwLimit; + auto tbwCongestionLevel = 100 * tbw / tbwLimit; + return std::max (bwCongestionLevel, tbwCongestionLevel); } void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr msg) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 206b0256..92d75efd 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -114,6 +114,17 @@ namespace transport const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds const int MAX_NUM_DELAYED_MESSAGES = 150; const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after + + const int TRAFFIC_SAMPLE_COUNT = 301; // seconds + + struct TrafficSample + { + uint64_t Timestamp; + uint64_t TotalReceivedBytes; + uint64_t TotalSentBytes; + uint64_t TotalTransitTransmittedBytes; + }; + class Transports { public: @@ -153,8 +164,7 @@ namespace transport uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; }; uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; }; uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; }; - bool IsBandwidthExceeded () const; - bool IsTransitBandwidthExceeded () const; + int GetCongestionLevel (bool longTerm) const; size_t GetNumPeers () const { return m_Peers.size (); }; std::shared_ptr GetRandomPeer (bool isHighBandwidth) const; @@ -186,6 +196,7 @@ namespace transport void HandlePeerCleanupTimer (const boost::system::error_code& ecode); void HandlePeerTestTimer (const boost::system::error_code& ecode); void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode); + void UpdateBandwidthValues (int interval, uint32_t& in, uint32_t& out, uint32_t& transit); void DetectExternalIP (); @@ -210,14 +221,15 @@ namespace transport std::atomic m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes; + TrafficSample m_TrafficSamples[TRAFFIC_SAMPLE_COUNT]; + int m_TrafficSamplePtr; + // Bandwidth per second uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; - uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes, m_LastTransitBandwidthUpdateBytes; - - // Bandwidth every 15 seconds + // Bandwidth during last 15 seconds uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s; - uint64_t m_LastInBandwidth15sUpdateBytes, m_LastOutBandwidth15sUpdateBytes, m_LastTransitBandwidth15sUpdateBytes; - uint64_t m_LastBandwidth15sUpdateTime; + // Bandwidth during last 5 minutes + uint32_t m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m; /** which router families to trust for first hops */ std::vector m_TrustedFamilies; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index a0815cba..0b125c70 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + int GetCongestionLevel() const { return 100 * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: From a4a3f8e96b55c83bcf3af66abf7e500cd47684b8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Feb 2024 22:04:43 -0500 Subject: [PATCH 244/264] support upstream proxy through local sockets --- libi2pd_client/SOCKS.cpp | 77 +++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 65bad1cf..3174bdb3 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -139,9 +139,11 @@ namespace proxy void HandleStreamRequestComplete (std::shared_ptr stream); void ForwardSOCKS(); - void SocksUpstreamSuccess(); + template + void SocksUpstreamSuccess(std::shared_ptr& upstreamSock); void AsyncUpstreamSockRead(); - void SendUpstreamRequest(); + template + void SendUpstreamRequest(std::shared_ptr& upstreamSock); void HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, @@ -150,6 +152,9 @@ namespace proxy boost::asio::ip::tcp::resolver m_proxy_resolver; uint8_t m_sock_buff[socks_buffer_size]; std::shared_ptr m_sock, m_upstreamSock; +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + std::shared_ptr m_upstreamLocalSock; +#endif std::shared_ptr m_stream; uint8_t *m_remaining_data; //Data left to be sent uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded @@ -212,6 +217,14 @@ namespace proxy m_upstreamSock->close(); m_upstreamSock = nullptr; } +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + if (m_upstreamLocalSock) + { + LogPrint(eLogDebug, "SOCKS: Closing upstream local socket"); + m_upstreamLocalSock->close(); + m_upstreamLocalSock = nullptr; + } +#endif if (m_stream) { LogPrint(eLogDebug, "SOCKS: Closing stream"); @@ -677,13 +690,45 @@ namespace proxy void SOCKSHandler::ForwardSOCKS() { LogPrint(eLogInfo, "SOCKS: Forwarding to upstream"); - EnterState(UPSTREAM_RESOLVE); - boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort)); - m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + if (m_UpstreamProxyPort) // TCP + { + EnterState(UPSTREAM_RESOLVE); + boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort)); + m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); + } + else if (!m_UpstreamProxyAddress.empty ())// local + { +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + EnterState(UPSTREAM_CONNECT); + m_upstreamLocalSock = std::make_shared(GetOwner()->GetService()); + auto s = shared_from_this (); + m_upstreamLocalSock->async_connect(m_UpstreamProxyAddress, + [s](const boost::system::error_code& ecode) + { + if (ecode) + { + LogPrint(eLogWarning, "SOCKS: Could not connect to local upstream proxy: ", ecode.message()); + s->SocksRequestFailed(SOCKS5_NET_UNREACH); + return; + } + LogPrint(eLogInfo, "SOCKS: Connected to local upstream proxy"); + s->SendUpstreamRequest(s->m_upstreamLocalSock); + }); +#else + LogPrint(eLogError, "SOCKS: Local sockets for upstream proxy not supported"); + SocksRequestFailed(SOCKS5_ADDR_UNSUP); +#endif + } + else + { + LogPrint(eLogError, "SOCKS: Incorrect upstream proxy address"); + SocksRequestFailed(SOCKS5_ADDR_UNSUP); + } } - void SOCKSHandler::SocksUpstreamSuccess() + template + void SOCKSHandler::SocksUpstreamSuccess(std::shared_ptr& upstreamSock) { LogPrint(eLogInfo, "SOCKS: Upstream success"); boost::asio::const_buffers_1 response(nullptr, 0); @@ -700,27 +745,27 @@ namespace proxy break; } m_sock->send(response); - auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, m_upstreamSock); - m_upstreamSock = nullptr; + auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, upstreamSock); + upstreamSock = nullptr; m_sock = nullptr; GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); } - - void SOCKSHandler::SendUpstreamRequest() + template + void SOCKSHandler::SendUpstreamRequest(std::shared_ptr& upstreamSock) { LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy"); EnterState(UPSTREAM_HANDSHAKE); - if (m_upstreamSock) + if (upstreamSock) { auto s = shared_from_this (); - i2p::transport::Socks5Handshake (*m_upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), - [s](const boost::system::error_code& ec) + i2p::transport::Socks5Handshake (*upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), + [s, &upstreamSock](const boost::system::error_code& ec) { if (!ec) - s->SocksUpstreamSuccess(); + s->SocksUpstreamSuccess(upstreamSock); else { s->SocksRequestFailed(SOCKS5_NET_UNREACH); @@ -740,7 +785,7 @@ namespace proxy return; } LogPrint(eLogInfo, "SOCKS: Connected to upstream proxy"); - SendUpstreamRequest(); + SendUpstreamRequest(m_upstreamSock); } void SOCKSHandler::HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) From 19e23b34da807476c4e1ed0dea3c1bef15df3a06 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 10:30:05 +0200 Subject: [PATCH 245/264] add constants for congestion levels --- libi2pd/I2NPProtocol.cpp | 4 ++-- libi2pd/I2NPProtocol.h | 4 ++++ libi2pd/RouterContext.cpp | 6 +++--- libi2pd/Transports.cpp | 6 +++--- libi2pd/Tunnel.h | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 78493df2..a1638326 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -376,7 +376,7 @@ namespace i2p if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; uint8_t retCode = 0; // replace record to reply - if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < 100) + if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < CONGESTION_LEVEL_FULL) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), @@ -586,7 +586,7 @@ namespace i2p // check if we accept this tunnel std::shared_ptr transitTunnel; uint8_t retCode = 0; - if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= 100) + if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL) retCode = 30; if (!retCode) { diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index a2877a08..36facbe3 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -139,6 +139,10 @@ namespace tunnel class TunnelPool; } + const int CONGESTION_LEVEL_MEDIUM = 70; + const int CONGESTION_LEVEL_HIGH = 90; + const int CONGESTION_LEVEL_FULL = 100; + const size_t I2NP_MAX_MESSAGE_SIZE = 62708; const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; const size_t I2NP_MAX_MEDIUM_MESSAGE_SIZE = 16384; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 64dd43e4..013f4dc5 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1448,14 +1448,14 @@ namespace i2p if (ecode != boost::asio::error::operation_aborted) { auto c = i2p::data::RouterInfo::eLowCongestion; - if (!AcceptsTunnels () || m_ShareRatio == 0) + if (!AcceptsTunnels () || !m_ShareRatio) c = i2p::data::RouterInfo::eRejectAll; else { int congestionLevel = GetCongestionLevel (true); - if (congestionLevel > 90) + if (congestionLevel > CONGESTION_LEVEL_HIGH) c = i2p::data::RouterInfo::eHighCongestion; - else if (congestionLevel > 70) + else if (congestionLevel > CONGESTION_LEVEL_MEDIUM) c = i2p::data::RouterInfo::eMediumCongestion; } if (m_RouterInfo.UpdateCongestion (c)) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index a3914d7c..bb5dcecc 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -411,7 +411,7 @@ namespace transport auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes if (tbwLimit == 0 || bwLimit == 0) - return 100; + return CONGESTION_LEVEL_FULL; uint32_t bw; uint32_t tbw; @@ -425,8 +425,8 @@ namespace transport bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); tbw = m_TransitBandwidth; } - auto bwCongestionLevel = 100 * bw / bwLimit; - auto tbwCongestionLevel = 100 * tbw / tbwLimit; + auto bwCongestionLevel = CONGESTION_LEVEL_FULL * bw / bwLimit; + auto tbwCongestionLevel = CONGESTION_LEVEL_FULL * tbw / tbwLimit; return std::max (bwCongestionLevel, tbwCongestionLevel); } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 0b125c70..cc5b9461 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - int GetCongestionLevel() const { return 100 * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } + int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: From b092e712ec0d9616eef7d73eb2d9e2bd11afba6d Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 17:39:48 +0200 Subject: [PATCH 246/264] make more attempts to select not bad hop --- libi2pd/NetDb.cpp | 2 +- libi2pd/TunnelPool.cpp | 22 +++++++++++++++++----- libi2pd/TunnelPool.h | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0adeb2e7..bfd07df3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1257,7 +1257,7 @@ namespace data std::shared_ptr NetDb::GetRandomRouter (Filter filter) const { if (m_RouterInfos.empty()) - return 0; + return nullptr; uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::lock_guard l(m_RouterInfosMutex); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5b472232..c342d546 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -494,11 +494,23 @@ namespace tunnel std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const { - auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint); - - if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + bool tryHighBandwidth = !IsExploratory (); + std::shared_ptr hop; + for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) + { + hop = tryHighBandwidth ? + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + if (hop) + { + if (!hop->GetProfile ()->IsBad ()) + break; + } + else if (tryHighBandwidth) + tryHighBandwidth = false; + else + return nullptr; + } return hop; } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 3d3d4e33..d9f5966d 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -32,6 +32,7 @@ namespace tunnel 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 = 3; + const int TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS = 3; class Tunnel; class InboundTunnel; From d524105727797825cf8e0310eef7120060b28c60 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 22:48:45 +0200 Subject: [PATCH 247/264] skip bandwidth updates in case of time going backwards --- libi2pd/Transports.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index bb5dcecc..04c58cf3 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -376,7 +376,12 @@ namespace transport { TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr]; TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT]; - auto delta = sample1.Timestamp - sample2.Timestamp; + auto delta = (int64_t)sample1.Timestamp - (int64_t)sample2.Timestamp; + if (delta <= 0) + { + LogPrint (eLogError, "Transports: Backward clock jump detected, got ", delta, " instead of ", interval * 1000); + return; + } in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta; out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta; transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta; From 2692aef53d45eb7b9a2a82a1c241a0f7ca9b175a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 21 Feb 2024 01:36:32 +0300 Subject: [PATCH 248/264] [gha] update windows msvc action --- .github/workflows/build-windows-msvc.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index dea64644..36a70d5a 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -38,13 +38,13 @@ jobs: - name: Install Boost run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" - ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_81_0-msvc-14.3-64.exe)" + ./boost_1_81_0-msvc-14.3-64.exe /VERYSILENT - name: Install OpenSSL run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" - ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -OutFile Win64OpenSSL-3_2_1.exe)" + ./Win64OpenSSL-3_2_1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - name: Configure working-directory: build From 695dc96a837d029999375ef80084c923d65cc4ad Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Feb 2024 18:32:51 -0500 Subject: [PATCH 249/264] common ServiceAcceptor for all stream protocols --- libi2pd_client/I2PService.cpp | 49 ---------------- libi2pd_client/I2PService.h | 103 +++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 81 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 5604f950..e9513e48 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -147,54 +147,5 @@ namespace client m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port); } } - - void TCPIPAcceptor::Start () - { - m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); - // update the local end point in case port has been set zero and got updated now - m_LocalEndpoint = m_Acceptor->local_endpoint(); - m_Acceptor->listen (); - Accept (); - } - - void TCPIPAcceptor::Stop () - { - if (m_Acceptor) - { - m_Acceptor->close(); - m_Acceptor.reset (nullptr); - } - m_Timer.cancel (); - ClearHandlers(); - } - - void TCPIPAcceptor::Accept () - { - auto newSocket = std::make_shared (GetService ()); - m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this, - std::placeholders::_1, newSocket)); - } - - void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr socket) - { - if (!ecode) - { - LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted"); - auto handler = CreateHandler(socket); - if (handler) - { - AddHandler(handler); - handler->Handle(); - } - else - socket->close(); - Accept(); - } - else - { - if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ()); - } - } } } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index b8973f9d..d35c954d 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -210,42 +210,81 @@ namespace client return std::make_shared >(owner, upstream, downstream); } - /* TODO: support IPv6 too */ - //This is a service that listens for connections on the IP network and interacts with I2P - class TCPIPAcceptor: public I2PService + //This is a service that listens for connections on the IP network or local socket and interacts with I2P + template + class ServiceAcceptor: public I2PService + { + public: + + ServiceAcceptor (const typename Protocol::endpoint& localEndpoint, std::shared_ptr localDestination = nullptr) : + I2PService(localDestination), m_LocalEndpoint (localEndpoint) {} + + virtual ~ServiceAcceptor () { Stop(); } + void Start () override + { + m_Acceptor.reset (new typename Protocol::acceptor (GetService (), m_LocalEndpoint)); + // update the local end point in case port has been set zero and got updated now + m_LocalEndpoint = m_Acceptor->local_endpoint(); + m_Acceptor->listen (); + Accept (); + } + void Stop () override + { + if (m_Acceptor) + { + m_Acceptor->close(); + m_Acceptor.reset (nullptr); + } + ClearHandlers(); + } + const typename Protocol::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; + + const char* GetName() override { return "Generic TCP/IP accepting daemon"; } + + protected: + + virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; + + private: + + void Accept() + { + auto newSocket = std::make_shared (GetService ()); + m_Acceptor->async_accept (*newSocket, + [newSocket, this](const boost::system::error_code& ecode) + { + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + { + LogPrint(eLogDebug, "ServiceAcceptor: ", GetName(), " accepted"); + auto handler = CreateHandler(newSocket); + if (handler) + { + AddHandler(handler); + handler->Handle(); + } + else + newSocket->close(); + Accept(); + } + else + LogPrint (eLogError, "ServiceAcceptor: ", GetName(), " closing socket on accept because: ", ecode.message ()); + }); + } + + private: + + typename Protocol::endpoint m_LocalEndpoint; + std::unique_ptr m_Acceptor; + }; + + class TCPIPAcceptor: public ServiceAcceptor { public: TCPIPAcceptor (const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : - I2PService(localDestination), - m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), - m_Timer (GetService ()) {} - TCPIPAcceptor (const std::string& address, uint16_t port, i2p::data::SigningKeyType kt) : - I2PService(kt), - m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), - m_Timer (GetService ()) {} - virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); } - //If you override this make sure you call it from the children - void Start (); - //If you override this make sure you call it from the children - void Stop (); - - const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; - - virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } - - protected: - - virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; - - private: - - void Accept(); - void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); - boost::asio::ip::tcp::endpoint m_LocalEndpoint; - std::unique_ptr m_Acceptor; - boost::asio::deadline_timer m_Timer; - }; + ServiceAcceptor (boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port), localDestination) {} + }; } } From 577ed56af023c792dccee3bed9fe731b59e137bd Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Feb 2024 18:51:37 -0500 Subject: [PATCH 250/264] store HTTP and SOCKS proxy as pointer to I2PService --- libi2pd_client/ClientContext.cpp | 1 + libi2pd_client/ClientContext.h | 11 ++++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index c27ce625..62295842 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -16,6 +16,7 @@ #include "Identity.h" #include "util.h" #include "ClientContext.h" +#include "HTTPProxy.h" #include "SOCKS.h" #include "MatchedDestination.h" diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 4e969a6b..adec607a 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,8 +15,6 @@ #include #include "Destination.h" #include "I2PService.h" -#include "HTTPProxy.h" -#include "SOCKS.h" #include "I2PTunnel.h" #include "UDPTunnel.h" #include "SAM.h" @@ -141,8 +139,7 @@ namespace client AddressBook m_AddressBook; - i2p::proxy::HTTPProxy * m_HttpProxy; - i2p::proxy::SOCKSProxy * m_SocksProxy; + I2PService * m_HttpProxy, * m_SocksProxy; std::map > m_ClientTunnels; // local endpoint -> tunnel std::map, std::shared_ptr > m_ServerTunnels; // -> tunnel @@ -167,8 +164,8 @@ namespace client const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; }; const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; } const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; } - const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; } - const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; } + const I2PService * GetHttpProxy () const { return m_HttpProxy; } + const I2PService * GetSocksProxy () const { return m_SocksProxy; } }; extern ClientContext context; From 36a060d50f66230251fe737b4c497eed961c1e67 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Feb 2024 12:37:33 -0500 Subject: [PATCH 251/264] Consider 'M' routers as low bandwidth --- libi2pd/RouterContext.cpp | 6 +++--- libi2pd/RouterInfo.cpp | 5 ++--- libi2pd/RouterInfo.h | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 013f4dc5..864d2c61 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -602,9 +602,9 @@ namespace i2p { case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48 - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH3 : limit = 64; type = low; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 128; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s default: diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index a034691a..a9c43b2e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -516,7 +516,6 @@ namespace data break; case CAPS_FLAG_HIGH_BANDWIDTH1: case CAPS_FLAG_HIGH_BANDWIDTH2: - case CAPS_FLAG_HIGH_BANDWIDTH3: m_Caps |= Caps::eHighBandwidth; break; case CAPS_FLAG_EXTRA_BANDWIDTH1: @@ -1178,7 +1177,7 @@ namespace data CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' else - caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' + caps += CAPS_FLAG_HIGH_BANDWIDTH2; // 'O' caps += CAPS_FLAG_FLOODFILL; // floodfill } else @@ -1186,7 +1185,7 @@ namespace data if (c & eExtraBandwidth) caps += (c & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ else - caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth + caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH2 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth } if (c & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index a95119ed..9e074b9a 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -39,9 +39,9 @@ namespace data /* bandwidth flags */ const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ + const char CAPS_FLAG_LOW_BANDWIDTH3 = 'M'; /* 48-64 KBps */ + const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'N'; /* 64-128 KBps */ + const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */ // bandwidth limits in kBps From 5d7c6fb0b3e89d672a631392f6b15f19156dee2c Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 21 Feb 2024 22:31:20 +0300 Subject: [PATCH 252/264] [gha] msvc: copy openssl libraries to fix build Signed-off-by: r4sas --- .github/workflows/build-windows-msvc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 36a70d5a..ef0bc52c 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -45,6 +45,7 @@ jobs: run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -OutFile Win64OpenSSL-3_2_1.exe)" ./Win64OpenSSL-3_2_1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + xcopy "c:\Program Files\OpenSSL-Win64\lib\VC\x64\MTd\*" "c:\Program Files\OpenSSL-Win64\lib\" - name: Configure working-directory: build From d25206abcefff1c914ee16adad8229197f14ca3b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Feb 2024 19:46:29 -0500 Subject: [PATCH 253/264] encrypted tunnel test messages --- libi2pd/Destination.cpp | 5 ++-- libi2pd/ECIESX25519AEADRatchetSession.cpp | 8 +++++- libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- libi2pd/RouterContext.cpp | 7 +++++ libi2pd/TunnelPool.cpp | 33 ++++++++++++++++------- libi2pd/TunnelPool.h | 1 + 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ef0d5db3..64e5d085 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -367,8 +367,9 @@ namespace client HandleDataMessage (payload, len); break; case eI2NPDeliveryStatus: - // we assume tunnel tests non-encrypted - HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); + // try tunnel test first + if (!m_Pool || !m_Pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET))) + HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (payload, len); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 3513b7ac..b4730d0e 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1154,7 +1154,7 @@ namespace garlic return len; } - std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) { auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128); m->Align (12); // in order to get buf aligned to 16 (12 + 4) @@ -1174,6 +1174,12 @@ namespace garlic htobe32buf (m->GetPayload (), offset); m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); + if (msg->onDrop) + { + // move onDrop to the wrapping I2NP messages + m->onDrop = msg->onDrop; + msg->onDrop = nullptr; + } return m; } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 030e2c45..e6deb2bc 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -247,7 +247,7 @@ namespace garlic i2p::crypto::NoiseSymmetricState m_CurrentNoiseState; }; - std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); } } diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 864d2c61..2c1dc979 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1152,6 +1152,13 @@ namespace i2p bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) { + if (typeID == eI2NPDeliveryStatus) + { + // try tunnel test + auto pool = GetTunnelPool (); + if (pool && pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET))) + return true; + } auto msg = CreateI2NPMessage (typeID, payload, len, msgID); if (!msg) return false; i2p::HandleI2NPMessage (msg); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index c342d546..898a05bc 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -13,6 +13,7 @@ #include "NetDb.hpp" #include "Timestamp.h" #include "Garlic.h" +#include "ECIESX25519AEADRatchetSession.h" #include "Transports.h" #include "Log.h" #include "Tunnel.h" @@ -383,6 +384,7 @@ namespace tunnel newTests.push_back(std::make_pair (*it1, *it2)); ++it1; ++it2; } + bool encrypt = m_LocalDestination ? m_LocalDestination->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) : false; for (auto& it: newTests) { uint32_t msgID; @@ -407,6 +409,14 @@ namespace tunnel s->m_OutboundTunnels.erase (outbound); } }; + if (encrypt) + { + // encrypt + uint8_t key[32]; RAND_bytes (key, 32); + uint64_t tag; RAND_bytes ((uint8_t *)&tag, 8); + m_LocalDestination->SubmitECIESx25519Key (key, tag); + msg = i2p::garlic::WrapECIESX25519Message (msg, key, tag); + } outbound->SendTunnelDataMsgTo (it.second->GetNextIdentHash (), it.second->GetNextTunnelID (), msg); } } @@ -436,6 +446,17 @@ namespace tunnel buf += 4; uint64_t timestamp = bufbe64toh (buf); + if (!ProcessDeliveryStatus (msgID, timestamp)) + { + if (m_LocalDestination) + m_LocalDestination->ProcessDeliveryStatusMessage (msg); + else + LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped"); + } + } + + bool TunnelPool::ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp) + { decltype(m_Tests)::mapped_type test; bool found = false; { @@ -477,15 +498,9 @@ namespace tunnel test.second->AddLatencySample(latency); } } - else - { - if (m_LocalDestination) - m_LocalDestination->ProcessDeliveryStatusMessage (msg); - else - LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped"); - } - } - + return found; + } + bool TunnelPool::IsExploratory () const { return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index d9f5966d..3e845c0e 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -85,6 +85,7 @@ namespace tunnel void ManageTunnels (uint64_t ts); void ProcessGarlicMessage (std::shared_ptr msg); void ProcessDeliveryStatus (std::shared_ptr msg); + bool ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp); bool IsExploratory () const; bool IsActive () const { return m_IsActive; }; From 7d73c304b5b77493079b9aa2c5f9e927c89e2907 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 22 Feb 2024 14:22:11 -0500 Subject: [PATCH 254/264] Extend transit tunnels limit to 4 bytes. Bump default value to 10K --- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/HTTPServer.h | 4 ++-- libi2pd/Config.cpp | 2 +- libi2pd/Tunnel.cpp | 2 +- libi2pd/Tunnel.h | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 17d17f72..090792bf 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -179,7 +179,7 @@ namespace util bool transit; i2p::config::GetOption("notransit", transit); i2p::context.SetAcceptsTunnels (!transit); - uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); + uint32_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels")) transitTunnels *= 2; // double default number of transit tunnels for floodfill i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 862d6e4a..494a4e8e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -772,7 +772,7 @@ namespace http { s << " info \r\n"; s << " debug
\r\n
\r\n"; - uint16_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); + uint32_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); s << "" << tr("Transit tunnels limit") << "
\r\n"; s << "
\r\n"; s << " \r\n"; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index f41d925d..f751c5a8 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -25,7 +25,7 @@ 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; + const int TRANSIT_TUNNELS_LIMIT = 1000000; class HTTPConnection: public std::enable_shared_from_this { diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index b2ad7a17..a6885178 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(5000), "Maximum active transit tunnels (default:5000)") + ("limits.transittunnels", value()->default_value(10000), "Maximum active transit tunnels (default:10000)") ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") ("limits.ntcphard", value()->default_value(0), "Ignored") diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 3e10ef1b..246f68e4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -986,7 +986,7 @@ namespace tunnel return m_OutboundTunnels.size(); } - void Tunnels::SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) + void Tunnels::SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels) { if (maxNumTransitTunnels > 0 && m_MaxNumTransitTunnels != maxNumTransitTunnels) { diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index cc5b9461..4903c75b 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -238,8 +238,8 @@ namespace tunnel std::shared_ptr NewI2NPTunnelMessage (bool endpoint); - void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); - uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; + void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels); + uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: @@ -300,7 +300,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - uint16_t m_MaxNumTransitTunnels; + uint32_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; From 5415598f60878cd4879f3ce265f5d791da9b7fe8 Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 22 Feb 2024 21:50:05 +0200 Subject: [PATCH 255/264] add zero check to congestion level calculations --- libi2pd/Tunnel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 4903c75b..4d9ea830 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels); uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } + int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; } private: From d4246edb8269292789a479b3236a4742532d1eef Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 11:37:09 -0500 Subject: [PATCH 256/264] don't fail last tunnel --- libi2pd/TunnelPool.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 898a05bc..04200428 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -337,7 +337,10 @@ namespace tunnel { it.second.first->SetState (eTunnelStateFailed); std::unique_lock l(m_OutboundTunnelsMutex); - m_OutboundTunnels.erase (it.second.first); + if (m_OutboundTunnels.size () > 1) // don't fail last tunnel + m_OutboundTunnels.erase (it.second.first); + else + it.second.first->SetState (eTunnelStateTestFailed); } else it.second.first->SetState (eTunnelStateTestFailed); @@ -349,7 +352,10 @@ namespace tunnel it.second.second->SetState (eTunnelStateFailed); { std::unique_lock l(m_InboundTunnelsMutex); - m_InboundTunnels.erase (it.second.second); + if (m_InboundTunnels.size () > 1) // don't fail last tunnel + m_InboundTunnels.erase (it.second.second); + else + it.second.first->SetState (eTunnelStateTestFailed); } if (m_LocalDestination) m_LocalDestination->SetLeaseSetUpdated (); From 8524a67895576a105b0b5248dc26790265151c91 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 12:32:21 -0500 Subject: [PATCH 257/264] fail last tunnel if tunnel quantity is 1 --- libi2pd/TunnelPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 04200428..22b9392f 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -337,7 +337,7 @@ namespace tunnel { it.second.first->SetState (eTunnelStateFailed); std::unique_lock l(m_OutboundTunnelsMutex); - if (m_OutboundTunnels.size () > 1) // don't fail last tunnel + if (m_OutboundTunnels.size () > 1 || m_NumOutboundTunnels <= 1) // don't fail last tunnel m_OutboundTunnels.erase (it.second.first); else it.second.first->SetState (eTunnelStateTestFailed); @@ -352,7 +352,7 @@ namespace tunnel it.second.second->SetState (eTunnelStateFailed); { std::unique_lock l(m_InboundTunnelsMutex); - if (m_InboundTunnels.size () > 1) // don't fail last tunnel + if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel m_InboundTunnels.erase (it.second.second); else it.second.first->SetState (eTunnelStateTestFailed); From f07c4bd1dd4170abc1d087217d71b859ad28e7a5 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 15:24:52 -0500 Subject: [PATCH 258/264] drop transit tunnel if next ident is ours --- libi2pd/I2NPProtocol.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index a1638326..f5df0d20 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -373,7 +373,16 @@ namespace i2p if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) { LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours"); - if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; + if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) + { + LogPrint (eLogWarning, "I2NP: Failed to decrypt tunnel build record"); + return false; + } + if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + { + LogPrint (eLogWarning, "I2NP: Next ident is ours in tunnel build record"); + return false; + } uint8_t retCode = 0; // replace record to reply if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < CONGESTION_LEVEL_FULL) @@ -562,6 +571,11 @@ namespace i2p LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); return; } + if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + { + LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record"); + return; + } if (clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE]) // not AES { LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record"); From 6bd1ee36f7d0c76923a7779b8fe83a53fec8219a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 16:09:32 -0500 Subject: [PATCH 259/264] fixed typo --- libi2pd/I2NPProtocol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index f5df0d20..d433e6fc 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -378,7 +378,7 @@ namespace i2p LogPrint (eLogWarning, "I2NP: Failed to decrypt tunnel build record"); return false; } - if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours { LogPrint (eLogWarning, "I2NP: Next ident is ours in tunnel build record"); return false; @@ -571,7 +571,7 @@ namespace i2p LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); return; } - if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours { LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record"); return; From 8874ea8033aff9486a23924c60b4b5e13e8fdddb Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 18:06:31 -0500 Subject: [PATCH 260/264] fixed typo --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 22b9392f..2a5e9dd1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -355,7 +355,7 @@ namespace tunnel if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel m_InboundTunnels.erase (it.second.second); else - it.second.first->SetState (eTunnelStateTestFailed); + it.second.second->SetState (eTunnelStateTestFailed); } if (m_LocalDestination) m_LocalDestination->SetLeaseSetUpdated (); From 78af34237e5f58b24974d73a24f733e91505e0c1 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 Feb 2024 19:22:49 -0500 Subject: [PATCH 261/264] reduce session termination timeout --- libi2pd/SSU2Session.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 14d76971..5dd45fd4 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -25,7 +25,7 @@ namespace i2p namespace transport { const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds - const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes + const int SSU2_TERMINATION_TIMEOUT = 165; // in seconds const int SSU2_CLOCK_SKEW = 60; // in seconds const int SSU2_CLOCK_THRESHOLD = 15; // in seconds, if more we should adjust const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // for Retry message, in seconds From a1dce017f41b538284fcacc320ec81813b424b6a Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 24 Feb 2024 11:40:43 -0500 Subject: [PATCH 262/264] allow tunnel endpoint to send tunnel build reply to itself --- libi2pd/I2NPProtocol.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index d433e6fc..49b5120c 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -378,7 +378,8 @@ namespace i2p LogPrint (eLogWarning, "I2NP: Failed to decrypt tunnel build record"); return false; } - if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32) && // if next ident is now ours + !(clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG)) // and not endpoint { LogPrint (eLogWarning, "I2NP: Next ident is ours in tunnel build record"); return false; @@ -571,11 +572,6 @@ namespace i2p LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); return; } - if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours - { - LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record"); - return; - } if (clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE]) // not AES { LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record"); @@ -595,7 +591,14 @@ namespace i2p memcpy (ivKey, noiseState.m_CK + 32, 32); } else + { + if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours + { + LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record"); + return; + } memcpy (ivKey, noiseState.m_CK , 32); + } // check if we accept this tunnel std::shared_ptr transitTunnel; From 34154596f24687d4d6cd373bd87233018d8d37b3 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 24 Feb 2024 23:35:56 +0000 Subject: [PATCH 263/264] [gha] build only when related to app and runner itself files are changed, disable temporary msvc Signed-off-by: r4sas --- .github/workflows/build-deb.yml | 20 ++++- .github/workflows/build-freebsd.yml | 20 ++++- .github/workflows/build-osx.yml | 18 ++++- .github/workflows/build-windows-msvc.yml | 63 --------------- .../workflows/build-windows-msvc.yml-disabled | 80 +++++++++++++++++++ .github/workflows/build-windows.yml | 21 ++++- .github/workflows/build.yml | 20 ++++- 7 files changed, 174 insertions(+), 68 deletions(-) delete mode 100644 .github/workflows/build-windows-msvc.yml create mode 100644 .github/workflows/build-windows-msvc.yml-disabled diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index ebc3df4d..124dd35e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -1,6 +1,24 @@ name: Build Debian packages -on: [push, pull_request] +on: + push: + branches: + - '*' + paths: + - .github/workflows/build-deb.yml + - contrib/** + - daemon/** + - debian/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.linux + tags: + - '*' + pull_request: + branches: + - '*' jobs: build: diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml index 6dc46a39..f0296d7e 100644 --- a/.github/workflows/build-freebsd.yml +++ b/.github/workflows/build-freebsd.yml @@ -1,6 +1,24 @@ name: Build on FreeBSD -on: [push, pull_request] +on: + push: + branches: + - '*' + paths: + - .github/workflows/build-freebsd.yml + - build/CMakeLists.txt + - build/cmake_modules/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.homebrew + tags: + - '*' + pull_request: + branches: + - '*' jobs: build: diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index 266f2c54..1ae1042a 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -1,6 +1,22 @@ name: Build on OSX -on: [push, pull_request] +on: + push: + branches: + - '*' + paths: + - .github/workflows/build-osx.yml + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.homebrew + tags: + - '*' + pull_request: + branches: + - '*' jobs: build: diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml deleted file mode 100644 index ef0bc52c..00000000 --- a/.github/workflows/build-windows-msvc.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Build on Windows with MSVC - -on: [push, pull_request] - -jobs: - build: - name: Build - runs-on: windows-latest - - strategy: - fail-fast: false - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Build and install zlib - run: | - powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)" - powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings - set BUILD_TYPE=Debug - ./install_zlib.bat - set BUILD_TYPE=Release - ./install_zlib.bat - del install_zlib.bat - - #- name: Install Boost - # uses: crazy-max/ghaction-chocolatey@v2 - # with: - # args: install boost-msvc-14.3 --version=1.81.0 - - #- name: Install OpenSSL - # uses: crazy-max/ghaction-chocolatey@v2 - # with: - # args: install openssl - - - name: Install Boost - run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_81_0-msvc-14.3-64.exe)" - ./boost_1_81_0-msvc-14.3-64.exe /VERYSILENT - - - name: Install OpenSSL - run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -OutFile Win64OpenSSL-3_2_1.exe)" - ./Win64OpenSSL-3_2_1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - xcopy "c:\Program Files\OpenSSL-Win64\lib\VC\x64\MTd\*" "c:\Program Files\OpenSSL-Win64\lib\" - - - name: Configure - working-directory: build - run: cmake -DWITH_STATIC=ON . - - - name: Build - working-directory: build - run: cmake --build . --config Debug -- -m - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: i2pd-msvc - path: build/Debug/i2pd.* - diff --git a/.github/workflows/build-windows-msvc.yml-disabled b/.github/workflows/build-windows-msvc.yml-disabled new file mode 100644 index 00000000..0afb9d6b --- /dev/null +++ b/.github/workflows/build-windows-msvc.yml-disabled @@ -0,0 +1,80 @@ +name: Build on Windows with MSVC + +on: + push: + branches: + - '*' + paths: + - .github/workflows/build-windows-msvc.yml + - build/CMakeLists.txt + - build/cmake_modules/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Win32/** + tags: + - '*' + pull_request: + branches: + - '*' + +jobs: + build: + name: Build + runs-on: windows-latest + env: + boost_path: ${{ github.workspace }}\boost_1_83_0 + openssl_path: ${{ github.workspace }}\openssl_3_2_1 + + strategy: + fail-fast: false + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Build and install zlib + run: | + powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)" + powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings + set BUILD_TYPE=Debug + ./install_zlib.bat + set BUILD_TYPE=Release + ./install_zlib.bat + del install_zlib.bat + + - name: Install Boost + run: | + powershell -Command "(Start-BitsTransfer -Source https://sourceforge.net/projects/boost/files/boost-binaries/1.83.0/boost_1_83_0-msvc-14.3-64.exe/download -Destination boost_1_83_0-msvc-14.3-64.exe)" + ./boost_1_83_0-msvc-14.3-64.exe /DIR="${{env.boost_path}}" /VERYSILENT /SUPPRESSMSGBOXES /SP- + + - name: Install OpenSSL + run: | + powershell -Command "(Start-BitsTransfer -Source https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -Destination Win64OpenSSL-3_2_1.exe)" + ./Win64OpenSSL-3_2_1.exe /DIR="${{env.openssl_path}}" /TASKS="copytobin" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + + - name: Make copy of the OpenSSL libraries for CMake + run: | + dir ${{ github.workspace }} + dir ${{env.openssl_path}}\lib\VC + dir ${{env.openssl_path}}\lib\VC\x64\ + dir ${{env.openssl_path}}\lib\VC\x64\MTd\ + xcopy /s /y "${{env.openssl_path}}\lib\VC\x64\MTd" "${{env.openssl_path}}\lib" + + - name: Configure + working-directory: build + run: cmake -DBoost_ROOT="${{env.boost_path}}" -DOPENSSL_ROOT_DIR="${{env.openssl_path}}" -DWITH_STATIC=ON . + + - name: Build + working-directory: build + run: cmake --build . --config Debug -- -m + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: i2pd-msvc + path: build/Debug/i2pd.* + diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 66c846c1..ed75dd69 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -1,6 +1,25 @@ name: Build on Windows -on: [push, pull_request] +on: + push: + branches: + - '*' + paths: + - .github/workflows/build-windows.yml + - build/CMakeLists.txt + - build/cmake_modules/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Win32/** + - Makefile + - Makefile.mingw + tags: + - '*' + pull_request: + branches: + - '*' defaults: run: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 935c2f93..3f35cfe5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,24 @@ name: Build on Ubuntu -on: [push, pull_request] +on: + push: + branches: + - '*' + paths: + - .github/workflows/build.yml + - build/CMakeLists.txt + - build/cmake_modules/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.linux + tags: + - '*' + pull_request: + branches: + - '*' jobs: build-make: From 821a76a7c5d3d58cc5e213ad61a57f7bc1b7703a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Feb 2024 09:15:08 -0500 Subject: [PATCH 264/264] flush IBGW if tunnel build request OBEP is on the same router --- libi2pd/I2NPProtocol.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 49b5120c..da6da638 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -675,7 +675,10 @@ namespace i2p uint32_t tunnelID = bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET); auto tunnel = i2p::tunnel::tunnels.GetTunnel (tunnelID); if (tunnel) + { tunnel->SendTunnelDataMsg (replyMsg); + tunnel->FlushTunnelDataMsgs (); + } else LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply"); }