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] 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);