Skip to content
Snippets Groups Projects
Commit 60d62cb9 authored by Mohamed Chibani's avatar Mohamed Chibani Committed by Sébastien Blin
Browse files

upnp: ignore callbacks from PUPNP lib if the client is not registered

A callback from PUPNP lib may be received during the shutdown of the
daemon.
To prevent this race, we lock the ctrl point and we ignore the callback
if the client is registered.

Change-Id: Ie6a3cb37fc189a271673e0935a5f03abce1ffc73
Gitlab: #335
parent 9d566c57
No related branches found
No related tags found
No related merge requests found
...@@ -94,6 +94,9 @@ errorOnResponse(IXML_Document* doc) ...@@ -94,6 +94,9 @@ errorOnResponse(IXML_Document* doc)
return false; return false;
} }
// UPNP class implementation
PUPnP::PUPnP() PUPnP::PUPnP()
{ {
if (not initUpnpLib()) if (not initUpnpLib())
...@@ -168,6 +171,7 @@ PUPnP::~PUPnP() ...@@ -168,6 +171,7 @@ PUPnP::~PUPnP()
removeAllLocalMappings(it); removeAllLocalMappings(it);
} }
validIgdList_.clear(); validIgdList_.clear();
clientRegistered_ = false;
UpnpUnRegisterClient(ctrlptHandle_); UpnpUnRegisterClient(ctrlptHandle_);
} }
...@@ -646,8 +650,10 @@ PUPnP::eventTypeToString(Upnp_EventType eventType) ...@@ -646,8 +650,10 @@ PUPnP::eventTypeToString(Upnp_EventType eventType)
int int
PUPnP::ctrlPtCallback(Upnp_EventType event_type, const void* event, void* user_data) PUPnP::ctrlPtCallback(Upnp_EventType event_type, const void* event, void* user_data)
{ {
if (auto pupnp = static_cast<PUPnP*>(user_data)) if (auto pupnp = static_cast<PUPnP*>(user_data)) {
std::lock_guard<std::mutex> lk(pupnp->ctrlptMutex_);
return pupnp->handleCtrlPtUPnPEvents(event_type, event); return pupnp->handleCtrlPtUPnPEvents(event_type, event);
}
JAMI_WARN("PUPnP: Control point callback without PUPnP"); JAMI_WARN("PUPnP: Control point callback without PUPnP");
return 0; return 0;
...@@ -786,6 +792,10 @@ PUPnP::processDiscoverySubscriptionExpired(const std::string& eventSubUrl) ...@@ -786,6 +792,10 @@ PUPnP::processDiscoverySubscriptionExpired(const std::string& eventSubUrl)
int int
PUPnP::handleCtrlPtUPnPEvents(Upnp_EventType event_type, const void* event) PUPnP::handleCtrlPtUPnPEvents(Upnp_EventType event_type, const void* event)
{ {
// Ignore if not registered
if (not PUPnP::clientRegistered_)
return UPNP_E_SUCCESS;
switch (event_type) { switch (event_type) {
// "ALIVE" events are processed as "SEARCH RESULT". It might be usefull // "ALIVE" events are processed as "SEARCH RESULT". It might be usefull
// if "SEARCH RESULT" was missed. // if "SEARCH RESULT" was missed.
......
...@@ -214,6 +214,10 @@ private: ...@@ -214,6 +214,10 @@ private:
static const char* eventTypeToString(Upnp_EventType eventType); static const char* eventTypeToString(Upnp_EventType eventType);
private: private:
// Indicates of the client is registered. Since at most only one instance
// of this class is created, using a static is unambiguous.
std::atomic_bool clientRegistered_ {false};
std::weak_ptr<PUPnP> weak() { return std::static_pointer_cast<PUPnP>(shared_from_this()); } std::weak_ptr<PUPnP> weak() { return std::static_pointer_cast<PUPnP>(shared_from_this()); }
NON_COPYABLE(PUPnP); NON_COPYABLE(PUPnP);
...@@ -235,7 +239,6 @@ private: ...@@ -235,7 +239,6 @@ private:
std::mutex ctrlptMutex_; // Mutex for client handle protection. std::mutex ctrlptMutex_; // Mutex for client handle protection.
UpnpClient_Handle ctrlptHandle_ {-1}; // Control point handle. UpnpClient_Handle ctrlptHandle_ {-1}; // Control point handle.
std::atomic_bool clientRegistered_ {false}; // Indicates of the client is registered.
std::atomic_bool searchForIgd_ {false}; // Variable to signal thread for a search. std::atomic_bool searchForIgd_ {false}; // Variable to signal thread for a search.
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment