@@ -1459,6 +1459,8 @@ void CConnman::WakeMessageHandler()
14591459
14601460
14611461#ifdef USE_UPNP
1462+ static CThreadInterrupt g_upnp_interrupt;
1463+ static std::thread g_upnp_thread;
14621464void ThreadMapPort ()
14631465{
14641466 std::string port = strprintf (" %u" , GetListenPort ());
@@ -1509,35 +1511,29 @@ void ThreadMapPort()
15091511
15101512 std::string strDesc = " Bitcoin " + FormatFullVersion ();
15111513
1512- try {
1513- while (true ) {
1514+ do {
15141515#ifndef UPNPDISCOVER_SUCCESS
1515- /* miniupnpc 1.5 */
1516- r = UPNP_AddPortMapping (urls.controlURL , data.first .servicetype ,
1517- port.c_str (), port.c_str (), lanaddr, strDesc.c_str (), " TCP" , 0 );
1516+ /* miniupnpc 1.5 */
1517+ r = UPNP_AddPortMapping (urls.controlURL , data.first .servicetype ,
1518+ port.c_str (), port.c_str (), lanaddr, strDesc.c_str (), " TCP" , 0 );
15181519#else
1519- /* miniupnpc 1.6 */
1520- r = UPNP_AddPortMapping (urls.controlURL , data.first .servicetype ,
1521- port.c_str (), port.c_str (), lanaddr, strDesc.c_str (), " TCP" , 0 , " 0" );
1520+ /* miniupnpc 1.6 */
1521+ r = UPNP_AddPortMapping (urls.controlURL , data.first .servicetype ,
1522+ port.c_str (), port.c_str (), lanaddr, strDesc.c_str (), " TCP" , 0 , " 0" );
15221523#endif
15231524
1524- if (r!=UPNPCOMMAND_SUCCESS)
1525- LogPrintf (" AddPortMapping(%s, %s, %s) failed with code %d (%s)\n " ,
1526- port, port, lanaddr, r, strupnperror (r));
1527- else
1528- LogPrintf (" UPnP Port Mapping successful.\n " );
1529-
1530- MilliSleep (20 *60 *1000 ); // Refresh every 20 minutes
1531- }
1532- }
1533- catch (const boost::thread_interrupted&)
1534- {
1535- r = UPNP_DeletePortMapping (urls.controlURL , data.first .servicetype , port.c_str (), " TCP" , 0 );
1536- LogPrintf (" UPNP_DeletePortMapping() returned: %d\n " , r);
1537- freeUPNPDevlist (devlist); devlist = nullptr ;
1538- FreeUPNPUrls (&urls);
1539- throw ;
1525+ if (r!=UPNPCOMMAND_SUCCESS)
1526+ LogPrintf (" AddPortMapping(%s, %s, %s) failed with code %d (%s)\n " ,
1527+ port, port, lanaddr, r, strupnperror (r));
1528+ else
1529+ LogPrintf (" UPnP Port Mapping successful.\n " );
15401530 }
1531+ while (g_upnp_interrupt.sleep_for (std::chrono::minutes (20 )));
1532+
1533+ r = UPNP_DeletePortMapping (urls.controlURL , data.first .servicetype , port.c_str (), " TCP" , 0 );
1534+ LogPrintf (" UPNP_DeletePortMapping() returned: %d\n " , r);
1535+ freeUPNPDevlist (devlist); devlist = nullptr ;
1536+ FreeUPNPUrls (&urls);
15411537 } else {
15421538 LogPrintf (" No valid UPnP IGDs found\n " );
15431539 freeUPNPDevlist (devlist); devlist = nullptr ;
@@ -1546,27 +1542,39 @@ void ThreadMapPort()
15461542 }
15471543}
15481544
1549- void MapPort ( bool fUseUPnP )
1545+ void StartMapPort ( )
15501546{
1551- static std::unique_ptr<boost::thread> upnp_thread;
1547+ if (!g_upnp_thread.joinable ()) {
1548+ assert (!g_upnp_interrupt);
1549+ g_upnp_thread = std::thread ((std::bind (&TraceThread<void (*)()>, " upnp" , &ThreadMapPort)));
1550+ }
1551+ }
15521552
1553- if (fUseUPnP )
1554- {
1555- if (upnp_thread) {
1556- upnp_thread->interrupt ();
1557- upnp_thread->join ();
1558- }
1559- upnp_thread.reset (new boost::thread (boost::bind (&TraceThread<void (*)()>, " upnp" , &ThreadMapPort)));
1553+ void InterruptMapPort ()
1554+ {
1555+ if (g_upnp_thread.joinable ()) {
1556+ g_upnp_interrupt ();
15601557 }
1561- else if (upnp_thread) {
1562- upnp_thread->interrupt ();
1563- upnp_thread->join ();
1564- upnp_thread.reset ();
1558+ }
1559+
1560+ void StopMapPort ()
1561+ {
1562+ if (g_upnp_thread.joinable ()) {
1563+ g_upnp_thread.join ();
1564+ g_upnp_interrupt.reset ();
15651565 }
15661566}
15671567
15681568#else
1569- void MapPort (bool )
1569+ void StartMapPort ()
1570+ {
1571+ // Intentionally left blank.
1572+ }
1573+ void InterruptMapPort ()
1574+ {
1575+ // Intentionally left blank.
1576+ }
1577+ void StopMapPort ()
15701578{
15711579 // Intentionally left blank.
15721580}
0 commit comments