aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/db/upnp/Discovery.cxx96
-rw-r--r--src/db/upnp/Discovery.hxx55
-rw-r--r--src/db/upnp/WorkQueue.hxx1
3 files changed, 80 insertions, 72 deletions
diff --git a/src/db/upnp/Discovery.cxx b/src/db/upnp/Discovery.cxx
index da0fe5c8d..d7982f670 100644
--- a/src/db/upnp/Discovery.cxx
+++ b/src/db/upnp/Discovery.cxx
@@ -19,20 +19,14 @@
#include "config.h"
#include "Discovery.hxx"
-#include "Device.hxx"
#include "Domain.hxx"
#include "ContentDirectoryService.hxx"
-#include "WorkQueue.hxx"
#include "upnpplib.hxx"
-#include "thread/Mutex.hxx"
-#include <upnp/upnp.h>
#include <upnp/upnptools.h>
#include <string.h>
-#include <map>
-
// The service type string we are looking for.
static const char *const ContentDirectorySType = "urn:schemas-upnp-org:service:ContentDirectory:1";
@@ -57,64 +51,14 @@ isMSDevice(const char *st)
return memcmp(MediaServerDType, st, sz) == 0;
}
-/**
- * Each appropriate discovery event (executing in a libupnp thread
- * context) queues the following task object for processing by the
- * discovery thread.
- */
-struct DiscoveredTask {
- bool alive;
- std::string url;
- std::string deviceId;
- int expires; // Seconds valid
-
- DiscoveredTask(bool _alive, const Upnp_Discovery *disco)
- : alive(_alive), url(disco->Location),
- deviceId(disco->DeviceId),
- expires(disco->Expires) {}
-
-};
-static WorkQueue<DiscoveredTask *> discoveredQueue("DiscoveredQueue");
-
-// Descriptor for one device having a Content Directory service found
-// on the network.
-class ContentDirectoryDescriptor {
-public:
- ContentDirectoryDescriptor(const std::string &url,
- const std::string &description,
- time_t last, int exp)
- :device(url, description), last_seen(last), expires(exp+20) {}
- UPnPDevice device;
- time_t last_seen;
- int expires; // seconds valid
-};
-
-// A ContentDirectoryPool holds the characteristics of the servers
-// currently on the network.
-// The map is referenced by deviceId (==UDN)
-// The class is instanciated as a static (unenforced) singleton.
-class ContentDirectoryPool {
-public:
- Mutex m_mutex;
- std::map<std::string, ContentDirectoryDescriptor> m_directories;
-};
-
-static ContentDirectoryPool contentDirectories;
-
-// Worker routine for the discovery queue. Get messages about devices
-// appearing and disappearing, and update the directory pool
-// accordingly.
-static void *
-discoExplorer(void *)
+inline void
+UPnPDeviceDirectory::discoExplorer()
{
- auto &mutex = contentDirectories.m_mutex;
- auto &directories = contentDirectories.m_directories;
-
for (;;) {
DiscoveredTask *tsk = 0;
if (!discoveredQueue.take(tsk)) {
discoveredQueue.workerExit();
- return (void*)1;
+ return;
}
const ScopeLock protect(mutex);
@@ -156,8 +100,16 @@ discoExplorer(void *)
}
}
-static int
-OnAlive(Upnp_Discovery *disco)
+void *
+UPnPDeviceDirectory::discoExplorer(void *ctx)
+{
+ UPnPDeviceDirectory &directory = *(UPnPDeviceDirectory *)ctx;
+ directory.discoExplorer();
+ return (void*)1;
+}
+
+inline int
+UPnPDeviceDirectory::OnAlive(Upnp_Discovery *disco)
{
if (isMSDevice(disco->DeviceType) ||
isCDService(disco->ServiceType)) {
@@ -169,8 +121,8 @@ OnAlive(Upnp_Discovery *disco)
return UPNP_E_SUCCESS;
}
-static int
-OnByeBye(Upnp_Discovery *disco)
+inline int
+UPnPDeviceDirectory::OnByeBye(Upnp_Discovery *disco)
{
if (isMSDevice(disco->DeviceType) ||
@@ -187,8 +139,8 @@ OnByeBye(Upnp_Discovery *disco)
// thread context.
// Example: ContentDirectories appearing and disappearing from the network
// We queue a task for our worker thread(s)
-static int
-cluCallBack(Upnp_EventType et, void *evp)
+inline int
+UPnPDeviceDirectory::cluCallBack(Upnp_EventType et, void *evp)
{
switch (et) {
case UPNP_DISCOVERY_SEARCH_RESULT:
@@ -215,8 +167,7 @@ cluCallBack(Upnp_EventType et, void *evp)
void
UPnPDeviceDirectory::expireDevices()
{
- const ScopeLock protect(contentDirectories.m_mutex);
- auto &directories = contentDirectories.m_directories;
+ const ScopeLock protect(mutex);
time_t now = time(0);
bool didsomething = false;
@@ -235,14 +186,16 @@ UPnPDeviceDirectory::expireDevices()
}
UPnPDeviceDirectory::UPnPDeviceDirectory(LibUPnP *_lib)
- :lib(_lib), m_searchTimeout(2), m_lastSearch(0)
+ :lib(_lib),
+ discoveredQueue("DiscoveredQueue"),
+ m_searchTimeout(2), m_lastSearch(0)
{
- if (!discoveredQueue.start(1, discoExplorer, 0)) {
+ if (!discoveredQueue.start(1, discoExplorer, this)) {
error.Set(upnp_domain, "Discover work queue start failed");
return;
}
- lib->SetHandler([](Upnp_EventType type, void *event){
+ lib->SetHandler([this](Upnp_EventType type, void *event){
cluCallBack(type, event);
});
@@ -288,8 +241,7 @@ UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out)
// Has locking, do it before our own lock
expireDevices();
- const ScopeLock protect(contentDirectories.m_mutex);
- auto &directories = contentDirectories.m_directories;
+ const ScopeLock protect(mutex);
for (auto dit = directories.begin();
dit != directories.end(); dit++) {
diff --git a/src/db/upnp/Discovery.hxx b/src/db/upnp/Discovery.hxx
index 412307fd7..c4704dc7e 100644
--- a/src/db/upnp/Discovery.hxx
+++ b/src/db/upnp/Discovery.hxx
@@ -20,9 +20,16 @@
#ifndef _UPNPPDISC_H_X_INCLUDED_
#define _UPNPPDISC_H_X_INCLUDED_
+#include "Device.hxx"
+#include "WorkQueue.hxx"
+#include "thread/Mutex.hxx"
#include "util/Error.hxx"
+#include <upnp/upnp.h>
+
+#include <map>
#include <vector>
+#include <string>
#include <time.h>
@@ -36,10 +43,46 @@ class ContentDirectoryService;
* for now, but this could be made more general, by removing the filtering.
*/
class UPnPDeviceDirectory {
+ /**
+ * Each appropriate discovery event (executing in a libupnp thread
+ * context) queues the following task object for processing by the
+ * discovery thread.
+ */
+ struct DiscoveredTask {
+ bool alive;
+ std::string url;
+ std::string deviceId;
+ int expires; // Seconds valid
+
+ DiscoveredTask(bool _alive, const Upnp_Discovery *disco)
+ : alive(_alive), url(disco->Location),
+ deviceId(disco->DeviceId),
+ expires(disco->Expires) {}
+ };
+
+ /**
+ * Descriptor for one device having a Content Directory
+ * service found on the network.
+ */
+ class ContentDirectoryDescriptor {
+ public:
+ ContentDirectoryDescriptor(const std::string &url,
+ const std::string &description,
+ time_t last, int exp)
+ :device(url, description), last_seen(last), expires(exp+20) {}
+ UPnPDevice device;
+ time_t last_seen;
+ int expires; // seconds valid
+ };
+
LibUPnP *const lib;
Error error;
+ Mutex mutex;
+ std::map<std::string, ContentDirectoryDescriptor> directories;
+ WorkQueue<DiscoveredTask *> discoveredQueue;
+
/**
* The UPnP device search timeout, which should actually be
* called delay because it's the base of a random delay that
@@ -85,6 +128,18 @@ private:
* directory.
*/
void expireDevices();
+
+ /**
+ * Worker routine for the discovery queue. Get messages about
+ * devices appearing and disappearing, and update the
+ * directory pool accordingly.
+ */
+ static void *discoExplorer(void *);
+ void discoExplorer();
+
+ int OnAlive(Upnp_Discovery *disco);
+ int OnByeBye(Upnp_Discovery *disco);
+ int cluCallBack(Upnp_EventType et, void *evp);
};
diff --git a/src/db/upnp/WorkQueue.hxx b/src/db/upnp/WorkQueue.hxx
index 7537fb874..fe8ce53f9 100644
--- a/src/db/upnp/WorkQueue.hxx
+++ b/src/db/upnp/WorkQueue.hxx
@@ -23,6 +23,7 @@
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
+#include <assert.h>
#include <pthread.h>
#include <string>