implemented trustedRouters tunnel param

This commit is contained in:
orignal
2026-01-18 17:25:47 -05:00
parent 837b0db803
commit 0518d8ff43
5 changed files with 82 additions and 33 deletions
+6
View File
@@ -41,6 +41,7 @@ namespace client
int numTags = DEFAULT_TAGS_TO_SEND;
bool isHighBandwidth = true;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
std::vector<i2p::data::IdentHash> trustedRouters;
try
{
if (params)
@@ -63,6 +64,9 @@ namespace client
auto explicitPeersStr = (*params)[I2CP_PARAM_EXPLICIT_PEERS];
if (!explicitPeersStr.empty ())
explicitPeers = std::make_shared<std::vector<i2p::data::IdentHash> > (i2p::data::ExtractIdentHashes (explicitPeersStr));
auto trustedRoutersStr = (*params)[I2CP_PARAM_TRUSTED_ROUTERS];
if (!trustedRoutersStr.empty ())
trustedRouters = i2p::data::ExtractIdentHashes (trustedRoutersStr);
m_Nickname = (*params)[I2CP_PARAM_INBOUND_NICKNAME];
if (m_Nickname.empty ()) // try outbound
@@ -105,6 +109,8 @@ namespace client
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar, isHighBandwidth);
if (explicitPeers)
m_Pool->SetExplicitPeers (explicitPeers);
if (!trustedRouters.empty ())
m_Pool->SetTrustedRouters (trustedRouters);
if(params)
{
int maxLatency = 0;
+1
View File
@@ -64,6 +64,7 @@ namespace client
const char I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE[] = "outbound.lengthVariance";
const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0;
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
const char I2CP_PARAM_TRUSTED_ROUTERS[] = "trustedRouters";
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
const int DEFAULT_TAGS_TO_SEND = 40;
+67 -30
View File
@@ -88,6 +88,11 @@ namespace tunnel
}
}
void TunnelPool::SetTrustedRouters (std::vector<i2p::data::IdentHash> routers)
{
m_TrustedRouters.swap (routers);
}
void TunnelPool::DetachTunnels ()
{
{
@@ -105,7 +110,7 @@ namespace tunnel
{
std::unique_lock<std::mutex> l(m_TestsMutex);
m_Tests.clear ();
}
}
}
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)
@@ -152,7 +157,7 @@ namespace tunnel
std::unique_lock<std::mutex> l(m_TestsMutex);
for (auto& it: m_Tests)
if (it.second.second == expiredTunnel) it.second.second = nullptr;
}
}
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
m_InboundTunnels.erase (expiredTunnel);
@@ -177,7 +182,7 @@ namespace tunnel
std::unique_lock<std::mutex> l(m_TestsMutex);
for (auto& it: m_Tests)
if (it.second.first == expiredTunnel) it.second.first = nullptr;
}
}
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
m_OutboundTunnels.erase (expiredTunnel);
@@ -280,10 +285,10 @@ namespace tunnel
}
if (!tunnel)
{
{
tunnel = GetNextOutboundTunnel ();
freshTunnel = true;
}
}
return std::make_pair(tunnel, freshTunnel);
}
@@ -309,7 +314,7 @@ 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)
@@ -353,10 +358,10 @@ namespace tunnel
if (m_OutboundTunnels.size () > 1) // don't fail last tunnel
m_OutboundTunnels.erase (it.second.first);
else
{
{
it.second.first->SetState (eTunnelStateTestFailed);
CreateOutboundTunnel (); // create new tunnel immediately because last one failed
}
}
}
else if (it.second.first->GetState () != eTunnelStateExpiring)
it.second.first->SetState (eTunnelStateTestFailed);
@@ -371,15 +376,15 @@ namespace tunnel
{
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
if (m_InboundTunnels.size () > 1) // don't fail last tunnel
{
{
m_InboundTunnels.erase (it.second.second);
failed = true;
}
failed = true;
}
else
{
it.second.second->SetState (eTunnelStateTestFailed);
CreateInboundTunnel (); // create new tunnel immediately because last one failed
}
}
}
if (failed && m_LocalDestination)
m_LocalDestination->SetLeaseSetUpdated (true);
@@ -393,7 +398,7 @@ namespace tunnel
}
// new tests
if (!m_LocalDestination) return;
if (!m_LocalDestination) return;
std::vector<std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > newTests;
std::vector<std::shared_ptr<OutboundTunnel> > outboundTunnels;
{
@@ -447,7 +452,7 @@ namespace tunnel
if (isECIES)
{
uint8_t key[32]; RAND_bytes (key, 32);
uint64_t tag; RAND_bytes ((uint8_t *)&tag, 8);
uint64_t tag; RAND_bytes ((uint8_t *)&tag, 8);
m_LocalDestination->SubmitECIESx25519Key (key, tag);
msg = i2p::garlic::WrapECIESX25519Message (msg, key, tag);
}
@@ -458,9 +463,9 @@ namespace tunnel
m_LocalDestination->SubmitSessionKey (key, tag);
i2p::garlic::ElGamalAESSession garlic (key, tag);
msg = garlic.WrapSingleMessage (msg);
}
}
outbound->SendTunnelDataMsgTo (it.second->GetNextIdentHash (), it.second->GetNextTunnelID (), msg);
}
}
}
void TunnelPool::ManageTunnels (uint64_t ts)
@@ -544,14 +549,14 @@ namespace tunnel
}
}
return found;
}
}
bool TunnelPool::IsExploratory () const
{
return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ();
}
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
bool reverse, bool endpoint) const
{
bool tryClient = !IsExploratory () && !i2p::context.IsLimitedConnectivity ();
@@ -560,7 +565,7 @@ namespace tunnel
{
hop = tryClient ?
(m_IsHighBandwidth ?
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) :
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)
@@ -580,10 +585,11 @@ namespace tunnel
{
int start = 0;
std::shared_ptr<const i2p::data::RouterInfo> prevHop = i2p::context.GetSharedRouterInfo ();
if(i2p::transport::transports.RoutesRestricted())
if(i2p::transport::transports.RoutesRestricted() || !m_TrustedRouters.empty ())
{
/** if routes are restricted prepend trusted first hop */
auto hop = i2p::transport::transports.GetRestrictedPeer();
/** if routes are restricted or trusted prepend trusted first hop */
auto hop = (!m_TrustedRouters.empty ()) ? SelectTrustedRouter (inbound) :
i2p::transport::transports.GetRestrictedPeer ();
if(!hop) return false;
path.Add (hop);
prevHop = hop;
@@ -658,7 +664,7 @@ namespace tunnel
if (m_CustomPeerSelector)
return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound);
}
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this,
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
@@ -695,6 +701,37 @@ namespace tunnel
return true;
}
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectTrustedRouter (bool inbound) const
{
size_t count = m_TrustedRouters.size ();
if (!count) return nullptr;
std::shared_ptr<const i2p::data::RouterInfo> r;
int ind = tunnels.GetRng ()() % count;
for (size_t i = 0; i < count; i++)
{
auto& ident = m_TrustedRouters[(ind + i) % count];
if (inbound)
{
if (i2p::transport::transports.IsConnected (ident))
{
r = i2p::data::netdb.FindRouter (ident);
break;
}
}
else
{
auto r1 = i2p::data::netdb.FindRouter (ident);
if (!r1) i2p::data::netdb.RequestDestination (ident, nullptr); // request one if not in NetDB
if (r1 && !r1->IsUnreachable () && r1->IsReachableFrom (i2p::context.GetRouterInfo ()))
{
r = r1;
break;
}
}
}
return r;
}
void TunnelPool::CreateInboundTunnel ()
{
LogPrint (eLogDebug, "Tunnels: Creating destination inbound tunnel...");
@@ -734,9 +771,9 @@ namespace tunnel
{
auto peers = tunnel->GetPeers();
if (peers.size ()&& ValidatePeers (peers))
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (),
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (),
tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ());
}
}
if (!m_NumInboundHops || config)
{
auto newTunnel = tunnels.CreateInboundTunnel (config, shared_from_this(), outboundTunnel);
@@ -856,11 +893,11 @@ namespace tunnel
{
if (r->IsHighCongestion (highBandwidth)) return false;
it = r->GetIdentity (); // use identity from updated RouterInfo
}
}
}
}
return true;
}
}
std::shared_ptr<InboundTunnel> TunnelPool::GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude) const
{
std::shared_ptr<InboundTunnel> tun = nullptr;
+6 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2026, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -67,6 +67,7 @@ namespace tunnel
std::shared_ptr<i2p::garlic::GarlicDestination> GetLocalDestination () const { return m_LocalDestination; };
void SetLocalDestination (std::shared_ptr<i2p::garlic::GarlicDestination> destination) { m_LocalDestination = destination; };
void SetExplicitPeers (std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers);
void SetTrustedRouters (std::vector<i2p::data::IdentHash> routers);
void CreateTunnels ();
void TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel);
@@ -117,7 +118,7 @@ namespace tunnel
// for overriding tunnel peer selection
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse, bool endpoint) const;
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop);
private:
void TestTunnels ();
@@ -130,6 +131,7 @@ namespace tunnel
bool SelectPeers (Path& path, bool isInbound);
bool SelectExplicitPeers (Path& path, bool isInbound);
bool ValidatePeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers) const;
std::shared_ptr<const i2p::data::RouterInfo> SelectTrustedRouter (bool inbound) const;
private:
@@ -137,6 +139,7 @@ namespace tunnel
int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels,
m_InboundVariance, m_OutboundVariance;
std::shared_ptr<std::vector<i2p::data::IdentHash> > m_ExplicitPeers;
std::vector<i2p::data::IdentHash> m_TrustedRouters;
mutable std::mutex m_InboundTunnelsMutex;
std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
mutable std::mutex m_OutboundTunnelsMutex;
@@ -150,7 +153,7 @@ namespace tunnel
int m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
int m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
public:
// for HTTP only
+2
View File
@@ -503,6 +503,8 @@ namespace client
}
std::string explicitPeers = GetI2CPStringOption(section, I2CP_PARAM_EXPLICIT_PEERS, "");
if (explicitPeers.length () > 0) options.Insert (I2CP_PARAM_EXPLICIT_PEERS, explicitPeers);
std::string trustedRouters = GetI2CPStringOption(section, I2CP_PARAM_TRUSTED_ROUTERS, "");
if (trustedRouters.length () > 0) options.Insert (I2CP_PARAM_TRUSTED_ROUTERS, trustedRouters);
std::string ratchetInboundTags = GetI2CPStringOption(section, I2CP_PARAM_RATCHET_INBOUND_TAGS, "");
if (ratchetInboundTags.length () > 0) options.Insert (I2CP_PARAM_RATCHET_INBOUND_TAGS, ratchetInboundTags);
}