|
|
|
@ -24,6 +24,22 @@ namespace i2p
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 |
|
|
|
|