diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index ea93f951..91c8abbb 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -669,13 +669,18 @@ namespace proxy { if(stream) { - m_ClientResponse.code = 200; - m_ClientResponse.status = "OK"; - m_send_buf = m_ClientResponse.to_string(); - m_sock->send(boost::asio::buffer(m_send_buf)); - auto connection = std::make_shared(GetOwner(), m_sock, stream); - GetOwner()->AddHandler(connection); - connection->I2PConnect(); + if (m_sock && m_sock->is_open ()) + { + m_ClientResponse.code = 200; + m_ClientResponse.status = "OK"; + m_send_buf = m_ClientResponse.to_string(); + m_sock->send(boost::asio::buffer(m_send_buf)); + auto connection = std::make_shared(GetOwner(), m_sock, stream); + GetOwner()->AddHandler(connection); + connection->I2PConnect(); + } + else + stream->AsyncClose (); m_sock = nullptr; Terminate(); } diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index b62e6e2c..f546ad81 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2025, The PurpleI2P Project +* Copyright (c) 2013-2026, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -90,7 +90,7 @@ namespace client boost::asio::ip::address ourIP = boost::asio::ip::address_v6 (bytes); return ourIP; } - + #ifdef __linux__ static void MapToLoopback(std::shared_ptr sock, const i2p::data::IdentHash & addr, bool isV4) { @@ -116,7 +116,7 @@ namespace client I2PTunnelSetSocketOptions (m_Socket); #ifdef __linux__ if (isUniqueLocal && m_RemoteEndpoint.address ().is_loopback ()) - { + { auto ident = m_Stream->GetRemoteIdentity()->GetIdentHash(); if (m_RemoteEndpoint.address ().is_v4 ()) { @@ -127,7 +127,7 @@ namespace client { m_Socket->open (boost::asio::ip::tcp::v6 ()); MapToLoopback(m_Socket, ident, false); - } + } } #endif m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, @@ -173,11 +173,11 @@ namespace client size_t bufSize = I2P_TUNNEL_CONNECTION_BUFFER_SIZE; size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; if (unsentSize) - { + { if (unsentSize >= I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full if (unsentSize > I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - I2P_TUNNEL_CONNECTION_BUFFER_SIZE) bufSize = I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - unsentSize; - } + } m_IsReceiving = true; if (m_SSL) m_SSL->async_read_some (boost::asio::buffer(m_Buffer, bufSize), @@ -201,7 +201,7 @@ namespace client } } else - { + { if (bytes_transferred < I2P_TUNNEL_CONNECTION_BUFFER_SIZE && !m_SSL) { boost::system::error_code ec; @@ -212,22 +212,22 @@ namespace client if (bytes_transferred + moreBytes > I2P_TUNNEL_CONNECTION_BUFFER_SIZE) moreBytes = I2P_TUNNEL_CONNECTION_BUFFER_SIZE - bytes_transferred; if (m_Stream->GetSendBufferSize () < I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) - { + { size_t remaining = I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - m_Stream->GetSendBufferSize (); if (remaining < moreBytes) moreBytes = remaining; - } + } else moreBytes = 0; - } + } if (moreBytes) { moreBytes = boost::asio::read (*m_Socket, boost::asio::buffer(m_Buffer + bytes_transferred, moreBytes), boost::asio::transfer_all (), ec); if (!ec) bytes_transferred += moreBytes; - } - } + } + } WriteToStream (m_Buffer, bytes_transferred); Receive (); // try to receive more while being sent to stream - } + } } void I2PTunnelConnection::WriteToStream (const uint8_t * buf, size_t len) @@ -493,8 +493,8 @@ namespace client // add X-I2P fields m_OutHeader << m_XI2P; // end of header - m_OutHeader << "\r\n"; - + m_OutHeader << "\r\n"; + m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header m_InHeader.str (""); m_HeaderSent = true; @@ -622,7 +622,7 @@ namespace client uint16_t destinationPort, std::shared_ptr socket): I2PServiceHandler(parent), m_Address(address), m_DestinationPort (destinationPort), m_Socket(socket) {}; - void Handle(); + void Handle() override; void Terminate(); private: void HandleStreamRequestComplete (std::shared_ptr stream); @@ -643,11 +643,19 @@ namespace client if (stream) { if (Kill()) return; - LogPrint (eLogDebug, "I2PTunnel: New connection"); - auto connection = std::make_shared(GetOwner(), m_Socket, stream); - GetOwner()->AddHandler (connection); - connection->I2PConnect (); - Done(shared_from_this()); + if (m_Socket && m_Socket->is_open ()) + { + LogPrint (eLogDebug, "I2PTunnel: New connection"); + auto connection = std::make_shared(GetOwner(), m_Socket, stream); + GetOwner()->AddHandler (connection); + connection->I2PConnect (); + Done(shared_from_this()); + } + else + { + stream->AsyncClose (); + Terminate (); + } } else { @@ -770,9 +778,9 @@ namespace client auto localDestination = GetLocalDestination (); if (localDestination) localDestination->StopAcceptingStreams (); - if (m_Resolver) + if (m_Resolver) m_Resolver->cancel (); - + ClearHandlers (); } @@ -784,8 +792,8 @@ namespace client std::bind (&I2PServerTunnel::HandleResolve, this, std::placeholders::_1, std::placeholders::_2, stream)); return true; - } - + } + void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::results_type endpoints, std::shared_ptr stream) { @@ -902,7 +910,7 @@ namespace client LogPrint (eLogWarning, "I2PTunnel: Address ", m_Address, " can't be resolved. Incoming connection dropped"); stream->Close (); return; - } + } } } @@ -915,8 +923,8 @@ namespace client conn->Connect (*m_LocalAddress); else conn->Connect (m_IsUniqueLocal); - } - + } + std::shared_ptr I2PServerTunnel::CreateI2PConnection (std::shared_ptr stream) { return std::make_shared (this, stream, GetEndpoint (), m_SSLCtx); @@ -942,7 +950,7 @@ namespace client ss << X_I2P_DEST_HASH << ": " << from->GetIdentHash ().ToBase64 () << "\r\n"; ss << X_I2P_DEST_B64 << ": " << from->ToBase64 () << "\r\n"; m_XI2P = ss.str (); - } + } return std::make_shared (this, stream, GetEndpoint (), m_Host, m_XI2P, GetSSLCtx ()); }