From e73f738bfa531504ba2419bbbf1e68338e8d1c94 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 26 Oct 2025 21:09:12 -0400 Subject: [PATCH] assign next available UDP port to UDP associate --- libi2pd_client/SOCKS.cpp | 27 +++++++++++++++++++++++---- libi2pd_client/SOCKS.h | 7 +++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index e0fdff64..20db444e 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -127,6 +127,7 @@ namespace proxy void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); + SOCKSServer * GetServer () { return (SOCKSServer *)GetOwner (); }; boost::asio::const_buffer GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port); boost::asio::const_buffer GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); bool Socks5ChooseAuth(); @@ -234,6 +235,7 @@ namespace proxy if (m_UDPTunnel) { m_UDPTunnel->Stop (); + GetServer ()->ReleaseLocalUDPPort (m_UDPTunnel->GetLocalEndpoint ().port ()); m_UDPTunnel = nullptr; } Done(shared_from_this()); @@ -647,19 +649,16 @@ namespace proxy shared_from_this(), std::placeholders::_1), m_address.dns.ToString(), m_port); break; case CMD_UDP: - { // create UDP client tunnel LogPrint (eLogInfo, "SOCKS: New UDP associate connection"); - const auto& localEndpoint = ((SOCKSServer *)GetOwner ())->GetLocalEndpoint (); m_UDPTunnel = std::make_unique("", addr, - boost::asio::ip::udp::endpoint (localEndpoint.address (), localEndpoint.port ()), // use proxy endpoint TODO: select UDP port + GetServer ()->GetNextLocalUDPEndpoint (), GetOwner ()->GetLocalDestination (), m_port, false, i2p::datagram::eDatagramV3); boost::asio::post (GetOwner ()->GetService (), [this](void) { SocksRequestSuccess(); }); break; - } default: ; } } @@ -872,5 +871,25 @@ namespace proxy m_UpstreamProxyPort = port; m_UseUpstreamProxy = true; } + + boost::asio::ip::udp::endpoint SOCKSServer::GetNextLocalUDPEndpoint () + { + const auto& localEndpoint = GetLocalEndpoint (); + uint16_t port = localEndpoint.port (); +#if __cplusplus >= 202002L // C++20 + while (m_UDPPorts.contains (port)) +#else + while (m_UDPPorts.count (port) > 0) +#endif + port++; + m_UDPPorts.insert (port); + + return boost::asio::ip::udp::endpoint (localEndpoint.address (), port); // use proxy address + } + + void SOCKSServer::ReleaseLocalUDPPort (uint16_t port) + { + m_UDPPorts.erase (port); + } } } diff --git a/libi2pd_client/SOCKS.h b/libi2pd_client/SOCKS.h index bd88d6e6..ee16b1ad 100644 --- a/libi2pd_client/SOCKS.h +++ b/libi2pd_client/SOCKS.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,7 +28,9 @@ namespace proxy ~SOCKSServer() {}; void SetUpstreamProxy(const std::string & addr, const uint16_t port); - + boost::asio::ip::udp::endpoint GetNextLocalUDPEndpoint (); + void ReleaseLocalUDPPort (uint16_t port); + protected: // Implements TCPIPAcceptor @@ -41,6 +43,7 @@ namespace proxy std::string m_UpstreamProxyAddress; uint16_t m_UpstreamProxyPort; bool m_UseUpstreamProxy; + std::set m_UDPPorts; }; typedef SOCKSServer SOCKSProxy;