From 828efcc9ebff12efbaa9e74adf4a3ebb9ecde463 Mon Sep 17 00:00:00 2001 From: PobreGato <315121269+pobregat0@users.noreply.github.com> Date: Mon, 24 Aug 2026 01:09:26 +0300 Subject: [PATCH] hold udp tunnel and session by shared_ptr in socket handlers --- libi2pd_client/UDPTunnel.cpp | 18 +++++++++++++----- libi2pd_client/UDPTunnel.h | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 300f74ac..6c509c08 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -155,6 +155,7 @@ namespace client auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort); s->SetMaxWindow (m_MaxWindow); + s->Receive (); std::lock_guard lock(m_SessionsMutex); m_Sessions.emplace (idx, s); return s; @@ -377,14 +378,18 @@ namespace client IPSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_SOCKET_BUFFER_SIZE)); IPSocket.set_option (boost::asio::socket_base::send_buffer_size (I2P_UDP_SOCKET_BUFFER_SIZE)); IPSocket.non_blocking (true); - Receive(); + // Receive is not called here: it takes a shared pointer to this session, + // which does not exist yet while the constructor runs } void UDPSession::Receive() { LogPrint(eLogDebug, "UDPSession: Receive"); - IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), - FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); + IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, + [s = std::static_pointer_cast(shared_from_this ())](const boost::system::error_code& ecode, std::size_t len) + { + s->HandleReceived (ecode, len); + }); } void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) @@ -662,8 +667,11 @@ namespace client void I2PUDPClientTunnel::RecvFromLocal () { - m_LocalSocket->async_receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), - m_RecvEndpoint, std::bind (&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2)); + m_LocalSocket->async_receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, + [s = std::static_pointer_cast(shared_from_this ())](const boost::system::error_code& ecode, std::size_t transferred) + { + s->HandleRecvFromLocal (ecode, transferred); + }); } void I2PUDPClientTunnel::HandleRecvFromLocal (const boost::system::error_code & ec, std::size_t transferred) diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index debe1a67..3b77615f 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -55,7 +55,9 @@ namespace client /** local socket buffers, not datagram size */ const size_t I2P_UDP_SOCKET_BUFFER_SIZE = 4*1024*1024; - struct UDPConnection + // handlers of both sides are queued on sockets and can outlive the object + // they belong to, so they hold it by a shared pointer + struct UDPConnection: public std::enable_shared_from_this { std::shared_ptr m_Destination; std::weak_ptr m_LastDatagramSession;