Changeset View
Changeset View
Standalone View
Standalone View
src/mapport.cpp
Show All 33 Lines | |||||
#include <thread> | #include <thread> | ||||
#ifdef USE_UPNP | #ifdef USE_UPNP | ||||
static CThreadInterrupt g_upnp_interrupt; | static CThreadInterrupt g_upnp_interrupt; | ||||
static std::thread g_upnp_thread; | static std::thread g_upnp_thread; | ||||
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 void ThreadMapPort() { | static bool ProcessUpnp() { | ||||
bool ret = false; | |||||
std::string port = strprintf("%u", GetListenPort()); | std::string port = strprintf("%u", GetListenPort()); | ||||
const char *multicastif = nullptr; | const char *multicastif = nullptr; | ||||
const char *minissdpdpath = nullptr; | const char *minissdpdpath = nullptr; | ||||
struct UPNPDev *devlist = nullptr; | struct UPNPDev *devlist = nullptr; | ||||
char lanaddr[64]; | char lanaddr[64]; | ||||
int error = 0; | int error = 0; | ||||
#if MINIUPNPC_API_VERSION < 14 | #if MINIUPNPC_API_VERSION < 14 | ||||
Show All 31 Lines | if (r == 1) { | ||||
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; | |||||
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; | |||||
} else { | } else { | ||||
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_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); | ||||
g_upnp_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; | |||||
} | |||||
static void ThreadMapPort() { | |||||
do { | |||||
if (ProcessUpnp()) { | |||||
return; | |||||
} | |||||
} while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); | |||||
} | } | ||||
void StartMapPort() { | void StartMapPort() { | ||||
if (!g_upnp_thread.joinable()) { | if (!g_upnp_thread.joinable()) { | ||||
assert(!g_upnp_interrupt); | assert(!g_upnp_interrupt); | ||||
g_upnp_thread = std::thread(&util::TraceThread, "upnp", &ThreadMapPort); | g_upnp_thread = std::thread(&util::TraceThread, "upnp", &ThreadMapPort); | ||||
} | } | ||||
} | } | ||||
Show All 25 Lines |