diff --git a/src/solanaceae/tox_upnp.cpp b/src/solanaceae/tox_upnp.cpp index 58602b9..5492f0c 100644 --- a/src/solanaceae/tox_upnp.cpp +++ b/src/solanaceae/tox_upnp.cpp @@ -5,6 +5,7 @@ #include #include +#include #include @@ -18,7 +19,53 @@ ToxUPnP::ToxUPnP(ToxI& tox) { // start upnp thread _thread = std::thread([this](void) { + const auto port_string = std::to_string(_local_port); int seconds_since_last {60*60}; + + std::unique_ptr devices(nullptr, freeUPNPDevlist); + UPNPUrls urls { nullptr, nullptr, nullptr, nullptr, nullptr, }; + IGDdatas data; + char lanaddr[64] = "unset"; + + while (!_quit) { + if (seconds_since_last < 60*60) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + seconds_since_last++; + continue; + } + seconds_since_last = 0; + + // first get available devices + int error {0}; + std::cerr << "TUPNP: starting search\n"; + devices.reset(upnpDiscover(2000, nullptr, nullptr, UPNP_LOCAL_PORT_ANY, 0, 2, &error)); + if (error != 0 || !static_cast(devices)) { + std::cerr << "TUPNP error: no device found\n"; + continue; + } + + std::cerr << "TUPNP: discovered devices:\n"; + for (auto* d = devices.get(); d != nullptr; d = d->pNext) { + std::cerr << " " << d->descURL << " " << d->st << " " << d->usn << "\n"; + } + + auto res = UPNP_GetValidIGD(devices.get(), &urls, &data, lanaddr, sizeof(lanaddr)); + + if (res < 1) { + std::cerr << "TUPNP error: no valid connected IGD has been found\n"; + if (res != 0) { + FreeUPNPUrls(&urls); + devices.reset(nullptr); + } + continue; + } + + std::cerr << "TUPNP: valid IGD found (" << res << "), local ip: " << lanaddr << "\n"; + break; + } + + seconds_since_last = 60*60; + bool last_mapping_succ {false}; while (!_quit) { if (seconds_since_last < 60*60) { @@ -29,37 +76,6 @@ ToxUPnP::ToxUPnP(ToxI& tox) { seconds_since_last = 0; last_mapping_succ = false; - // first get available devices - int error {0}; - std::cerr << "TUPNP: starting search\n"; - auto* devices = upnpDiscover(2000, nullptr, nullptr, UPNP_LOCAL_PORT_ANY, 0, 2, &error); - if (error != 0 || devices == nullptr) { - std::cerr << "TUPNP error: no device found\n"; - continue; - } - - std::cerr << "TUPNP: discovered devices:\n"; - for (auto* d = devices; d != nullptr; d = d->pNext) { - std::cerr << " " << d->descURL << " " << d->st << " " << d->usn << "\n"; - } - - UPNPUrls urls; - IGDdatas data; - char lanaddr[64] = "unset"; - auto res = UPNP_GetValidIGD(devices, &urls, &data, lanaddr, sizeof(lanaddr)); - - if (res < 1) { - std::cerr << "TUPNP error: no valid connected IGD has been found\n"; - if (res != 0) { - FreeUPNPUrls(&urls); - freeUPNPDevlist(devices); - } - continue; - } - - std::cerr << "TUPNP: valid IGD found (" << res << "), local ip: " << lanaddr << "\n"; - - const auto port_string = std::to_string(_local_port); auto map_ret = UPNP_AddPortMapping( urls.controlURL, data.first.servicetype, @@ -75,8 +91,6 @@ ToxUPnP::ToxUPnP(ToxI& tox) { if (map_ret != UPNPCOMMAND_SUCCESS) { std::cerr << "TUPNP error: adding port mapping failed " << strupnperror(map_ret) << "\n"; - FreeUPNPUrls(&urls); - freeUPNPDevlist(devices); continue; } @@ -101,21 +115,24 @@ ToxUPnP::ToxUPnP(ToxI& tox) { // potentially succ ??? last_mapping_succ = true; - - FreeUPNPUrls(&urls); - freeUPNPDevlist(devices); continue; } std::cerr << "TUPNP: mapping active external :" << port_string << " is redirected to internal " << intClient << ":" << intPort << " (for " << duration << "s)\n"; // potentially succ last_mapping_succ = true; - - FreeUPNPUrls(&urls); - freeUPNPDevlist(devices); } - // remove mapping here? + if (last_mapping_succ) { + UPNP_DeletePortMapping( + urls.controlURL, + data.first.servicetype, + port_string.c_str(), + "UDP", + nullptr + ); + } + FreeUPNPUrls(&urls); }); }