diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 66d15cae..7f71619e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -57,7 +57,7 @@ namespace data uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold Reseed (); - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo ())) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false)) Reseed (); // we don't have a router we can connect to. Trying to reseed i2p::config::GetOption("persist.profiles", m_PersistProfiles); @@ -1135,13 +1135,14 @@ namespace data }); } - std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith) const + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool + [compatibleWith, reverse](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith); + (reverse ? compatibleWith->IsReachableFrom (*router) : + router->IsReachableFrom (*compatibleWith)); }); } @@ -1172,13 +1173,14 @@ namespace data }); } - std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool + [compatibleWith, reverse](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith) && + (reverse ? compatibleWith->IsReachableFrom (*router) : + router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION; }); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 845217e1..5dbef743 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -83,8 +83,8 @@ namespace data void HandleDeliveryStatusMsg (std::shared_ptr msg); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; - std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) 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 GetRandomPeerTestRouter (bool v4only = true) const; std::shared_ptr GetRandomSSUV6Router () const; // TODO: change to v6 peer test later std::shared_ptr GetRandomIntroducer () const; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 4ea66add..03186c54 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1079,22 +1079,37 @@ namespace data auto supportedTransports = m_SupportedTransports & (eSSUV4 | eSSUV6); if (!supportedTransports) return false; // no SSU if (v4only && !(supportedTransports & eSSUV4)) return false; // no SSU v4 - return GetAddress ( + return (bool)GetAddress ( [](std::shared_ptr address)->bool { return (address->transportStyle == eTransportSSU) && address->IsPeerTesting (); - }) != nullptr; + }); } bool RouterInfo::IsIntroducer () const { // TODO: support ipv6 if (!(m_SupportedTransports & eSSUV4)) return false; - return GetAddress ( + return (bool)GetAddress ( [](std::shared_ptr address)->bool { return (address->transportStyle == eTransportSSU) && address->IsIntroducer (); - }) != nullptr; + }); + } + + bool RouterInfo::IsReachableFrom (const RouterInfo& other) const + { + auto commonTransports = m_SupportedTransports & other.m_SupportedTransports; + if (!commonTransports) return false; + if (commonTransports & eNTCP2V6Mesh) return true; + return (bool)GetAddress ( + [commonTransports](std::shared_ptr address)->bool + { + // TODO:check v4 and v6 separately based on caps + if ((commonTransports & (eNTCP2V4 | eNTCP2V6)) && address->IsPublishedNTCP2 ()) return true; + if ((commonTransports & (eSSUV4 | eSSUV6)) && address->IsReachableSSU ()) return true; + return false; + }); } } } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 9e9f00cd..2dbaefe2 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -147,7 +147,8 @@ namespace data bool IsNTCP2 () const { return (bool)ntcp2; }; bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; }; - + bool IsReachableSSU () const { return (bool)ssu && (!host.is_unspecified () || !ssu->introducers.empty ()); }; + bool IsIntroducer () const { return caps & eSSUIntroducer; }; bool IsPeerTesting () const { return caps & eSSUTesting; }; }; @@ -196,7 +197,8 @@ namespace data void DisableV4 (); void EnableMesh (); void DisableMesh (); - bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; + bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; + bool IsReachableFrom (const RouterInfo& other) const; bool HasValidAddresses () const { return m_SupportedTransports; }; bool UsesIntroducer () const; bool IsHidden () const { return m_Caps & eHidden; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 705754f0..b9a53905 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -503,7 +503,7 @@ namespace transport } peer.numAttempts++; } - if (address) + if (address && address->IsReachableSSU ()) { m_SSUServer->CreateSession (peer.router, address); return true; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 22563e2d..f7603652 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -393,14 +393,14 @@ namespace tunnel } } - std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop) const + std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse) const { bool isExploratory = (i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ()); - auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop); + auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse); if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop); + hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse); return hop; } @@ -429,7 +429,7 @@ namespace tunnel for(int i = 0; i < numHops; i++ ) { - auto hop = nextHop (prevHop); + auto hop = nextHop (prevHop, inbound); if (!hop) { LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); @@ -438,7 +438,7 @@ namespace tunnel if (inbound && (i == numHops - 1) && !hop->IsReachable ()) { // if first is not reachable try again - auto hop1 = nextHop (prevHop); + auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; } prevHop = hop; @@ -460,7 +460,7 @@ namespace tunnel } // explicit peers in use if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); - return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1)); + return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2)); } bool TunnelPool::SelectExplicitPeers (std::vector >& peers, bool isInbound) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 4742a1f6..5fd1d83c 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -46,7 +46,7 @@ namespace tunnel }; - typedef std::function(std::shared_ptr)> SelectHopFunc; + typedef std::function(std::shared_ptr, bool)> SelectHopFunc; // standard peer selection algorithm bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop); @@ -104,7 +104,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) const; + std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; private: diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 4ffa7442..c0766096 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -72,7 +72,8 @@ namespace client bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) { auto pool = GetTunnelPool(); - if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1))) + if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, + std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) return false; // more here for outbound tunnels if(!inbound && m_RemoteLeaseSet)