From a30e6ae50f69f8e47a7b656131e4c1545494d766 Mon Sep 17 00:00:00 2001 From: PobreGato <315121269+pobregat0@users.noreply.github.com> Date: Tue, 18 Aug 2026 04:34:47 +0300 Subject: [PATCH 1/2] keep the acceptor of a server tunnel through a reload --- libi2pd_client/ClientContext.cpp | 6 ++++++ libi2pd_client/I2PTunnel.cpp | 13 ++++++++++++- libi2pd_client/I2PTunnel.h | 4 +++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index e7197f27..b57cf4cd 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -262,6 +262,10 @@ namespace client ReadSocksProxy (); // handle tunnels + // take the acceptors off first, a tunnel still in the config sets its own back + // while it is read, incoming streams wait in the queue meanwhile + for (auto& it: m_ServerTunnels) + it.second->DetachAcceptor (); // reset isUpdated for each tunnel VisitTunnels (false); // reload tunnels @@ -980,6 +984,8 @@ namespace client ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ()); ins.first->second->Start (); } + else + ins.first->second->Accept (); // still in the config, take the acceptor back ins.first->second->isUpdated = true; LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); } diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 7ed7528e..2245648b 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -822,13 +822,24 @@ namespace client Accept (); } - void I2PServerTunnel::Stop () + void I2PServerTunnel::DetachAcceptor () { if (m_PortDestination) m_PortDestination->ResetAcceptor (); auto localDestination = GetLocalDestination (); if (localDestination) localDestination->StopAcceptingStreams (); + } + + void I2PServerTunnel::Stop () + { + if (m_PortDestination) + m_PortDestination->ResetAcceptor (); + auto localDestination = GetLocalDestination (); + // another tunnel on the same destination may hold the acceptor by now, + // taking it away would leave that one deaf + if (localDestination && localDestination->GetRefCounter () <= 1) + localDestination->StopAcceptingStreams (); if (m_Resolver) m_Resolver->cancel (); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 626fc0f2..90320ce7 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -213,13 +213,15 @@ namespace client const char* GetName() const override { return m_Name.c_str (); } + void Accept (); + void DetachAcceptor (); // called before the tunnels are read again on reload + private: bool Resolve (std::shared_ptr stream); void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::results_type endpoints, std::shared_ptr stream); - void Accept (); void HandleAccept (std::shared_ptr stream); void Connect (std::shared_ptr stream); virtual std::shared_ptr CreateI2PConnection (std::shared_ptr stream); From bde02543b0729ba0ba65881dfa80bf13fbaf2b76 Mon Sep 17 00:00:00 2001 From: PobreGato <315121269+pobregat0@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:14:42 +0300 Subject: [PATCH 2/2] take the acceptor off only if this tunnel set it --- libi2pd_client/I2PTunnel.cpp | 19 ++++++++++--------- libi2pd_client/I2PTunnel.h | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 2245648b..b8fd4604 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -803,7 +803,7 @@ namespace client I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination, uint16_t inport, bool gzip): - I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) + I2PService (localDestination), m_IsUniqueLocal(true), m_IsDefaultAcceptor (false), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { m_PortDestination = localDestination->GetStreamingDestination (inport); if (!m_PortDestination) // default destination @@ -827,19 +827,17 @@ namespace client if (m_PortDestination) m_PortDestination->ResetAcceptor (); auto localDestination = GetLocalDestination (); - if (localDestination) + // the default acceptor may belong to another tunnel on the same destination + if (localDestination && m_IsDefaultAcceptor) + { localDestination->StopAcceptingStreams (); + m_IsDefaultAcceptor = false; + } } void I2PServerTunnel::Stop () { - if (m_PortDestination) - m_PortDestination->ResetAcceptor (); - auto localDestination = GetLocalDestination (); - // another tunnel on the same destination may hold the acceptor by now, - // taking it away would leave that one deaf - if (localDestination && localDestination->GetRefCounter () <= 1) - localDestination->StopAcceptingStreams (); + DetachAcceptor (); if (m_Resolver) m_Resolver->cancel (); @@ -946,7 +944,10 @@ namespace client if (localDestination) { if (!localDestination->IsAcceptingStreams ()) // set it as default if not set yet + { localDestination->AcceptStreams (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); + m_IsDefaultAcceptor = true; + } } else LogPrint (eLogError, "I2PTunnel: Local destination not set for server tunnel"); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 90320ce7..c6aa3083 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -229,6 +229,7 @@ namespace client private: bool m_IsUniqueLocal; + bool m_IsDefaultAcceptor; // this tunnel is the one accepting on the destination std::string m_Name, m_Address; uint16_t m_Port; boost::asio::ip::tcp::endpoint m_Endpoint;