Merge pull request #738 from majestrate/udptunnel-fix

make udp tunnel utilize GarlicRoutingPath correctly
pull/739/head
orignal 8 years ago committed by GitHub
commit 2e66c4c9f5

@ -842,7 +842,7 @@ namespace client
else else
memset (response + 8, 0, 32); // not found memset (response + 8, 0, 32); // not found
memset (response + 40, 0, 4); // set expiration time to zero memset (response + 40, 0, 4); // set expiration time to zero
m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash (), toPort, fromPort); m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash(), toPort, fromPort);
} }
void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident) void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident)

@ -22,9 +22,9 @@ namespace datagram
{ {
m_Sessions.clear(); m_Sessions.clear();
} }
void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
{ {
auto owner = m_Owner; auto owner = m_Owner;
std::vector<uint8_t> v(MAX_DATAGRAM_SIZE); std::vector<uint8_t> v(MAX_DATAGRAM_SIZE);
uint8_t * buf = v.data(); uint8_t * buf = v.data();
@ -45,8 +45,7 @@ namespace datagram
owner->Sign (buf1, len, signature); owner->Sign (buf1, len, signature);
auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort);
auto session = ObtainSession(ident); ObtainSession(identity)->SendMsg(msg);
session->SendMsg(msg);
} }
@ -69,6 +68,8 @@ namespace datagram
if (verified) if (verified)
{ {
auto h = identity.GetIdentHash();
ObtainSession(h)->Ack();
auto r = FindReceiver(toPort); auto r = FindReceiver(toPort);
if(r) if(r)
r(identity, fromPort, toPort, buf + headerLen, len -headerLen); r(identity, fromPort, toPort, buf + headerLen, len -headerLen);
@ -138,15 +139,15 @@ namespace datagram
} }
} }
std::shared_ptr<DatagramSession> DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) std::shared_ptr<DatagramSession> DatagramDestination::ObtainSession(const i2p::data::IdentHash & identity)
{ {
std::shared_ptr<DatagramSession> session = nullptr; std::shared_ptr<DatagramSession> session = nullptr;
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
auto itr = m_Sessions.find(ident); auto itr = m_Sessions.find(identity);
if (itr == m_Sessions.end()) { if (itr == m_Sessions.end()) {
// not found, create new session // not found, create new session
session = std::make_shared<DatagramSession>(m_Owner, ident); session = std::make_shared<DatagramSession>(m_Owner, identity);
m_Sessions[ident] = session; m_Sessions[identity] = session;
} else { } else {
session = itr->second; session = itr->second;
} }
@ -164,13 +165,13 @@ namespace datagram
} }
DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination,
const i2p::data::IdentHash & remoteIdent) : const i2p::data::IdentHash & remoteIdent) :
m_LocalDestination(localDestination), m_LocalDestination(localDestination),
m_RemoteIdentity(remoteIdent), m_RemoteIdent(remoteIdent),
m_LastUse(i2p::util::GetMillisecondsSinceEpoch ()), m_SendQueueTimer(localDestination->GetService())
m_LastPathChange(0),
m_LastSuccess(0)
{ {
m_LastUse = i2p::util::GetMillisecondsSinceEpoch ();
ScheduleFlushSendQueue();
} }
void DatagramSession::SendMsg(std::shared_ptr<I2NPMessage> msg) void DatagramSession::SendMsg(std::shared_ptr<I2NPMessage> msg)
@ -184,262 +185,151 @@ namespace datagram
DatagramSession::Info DatagramSession::GetSessionInfo() const DatagramSession::Info DatagramSession::GetSessionInfo() const
{ {
if(!m_RoutingSession) if(!m_RoutingSession)
return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); return DatagramSession::Info(nullptr, nullptr, m_LastUse);
auto routingPath = m_RoutingSession->GetSharedRoutingPath(); auto routingPath = m_RoutingSession->GetSharedRoutingPath();
if (!routingPath) if (!routingPath)
return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); return DatagramSession::Info(nullptr, nullptr, m_LastUse);
auto lease = routingPath->remoteLease; auto lease = routingPath->remoteLease;
auto tunnel = routingPath->outboundTunnel; auto tunnel = routingPath->outboundTunnel;
if(lease) if(lease)
{ {
if(tunnel) if(tunnel)
return DatagramSession::Info(lease->tunnelGateway, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess); return DatagramSession::Info(lease->tunnelGateway, tunnel->GetEndpointIdentHash(), m_LastUse);
else else
return DatagramSession::Info(lease->tunnelGateway, nullptr, m_LastUse, m_LastSuccess); return DatagramSession::Info(lease->tunnelGateway, nullptr, m_LastUse);
} }
else if(tunnel) else if(tunnel)
return DatagramSession::Info(nullptr, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess); return DatagramSession::Info(nullptr, tunnel->GetEndpointIdentHash(), m_LastUse);
else else
return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); return DatagramSession::Info(nullptr, nullptr, m_LastUse);
}
void DatagramSession::HandleSend(std::shared_ptr<I2NPMessage> msg)
{
if(!m_RoutingSession)
{
// try to get one
if(m_RemoteLeaseSet) m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
else
{
UpdateLeaseSet(msg);
return;
}
}
// do we have a routing session?
if(m_RoutingSession)
{
// should we switch paths?
if(ShouldUpdateRoutingPath ())
{
LogPrint(eLogDebug, "DatagramSession: try getting new routing path");
// try switching paths
auto path = GetNextRoutingPath();
if(path)
UpdateRoutingPath (path);
else
ResetRoutingPath();
}
auto routingPath = m_RoutingSession->GetSharedRoutingPath ();
// make sure we have a routing path
if (routingPath)
{
auto outboundTunnel = routingPath->outboundTunnel;
if (outboundTunnel)
{
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);
routingPath->outboundTunnel->SendTunnelDataMsg({i2p::tunnel::TunnelMessageBlock{
i2p::tunnel::eDeliveryTypeTunnel,
routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID,
m
}});
return;
}
}
}
}
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 (m_LastPathChange && now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath();
UpdateLeaseSet(msg);
}
void DatagramSession::UpdateRoutingPath(const std::shared_ptr<i2p::garlic::GarlicRoutingPath> & path)
{
if(m_RoutingSession == nullptr && m_RemoteLeaseSet)
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
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 void DatagramSession::Ack()
{ {
bool dead = m_RoutingSession == nullptr || m_RoutingSession->GetSharedRoutingPath () == nullptr; m_LastUse = i2p::util::GetMillisecondsSinceEpoch();
auto now = i2p::util::GetMillisecondsSinceEpoch (); auto path = GetSharedRoutingPath();
// we need to rotate paths becuase the routing path is too old if(path)
// if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; path->updateTime = i2p::util::GetSecondsSinceEpoch ();
// too fast switching paths
if (now - m_LastPathChange < DATAGRAM_SESSION_PATH_MIN_LIFETIME ) return false;
// our path looks dead so we need to rotate paths
if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return !dead;
// if we have a routing session and routing path we don't need to switch paths
return dead;
} }
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetSharedRoutingPath ()
bool DatagramSession::ShouldSwitchLease() const
{
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 currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE );
// we have no current lease, we should switch
return currentLease == nullptr;
}
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetNextRoutingPath()
{ {
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel = nullptr; if(!m_RoutingSession) {
std::shared_ptr<i2p::garlic::GarlicRoutingPath> routingPath = nullptr; if(!m_RemoteLeaseSet) {
// get existing routing path if we have one m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
if(m_RoutingSession)
routingPath = m_RoutingSession->GetSharedRoutingPath();
// do we have an existing outbound tunnel and routing path?
if(routingPath && routingPath->outboundTunnel)
{
// is the outbound tunnel we are using good?
if (routingPath->outboundTunnel->IsEstablished())
{
// ya so let's stick with it
outboundTunnel = routingPath->outboundTunnel;
} }
else if(!m_RemoteLeaseSet) {
outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels // no remote lease set
m_LocalDestination->RequestDestination(m_RemoteIdent, std::bind(&DatagramSession::HandleLeaseSetUpdated, this, std::placeholders::_1));
return nullptr;
}
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
} }
// do we have an outbound tunnel that works already ? auto path = m_RoutingSession->GetSharedRoutingPath();
if(!outboundTunnel) if(path) {
outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); // no, let's get a new outbound tunnel as we probably just started if (m_CurrentOutboundTunnel && !m_CurrentOutboundTunnel->IsEstablished()) {
// bad outbound tunnel, switch outbound tunnel
if(outboundTunnel) m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel);
{ path->outboundTunnel = m_CurrentOutboundTunnel;
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) if(m_CurrentRemoteLease && ! m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) {
{ // bad lease, switch to next one
if(routingPath->remoteLease) if(m_RemoteLeaseSet) {
{ auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&](const i2p::data::Lease& l) -> bool {
if(routingPath->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE)) return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway || l.endDate <= m_CurrentRemoteLease->endDate;
lease = GetNextLease(); });
else auto sz = ls.size();
lease = routingPath->remoteLease; if (sz) {
auto idx = rand() % sz;
m_CurrentRemoteLease = ls[idx];
} else {
// no more leases, bail
LogPrint(eLogWarning, "DatagramSession: no more valid remote leases to ", m_RemoteIdent.ToBase32());
}
} else {
// no remote lease set?
LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32());
} }
path->remoteLease = m_CurrentRemoteLease;
} }
else } else {
lease = GetNextLease(); // no current path, make one
if(lease) path = std::make_shared<i2p::garlic::GarlicRoutingPath>();
{ // switch outbound tunnel if bad
// we have a valid lease to use and an outbound tunnel if(m_CurrentOutboundTunnel == nullptr || ! m_CurrentOutboundTunnel->IsEstablished()) {
// create new routing path m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel);
uint32_t now = i2p::util::GetSecondsSinceEpoch(); }
routingPath = std::make_shared<i2p::garlic::GarlicRoutingPath>(i2p::garlic::GarlicRoutingPath{ // switch lease if bad
outboundTunnel, if(m_CurrentRemoteLease == nullptr || m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) {
lease, if(!m_RemoteLeaseSet) {
0, m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
now, }
0 if(m_RemoteLeaseSet) {
}); // pick random next good lease
auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&] (const i2p::data::Lease & l) -> bool {
if(m_CurrentRemoteLease)
return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway;
return false;
});
auto sz = ls.size();
if(sz) {
auto idx = rand() % sz;
m_CurrentRemoteLease = ls[idx];
}
} else {
// no remote lease set currently, bail
LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32());
return nullptr;
}
} }
else // we don't have a new routing path to give path->outboundTunnel = m_CurrentOutboundTunnel;
routingPath = nullptr; path->remoteLease = m_CurrentRemoteLease;
m_RoutingSession->SetSharedRoutingPath(path);
} }
return routingPath; return path;
} }
void DatagramSession::ResetRoutingPath() void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls)
{ {
if(m_RoutingSession) // only update lease set if found and newer than previous lease set
{ uint64_t oldExpire = 0;
auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if(m_RemoteLeaseSet) oldExpire = m_RemoteLeaseSet->GetExpirationTime();
if(routingPath && routingPath->remoteLease) // we have a remote lease already specified and a routing path if(ls && ls->GetExpirationTime() > oldExpire) m_RemoteLeaseSet = ls;
{
// get outbound tunnel on this path
auto outboundTunnel = routingPath->outboundTunnel;
// is this outbound tunnel there and established
if (outboundTunnel && outboundTunnel->IsEstablished())
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
UpdateRoutingPath(nullptr);
}
} }
std::shared_ptr<const i2p::data::Lease> DatagramSession::GetNextLease() void DatagramSession::HandleSend(std::shared_ptr<I2NPMessage> msg)
{ {
auto now = i2p::util::GetMillisecondsSinceEpoch (); m_SendQueue.push_back(msg);
std::shared_ptr<const i2p::data::Lease> next = nullptr; // flush queue right away if full
if(m_RemoteLeaseSet) if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue();
}
void DatagramSession::FlushSendQueue ()
{
std::vector<i2p::tunnel::TunnelMessageBlock> send;
auto routingPath = GetSharedRoutingPath();
// if we don't have a routing path we will drop all queued messages
if(routingPath)
{ {
std::vector<i2p::data::IdentHash> exclude; for (const auto & msg : m_SendQueue)
for(const auto & ident : m_InvalidIBGW)
exclude.push_back(ident);
// 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, now] ( const i2p::data::IdentHash & ident) -> bool {
return ident == l.tunnelGateway;
}) != end;
}
else
return false;
});
if(leases.size())
{ {
// pick random valid next lease auto m = m_RoutingSession->WrapSingleMessage(msg);
uint32_t idx = rand() % leases.size(); send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
next = leases[idx];
} }
else routingPath->outboundTunnel->SendTunnelDataMsg(send);
LogPrint(eLogWarning, "DatagramDestination: no leases to use");
} }
return next; m_SendQueue.clear();
} ScheduleFlushSendQueue();
void DatagramSession::UpdateLeaseSet(std::shared_ptr<I2NPMessage> msg)
{
LogPrint(eLogInfo, "DatagramSession: updating lease set");
m_LocalDestination->RequestDestination(m_RemoteIdentity, std::bind(&DatagramSession::HandleGotLeaseSet, this, std::placeholders::_1, msg));
} }
void DatagramSession::HandleGotLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> remoteIdent, std::shared_ptr<I2NPMessage> msg) void DatagramSession::ScheduleFlushSendQueue()
{ {
if(remoteIdent) boost::posix_time::milliseconds dlt(100);
{ m_SendQueueTimer.expires_from_now(dlt);
// update routing session m_SendQueueTimer.async_wait([&](const boost::system::error_code & ec) { if(ec) return; FlushSendQueue(); });
if(m_RoutingSession)
m_RoutingSession = nullptr;
m_RoutingSession = m_LocalDestination->GetRoutingSession(remoteIdent, true);
// clear invalid IBGW as we have a new lease set
m_InvalidIBGW.clear();
m_RemoteLeaseSet = remoteIdent;
// update routing path
auto path = GetNextRoutingPath();
if (path)
UpdateRoutingPath(path);
else
ResetRoutingPath();
// send the message that was queued if it was provided
if(msg)
HandleSend(msg);
}
} }
} }
} }

@ -31,29 +31,33 @@ namespace datagram
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
// milliseconds minimum time between path switches // milliseconds minimum time between path switches
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
// max 64 messages buffered in send queue for each datagram session
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
class DatagramSession class DatagramSession
{ {
public: public:
DatagramSession(i2p::client::ClientDestination * localDestination, DatagramSession(i2p::client::ClientDestination * localDestination,
const i2p::data::IdentHash & remoteIdent); const i2p::data::IdentHash & remoteIdent);
/** @brief ack the garlic routing path */
void Ack();
/** send an i2np message to remote endpoint for this session */ /** send an i2np message to remote endpoint for this session */
void SendMsg(std::shared_ptr<I2NPMessage> msg); void SendMsg(std::shared_ptr<I2NPMessage> msg);
/** get the last time in milliseconds for when we used this datagram session */ /** get the last time in milliseconds for when we used this datagram session */
uint64_t LastActivity() const { return m_LastUse; } uint64_t LastActivity() const { return m_LastUse; }
/** get the last time in milliseconds when we successfully sent data */
uint64_t LastSuccess() const { return m_LastSuccess; }
struct Info struct Info
{ {
std::shared_ptr<const i2p::data::IdentHash> IBGW; std::shared_ptr<const i2p::data::IdentHash> IBGW;
std::shared_ptr<const i2p::data::IdentHash> OBEP; std::shared_ptr<const i2p::data::IdentHash> OBEP;
const uint64_t activity; const uint64_t activity;
const uint64_t success;
Info() : IBGW(nullptr), OBEP(nullptr), activity(0), success(0) {} Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a, const uint64_t s) : Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
activity(a), activity(a) {
success(s) {
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw); if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
else IBGW = nullptr; else IBGW = nullptr;
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep); if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
@ -63,44 +67,28 @@ namespace datagram
Info GetSessionInfo() const; Info GetSessionInfo() const;
private: private:
/** update our routing path we are using, mark that we have changed paths */ void FlushSendQueue();
void UpdateRoutingPath(const std::shared_ptr<i2p::garlic::GarlicRoutingPath> & path); void ScheduleFlushSendQueue();
/** return true if we should switch routing paths because of path lifetime or timeout otherwise false */ void HandleSend(std::shared_ptr<I2NPMessage> msg);
bool ShouldUpdateRoutingPath() const;
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
/** 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 */
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetNextRoutingPath();
/**
* mark current routing path as invalid and clear it
* if the outbound tunnel we were using was okay don't use the IBGW in the routing path's lease next time
*/
void ResetRoutingPath();
/** get next usable lease, does not fetch or update if expired or have no lease set */
std::shared_ptr<const i2p::data::Lease> GetNextLease();
void HandleSend(std::shared_ptr<I2NPMessage> msg);
void HandleGotLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> remoteIdent,
std::shared_ptr<I2NPMessage> msg);
void UpdateLeaseSet(std::shared_ptr<I2NPMessage> msg=nullptr);
private: private:
i2p::client::ClientDestination * m_LocalDestination; i2p::client::ClientDestination * m_LocalDestination;
i2p::data::IdentHash m_RemoteIdentity; i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession; std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
// Ident hash of IBGW that are invalid std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::vector<i2p::data::IdentHash> m_InvalidIBGW; std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet; std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
uint64_t m_LastUse; boost::asio::deadline_timer m_SendQueueTimer;
uint64_t m_LastPathChange; std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
uint64_t m_LastSuccess; uint64_t m_LastUse;
}; };
const size_t MAX_DATAGRAM_SIZE = 32768; const size_t MAX_DATAGRAM_SIZE = 32768;
@ -112,9 +100,9 @@ namespace datagram
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner); DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
~DatagramDestination (); ~DatagramDestination ();
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
@ -130,7 +118,7 @@ namespace datagram
private: private:
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident); std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);

@ -540,9 +540,13 @@ namespace client
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
std::remove_if(m_Sessions.begin(), m_Sessions.end(), [now, delta](const UDPSession * u) -> bool { auto itr = m_Sessions.begin();
return now - u->LastActivity >= delta; while(itr != m_Sessions.end()) {
}); if(now - (*itr)->LastActivity >= delta )
itr = m_Sessions.erase(itr);
else
++itr;
}
} }
UDPSession * I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) UDPSession * I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort)

Loading…
Cancel
Save