From 4f73f60e5177a3b6add0a06934227bea47556bb0 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Oct 2024 12:07:13 -0400 Subject: [PATCH] don't create relay response block twice --- libi2pd/SSU2OutOfSession.cpp | 24 +++++++++--- libi2pd/SSU2OutOfSession.h | 8 +++- libi2pd/SSU2Session.cpp | 74 ++++++++++-------------------------- libi2pd/SSU2Session.h | 6 +-- 4 files changed, 47 insertions(+), 65 deletions(-) diff --git a/libi2pd/SSU2OutOfSession.cpp b/libi2pd/SSU2OutOfSession.cpp index 574ad75b..46809217 100644 --- a/libi2pd/SSU2OutOfSession.cpp +++ b/libi2pd/SSU2OutOfSession.cpp @@ -227,19 +227,18 @@ namespace transport SSU2HolePunchSession::SSU2HolePunchSession (SSU2Server& server, uint32_t nonce, const boost::asio::ip::udp::endpoint& remoteEndpoint, - std::shared_ptr localAddr): + std::shared_ptr addr): SSU2Session (server), // we create full incoming session m_Nonce (nonce) { // we are Charlie - m_Token = GetServer ().GetIncomingToken (remoteEndpoint); uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id uint32_t sourceConnID = ~destConnID; SetSourceConnID (sourceConnID); SetDestConnID (destConnID); SetState (eSSU2SessionStateHolePunch); SetRemoteEndpoint (remoteEndpoint); - SetAddress (localAddr); + SetAddress (addr); SetTerminationTimeout (SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT); } @@ -267,8 +266,12 @@ namespace transport htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); size_t payloadSize = 7; payloadSize += CreateAddressBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, ep); - payloadSize += CreateRelayResponseBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, - eSSU2RelayResponseCodeAccept, m_Nonce, m_Token, ep.address ().is_v4 ()); + // relay response block + if (payloadSize + m_RelayResponseBlock.size () < GetMaxPayloadSize ()) + { + memcpy (payload + payloadSize, m_RelayResponseBlock.data (), m_RelayResponseBlock.size ()); + payloadSize += m_RelayResponseBlock.size (); + } payloadSize += CreatePaddingBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize); // encrypt uint8_t n[12]; @@ -282,5 +285,16 @@ namespace transport // send GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep); } + + void SSU2HolePunchSession::SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen) + { +#if __cplusplus >= 202002L // C++20 + m_RelayResponseBlock.assign (relayResponseBlock, relayResponseBlock + relayResponseBlockLen); +#else + m_RelayResponseBlock.resize (relayResponseBlockLen); + memcpy (m_RelayResponseBlock.data (), relayResponseBlock, relayResponseBlockLen); +#endif + SendHolePunch (); + } } } diff --git a/libi2pd/SSU2OutOfSession.h b/libi2pd/SSU2OutOfSession.h index d0d944d1..1069ab40 100644 --- a/libi2pd/SSU2OutOfSession.h +++ b/libi2pd/SSU2OutOfSession.h @@ -57,14 +57,18 @@ namespace transport public: SSU2HolePunchSession (SSU2Server& server, uint32_t nonce, const boost::asio::ip::udp::endpoint& remoteEndpoint, - std::shared_ptr localAddr); + std::shared_ptr addr); + void SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen); + + private: + void SendHolePunch (); private: uint32_t m_Nonce; - uint64_t m_Token; // for RelayResponse block + std::vector m_RelayResponseBlock; }; } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index f68231db..47f6a9b2 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1351,46 +1351,6 @@ namespace transport SendSessionRequest (token); return true; } - - void SSU2Session::SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, - const uint8_t * introKey, uint64_t token) - { - // we are Charlie - LogPrint (eLogDebug, "SSU2: Sending HolePunch to ", ep); - Header header; - uint8_t h[32], payload[SSU2_MAX_PACKET_SIZE]; - // fill packet - header.h.connID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id - RAND_bytes (header.buf + 8, 4); // random packet num - header.h.type = eSSU2HolePunch; - header.h.flags[0] = 2; // ver - header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID - header.h.flags[2] = 0; // flag - memcpy (h, header.buf, 16); - uint64_t c = ~header.h.connID; - memcpy (h + 16, &c, 8); // source id - RAND_bytes (h + 24, 8); // token - // payload - payload[0] = eSSU2BlkDateTime; - htobe16buf (payload + 1, 4); - htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); - size_t payloadSize = 7; - payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, ep); - payloadSize += CreateRelayResponseBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, - eSSU2RelayResponseCodeAccept, nonce, token, ep.address ().is_v4 ()); - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); - // encrypt - uint8_t n[12]; - CreateNonce (be32toh (header.h.packetNum), n); - i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, h, 32, introKey, n, payload, payloadSize + 16, true); - payloadSize += 16; - header.ll[0] ^= CreateHeaderMask (introKey, payload + (payloadSize - 24)); - header.ll[1] ^= CreateHeaderMask (introKey, payload + (payloadSize - 12)); - memset (n, 0, 12); - i2p::crypto::ChaCha20 (h + 16, 16, introKey, n, h + 16); - // send - m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep); - } bool SSU2Session::ProcessHolePunch (uint8_t * buf, size_t len) { @@ -1985,8 +1945,8 @@ namespace transport { // we are Charlie SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept; - uint64_t token = 0; - bool isV4 = false; + boost::asio::ip::udp::endpoint ep; + std::shared_ptr addr; auto r = i2p::data::netdb.FindRouter (buf + 1); // Alice if (r) { @@ -1999,31 +1959,29 @@ namespace transport s.Insert (buf + 47, asz); // Alice Port, Alice IP if (s.Verify (r->GetIdentity (), buf + 47 + asz)) { - // send HolePunch - boost::asio::ip::udp::endpoint ep; + // obtain and check endpoint and address for HolePunch if (ExtractEndpoint (buf + 47, asz, ep)) { - std::shared_ptr addr; if (!ep.address ().is_unspecified () && ep.port ()) - addr = ep.address ().is_v6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address (); - if (addr) { if (m_Server.IsSupported (ep.address ())) { - token = m_Server.GetIncomingToken (ep); - isV4 = ep.address ().is_v4 (); - SendHolePunch (bufbe32toh (buf + 33), ep, addr->i, token); - m_Server.AddConnectedRecently (ep, i2p::util::GetSecondsSinceEpoch ()); + addr = ep.address ().is_v6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address (); + if (!addr) + { + LogPrint (eLogWarning, "SSU2: RelayIntro address for endpoint not found"); + code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; + } } else { LogPrint (eLogWarning, "SSU2: RelayIntro unsupported address"); code = eSSU2RelayResponseCodeCharlieUnsupportedAddress; - } + } } else { - LogPrint (eLogWarning, "SSU2: RelayIntro unknown address"); + LogPrint (eLogWarning, "SSU2: RelayIntro invalid endpoint"); code = eSSU2RelayResponseCodeCharlieAliceIsUnknown; } } @@ -2059,8 +2017,16 @@ namespace transport } // send relay response to Bob auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); + uint32_t nonce = bufbe32toh (buf + 33); packet->payloadSize = CreateRelayResponseBlock (packet->payload, m_MaxPayloadSize, - code, bufbe32toh (buf + 33), token, isV4); + code, nonce, m_Server.GetIncomingToken (ep), ep.address ().is_v4 ()); + if (code == eSSU2RelayResponseCodeAccept && addr) + { + // send HolePunch + auto holePunchSession = std::make_shared(m_Server, nonce, ep, addr); + m_Server.AddSession (holePunchSession); + holePunchSession->SendHolePunch (packet->payload, packet->payloadSize); // relay response block + } packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); /*uint32_t packetNum = */SendData (packet->payload, packet->payloadSize); // sometimes Bob doesn't ack this RelayResponse diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 6a5ae5e2..ae0f18f4 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -274,8 +274,6 @@ namespace transport bool ProcessSessionConfirmed (uint8_t * buf, size_t len); bool ProcessRetry (uint8_t * buf, size_t len); bool ProcessHolePunch (uint8_t * buf, size_t len); - void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, - const uint8_t * introKey, uint64_t token); virtual bool ProcessPeerTest (uint8_t * buf, size_t len); void ProcessData (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from); @@ -298,8 +296,6 @@ namespace transport size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0); size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); - - size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4); private: @@ -356,6 +352,8 @@ namespace transport size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr msg); size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr msg, uint8_t& fragmentNum, uint32_t msgID); size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen); + size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4); + size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice size_t CreateTerminationBlock (uint8_t * buf, size_t len);