Browse Source

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

pull/2101/head
orignal 2 months ago
parent
commit
9f30499984
  1. 8
      libi2pd/Destination.cpp
  2. 4
      libi2pd/Destination.h
  3. 11
      libi2pd/NetDb.cpp
  4. 2
      libi2pd/NetDb.hpp
  5. 14
      libi2pd/Tunnel.cpp
  6. 5
      libi2pd/Tunnel.h
  7. 18
      libi2pd/TunnelPool.cpp
  8. 4
      libi2pd/TunnelPool.h
  9. 3
      libi2pd_client/ClientContext.cpp

8
libi2pd/Destination.cpp

@ -37,6 +37,7 @@ namespace client
int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE; int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE;
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE; int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
int numTags = DEFAULT_TAGS_TO_SEND; int numTags = DEFAULT_TAGS_TO_SEND;
bool isHighBandwidth = true;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers; std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
try try
{ {
@ -92,7 +93,7 @@ namespace client
it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET); it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET);
if (it != params->end ()) if (it != params->end ())
{ {
// oveeride isPublic // override isPublic
m_IsPublic = (it->second != "true"); m_IsPublic = (it->second != "true");
} }
it = params->find (I2CP_PARAM_LEASESET_TYPE); it = params->find (I2CP_PARAM_LEASESET_TYPE);
@ -121,6 +122,9 @@ namespace client
m_LeaseSetPrivKey.reset (nullptr); 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) catch (std::exception & ex)
@ -128,7 +132,7 @@ namespace client
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
} }
SetNumTags (numTags); 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) if (explicitPeers)
m_Pool->SetExplicitPeers (explicitPeers); m_Pool->SetExplicitPeers (explicitPeers);
if(params) if(params)

4
libi2pd/Destination.h

@ -90,6 +90,10 @@ namespace client
const int DEFAULT_MAX_INBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s 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 char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
const int DEFAULT_ANSWER_PINGS = true; 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; typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;

11
libi2pd/NetDb.cpp

@ -69,7 +69,7 @@ namespace data
{ {
Reseed (); 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 Reseed (); // we don't have a router we can connect to. Trying to reseed
auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); 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, 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 ( 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 && return !router->IsHidden () && router != compatibleWith &&
(reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)):
router->IsReachableFrom (*compatibleWith)) && !router->IsNAT2NATOnly (*compatibleWith) && 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) (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse)
}); });
} }

2
libi2pd/NetDb.hpp

@ -87,7 +87,7 @@ namespace data
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true); 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 () 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> 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> 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; std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::unordered_set<IdentHash>& excluded) const;

14
libi2pd/Tunnel.cpp

@ -411,10 +411,12 @@ namespace tunnel
return tunnel; return tunnel;
} }
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops,
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance) 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); std::unique_lock<std::mutex> l(m_PoolsMutex);
m_Pools.push_back (pool); m_Pools.push_back (pool);
return pool; return pool;
@ -705,7 +707,7 @@ namespace tunnel
auto inboundTunnel = GetNextInboundTunnel (); auto inboundTunnel = GetNextInboundTunnel ();
auto router = i2p::transport::transports.RoutesRestricted() ? auto router = i2p::transport::transports.RoutesRestricted() ?
i2p::transport::transports.GetRestrictedPeer() : 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; if (!inboundTunnel || !router) return;
LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel");
CreateTunnel<OutboundTunnel> ( CreateTunnel<OutboundTunnel> (
@ -765,7 +767,7 @@ namespace tunnel
int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen); int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen);
int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum); int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum);
int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum); 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 ()); m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ());
} }
return; return;
@ -777,7 +779,7 @@ namespace tunnel
auto router = i2p::transport::transports.RoutesRestricted() ? auto router = i2p::transport::transports.RoutesRestricted() ?
i2p::transport::transports.GetRestrictedPeer() : i2p::transport::transports.GetRestrictedPeer() :
// should be reachable by us because we send build request directly // 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) { if (!router) {
LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel");
return; return;

5
libi2pd/Tunnel.h

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

18
libi2pd/TunnelPool.cpp

@ -41,11 +41,11 @@ namespace tunnel
} }
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, 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_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance), 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) m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL)
{ {
if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) 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, std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
bool reverse, bool endpoint) const bool reverse, bool endpoint) const
{ {
bool tryHighBandwidth = !IsExploratory (); bool tryClient = !IsExploratory ();
std::shared_ptr<const i2p::data::RouterInfo> hop; std::shared_ptr<const i2p::data::RouterInfo> hop;
for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++)
{ {
hop = tryHighBandwidth ? hop = tryClient ?
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : (m_IsHighBandwidth ?
i2p::data::netdb.GetRandomRouter (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) if (hop)
{ {
if (!hop->GetProfile ()->IsBad ()) if (!hop->GetProfile ()->IsBad ())
break; break;
} }
else if (tryHighBandwidth) else if (tryClient)
tryHighBandwidth = false; tryClient = false;
else else
return nullptr; return nullptr;
} }

4
libi2pd/TunnelPool.h

@ -62,7 +62,7 @@ namespace tunnel
public: public:
TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels,
int numOutboundTunnels, int inboundVariance, int outboundVariance); int numOutboundTunnels, int inboundVariance, int outboundVariance, bool isHighBandwidth);
~TunnelPool (); ~TunnelPool ();
std::shared_ptr<i2p::garlic::GarlicDestination> GetLocalDestination () const { return m_LocalDestination; }; 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; std::set<std::shared_ptr<OutboundTunnel>, TunnelCreationTimeCmp> m_OutboundTunnels;
mutable std::mutex m_TestsMutex; mutable std::mutex m_TestsMutex;
std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests; 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 uint64_t m_NextManageTime; // in seconds
std::mutex m_CustomPeerSelectorMutex; std::mutex m_CustomPeerSelectorMutex;
ITunnelPeerSelector * m_CustomPeerSelector; ITunnelPeerSelector * m_CustomPeerSelector;

3
libi2pd_client/ClientContext.cpp

@ -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_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_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_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); 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"); 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; if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType;
@ -519,6 +520,8 @@ namespace client
options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = value; options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = value;
if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_PRIV_KEY, value) && !value.empty ()) if (i2p::config::GetOption(prefix + I2CP_PARAM_LEASESET_PRIV_KEY, value) && !value.empty ())
options[I2CP_PARAM_LEASESET_PRIV_KEY] = value; 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 () void ClientContext::ReadTunnels ()

Loading…
Cancel
Save