mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
Update Indentation and don't spam route changes in datagram sessions
This commit is contained in:
parent
c770bcbf96
commit
9acbb2203c
|
@ -222,7 +222,8 @@ namespace client
|
||||||
m_Destinations.clear ();
|
m_Destinations.clear ();
|
||||||
m_SharedLocalDestination = nullptr;
|
m_SharedLocalDestination = nullptr;
|
||||||
// stop io service thread
|
// stop io service thread
|
||||||
if(m_ServiceThread) {
|
if(m_ServiceThread)
|
||||||
|
{
|
||||||
m_Service.stop();
|
m_Service.stop();
|
||||||
m_ServiceThread->join();
|
m_ServiceThread->join();
|
||||||
delete m_ServiceThread;
|
delete m_ServiceThread;
|
||||||
|
|
|
@ -92,7 +92,6 @@ namespace client
|
||||||
std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port>->tunnel
|
std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port>->tunnel
|
||||||
|
|
||||||
std::mutex m_ForwardsMutex;
|
std::mutex m_ForwardsMutex;
|
||||||
|
|
||||||
std::map<boost::asio::ip::udp::endpoint, std::unique_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
|
std::map<boost::asio::ip::udp::endpoint, std::unique_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
|
||||||
std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
|
std::map<std::pair<i2p::data::IdentHash, int>, std::unique_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
|
||||||
|
|
||||||
|
@ -110,6 +109,8 @@ namespace client
|
||||||
const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
|
const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
|
||||||
const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; };
|
const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; };
|
||||||
const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; };
|
const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; };
|
||||||
|
const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; }
|
||||||
|
const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ClientContext context;
|
extern ClientContext context;
|
||||||
|
|
92
Datagram.cpp
92
Datagram.cpp
|
@ -169,7 +169,9 @@ namespace datagram
|
||||||
const i2p::data::IdentHash & remoteIdent) :
|
const i2p::data::IdentHash & remoteIdent) :
|
||||||
m_LocalDestination(localDestination),
|
m_LocalDestination(localDestination),
|
||||||
m_RemoteIdentity(remoteIdent),
|
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
|
||||||
// do we have a routing session?
|
// do we have a routing session?
|
||||||
if(m_RoutingSession)
|
if(m_RoutingSession)
|
||||||
{
|
{
|
||||||
// do we have a routing path ?
|
// should we switch paths?
|
||||||
auto routingPath = m_RoutingSession->GetSharedRoutingPath();
|
if(ShouldUpdateRoutingPath ())
|
||||||
if(!routingPath)
|
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "DatagramSession: try getting new routing path");
|
LogPrint(eLogDebug, "DatagramSession: try getting new routing path");
|
||||||
// no routing path, try getting one
|
// try switching paths
|
||||||
routingPath = GetNextRoutingPath();
|
UpdateRoutingPath (GetNextRoutingPath ());
|
||||||
if(routingPath) // remember the routing path if we got one
|
|
||||||
m_RoutingSession->SetSharedRoutingPath(routingPath);
|
|
||||||
}
|
}
|
||||||
|
auto routingPath = m_RoutingSession->GetSharedRoutingPath ();
|
||||||
// make sure we have a routing path
|
// make sure we have a routing path
|
||||||
if (routingPath)
|
if (routingPath)
|
||||||
{
|
{
|
||||||
|
@ -204,6 +204,7 @@ namespace datagram
|
||||||
{
|
{
|
||||||
if(outboundTunnel->IsEstablished())
|
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
|
// 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
|
// wrap message with routing session and send down routing path's outbound tunnel wrapped for the IBGW
|
||||||
auto m = m_RoutingSession->WrapSingleMessage(msg);
|
auto m = m_RoutingSession->WrapSingleMessage(msg);
|
||||||
|
@ -217,12 +218,49 @@ namespace datagram
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we couldn't send so let's try resetting the routing path and updating lease set
|
auto now = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
ResetRoutingPath();
|
// 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);
|
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::garlic::GarlicRoutingPath> DatagramSession::GetNextRoutingPath()
|
||||||
{
|
{
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel = nullptr;
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel = nullptr;
|
||||||
|
@ -241,8 +279,6 @@ namespace datagram
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels
|
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 ?
|
// do we have an outbound tunnel that works already ?
|
||||||
if(!outboundTunnel)
|
if(!outboundTunnel)
|
||||||
|
@ -250,8 +286,18 @@ namespace datagram
|
||||||
|
|
||||||
if(outboundTunnel)
|
if(outboundTunnel)
|
||||||
{
|
{
|
||||||
// get next available lease
|
std::shared_ptr<const i2p::data::Lease> lease = nullptr;
|
||||||
auto lease = GetNextLease();
|
// 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)
|
if(lease)
|
||||||
{
|
{
|
||||||
// we have a valid lease to use and an outbound tunnel
|
// we have a valid lease to use and an outbound tunnel
|
||||||
|
@ -265,6 +311,8 @@ namespace datagram
|
||||||
0
|
0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else // we don't have a new routing path to give
|
||||||
|
routingPath = nullptr;
|
||||||
}
|
}
|
||||||
return routingPath;
|
return routingPath;
|
||||||
}
|
}
|
||||||
|
@ -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
|
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
|
// reset the routing path
|
||||||
m_RoutingSession->SetSharedRoutingPath(nullptr);
|
UpdateRoutingPath(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::Lease> DatagramSession::GetNextLease()
|
std::shared_ptr<const i2p::data::Lease> DatagramSession::GetNextLease()
|
||||||
{
|
{
|
||||||
|
auto now = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
std::shared_ptr<const i2p::data::Lease> next = nullptr;
|
std::shared_ptr<const i2p::data::Lease> next = nullptr;
|
||||||
if(m_RemoteLeaseSet)
|
if(m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
std::vector<i2p::data::IdentHash> exclude;
|
std::vector<i2p::data::IdentHash> exclude;
|
||||||
for(const auto & ident : m_InvalidIBGW)
|
for(const auto & ident : m_InvalidIBGW)
|
||||||
exclude.push_back(ident);
|
exclude.push_back(ident);
|
||||||
// find get all leases that are not in our ban list
|
// 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] (const i2p::data::Lease & l) -> bool {
|
auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude, now] (const i2p::data::Lease & l) -> bool {
|
||||||
if(exclude.size())
|
if(exclude.size())
|
||||||
{
|
{
|
||||||
auto end = std::end(exclude);
|
auto end = std::end(exclude);
|
||||||
return std::find_if(exclude.begin(), end, [l] ( const i2p::data::IdentHash & ident) -> bool {
|
return std::find_if(exclude.begin(), end, [l, now] ( const i2p::data::IdentHash & ident) -> bool {
|
||||||
return ident == l.tunnelGateway;
|
return ident == l.tunnelGateway || l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE);
|
||||||
}) != end;
|
}) != end;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE);
|
||||||
});
|
});
|
||||||
if(leases.size())
|
if(leases.size())
|
||||||
{
|
{
|
||||||
|
@ -325,7 +374,8 @@ namespace datagram
|
||||||
|
|
||||||
void DatagramSession::HandleGotLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> remoteIdent, std::shared_ptr<I2NPMessage> msg)
|
void DatagramSession::HandleGotLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> remoteIdent, std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
if(remoteIdent) {
|
if(remoteIdent)
|
||||||
|
{
|
||||||
// update routing session
|
// update routing session
|
||||||
if(m_RoutingSession)
|
if(m_RoutingSession)
|
||||||
m_RoutingSession = nullptr;
|
m_RoutingSession = nullptr;
|
||||||
|
|
23
Datagram.h
23
Datagram.h
|
@ -22,8 +22,16 @@ namespace datagram
|
||||||
|
|
||||||
// seconds interval for cleanup timer
|
// seconds interval for cleanup timer
|
||||||
const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3;
|
const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3;
|
||||||
// milliseconds for max session idle time (10 minutes)
|
// milliseconds for max session idle time
|
||||||
const uint64_t DATAGRAM_SESSION_MAX_IDLE = 3600 * 1000;
|
const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000;
|
||||||
|
// milliseconds for how long we try sticking to a dead routing path before trying to switch
|
||||||
|
const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 5000;
|
||||||
|
// milliseconds interval a routing path is used before switching
|
||||||
|
const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 60 * 1000;
|
||||||
|
// milliseconds before lease expire should we try switching leases
|
||||||
|
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000;
|
||||||
|
// milliseconds fudge factor for leases handover
|
||||||
|
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
|
||||||
|
|
||||||
|
|
||||||
class DatagramSession
|
class DatagramSession
|
||||||
|
@ -38,6 +46,15 @@ namespace datagram
|
||||||
uint64_t LastActivity() const { return m_LastUse; }
|
uint64_t LastActivity() const { return m_LastUse; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/** update our routing path we are using, mark that we have changed paths */
|
||||||
|
void UpdateRoutingPath(const std::shared_ptr<i2p::garlic::GarlicRoutingPath> & path);
|
||||||
|
|
||||||
|
/** return true if we should switch routing paths because of path lifetime or timeout otherwise false */
|
||||||
|
bool ShouldUpdateRoutingPath() const;
|
||||||
|
|
||||||
|
/** return true if we should switch the lease for out routing path otherwise return false */
|
||||||
|
bool ShouldSwitchLease() const;
|
||||||
|
|
||||||
/** get next usable routing path, try reusing outbound tunnels */
|
/** get next usable routing path, try reusing outbound tunnels */
|
||||||
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetNextRoutingPath();
|
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetNextRoutingPath();
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +79,8 @@ namespace datagram
|
||||||
std::vector<i2p::data::IdentHash> m_InvalidIBGW;
|
std::vector<i2p::data::IdentHash> m_InvalidIBGW;
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
||||||
uint64_t m_LastUse;
|
uint64_t m_LastUse;
|
||||||
|
uint64_t m_LastPathChange;
|
||||||
|
uint64_t m_LastSuccess;
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t MAX_DATAGRAM_SIZE = 32768;
|
const size_t MAX_DATAGRAM_SIZE = 32768;
|
||||||
|
|
|
@ -163,9 +163,10 @@ namespace data
|
||||||
return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen);
|
return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LeaseSet::ExpiresSoon(const uint64_t dlt) const
|
bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const
|
||||||
{
|
{
|
||||||
auto now = i2p::util::GetMillisecondsSinceEpoch ();
|
auto now = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
if (fudge) now += rand() % fudge;
|
||||||
if (now >= m_ExpirationTime) return true;
|
if (now >= m_ExpirationTime) return true;
|
||||||
return m_ExpirationTime - now <= dlt;
|
return m_ExpirationTime - now <= dlt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -25,6 +26,12 @@ namespace data
|
||||||
uint32_t tunnelID;
|
uint32_t tunnelID;
|
||||||
uint64_t endDate; // 0 means invalid
|
uint64_t endDate; // 0 means invalid
|
||||||
bool isUpdated; // trasient
|
bool isUpdated; // trasient
|
||||||
|
/* return true if this lease expires within t millisecond + fudge factor */
|
||||||
|
bool ExpiresWithin( const uint64_t t, const uint64_t fudge = 1000 ) const {
|
||||||
|
auto expire = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
if(fudge) expire += rand() % fudge;
|
||||||
|
return expire - endDate >= t;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LeaseCmp
|
struct LeaseCmp
|
||||||
|
@ -63,7 +70,7 @@ namespace data
|
||||||
bool IsExpired () const;
|
bool IsExpired () const;
|
||||||
bool IsEmpty () const { return m_Leases.empty (); };
|
bool IsEmpty () const { return m_Leases.empty (); };
|
||||||
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
|
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
|
||||||
bool ExpiresSoon(const uint64_t dlt=1000 * 5) const ;
|
bool ExpiresSoon(const uint64_t dlt=1000 * 5, const uint64_t fudge = 0) const ;
|
||||||
bool operator== (const LeaseSet& other) const
|
bool operator== (const LeaseSet& other) const
|
||||||
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
|
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue