From 9f30499984d8f854024fe751fadc284af8f74cec Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Sep 2024 21:16:16 -0400 Subject: [PATCH] implement i2p.streaming.profile to specify high or low bandwidth tunnel pools --- libi2pd/Destination.cpp | 8 ++++++-- libi2pd/Destination.h | 4 ++++ libi2pd/NetDb.cpp | 11 +++++++---- libi2pd/NetDb.hpp | 2 +- libi2pd/Tunnel.cpp | 14 ++++++++------ libi2pd/Tunnel.h | 5 +++-- libi2pd/TunnelPool.cpp | 18 ++++++++++-------- libi2pd/TunnelPool.h | 4 ++-- libi2pd_client/ClientContext.cpp | 3 +++ 9 files changed, 44 insertions(+), 25 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 05c4be00..28b23950 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -37,6 +37,7 @@ namespace client int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE; int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE; int numTags = DEFAULT_TAGS_TO_SEND; + bool isHighBandwidth = true; std::shared_ptr > explicitPeers; try { @@ -92,7 +93,7 @@ namespace client it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET); if (it != params->end ()) { - // oveeride isPublic + // override isPublic m_IsPublic = (it->second != "true"); } it = params->find (I2CP_PARAM_LEASESET_TYPE); @@ -121,6 +122,9 @@ namespace client m_LeaseSetPrivKey.reset (nullptr); } } + it = params->find (I2CP_PARAM_STREAMING_PROFILE); + if (it != params->end ()) + isHighBandwidth = std::stoi (it->second) != STREAMING_PROFILE_INTERACTIVE; } } catch (std::exception & ex) @@ -128,7 +132,7 @@ namespace client LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); } SetNumTags (numTags); - m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar, isHighBandwidth); if (explicitPeers) m_Pool->SetExplicitPeers (explicitPeers); if(params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 1cd004a4..4a51a257 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -90,6 +90,10 @@ namespace client const int DEFAULT_MAX_INBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings"; const int DEFAULT_ANSWER_PINGS = true; + const char I2CP_PARAM_STREAMING_PROFILE[] = "i2p.streaming.profile"; + const int STREAMING_PROFILE_BULK = 1; // high bandwidth + const int STREAMING_PROFILE_INTERACTIVE = 2; // low bandwidth + const int DEFAULT_STREAMING_PROFILE = STREAMING_PROFILE_BULK; typedef std::function stream)> StreamRequestComplete; diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 55e17b23..f6067ce3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -69,7 +69,7 @@ namespace data { Reseed (); } - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false)) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false, false)) Reseed (); // we don't have a router we can connect to. Trying to reseed auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); @@ -1130,15 +1130,18 @@ namespace data } std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, - bool reverse, bool endpoint) const + bool reverse, bool endpoint, bool clientTunnel) const { + bool checkIsReal = clientTunnel && i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD && // too low rate + context.GetUptime () > NETDB_CHECK_FOR_EXPIRATION_UPTIME; // after 10 minutes uptime return GetRandomRouter ( - [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint, clientTunnel, checkIsReal](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && !router->IsNAT2NATOnly (*compatibleWith) && - router->IsECIES () && !router->IsHighCongestion (false) && + router->IsECIES () && !router->IsHighCongestion (clientTunnel) && + (!checkIsReal || router->GetProfile ()->IsReal ()) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 1797c04d..b84387de 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -87,7 +87,7 @@ namespace data void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; + std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint, bool clientTunnel) const; std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::unordered_set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::unordered_set& excluded) const; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 55c4d38c..1b63b7a7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -411,10 +411,12 @@ namespace tunnel return tunnel; } - std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, - int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance) + std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, + int numOutboundHops, int numInboundTunnels, int numOutboundTunnels, + int inboundVariance, int outboundVariance, bool isHighBandwidth) { - auto pool = std::make_shared (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance); + auto pool = std::make_shared (numInboundHops, numOutboundHops, + numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance, isHighBandwidth); std::unique_lock l(m_PoolsMutex); m_Pools.push_back (pool); return pool; @@ -705,7 +707,7 @@ namespace tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true, false); // reachable by us if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); CreateTunnel ( @@ -765,7 +767,7 @@ namespace tunnel int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen); int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum); int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum); - m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0); + m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0, false); m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ()); } return; @@ -777,7 +779,7 @@ namespace tunnel auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : // should be reachable by us because we send build request directly - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true, false); if (!router) { LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); return; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index d3de272d..6b014af2 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -232,8 +232,9 @@ namespace tunnel void PostTunnelData (const std::vector >& msgs); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); - std::shared_ptr CreateTunnelPool (int numInboundHops, int numOuboundHops, - int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance); + std::shared_ptr CreateTunnelPool (int numInboundHops, + int numOuboundHops, int numInboundTunnels, int numOutboundTunnels, + int inboundVariance, int outboundVariance, bool isHighBandwidth); void DeleteTunnelPool (std::shared_ptr pool); void StopTunnelPool (std::shared_ptr pool); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 0a855350..e17932f9 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -41,11 +41,11 @@ namespace tunnel } TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, - int numOutboundTunnels, int inboundVariance, int outboundVariance): + int numOutboundTunnels, int inboundVariance, int outboundVariance, bool isHighBandwidth): m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance), - m_IsActive (true), m_CustomPeerSelector(nullptr), + m_IsActive (true), m_IsHighBandwidth (isHighBandwidth), m_CustomPeerSelector(nullptr), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL) { if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) @@ -549,20 +549,22 @@ namespace tunnel std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const { - bool tryHighBandwidth = !IsExploratory (); + bool tryClient = !IsExploratory (); std::shared_ptr hop; for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) { - hop = tryHighBandwidth ? - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : - i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + hop = tryClient ? + (m_IsHighBandwidth ? + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, true)): + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false); if (hop) { if (!hop->GetProfile ()->IsBad ()) break; } - else if (tryHighBandwidth) - tryHighBandwidth = false; + else if (tryClient) + tryClient = false; else return nullptr; } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index c19114e2..0ebfd1ac 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -62,7 +62,7 @@ namespace tunnel public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, - int numOutboundTunnels, int inboundVariance, int outboundVariance); + int numOutboundTunnels, int inboundVariance, int outboundVariance, bool isHighBandwidth); ~TunnelPool (); std::shared_ptr GetLocalDestination () const { return m_LocalDestination; }; @@ -146,7 +146,7 @@ namespace tunnel std::set, TunnelCreationTimeCmp> m_OutboundTunnels; mutable std::mutex m_TestsMutex; std::map, std::shared_ptr > > m_Tests; - bool m_IsActive; + bool m_IsActive, m_IsHighBandwidth; uint64_t m_NextManageTime; // in seconds std::mutex m_CustomPeerSelectorMutex; ITunnelPeerSelector * m_CustomPeerSelector; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b8c4e335..8cb4b67b 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -474,6 +474,7 @@ namespace client options[I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED); options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); + options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "0,4"); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; @@ -519,6 +520,8 @@ namespace client options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_PRIV_KEY, value) && !value.empty ()) options[I2CP_PARAM_LEASESET_PRIV_KEY] = value; + if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_PROFILE, value)) + options[I2CP_PARAM_STREAMING_PROFILE] = value; } void ClientContext::ReadTunnels ()