--- a/libupnpp/control/discovery.hxx
+++ b/libupnpp/control/discovery.hxx
@@ -23,6 +23,7 @@
#include <string>
#include <functional>
+#include <unordered_map>
namespace UPnPClient {
class UPnPDeviceDesc;
@@ -37,14 +38,14 @@
* Manage UPnP discovery and maintain a directory of active devices. Singleton.
*
*
- * The service is initialize on the first call, starting
+ * The service is initialized on the first call, starting
* the message-handling thread, registering our message handlers,
* and initiating an asynchronous UPnP device search.
*
* The search implies a timeout period (the specified interval
* over which the servers will send replies at random points). Any
* subsequent traverse() call will block until the timeout
- * is expired. Use getRemainingDelay() to know the current
+ * is expired. Use getRemainingDelayMs() to know the current
* remaining delay, and use it to do something else.
*
* We need a separate thread to process the messages coming up
@@ -52,35 +53,42 @@
* calls to libupnp, and this must not be done from the libupnp
* thread context which reported the initial message.
* So there are three threads in action:
- * - the reporting thread from libupnp.
- * - the discovery service processing thread, which also runs the callbacks.
- * - the user thread (typically the main thread), which calls traverse.
+ * - The reporting thread from libupnp.
+ * - The discovery service processing thread, which also runs the callbacks.
+ * - The user thread (typically the main thread), which calls traverse.
*/
class UPnPDeviceDirectory {
public:
/** Retrieve the singleton object for the discovery service,
- * and possibly start it up if this is the first call. This does not wait
- * significantly, a subsequent traverse() will wait until the
- * initial delay is consumed.
+ * and possibly start it up if this is the first call. This does
+ * not wait significantly: a subsequent traverse() will wait until
+ * the initial delay is consumed. 2 S is libupnp MIN_SEARCH_WAIT,
+ * I don't see much reason to use more
*/
- static UPnPDeviceDirectory *getTheDir(time_t search_window = 3);
+ static UPnPDeviceDirectory *getTheDir(time_t search_window = 2);
/** Clean up before exit. Do call this.*/
static void terminate();
+ /** Type of user callback functions used for reporting devices and
+ * services */
typedef std::function<bool (const UPnPDeviceDesc&,
- const UPnPServiceDesc&)> Visitor;
+ const UPnPServiceDesc&)> Visitor;
/** Possibly wait for the end of the initial delay, then traverse
- the directory and call Visitor for each device/service pair */
+ * the directory and call Visitor for each device/service pair */
bool traverse(Visitor);
- /** Remaining time until current search complete */
+ /** Remaining milliseconds until current search complete. */
time_t getRemainingDelayMs();
+ /** Remaining seconds until current search complete. Better use
+ * getRemainingDelayMs(), this is kept only for compatibility. */
time_t getRemainingDelay();
/** Set a callback to be called when devices report their existence
- * The visitor will be called once per device, with an empty service.
+ * The function will be called once per device, with an empty service,
+ * Note that calls to v may be performed from a separate thread
+ * and some may occur before addCallback() returns.
*/
static unsigned int addCallback(Visitor v);
static void delCallback(unsigned int idx);
@@ -89,7 +97,11 @@
*
* This will wait for the remaining duration of the search window if the
* device is not found at once.
- * Note that "friendly names" are not necessarily unique.
+ * Note that "friendly names" are not necessarily unique. The method will
+ * return a random instance (the first found) if there are several.
+ * @param fname the device UPnP "friendly name" to be looked for
+ * @param[out] ddesc the description data if the device was found.
+ * @return true if the name was found, else false.
*/
bool getDevByFName(const std::string& fname, UPnPDeviceDesc& ddesc);
@@ -97,44 +109,34 @@
*
* This will wait for the remaining duration of the search window if the
* device is not found at once.
+ * @param udn the device Unique Device Name, a UUID.
+ * @param[out] ddesc the description data if the device was found.
+ * @return true if the device was found, else false.
*/
bool getDevByUDN(const std::string& udn, UPnPDeviceDesc& ddesc);
+ /** Helper function: retrieve all description data for a named device
+ * @param uidOrFriendly device identification. First tried as UUID then
+ * friendly name.
+ * @param[output] deviceXML device description document.
+ * @param[output] srvsXML service name - service description map.
+ * @return true for success.
+ */
+ bool getDescriptionDocuments(
+ const std::string &uidOrFriendly, std::string& deviceXML,
+ std::unordered_map<std::string, std::string>& srvsXML);
+
+
/** My health */
- bool ok() {
- return m_ok;
- }
+ bool ok();
+
/** My diagnostic if health is bad */
- const std::string getReason() {
- return m_reason;
- }
+ const std::string getReason();
private:
- UPnPDeviceDirectory(time_t search_window);
UPnPDeviceDirectory(const UPnPDeviceDirectory &);
UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &);
-
- // Start UPnP search and record start of timeout
- bool search();
- // Look at the current pool and remove expired entries
- void expireDevices();
-
- // This is called by the thread which processes the device events
- // when a new device appears. It wakes up any thread waiting for a
- // device.
- bool deviceFound(const UPnPDeviceDesc&, const UPnPServiceDesc&);
-
- // Lookup a device in the pool. If not found and a search is active,
- // use a cond_wait to wait for device events (awaken by deviceFound).
- bool getDevBySelector(bool cmp(const UPnPDeviceDesc&, const std::string&),
- const std::string& value, UPnPDeviceDesc& ddesc);
-
- static void *discoExplorer(void *);
-
- bool m_ok;
- std::string m_reason;
- int m_searchTimeout;
- time_t m_lastSearch;
+ UPnPDeviceDirectory(time_t search_window);
};
} // namespace UPnPClient