implement i2p.streaming.profile to specify high or low bandwidth tunnel pools

This commit is contained in:
orignal 2024-09-19 21:16:16 -04:00
parent 5324197e43
commit 9f30499984
9 changed files with 44 additions and 25 deletions

View File

@ -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<std::vector<i2p::data::IdentHash> > 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)

View File

@ -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<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;

View File

@ -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<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> 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<const RouterInfo> router)->bool
[compatibleWith, reverse, endpoint, clientTunnel, checkIsReal](std::shared_ptr<const RouterInfo> 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)
});
}

View File

@ -87,7 +87,7 @@ namespace data
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true);
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint, bool clientTunnel) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::unordered_set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::unordered_set<IdentHash>& excluded) const;

View File

@ -411,10 +411,12 @@ namespace tunnel
return tunnel;
}
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops,
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance)
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops,
int numOutboundHops, int numInboundTunnels, int numOutboundTunnels,
int inboundVariance, int outboundVariance, bool isHighBandwidth)
{
auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance);
auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops,
numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance, isHighBandwidth);
std::unique_lock<std::mutex> 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<OutboundTunnel> (
@ -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;

View File

@ -232,8 +232,9 @@ namespace tunnel
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel);
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops, int numOuboundHops,
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance);
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops,
int numOuboundHops, int numInboundTunnels, int numOutboundTunnels,
int inboundVariance, int outboundVariance, bool isHighBandwidth);
void DeleteTunnelPool (std::shared_ptr<TunnelPool> pool);
void StopTunnelPool (std::shared_ptr<TunnelPool> pool);

View File

@ -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<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
bool reverse, bool endpoint) const
{
bool tryHighBandwidth = !IsExploratory ();
bool tryClient = !IsExploratory ();
std::shared_ptr<const i2p::data::RouterInfo> 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;
}

View File

@ -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<i2p::garlic::GarlicDestination> GetLocalDestination () const { return m_LocalDestination; };
@ -146,7 +146,7 @@ namespace tunnel
std::set<std::shared_ptr<OutboundTunnel>, TunnelCreationTimeCmp> m_OutboundTunnels;
mutable std::mutex m_TestsMutex;
std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
bool m_IsActive;
bool m_IsActive, m_IsHighBandwidth;
uint64_t m_NextManageTime; // in seconds
std::mutex m_CustomPeerSelectorMutex;
ITunnelPeerSelector * m_CustomPeerSelector;

View File

@ -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 ()