|
|
|
@ -169,7 +169,9 @@ namespace datagram
@@ -169,7 +169,9 @@ namespace datagram
|
|
|
|
|
const i2p::data::IdentHash & remoteIdent) : |
|
|
|
|
m_LocalDestination(localDestination), |
|
|
|
|
m_RemoteIdentity(remoteIdent), |
|
|
|
|
m_LastUse(i2p::util::GetMillisecondsSinceEpoch()) |
|
|
|
|
m_LastUse(i2p::util::GetMillisecondsSinceEpoch ()), |
|
|
|
|
m_LastPathChange(0), |
|
|
|
|
m_LastSuccess(0) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -186,16 +188,14 @@ namespace datagram
@@ -186,16 +188,14 @@ namespace datagram
|
|
|
|
|
// do we have a routing session?
|
|
|
|
|
if(m_RoutingSession) |
|
|
|
|
{ |
|
|
|
|
// do we have a routing path ?
|
|
|
|
|
auto routingPath = m_RoutingSession->GetSharedRoutingPath(); |
|
|
|
|
if(!routingPath) |
|
|
|
|
// should we switch paths?
|
|
|
|
|
if(ShouldUpdateRoutingPath ()) |
|
|
|
|
{ |
|
|
|
|
LogPrint(eLogDebug, "DatagramSession: try getting new routing path"); |
|
|
|
|
// no routing path, try getting one
|
|
|
|
|
routingPath = GetNextRoutingPath(); |
|
|
|
|
if(routingPath) // remember the routing path if we got one
|
|
|
|
|
m_RoutingSession->SetSharedRoutingPath(routingPath); |
|
|
|
|
// try switching paths
|
|
|
|
|
UpdateRoutingPath (GetNextRoutingPath ()); |
|
|
|
|
} |
|
|
|
|
auto routingPath = m_RoutingSession->GetSharedRoutingPath (); |
|
|
|
|
// make sure we have a routing path
|
|
|
|
|
if (routingPath) |
|
|
|
|
{ |
|
|
|
@ -204,6 +204,7 @@ namespace datagram
@@ -204,6 +204,7 @@ namespace datagram
|
|
|
|
|
{ |
|
|
|
|
if(outboundTunnel->IsEstablished()) |
|
|
|
|
{ |
|
|
|
|
m_LastSuccess = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
// we have a routing path and routing session and the outbound tunnel we are using is good
|
|
|
|
|
// wrap message with routing session and send down routing path's outbound tunnel wrapped for the IBGW
|
|
|
|
|
auto m = m_RoutingSession->WrapSingleMessage(msg); |
|
|
|
@ -217,12 +218,49 @@ namespace datagram
@@ -217,12 +218,49 @@ namespace datagram
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// we couldn't send so let's try resetting the routing path and updating lease set
|
|
|
|
|
ResetRoutingPath(); |
|
|
|
|
auto now = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
// if this path looks dead reset the routing path since we didn't seem to be able to get a path in time
|
|
|
|
|
if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath(); |
|
|
|
|
UpdateLeaseSet(msg); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DatagramSession::UpdateRoutingPath(const std::shared_ptr<i2p::garlic::GarlicRoutingPath> & path) |
|
|
|
|
{ |
|
|
|
|
// we can't update routing path because we have no routing session
|
|
|
|
|
if(!m_RoutingSession) return; |
|
|
|
|
// set routing path and update time we last updated the routing path
|
|
|
|
|
m_RoutingSession->SetSharedRoutingPath (path); |
|
|
|
|
m_LastPathChange = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool DatagramSession::ShouldUpdateRoutingPath() const |
|
|
|
|
{ |
|
|
|
|
auto now = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
// we need to rotate paths becuase the routing path is too old
|
|
|
|
|
if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; |
|
|
|
|
// our path looks dead so we need to rotate paths
|
|
|
|
|
if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return true; |
|
|
|
|
// if we have a routing session and routing path we don't need to switch paths
|
|
|
|
|
return m_RoutingSession != nullptr && m_RoutingSession->GetSharedRoutingPath () != nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DatagramSession::ShouldSwitchLease() const |
|
|
|
|
{ |
|
|
|
|
auto now = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
std::shared_ptr<i2p::garlic::GarlicRoutingPath> routingPath = nullptr; |
|
|
|
|
std::shared_ptr<const i2p::data::Lease> currentLease = nullptr; |
|
|
|
|
if(m_RoutingSession) |
|
|
|
|
routingPath = m_RoutingSession->GetSharedRoutingPath (); |
|
|
|
|
if(routingPath) |
|
|
|
|
currentLease = routingPath->remoteLease; |
|
|
|
|
if(currentLease) // if we have a lease return true if it's about to expire otherwise return false
|
|
|
|
|
return now - currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); |
|
|
|
|
// we have no current lease, we should switch
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetNextRoutingPath() |
|
|
|
|
{ |
|
|
|
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel = nullptr; |
|
|
|
@ -241,8 +279,6 @@ namespace datagram
@@ -241,8 +279,6 @@ namespace datagram
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels
|
|
|
|
|
// don't reuse the old path as we are making a new one
|
|
|
|
|
routingPath = nullptr; |
|
|
|
|
} |
|
|
|
|
// do we have an outbound tunnel that works already ?
|
|
|
|
|
if(!outboundTunnel) |
|
|
|
@ -250,8 +286,18 @@ namespace datagram
@@ -250,8 +286,18 @@ namespace datagram
|
|
|
|
|
|
|
|
|
|
if(outboundTunnel) |
|
|
|
|
{ |
|
|
|
|
// get next available lease
|
|
|
|
|
auto lease = GetNextLease(); |
|
|
|
|
std::shared_ptr<const i2p::data::Lease> lease = nullptr; |
|
|
|
|
// should we switch leases ?
|
|
|
|
|
if (ShouldSwitchLease ()) |
|
|
|
|
{ |
|
|
|
|
// yes, get next available lease
|
|
|
|
|
lease = GetNextLease(); |
|
|
|
|
} |
|
|
|
|
else if (routingPath) |
|
|
|
|
{ |
|
|
|
|
// stick with the lease we have if we have one
|
|
|
|
|
lease = routingPath->remoteLease; |
|
|
|
|
} |
|
|
|
|
if(lease) |
|
|
|
|
{ |
|
|
|
|
// we have a valid lease to use and an outbound tunnel
|
|
|
|
@ -265,6 +311,8 @@ namespace datagram
@@ -265,6 +311,8 @@ namespace datagram
|
|
|
|
|
0 |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
else // we don't have a new routing path to give
|
|
|
|
|
routingPath = nullptr; |
|
|
|
|
} |
|
|
|
|
return routingPath; |
|
|
|
|
} |
|
|
|
@ -283,29 +331,30 @@ namespace datagram
@@ -283,29 +331,30 @@ namespace datagram
|
|
|
|
|
m_InvalidIBGW.push_back(routingPath->remoteLease->tunnelGateway); // yes, let's mark remote lease as dead because the outbound tunnel seems fine
|
|
|
|
|
} |
|
|
|
|
// reset the routing path
|
|
|
|
|
m_RoutingSession->SetSharedRoutingPath(nullptr); |
|
|
|
|
UpdateRoutingPath(nullptr); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::shared_ptr<const i2p::data::Lease> DatagramSession::GetNextLease() |
|
|
|
|
{ |
|
|
|
|
auto now = i2p::util::GetMillisecondsSinceEpoch (); |
|
|
|
|
std::shared_ptr<const i2p::data::Lease> next = nullptr; |
|
|
|
|
if(m_RemoteLeaseSet) |
|
|
|
|
{ |
|
|
|
|
std::vector<i2p::data::IdentHash> exclude; |
|
|
|
|
for(const auto & ident : m_InvalidIBGW) |
|
|
|
|
exclude.push_back(ident); |
|
|
|
|
// find get all leases that are not in our ban list
|
|
|
|
|
auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude] (const i2p::data::Lease & l) -> bool { |
|
|
|
|
// find get all leases that are not in our ban list and are not going to expire within our lease set handover window + fudge
|
|
|
|
|
auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude, now] (const i2p::data::Lease & l) -> bool { |
|
|
|
|
if(exclude.size()) |
|
|
|
|
{ |
|
|
|
|
auto end = std::end(exclude); |
|
|
|
|
return std::find_if(exclude.begin(), end, [l] ( const i2p::data::IdentHash & ident) -> bool { |
|
|
|
|
return ident == l.tunnelGateway; |
|
|
|
|
return std::find_if(exclude.begin(), end, [l, now] ( const i2p::data::IdentHash & ident) -> bool { |
|
|
|
|
return ident == l.tunnelGateway || l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); |
|
|
|
|
}) != end; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
return false; |
|
|
|
|
return l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); |
|
|
|
|
}); |
|
|
|
|
if(leases.size()) |
|
|
|
|
{ |
|
|
|
@ -325,7 +374,8 @@ namespace datagram
@@ -325,7 +374,8 @@ namespace datagram
|
|
|
|
|
|
|
|
|
|
void DatagramSession::HandleGotLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> remoteIdent, std::shared_ptr<I2NPMessage> msg) |
|
|
|
|
{ |
|
|
|
|
if(remoteIdent) { |
|
|
|
|
if(remoteIdent) |
|
|
|
|
{ |
|
|
|
|
// update routing session
|
|
|
|
|
if(m_RoutingSession) |
|
|
|
|
m_RoutingSession = nullptr; |
|
|
|
|