Changeset View
Changeset View
Standalone View
Standalone View
src/mapport.cpp
Show All 29 Lines | |||||
#include <atomic> | #include <atomic> | ||||
#include <cassert> | #include <cassert> | ||||
#include <chrono> | #include <chrono> | ||||
#include <functional> | #include <functional> | ||||
#include <string> | #include <string> | ||||
#include <thread> | #include <thread> | ||||
#ifdef USE_UPNP | #ifdef USE_UPNP | ||||
static CThreadInterrupt g_upnp_interrupt; | static CThreadInterrupt g_mapport_interrupt; | ||||
static std::thread g_upnp_thread; | static std::thread g_mapport_thread; | ||||
static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; | static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; | ||||
using namespace std::chrono_literals; | using namespace std::chrono_literals; | ||||
static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD{20min}; | static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD{20min}; | ||||
static constexpr auto PORT_MAPPING_RETRY_PERIOD{5min}; | static constexpr auto PORT_MAPPING_RETRY_PERIOD{5min}; | ||||
static bool ProcessUpnp() { | static bool ProcessUpnp() { | ||||
bool ret = false; | bool ret = false; | ||||
Show All 23 Lines | if (r == 1) { | ||||
if (r != UPNPCOMMAND_SUCCESS) { | if (r != UPNPCOMMAND_SUCCESS) { | ||||
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); | LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); | ||||
} else { | } else { | ||||
if (externalIPAddress[0]) { | if (externalIPAddress[0]) { | ||||
CNetAddr resolved; | CNetAddr resolved; | ||||
if (LookupHost(externalIPAddress, resolved, false)) { | if (LookupHost(externalIPAddress, resolved, false)) { | ||||
LogPrintf("UPnP: ExternalIPAddress = %s\n", | LogPrintf("UPnP: ExternalIPAddress = %s\n", | ||||
resolved.ToString()); | resolved.ToString()); | ||||
AddLocal(resolved, LOCAL_UPNP); | AddLocal(resolved, LOCAL_MAPPED); | ||||
} | } | ||||
} else { | } else { | ||||
LogPrintf("UPnP: GetExternalIPAddress failed.\n"); | LogPrintf("UPnP: GetExternalIPAddress failed.\n"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
std::string strDesc = PACKAGE_NAME " " + FormatFullVersion(); | std::string strDesc = PACKAGE_NAME " " + FormatFullVersion(); | ||||
do { | do { | ||||
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | ||||
port.c_str(), port.c_str(), lanaddr, | port.c_str(), port.c_str(), lanaddr, | ||||
strDesc.c_str(), "TCP", 0, "0"); | strDesc.c_str(), "TCP", 0, "0"); | ||||
if (r != UPNPCOMMAND_SUCCESS) { | if (r != UPNPCOMMAND_SUCCESS) { | ||||
ret = false; | ret = false; | ||||
LogPrintf( | LogPrintf( | ||||
"AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | "AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | ||||
port, port, lanaddr, r, strupnperror(r)); | port, port, lanaddr, r, strupnperror(r)); | ||||
break; | break; | ||||
} else { | } else { | ||||
ret = true; | ret = true; | ||||
LogPrintf("UPnP Port Mapping successful.\n"); | LogPrintf("UPnP Port Mapping successful.\n"); | ||||
} | } | ||||
} while (g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); | } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); | ||||
g_upnp_interrupt.reset(); | g_mapport_interrupt.reset(); | ||||
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, | r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, | ||||
port.c_str(), "TCP", 0); | port.c_str(), "TCP", 0); | ||||
LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); | LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); | ||||
freeUPNPDevlist(devlist); | freeUPNPDevlist(devlist); | ||||
devlist = nullptr; | devlist = nullptr; | ||||
FreeUPNPUrls(&urls); | FreeUPNPUrls(&urls); | ||||
} else { | } else { | ||||
LogPrintf("No valid UPnP IGDs found\n"); | LogPrintf("No valid UPnP IGDs found\n"); | ||||
freeUPNPDevlist(devlist); | freeUPNPDevlist(devlist); | ||||
devlist = nullptr; | devlist = nullptr; | ||||
if (r != 0) { | if (r != 0) { | ||||
FreeUPNPUrls(&urls); | FreeUPNPUrls(&urls); | ||||
} | } | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
static void ThreadMapPort() { | static void ThreadMapPort() { | ||||
do { | do { | ||||
if (ProcessUpnp()) { | if (ProcessUpnp()) { | ||||
return; | return; | ||||
} | } | ||||
} while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); | } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); | ||||
} | } | ||||
void StartThreadMapPort() { | void StartThreadMapPort() { | ||||
if (!g_upnp_thread.joinable()) { | if (!g_mapport_thread.joinable()) { | ||||
assert(!g_upnp_interrupt); | assert(!g_mapport_interrupt); | ||||
g_upnp_thread = std::thread(&util::TraceThread, "upnp", &ThreadMapPort); | g_mapport_thread = | ||||
std::thread(&util::TraceThread, "mapport", &ThreadMapPort); | |||||
} | } | ||||
} | } | ||||
static void DispatchMapPort() { | static void DispatchMapPort() { | ||||
if (g_mapport_target_proto == MapPortProtoFlag::UPNP) { | if (g_mapport_target_proto == MapPortProtoFlag::UPNP) { | ||||
StartThreadMapPort(); | StartThreadMapPort(); | ||||
} else { | } else { | ||||
InterruptMapPort(); | InterruptMapPort(); | ||||
Show All 10 Lines | |||||
} | } | ||||
void StartMapPort(bool use_upnp) { | void StartMapPort(bool use_upnp) { | ||||
MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp); | MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp); | ||||
DispatchMapPort(); | DispatchMapPort(); | ||||
} | } | ||||
void InterruptMapPort() { | void InterruptMapPort() { | ||||
if (g_upnp_thread.joinable()) { | if (g_mapport_thread.joinable()) { | ||||
g_upnp_interrupt(); | g_mapport_interrupt(); | ||||
} | } | ||||
} | } | ||||
void StopMapPort() { | void StopMapPort() { | ||||
if (g_upnp_thread.joinable()) { | if (g_mapport_thread.joinable()) { | ||||
g_upnp_thread.join(); | g_mapport_thread.join(); | ||||
g_upnp_interrupt.reset(); | g_mapport_interrupt.reset(); | ||||
} | } | ||||
} | } | ||||
#else | #else | ||||
void StartMapPort(bool use_upnp) { | void StartMapPort(bool use_upnp) { | ||||
// Intentionally left blank. | // Intentionally left blank. | ||||
} | } | ||||
void InterruptMapPort() { | void InterruptMapPort() { | ||||
// Intentionally left blank. | // Intentionally left blank. | ||||
} | } | ||||
void StopMapPort() { | void StopMapPort() { | ||||
// Intentionally left blank. | // Intentionally left blank. | ||||
} | } | ||||
#endif | #endif |