diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 05776dc4..7a2fb431 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -476,7 +476,7 @@ namespace transport bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer) { if (!peer.router) // reconnect - peer.router = netdb.FindRouter (ident); // try to get new one from netdb + peer.SetRouter (netdb.FindRouter (ident)); // try to get new one from netdb if (peer.router) // we have RI already { if (peer.priority.empty ()) @@ -598,7 +598,7 @@ namespace transport if (r) { LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect"); - it->second.router = r; + it->second.SetRouter (r); ConnectToPeer (ident, it->second); } else @@ -900,14 +900,15 @@ namespace transport return found ? i2p::data::netdb.FindRouter (ident) : nullptr; } - std::shared_ptr Transports::GetRandomPeer () const + std::shared_ptr Transports::GetRandomPeer (bool isHighBandwidth) const { return GetRandomPeer ( - [](const Peer& peer)->bool + [isHighBandwidth](const Peer& peer)->bool { // connected and not overloaded return !peer.router && !peer.sessions.empty () && - peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE; + peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && + (!isHighBandwidth || peer.isHighBandwidth); }); } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 76b6a089..ebb6261e 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -72,11 +72,15 @@ namespace transport uint64_t creationTime, nextRouterInfoUpdateTime; std::vector > delayedMessages; std::vector priority; + bool isHighBandwidth; Peer (std::shared_ptr r, uint64_t ts): numAttempts (0), router (r), creationTime (ts), - nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL) + nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL), + isHighBandwidth (false) { + if (router) + isHighBandwidth = router->IsHighBandwidth (); } void Done () @@ -84,6 +88,13 @@ namespace transport for (auto& it: sessions) it->Done (); } + + void SetRouter (std::shared_ptr r) + { + router = r; + if (router) + isHighBandwidth = router->IsHighBandwidth (); + } }; const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds @@ -131,7 +142,7 @@ namespace transport bool IsBandwidthExceeded () const; bool IsTransitBandwidthExceeded () const; size_t GetNumPeers () const { return m_Peers.size (); }; - std::shared_ptr GetRandomPeer () const; + std::shared_ptr GetRandomPeer (bool isHighBandwidth) const; /** get a trusted first hop for restricted routes */ std::shared_ptr GetRestrictedPeer() const; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index ee115b7e..a9592efd 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -480,7 +480,7 @@ namespace tunnel return hop; } - bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop) + bool TunnelPool::StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop) { int start = 0; std::shared_ptr prevHop = i2p::context.GetSharedRouterInfo (); @@ -496,7 +496,7 @@ namespace tunnel else if (i2p::transport::transports.GetNumPeers () > 100 || (inbound && i2p::transport::transports.GetNumPeers () > 25)) { - auto r = i2p::transport::transports.GetRandomPeer (); + auto r = i2p::transport::transports.GetRandomPeer (IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable { @@ -512,7 +512,7 @@ namespace tunnel if (!hop && !i) // if no suitable peer found for first hop, try already connected { LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); - hop = i2p::transport::transports.GetRandomPeer (); + hop = i2p::transport::transports.GetRandomPeer (false); if (hop && !hop->IsECIES ()) hop = nullptr; } if (!hop) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index aed29eaf..6936d3ad 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -54,12 +54,9 @@ namespace tunnel virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0; }; - - typedef std::function(std::shared_ptr, bool)> SelectHopFunc; - bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); - class TunnelPool: public std::enable_shared_from_this // per local destination { + typedef std::function(std::shared_ptr, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -116,7 +113,8 @@ namespace tunnel // for overriding tunnel peer selection std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; - + bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); + private: void TestTunnels (); diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index ce800ecc..1e2e8275 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -72,7 +72,7 @@ namespace client bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) { auto pool = GetTunnelPool(); - if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, + if(!pool || !pool->StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) return false; // more here for outbound tunnels