diff --git a/src/tcp_server.h b/src/tcp_server.h index c721ec1..5677d16 100644 --- a/src/tcp_server.h +++ b/src/tcp_server.h @@ -160,6 +160,10 @@ private: protected: void start_listening(const std::string& listen_addresses, bool upnp); +#ifdef WITH_UPNP + int m_portMapping; +#endif + std::string m_socks5Proxy; bool m_socks5ProxyV6; raw_ip m_socks5ProxyIP; diff --git a/src/tcp_server.inl b/src/tcp_server.inl index ff5d633..4bf3427 100644 --- a/src/tcp_server.inl +++ b/src/tcp_server.inl @@ -25,6 +25,9 @@ template TCPServer::TCPServer(allocate_client_callback allocate_new_client) : m_allocateNewClient(allocate_new_client) , m_loopThread{} +#ifdef WITH_UPNP + , m_portMapping(0) +#endif , m_socks5ProxyV6(false) , m_socks5ProxyIP{} , m_socks5ProxyPort(-1) @@ -208,7 +211,7 @@ void TCPServer::start_listening(const std::string #ifdef WITH_UPNP if (upnp) { - add_portmapping(external_listen_port(), m_listenPort); + m_portMapping = add_portmapping(external_listen_port(), m_listenPort); } #else (void)upnp; @@ -428,6 +431,13 @@ void TCPServer::shutdown_tcp() } uv_async_send(&m_shutdownAsync); + +#ifdef WITH_UPNP + if (m_portMapping) { + remove_portmapping(m_portMapping); + } +#endif + uv_thread_join(&m_loopThread); uv_mutex_destroy(&m_bansLock); diff --git a/src/util.cpp b/src/util.cpp index e88439f..4d17c9e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -614,7 +614,7 @@ void destroy_upnp() uv_mutex_destroy(&upnp_discover.lock); } -void add_portmapping(int external_port, int internal_port) +int add_portmapping(int external_port, int internal_port) { LOGINFO(1, "UPnP: trying to map WAN:" << external_port << " to LAN:" << internal_port); @@ -622,7 +622,7 @@ void add_portmapping(int external_port, int internal_port) if (!upnp_discover.devlist) { LOGWARN(1, "upnpDiscover: no UPnP IGD devices found, error " << upnp_discover.error); - return; + return 0; } UPNPUrls urls; @@ -632,7 +632,7 @@ void add_portmapping(int external_port, int internal_port) int result = UPNP_GetValidIGD(upnp_discover.devlist, &urls, &data, local_addr, sizeof(local_addr)); if (result != 1) { LOGWARN(1, "UPNP_GetValidIGD returned " << result << ", no valid UPnP IGD devices found"); - return; + return 0; } LOGINFO(1, "UPnP: LAN IP address " << log::Gray() << static_cast(local_addr)); @@ -658,7 +658,7 @@ void add_portmapping(int external_port, int internal_port) result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), "TCP", nullptr); if (result) { LOGWARN(1, "UPNP_DeletePortMapping returned error " << result); - return; + return 0; } else { LOGINFO(1, "UPnP: Deleted mapping for external port " << external_port); @@ -668,9 +668,41 @@ void add_portmapping(int external_port, int internal_port) if (result) { LOGWARN(1, "UPNP_AddPortMapping returned error " << result); + return 0; + } + + LOGINFO(1, "UPnP: Mapped " << log::Gray() << static_cast(ext_addr) << ':' << external_port << log::NoColor() << " to " << log::Gray() << static_cast(local_addr) << ':' << internal_port); + return external_port; +} + +void remove_portmapping(int external_port) +{ + LOGINFO(1, "UPnP: trying to delete mapping for external port " << external_port); + + MutexLock lock(upnp_discover.lock); + + if (!upnp_discover.devlist) { + LOGWARN(1, "upnpDiscover: no UPnP IGD devices found, error " << upnp_discover.error); + return; + } + + UPNPUrls urls; + IGDdatas data; + char local_addr[64] = {}; + + int result = UPNP_GetValidIGD(upnp_discover.devlist, &urls, &data, local_addr, sizeof(local_addr)); + if (result != 1) { + LOGWARN(1, "UPNP_GetValidIGD returned " << result << ", no valid UPnP IGD devices found"); + return; + } + + const std::string eport = std::to_string(external_port); + result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), "TCP", nullptr); + if (result) { + LOGWARN(1, "UPNP_DeletePortMapping returned error " << result); } else { - LOGINFO(1, "UPnP: Mapped " << log::Gray() << static_cast(ext_addr) << ':' << external_port << log::NoColor() << " to " << log::Gray() << static_cast(local_addr) << ':' << internal_port); + LOGINFO(1, "UPnP: Deleted mapping for external port " << external_port); } } #endif diff --git a/src/util.h b/src/util.h index aa274b6..a4bd4bb 100644 --- a/src/util.h +++ b/src/util.h @@ -249,7 +249,8 @@ bool is_localhost(const std::string& host); #ifdef WITH_UPNP void init_upnp(); void destroy_upnp(); -void add_portmapping(int external_port, int internal_port); +int add_portmapping(int external_port, int internal_port); +void remove_portmapping(int external_port); #endif } // namespace p2pool