mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-13 01:20:22 +03:00
check if we connected recently to an endpoint before sending peer test
This commit is contained in:
parent
ca4db7aab2
commit
f20391d460
@ -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 ();
|
||||||
|
@ -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,7 +177,8 @@ 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;
|
||||||
uint8_t m_UDPRequestHeader[SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE];
|
uint8_t m_UDPRequestHeader[SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE];
|
||||||
|
@ -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…
Reference in New Issue
Block a user