Skip to content
Snippets Groups Projects
Commit af46a372 authored by Mohamed Chibani's avatar Mohamed Chibani
Browse files

upnp/pupnp: request all mapping remove on IGD discovery

Send a request to delete all mappings created by previous
JAMI instances as soon as a new upnp IGD is discovered.
This is necessary with some implementations since they may
not respond well if the list of existing mappings is large.
Also make new requests for mappings with failing states.

Change-Id: I97308f1620128a63f111bcfc02122b472def5c85
Gitlab: #335
parent 31fa5f12
No related branches found
No related tags found
No related merge requests found
...@@ -419,6 +419,9 @@ PUPnP::validateIgd(const IGDInfo& info) ...@@ -419,6 +419,9 @@ PUPnP::validateIgd(const IGDInfo& info)
validIgdList_.emplace_back(igd_candidate); validIgdList_.emplace_back(igd_candidate);
} }
// Clear existing mappings
removeAllLocalMappings(igd_candidate);
// Report to the listener. // Report to the listener.
observer_->onIgdUpdated(igd_candidate, UpnpIgdEvent::ADDED); observer_->onIgdUpdated(igd_candidate, UpnpIgdEvent::ADDED);
......
...@@ -506,6 +506,10 @@ UPnPContext::updateMappingList(bool async) ...@@ -506,6 +506,10 @@ UPnPContext::updateMappingList(bool async)
return; return;
} }
// Make new requests for mappings that failed and have
// the auto-update option enabled.
processMappingWithAutoUpdate();
PortType typeArray[2] = {PortType::TCP, PortType::UDP}; PortType typeArray[2] = {PortType::TCP, PortType::UDP};
for (auto idx : {0, 1}) { for (auto idx : {0, 1}) {
...@@ -729,6 +733,45 @@ UPnPContext::processPendingRequests(const std::shared_ptr<IGD>& igd) ...@@ -729,6 +733,45 @@ UPnPContext::processPendingRequests(const std::shared_ptr<IGD>& igd)
} }
} }
void
UPnPContext::processMappingWithAutoUpdate()
{
// This list holds the mappings to be requested. This is
// needed to avoid performing the requests while holding
// the lock.
std::list<Mapping::sharedPtr_t> requestsList;
// Populate the list of requests for mappings with auto-update enabled.
{
std::lock_guard<std::mutex> lock(mappingMutex_);
PortType typeArray[2] {PortType::TCP, PortType::UDP};
for (auto type : typeArray) {
auto& mappingList = getMappingList(type);
for (auto const& [_, map] : mappingList) {
if (map->getState() == MappingState::FAILED and map->getAutoUpdate()) {
requestsList.emplace_back(map);
}
}
}
}
for (auto const& map : requestsList) {
// Request a new mapping if auto-update is enabled.
JAMI_DBG("Mapping %s has auto-update enabled, a new mapping will be requested",
map->toString().c_str());
// Reserve a new mapping.
Mapping newMapping(*map);
newMapping.setExternalPort(0);
newMapping.setInternalPort(0);
registerMapping(newMapping);
// Release the old one.
map->setAvailable(true);
unregisterMapping(map);
}
}
void void
UPnPContext::onIgdUpdated(const std::shared_ptr<IGD>& igd, UpnpIgdEvent event) UPnPContext::onIgdUpdated(const std::shared_ptr<IGD>& igd, UpnpIgdEvent event)
{ {
...@@ -1178,26 +1221,6 @@ UPnPContext::updateMappingState(const Mapping::sharedPtr_t& map, MappingState ne ...@@ -1178,26 +1221,6 @@ UPnPContext::updateMappingState(const Mapping::sharedPtr_t& map, MappingState ne
// Notify the listener if set. // Notify the listener if set.
if (notify and map->getNotifyCallback()) if (notify and map->getNotifyCallback())
map->getNotifyCallback()(map); map->getNotifyCallback()(map);
// Nothing more to do if there is no valid IGD.
if (not hasValidIGD())
return;
// On fail, request a new mapping if auto-update is enabled.
if (newState == MappingState::FAILED and map->getAutoUpdate()) {
JAMI_DBG("Mapping %s has auto-update enabled, a new mapping will be requested",
map->toString().c_str());
// Run async to avoid double locks.
runOnUpnpContextThread([this, map] {
// Reserve a new mapping.
Mapping newMapping(*map);
newMapping.setExternalPort(0);
newMapping.setInternalPort(0);
reserveMapping(newMapping);
// Release the old one.
releaseMapping(*map);
});
}
} }
#if HAVE_LIBNATPMP #if HAVE_LIBNATPMP
......
...@@ -221,8 +221,12 @@ private: ...@@ -221,8 +221,12 @@ private:
void renewAllocations(); void renewAllocations();
#endif #endif
// Process requests with pending status.
void processPendingRequests(const std::shared_ptr<IGD>& igd); void processPendingRequests(const std::shared_ptr<IGD>& igd);
// Process mapping with auto-update flag enabled.
void processMappingWithAutoUpdate();
// Implementation of UpnpMappingObserver interface. // Implementation of UpnpMappingObserver interface.
// Callback used to report changes in IGD status. // Callback used to report changes in IGD status.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment