Browse Source

check if we connected recently to an endpoint before sending peer test

pull/2101/head
orignal 2 months ago
parent
commit
f20391d460
  1. 24
      libi2pd/SSU2.cpp
  2. 6
      libi2pd/SSU2.h
  3. 28
      libi2pd/SSU2Session.cpp

24
libi2pd/SSU2.cpp

@ -210,6 +210,22 @@ namespace transport
return ep.port (); return ep.port ();
} }
bool SSU2Server::IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const
{
if (!ep.port () || ep.address ().is_unspecified ()) return false;
auto it = m_ConnectedRecently.find (ep);
if (it != m_ConnectedRecently.end ())
return i2p::util::GetSecondsSinceEpoch () <= it->second + SSU2_HOLE_PUNCH_EXPIRATION;
return false;
}
void SSU2Server::AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts)
{
if (!ep.port () || ep.address ().is_unspecified () ||
i2p::util::GetSecondsSinceEpoch () > ts + SSU2_HOLE_PUNCH_EXPIRATION) return;
m_ConnectedRecently.try_emplace (ep, ts);
}
void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from) void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from)
{ {
if (offset) if (offset)
@ -1001,6 +1017,14 @@ namespace transport
it++; it++;
} }
for (auto it = m_ConnectedRecently.begin (); it != m_ConnectedRecently.end (); )
{
if (ts > it->second + SSU2_HOLE_PUNCH_EXPIRATION)
it = m_ConnectedRecently.erase (it);
else
it++;
}
m_PacketsPool.CleanUpMt (); m_PacketsPool.CleanUpMt ();
m_SentPacketsPool.CleanUp (); m_SentPacketsPool.CleanUp ();
m_IncompleteMessagesPool.CleanUp (); m_IncompleteMessagesPool.CleanUp ();

6
libi2pd/SSU2.h

@ -39,6 +39,7 @@ namespace transport
const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds
const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
const int SSU2_HOLE_PUNCH_EXPIRATION = 20; // in seconds
class SSU2Server: private i2p::util::RunnableServiceWithWork class SSU2Server: private i2p::util::RunnableServiceWithWork
{ {
@ -72,6 +73,8 @@ namespace transport
bool UsesProxy () const { return m_IsThroughProxy; }; bool UsesProxy () const { return m_IsThroughProxy; };
bool IsSupported (const boost::asio::ip::address& addr) const; bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const; uint16_t GetPort (bool v4) const;
bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep) const;
void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts);
std::mt19937& GetRng () { return m_Rng; } std::mt19937& GetRng () { return m_Rng; }
bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; } bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
@ -160,7 +163,7 @@ namespace transport
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions; std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
mutable std::mutex m_PendingOutgoingSessionsMutex; mutable std::mutex m_PendingOutgoingSessionsMutex;
std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds)
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session std::unordered_map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
std::list<i2p::data::IdentHash> m_Introducers, m_IntroducersV6; // introducers we are connected to std::list<i2p::data::IdentHash> m_Introducers, m_IntroducersV6; // introducers we are connected to
i2p::util::MemoryPoolMt<Packet> m_PacketsPool; i2p::util::MemoryPoolMt<Packet> m_PacketsPool;
i2p::util::MemoryPool<SSU2SentPacket> m_SentPacketsPool; i2p::util::MemoryPool<SSU2SentPacket> m_SentPacketsPool;
@ -174,6 +177,7 @@ namespace transport
int64_t m_PendingTimeOffset; // during peer test int64_t m_PendingTimeOffset; // during peer test
std::shared_ptr<const i2p::data::IdentityEx> m_PendingTimeOffsetFrom; std::shared_ptr<const i2p::data::IdentityEx> m_PendingTimeOffsetFrom;
std::mt19937 m_Rng; std::mt19937 m_Rng;
std::map<boost::asio::ip::udp::endpoint, uint64_t> m_ConnectedRecently; // endpoint -> last activity time in seconds
// proxy // proxy
bool m_IsThroughProxy; bool m_IsThroughProxy;

28
libi2pd/SSU2Session.cpp

@ -265,6 +265,7 @@ namespace transport
m_OnEstablished = nullptr; m_OnEstablished = nullptr;
if (m_RelayTag) if (m_RelayTag)
m_Server.RemoveRelay (m_RelayTag); m_Server.RemoveRelay (m_RelayTag);
m_Server.AddConnectedRecently (m_RemoteEndpoint, GetLastActivityTimestamp ());
m_SentHandshakePacket.reset (nullptr); m_SentHandshakePacket.reset (nullptr);
m_SessionConfirmedFragment.reset (nullptr); m_SessionConfirmedFragment.reset (nullptr);
m_PathChallenge.reset (nullptr); m_PathChallenge.reset (nullptr);
@ -281,14 +282,10 @@ namespace transport
transports.PeerDisconnected (shared_from_this ()); transports.PeerDisconnected (shared_from_this ());
auto remoteIdentity = GetRemoteIdentity (); auto remoteIdentity = GetRemoteIdentity ();
if (remoteIdentity) if (remoteIdentity)
{
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated");
}
else else
{
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated"); LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated");
}
} }
} }
@ -1153,7 +1150,7 @@ namespace transport
if (profile) // older router? if (profile) // older router?
profile->Duplicated (); // mark router as duplicated in profile profile->Duplicated (); // mark router as duplicated in profile
else else
LogPrint (eLogError, "SSU2: Host mismatch between published address ", m_Address->host, LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
return false; return false;
} }
@ -2276,14 +2273,19 @@ namespace transport
if (addr && m_Server.IsSupported (ep.address ()) && if (addr && m_Server.IsSupported (ep.address ()) &&
i2p::context.GetRouterInfo ().IsSSU2PeerTesting (ep.address ().is_v4 ())) i2p::context.GetRouterInfo ().IsSSU2PeerTesting (ep.address ().is_v4 ()))
{ {
// send msg 5 to Alice if (!m_Server.IsConnectedRecently (ep)) // no alive hole punch
auto session = std::make_shared<SSU2Session> (m_Server, r, addr); {
session->SetState (eSSU2SessionStatePeerTest); // send msg 5 to Alice
session->m_RemoteEndpoint = ep; // might be different auto session = std::make_shared<SSU2Session> (m_Server, r, addr);
session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); session->SetState (eSSU2SessionStatePeerTest);
session->m_SourceConnID = ~session->m_DestConnID; session->m_RemoteEndpoint = ep; // might be different
m_Server.AddSession (session); session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce);
session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i); session->m_SourceConnID = ~session->m_DestConnID;
m_Server.AddSession (session);
session->SendPeerTest (5, newSignedData.data (), newSignedData.size (), addr->i);
}
else
code = eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected;
} }
else else
code = eSSU2PeerTestCodeCharlieUnsupportedAddress; code = eSSU2PeerTestCodeCharlieUnsupportedAddress;

Loading…
Cancel
Save