From c6f898b8ca90a6ae1415c19065bfc66a367f0431 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 8 Aug 2022 13:08:12 -0400 Subject: [PATCH] connect to Charlie if RelayResponse from Bob was received before HolePunch --- libi2pd/SSU2Session.cpp | 49 +++++++++++++++++++++++++++++------------ libi2pd/SSU2Session.h | 1 + 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index fd109609..205da574 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -147,6 +147,22 @@ namespace transport m_State = eSSU2SessionStateIntroduced; ScheduleConnectTimer (); } + + void SSU2Session::ConnectAfterIntroduction () + { + if (m_State == eSSU2SessionStateIntroduced) + { + // create new connID + uint64_t oldConnID = GetConnID (); + RAND_bytes ((uint8_t *)&m_DestConnID, 8); + RAND_bytes ((uint8_t *)&m_SourceConnID, 8); + // connect + m_State = eSSU2SessionStateTokenReceived; + m_Server.AddPendingOutgoingSession (shared_from_this ()); + m_Server.RemoveSession (oldConnID); + Connect (); + } + } void SSU2Session::SendPeerTest () { @@ -486,7 +502,10 @@ namespace transport i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]); break; - } + } + case eSSU2HolePunch: + LogPrint (eLogDebug, "SSU2: Late HolePunch for ", connID); + break; default: { LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type, " from ", m_RemoteEndpoint, " of ", len, " bytes"); @@ -1152,18 +1171,7 @@ namespace transport } HandlePayload (payload, len - 48); // connect to Charlie - if (m_State == eSSU2SessionStateIntroduced) - { - // create new connID - uint64_t oldConnID = GetConnID (); - RAND_bytes ((uint8_t *)&m_DestConnID, 8); - RAND_bytes ((uint8_t *)&m_SourceConnID, 8); - // connect - m_State = eSSU2SessionStateTokenReceived; - m_Server.AddPendingOutgoingSession (shared_from_this ()); - m_Server.RemoveSession (oldConnID); - Connect (); - } + ConnectAfterIntroduction (); return true; } @@ -1783,8 +1791,21 @@ namespace transport if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz)) { if (it->second.first->m_State == eSSU2SessionStateIntroduced) // HolePunch not received yet + { // update Charlie's endpoint - ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint); + if (ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint)) + { + // update token + uint64_t token; + memcpy (&token, buf + len - 8, 8); + m_Server.UpdateOutgoingToken (it->second.first->m_RemoteEndpoint, + token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); + // connect to Charlie, HolePunch will be ignored + it->second.first->ConnectAfterIntroduction (); + } + else + LogPrint (eLogWarning, "SSU2: RelayResponse can't extract endpoint"); + } } else { diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 767c3e04..9a9ac0d6 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -261,6 +261,7 @@ namespace transport bool SendQueue (); // returns true if ack block was sent bool SendFragmentedMessage (std::shared_ptr msg); void ResendHandshakePacket (); + void ConnectAfterIntroduction (); void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len); void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);