From 36939898fe782e0744ee316f83744e2056f24461 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Dec 2024 20:50:54 -0500 Subject: [PATCH] send tunnel endpoint data to transport session to gateway directly --- libi2pd/TransitTunnel.cpp | 24 ++++++++++++++++++++++ libi2pd/TransitTunnel.h | 3 ++- libi2pd/TunnelBase.cpp | 3 ++- libi2pd/TunnelEndpoint.cpp | 42 +++++++++++++++++++++++++++++++------- libi2pd/TunnelEndpoint.h | 17 ++++++++++++--- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index 3d3f20f2..ba505ae3 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -133,6 +133,30 @@ namespace tunnel m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); } + void TransitTunnelEndpoint::FlushTunnelDataMsgs () + { + m_Endpoint.FlushI2NPMsgs (); + } + + std::string TransitTunnelEndpoint::GetNextPeerName () const + { + auto hash = m_Endpoint.GetCurrentHash (); + if (hash) + { + const auto& sender = m_Endpoint.GetSender (); + if (sender) + { + auto transport = sender->GetCurrentTransport (); + if (transport) + return i2p::data::GetIdentHashAbbreviation (*hash) + "-" + + i2p::data::RouterInfo::GetTransportName (transport->GetTransportType ()); + else + return i2p::data::GetIdentHashAbbreviation (*hash); + } + } + return ""; + } + std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey, diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index 58aba35b..c0f9c276 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -103,8 +103,9 @@ namespace tunnel void Cleanup () override { m_Endpoint.Cleanup (); } void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; + void FlushTunnelDataMsgs () override; size_t GetNumTransmittedBytes () const override { return m_Endpoint.GetNumReceivedBytes (); } - std::string GetNextPeerName () const override { return ""; } + std::string GetNextPeerName () const override; private: diff --git a/libi2pd/TunnelBase.cpp b/libi2pd/TunnelBase.cpp index 1f437758..b5a4a0b3 100644 --- a/libi2pd/TunnelBase.cpp +++ b/libi2pd/TunnelBase.cpp @@ -64,7 +64,8 @@ namespace tunnel void TunnelTransportSender::Reset () { m_CurrentTransport.reset (); - m_PendingTransport = std::future >(); + if (m_PendingTransport.valid ()) + m_PendingTransport = std::future >(); } } } diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 3dc0dc07..6eb08ef3 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -21,10 +21,7 @@ namespace i2p { namespace tunnel { - TunnelEndpoint::~TunnelEndpoint () - { - } - + void TunnelEndpoint::HandleDecryptedTunnelDataMsg (std::shared_ptr msg) { m_NumReceivedBytes += TUNNEL_DATA_MSG_SIZE; @@ -331,13 +328,13 @@ namespace tunnel break; case eDeliveryTypeTunnel: if (!m_IsInbound) // outbound transit tunnel - i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); + SendMessageTo (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); else LogPrint (eLogError, "TunnelMessage: Delivery type 'tunnel' arrived from an inbound tunnel, dropped"); break; case eDeliveryTypeRouter: if (!m_IsInbound) // outbound transit tunnel - i2p::transport::transports.SendMessage (msg.hash, msg.data); + i2p::transport::transports.SendMessage (msg.hash, msg.data); // send right away, because most likely it's single message else // we shouldn't send this message. possible leakage LogPrint (eLogError, "TunnelMessage: Delivery type 'router' arrived from an inbound tunnel, dropped"); break; @@ -366,5 +363,36 @@ namespace tunnel ++it; } } + + void TunnelEndpoint::SendMessageTo (const i2p::data::IdentHash& to, std::shared_ptr msg) + { + if (msg) + { + if (!m_Sender && m_I2NPMsgs.empty ()) // first message + m_CurrentHash = to; + else if (m_CurrentHash != to) // new target router + { + FlushI2NPMsgs (); // flush message to previous + if (m_Sender) m_Sender->Reset (); // reset sender + m_CurrentHash = to; // set new target router + } // otherwise add msg to the list for current target router + m_I2NPMsgs.push_back (msg); + i2p::transport::transports.SendMessage (to, msg); + } + } + + void TunnelEndpoint::FlushI2NPMsgs () + { + if (!m_I2NPMsgs.empty ()) + { + if (!m_Sender) m_Sender = std::make_unique(); + m_Sender->SendMessagesTo (m_CurrentHash, m_I2NPMsgs); // send and clear + } + } + + const i2p::data::IdentHash * TunnelEndpoint::GetCurrentHash () const + { + return (m_Sender || !m_I2NPMsgs.empty ()) ? &m_CurrentHash : nullptr; + } } } diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index 17590a5f..ac1e8e87 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,8 +11,10 @@ #include #include +#include #include #include +#include #include "I2NPProtocol.h" #include "TunnelBase.h" @@ -20,7 +22,7 @@ namespace i2p { namespace tunnel { - class TunnelEndpoint + class TunnelEndpoint final { struct TunnelMessageBlockEx: public TunnelMessageBlock { @@ -39,18 +41,23 @@ namespace tunnel public: TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0), m_CurrentMsgID (0) {}; - ~TunnelEndpoint (); + ~TunnelEndpoint () = default; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; void Cleanup (); void HandleDecryptedTunnelDataMsg (std::shared_ptr msg); + void FlushI2NPMsgs (); + const i2p::data::IdentHash * GetCurrentHash () const; // return null if not avaiable + const std::unique_ptr& GetSender () const { return m_Sender; }; + private: void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, uint8_t fragmentNum, const uint8_t * fragment, size_t size); bool ConcatFollowOnFragment (TunnelMessageBlockEx& msg, const uint8_t * fragment, size_t size) const; // true if success void HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment); void HandleNextMessage (const TunnelMessageBlock& msg); + void SendMessageTo (const i2p::data::IdentHash& to, std::shared_ptr msg); void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, const uint8_t * fragment, size_t size); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added @@ -65,6 +72,10 @@ namespace tunnel size_t m_NumReceivedBytes; TunnelMessageBlockEx m_CurrentMessage; uint32_t m_CurrentMsgID; + // I2NP messages to send + std::list > m_I2NPMsgs; // to send + i2p::data::IdentHash m_CurrentHash; // send msgs to + std::unique_ptr m_Sender; }; } }