don't rely on inbound/outbound tunnels if no peer tests for a long time

This commit is contained in:
orignal
2026-02-19 14:37:44 -05:00
parent 4e11c3f11b
commit 3b388fb3ef
2 changed files with 43 additions and 20 deletions
+37 -16
View File
@@ -59,7 +59,9 @@ namespace tunnel
m_InboundVariance = (m_NumInboundHops < STANDARD_NUM_RECORDS) ? STANDARD_NUM_RECORDS - m_NumInboundHops : 0;
if (m_OutboundVariance > 0 && m_NumOutboundHops + m_OutboundVariance > STANDARD_NUM_RECORDS)
m_OutboundVariance = (m_NumOutboundHops < STANDARD_NUM_RECORDS) ? STANDARD_NUM_RECORDS - m_NumOutboundHops : 0;
m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL;
auto ts = i2p::util::GetSecondsSinceEpoch ();
m_LastTunnelTestTime = ts;
m_NextManageTime = ts + rand () % TUNNEL_POOL_MANAGE_INTERVAL;
}
TunnelPool::~TunnelPool ()
@@ -293,6 +295,11 @@ namespace tunnel
}
void TunnelPool::CreateTunnels ()
{
CreateTunnels (i2p::util::GetSecondsSinceEpoch ());
}
void TunnelPool::CreateTunnels (uint64_t ts)
{
int num = 0;
{
@@ -305,7 +312,7 @@ namespace tunnel
{
if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS;
for (int i = 0; i < num; i++)
CreateOutboundTunnel ();
CreateOutboundTunnel (ts);
}
num = 0;
@@ -330,14 +337,14 @@ namespace tunnel
{
if (num > TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS) num = TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS;
for (int i = 0; i < num; i++)
CreateInboundTunnel ();
CreateInboundTunnel (ts);
}
if (num < m_NumInboundTunnels && m_NumInboundHops <= 0 && m_LocalDestination) // zero hops IB
m_LocalDestination->SetLeaseSetUpdated (true); // update LeaseSet immediately
}
void TunnelPool::TestTunnels ()
void TunnelPool::TestTunnels (uint64_t ts)
{
decltype(m_Tests) tests;
{
@@ -360,7 +367,7 @@ namespace tunnel
else
{
it.second.first->SetState (eTunnelStateTestFailed);
CreateOutboundTunnel (); // create new tunnel immediately because last one failed
CreateOutboundTunnel (ts); // create new tunnel immediately because last one failed
}
}
else if (it.second.first->GetState () != eTunnelStateExpiring)
@@ -383,7 +390,7 @@ namespace tunnel
else
{
it.second.second->SetState (eTunnelStateTestFailed);
CreateInboundTunnel (); // create new tunnel immediately because last one failed
CreateInboundTunnel (ts); // create new tunnel immediately because last one failed
}
}
if (failed && m_LocalDestination)
@@ -423,6 +430,10 @@ namespace tunnel
newTests.push_back(std::make_pair (*it1, *it2));
++it1; ++it2;
}
if (!newTests.empty ())
m_LastTunnelTestTime = ts;
else
return;
bool isECIES = m_LocalDestination->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
for (auto& it: newTests)
{
@@ -472,8 +483,8 @@ namespace tunnel
{
if (ts > m_NextManageTime || ts + 2*TUNNEL_POOL_MANAGE_INTERVAL < m_NextManageTime) // in case if clock was adjusted
{
CreateTunnels ();
TestTunnels ();
CreateTunnels (ts);
TestTunnels (ts);
m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (tunnels.GetRng ()() % TUNNEL_POOL_MANAGE_INTERVAL)/2;
}
}
@@ -732,13 +743,15 @@ namespace tunnel
return r;
}
void TunnelPool::CreateInboundTunnel ()
void TunnelPool::CreateInboundTunnel (uint64_t ts)
{
LogPrint (eLogDebug, "Tunnels: Creating destination inbound tunnel...");
Path path;
if (SelectPeers (path, true))
{
auto outboundTunnel = GetNextOutboundTunnel (nullptr, path.farEndTransports);
// if we didn't run tunnel tests for a long time outbound tunnels might be dead
auto outboundTunnel = (ts < m_LastTunnelTestTime + TUNNEL_POOL_TUNNEL_TESTS_VALIDITY_INTERVAL) ?
GetNextOutboundTunnel (nullptr, path.farEndTransports) : nullptr;
if (!outboundTunnel)
outboundTunnel = tunnels.GetNextOutboundTunnel ();
std::shared_ptr<TunnelConfig> config;
@@ -757,12 +770,15 @@ namespace tunnel
void TunnelPool::RecreateInboundTunnel (std::shared_ptr<InboundTunnel> tunnel)
{
auto ts = i2p::util::GetSecondsSinceEpoch ();
if (IsExploratory () || tunnel->IsSlow ()) // always create new exploratory tunnel or if slow
{
CreateInboundTunnel ();
CreateInboundTunnel (ts);
return;
}
auto outboundTunnel = GetNextOutboundTunnel (nullptr, tunnel->GetFarEndTransports ());
// if we didn't run tunnel tests for a long time outbound tunnels might be dead
auto outboundTunnel = (ts < m_LastTunnelTestTime + TUNNEL_POOL_TUNNEL_TESTS_VALIDITY_INTERVAL) ?
GetNextOutboundTunnel (nullptr, tunnel->GetFarEndTransports ()) : nullptr;
if (!outboundTunnel)
outboundTunnel = tunnels.GetNextOutboundTunnel ();
LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel...");
@@ -784,13 +800,15 @@ namespace tunnel
}
}
void TunnelPool::CreateOutboundTunnel ()
void TunnelPool::CreateOutboundTunnel (uint64_t ts)
{
LogPrint (eLogDebug, "Tunnels: Creating destination outbound tunnel...");
Path path;
if (SelectPeers (path, false))
{
auto inboundTunnel = GetNextInboundTunnel (nullptr, path.farEndTransports);
// if we didn't run tunnel tests for a long time inbound tunnels might be dead
auto inboundTunnel = (ts < m_LastTunnelTestTime + TUNNEL_POOL_TUNNEL_TESTS_VALIDITY_INTERVAL) ?
GetNextInboundTunnel (nullptr, path.farEndTransports) : nullptr;
if (!inboundTunnel)
inboundTunnel = tunnels.GetNextInboundTunnel ();
if (!inboundTunnel)
@@ -825,12 +843,15 @@ namespace tunnel
void TunnelPool::RecreateOutboundTunnel (std::shared_ptr<OutboundTunnel> tunnel)
{
auto ts = i2p::util::GetSecondsSinceEpoch ();
if (IsExploratory () || tunnel->IsSlow ()) // always create new exploratory tunnel or if slow
{
CreateOutboundTunnel ();
CreateOutboundTunnel (ts);
return;
}
auto inboundTunnel = GetNextInboundTunnel (nullptr, tunnel->GetFarEndTransports ());
// if we didn't run tunnel tests for a long time inbound tunnels might be dead
auto inboundTunnel = (ts < m_LastTunnelTestTime + TUNNEL_POOL_TUNNEL_TESTS_VALIDITY_INTERVAL) ?
GetNextInboundTunnel (nullptr, tunnel->GetFarEndTransports ()) : nullptr;
if (!inboundTunnel)
inboundTunnel = tunnels.GetNextInboundTunnel ();
if (inboundTunnel)
+6 -4
View File
@@ -28,6 +28,7 @@ namespace i2p
namespace tunnel
{
const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds
const int TUNNEL_POOL_TUNNEL_TESTS_VALIDITY_INTERVAL = 3*TUNNEL_POOL_MANAGE_INTERVAL; // 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 = 3;
@@ -121,9 +122,10 @@ namespace tunnel
private:
void TestTunnels ();
void CreateInboundTunnel ();
void CreateOutboundTunnel ();
void TestTunnels (uint64_t ts);
void CreateTunnels (uint64_t ts);
void CreateInboundTunnel (uint64_t ts);
void CreateOutboundTunnel (uint64_t ts);
void CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel);
template<class TTunnels>
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels,
@@ -146,7 +148,7 @@ namespace tunnel
mutable std::mutex m_TestsMutex;
std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
bool m_IsActive, m_IsHighBandwidth;
uint64_t m_NextManageTime; // in seconds
uint64_t m_NextManageTime, m_LastTunnelTestTime; // in seconds
std::mutex m_CustomPeerSelectorMutex;
ITunnelPeerSelector * m_CustomPeerSelector;