Parent: [088eac] (diff)

Child: [280d16] (diff)

Download this file

discovery.hxx    135 lines (114 with data), 4.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Copyright (C) 2006-2016 J.F.Dockes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _UPNPPDISC_H_X_INCLUDED_
#define _UPNPPDISC_H_X_INCLUDED_
#include "libupnpp/config.h"
#include <time.h>
#include <string>
#include <functional>
namespace UPnPClient {
class UPnPDeviceDesc;
}
namespace UPnPClient {
class UPnPServiceDesc;
}
namespace UPnPClient {
/**
* Manage UPnP discovery and maintain a directory of active devices. Singleton.
*
*
* The service is initialize 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
* remaining delay, and use it to do something else.
*
* We need a separate thread to process the messages coming up
* from libupnp, because some of them will in turn trigger other
* 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.
*/
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.
*/
static UPnPDeviceDirectory *getTheDir(time_t search_window = 3);
/** Clean up before exit. Do call this.*/
static void terminate();
typedef std::function<bool (const UPnPDeviceDesc&,
const UPnPServiceDesc&)> Visitor;
/** Possibly wait for the end of the initial delay, then traverse
the directory and call Visitor for each device/service pair */
bool traverse(Visitor);
/** Remaining time until current search complete */
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.
*/
static unsigned int addCallback(Visitor v);
static void delCallback(unsigned int idx);
/** Find device by friendlyName or UDN. Unlike traverse, this does
* not necessarily wait for the initial timeout, it returns as
* soon as a device with this name reports (or the timeout expires).
* Note that "friendly names" are not necessarily unique.
*/
bool getDevByFName(const std::string& fname, UPnPDeviceDesc& ddesc);
bool getDevByUDN(const std::string& udn, UPnPDeviceDesc& ddesc);
/** My health */
bool ok() {
return m_ok;
}
/** My diagnostic if health is bad */
const std::string getReason() {
return m_reason;
}
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;
};
} // namespace UPnPClient
#endif /* _UPNPPDISC_H_X_INCLUDED_ */