use short tunnel build if possible

pull/1677/head
orignal 3 years ago
parent 28369faa00
commit c153471c49

@ -45,6 +45,7 @@ namespace data
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36
const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 38); // 0.9.38
const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51
/** function for visiting a leaseset stored in a floodfill */
typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor;

@ -24,6 +24,22 @@ namespace i2p
{
namespace tunnel
{
void Path::Add (std::shared_ptr<const i2p::data::RouterInfo> r)
{
if (r)
{
peers.push_back (r->GetRouterIdentity ());
if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION ||
r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
isShort = false;
}
}
void Path::Reverse ()
{
std::reverse (peers.begin (), peers.end ());
}
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
@ -420,7 +436,7 @@ namespace tunnel
return hop;
}
bool StandardSelectPeers(Path & peers, int numHops, bool inbound, SelectHopFunc nextHop)
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop)
{
int start = 0;
std::shared_ptr<const i2p::data::RouterInfo> prevHop = i2p::context.GetSharedRouterInfo ();
@ -429,7 +445,7 @@ namespace tunnel
/** if routes are restricted prepend trusted first hop */
auto hop = i2p::transport::transports.GetRestrictedPeer();
if(!hop) return false;
peers.push_back(hop->GetRouterIdentity());
path.Add (hop);
prevHop = hop;
start++;
}
@ -441,7 +457,7 @@ namespace tunnel
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable
{
prevHop = r;
peers.push_back (r->GetRouterIdentity ());
path.Add (r);
start++;
}
}
@ -466,12 +482,12 @@ namespace tunnel
if (hop1) hop = hop1;
}
prevHop = hop;
peers.push_back (hop->GetRouterIdentity ());
path.Add (hop);
}
return true;
}
bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
bool TunnelPool::SelectPeers (Path& path, bool isInbound)
{
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
// peers is empty
@ -480,14 +496,14 @@ namespace tunnel
{
std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
if (m_CustomPeerSelector)
return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound);
}
// explicit peers in use
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
if (m_ExplicitPeers) return SelectExplicitPeers (path, isInbound);
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
}
bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound)
{
int size = m_ExplicitPeers->size ();
std::vector<int> peerIndicies;
@ -500,7 +516,7 @@ namespace tunnel
auto& ident = (*m_ExplicitPeers)[peerIndicies[i]];
auto r = i2p::data::netdb.FindRouter (ident);
if (r)
peers.push_back (r->GetRouterIdentity ());
path.Add (r);
else
{
LogPrint (eLogInfo, "Tunnels: Can't find router for ", ident.ToBase64 ());
@ -517,14 +533,14 @@ namespace tunnel
if (!outboundTunnel)
outboundTunnel = tunnels.GetNextOutboundTunnel ();
LogPrint (eLogDebug, "Tunnels: Creating destination inbound tunnel...");
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
if (SelectPeers (peers, true))
Path path;
if (SelectPeers (path, true))
{
std::shared_ptr<TunnelConfig> config;
if (m_NumInboundHops > 0)
{
std::reverse (peers.begin (), peers.end ());
config = std::make_shared<TunnelConfig> (peers);
path.Reverse ();
config = std::make_shared<TunnelConfig> (path.peers, path.isShort);
}
auto tunnel = tunnels.CreateInboundTunnel (config, shared_from_this (), outboundTunnel);
if (tunnel->IsEstablished ()) // zero hops
@ -566,14 +582,23 @@ namespace tunnel
if (inboundTunnel)
{
LogPrint (eLogDebug, "Tunnels: Creating destination outbound tunnel...");
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
if (SelectPeers (peers, false))
Path path;
if (SelectPeers (path, false))
{
std::shared_ptr<TunnelConfig> config;
if (m_NumOutboundHops > 0)
config = std::make_shared<TunnelConfig>(peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
auto tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ());
if (tunnel->IsEstablished ()) // zero hops
config = std::make_shared<TunnelConfig>(path.peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash (), path.isShort);
std::shared_ptr<OutboundTunnel> tunnel;
if (path.isShort)
{
// TODO: implement it better
tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ());
tunnel->SetTunnelPool (shared_from_this ());
}
else
tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ());
if (tunnel && tunnel->IsEstablished ()) // zero hops
TunnelCreated (tunnel);
}
else

@ -36,7 +36,14 @@ namespace tunnel
class OutboundTunnel;
typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
typedef std::vector<Peer> Path;
struct Path
{
std::vector<Peer> peers;
bool isShort = true;
void Add (std::shared_ptr<const i2p::data::RouterInfo> r);
void Reverse ();
};
/** interface for custom tunnel peer selection algorithm */
struct ITunnelPeerSelector
@ -47,9 +54,8 @@ namespace tunnel
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool)> SelectHopFunc;
// standard peer selection algorithm
bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop);
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop);
class TunnelPool: public std::enable_shared_from_this<TunnelPool> // per local destination
{
public:
@ -114,8 +120,8 @@ namespace tunnel
void CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel);
template<class TTunnels>
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const;
bool SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& hops, bool isInbound);
bool SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& hops, bool isInbound);
bool SelectPeers (Path& path, bool isInbound);
bool SelectExplicitPeers (Path& path, bool isInbound);
private:

@ -79,23 +79,23 @@ namespace client
if(!inbound && m_RemoteLeaseSet)
{
if(m_RemoteLeaseSet->IsExpired())
{
ResolveCurrentLeaseSet();
}
if(m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired())
{
// remote lease set is good
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases();
// pick lease
std::shared_ptr<i2p::data::RouterInfo> obep;
while(!obep && leases.size() > 0) {
while(!obep && leases.size() > 0)
{
auto idx = rand() % leases.size();
auto lease = leases[idx];
obep = i2p::data::netdb.FindRouter(lease->tunnelGateway);
leases.erase(leases.begin()+idx);
}
if(obep) {
path.push_back(obep->GetRouterIdentity());
if(obep)
{
path.Add (obep);
LogPrint(eLogDebug, "Destination: found OBEP matching IBGW");
} else
LogPrint(eLogWarning, "Destination: could not find proper IBGW for matched outbound tunnel");

Loading…
Cancel
Save