Open Lighting Architecture  0.9.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SLPThread.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15  *
16  * SLPThread.h
17  * Copyright (C) 2011 Simon Newton
18  *
19  * The BaseSLPThread abstracts away all the SLP code in an implementation
20  * independant manner. There are two implementations, one that uses openslp and
21  * the other that uses OLA's SLP server.
22  *
23  * Like the name implies, the SLPThread starts up a new thread to handle SLP
24  * operations. You simple have to call RegisterDevice / RegisterController
25  * once, and the thread will take care of re-registering your service before
26  * the lifetime expires.
27  *
28  * To de-register the service entirely call DeRegisterDevice /
29  * DeRegisterController.
30  *
31  * The Register* and DeRegister* methods can be called from any thread.
32  * The callbacks will run the in Executor passed to the constructor.
33  */
34 
35 #ifndef INCLUDE_OLA_E133_SLPTHREAD_H_
36 #define INCLUDE_OLA_E133_SLPTHREAD_H_
37 
38 #include <ola/Callback.h>
39 #include <ola/base/Macro.h>
40 #include <ola/io/SelectServer.h>
42 #include <ola/network/Socket.h>
43 #include <ola/rdm/UID.h>
44 #include <ola/slp/SLPClient.h>
45 #include <ola/slp/URLEntry.h>
46 #include <ola/thread/ExecutorInterface.h>
47 #include <ola/thread/Thread.h>
48 
49 #include <map>
50 #include <string>
51 #include <vector>
52 
53 namespace ola {
54 namespace e133 {
55 
56 using std::string;
57 using ola::rdm::UID;
59 using ola::slp::URLEntries;
60 
62  public:
63  string backend_type;
64 
65  SLPThreadServerInfo() : ServerInfo() {}
66 
67  SLPThreadServerInfo(const SLPThreadServerInfo &server_info)
68  : ServerInfo(server_info),
69  backend_type(server_info.backend_type) {
70  }
71 
72  explicit SLPThreadServerInfo(const ola::slp::ServerInfo &server_info)
73  : ServerInfo(server_info) {
74  }
75 };
76 
81  public:
87 
88  // Ownership is not transferred.
89  explicit BaseSLPThread(
91  unsigned int discovery_interval = DEFAULT_DISCOVERY_INTERVAL_SECONDS);
92  virtual ~BaseSLPThread();
93 
94  // These must be called before Init(); Once Initialized the callbacks can't
95  // be changed. Ownership of the callback is transferred.
96  bool SetNewControllerCallback(DiscoveryCallback *callback);
97  bool SetNewDeviceCallback(DiscoveryCallback *callback);
98 
99  void RegisterDevice(RegistrationCallback *callback,
100  const IPV4Address &address,
101  const UID &uid,
102  uint16_t lifetime);
103 
104  void RegisterController(RegistrationCallback *callback,
105  const IPV4Address &address,
106  uint16_t lifetime);
107 
108  void DeRegisterDevice(RegistrationCallback *callback,
109  const IPV4Address &address,
110  const UID &uid);
111 
112  void DeRegisterController(RegistrationCallback *callback,
113  const IPV4Address &address);
114 
115  void ServerInfo(ServerInfoCallback *callback);
116 
117  void RunDeviceDiscoveryNow();
118 
119  virtual bool Init();
120  bool Start();
121  bool Join(void *ptr = NULL);
122  virtual void Cleanup() = 0;
123 
124  static const unsigned int DEFAULT_DISCOVERY_INTERVAL_SECONDS;
125 
126  protected:
129 
131  ola::thread::ExecutorInterface *m_executor;
132 
133  void *Run();
134  void RunCallbackInExecutor(RegistrationCallback *callback, bool ok);
135 
136  // The sub class provides these, they are allowed to block.
137  virtual void RunDiscovery(InternalDiscoveryCallback *callback,
138  const string &service) = 0;
139  virtual void RegisterSLPService(RegistrationCallback *callback,
140  const string& url,
141  uint16_t lifetime) = 0;
142  virtual void DeRegisterSLPService(RegistrationCallback *callback,
143  const string& url) = 0;
144  virtual void SLPServerInfo(ServerInfoCallback *callback) = 0;
145 
146  // Called after the SelectServer has finished and just before the thread
147  // completes.
148  virtual void ThreadStopping() {}
149 
150  // This enables us to limit the refresh-time, 0 means the implementation
151  // doesn't have a min-refresh-time.
152  virtual uint16_t MinRefreshTime() { return 0; }
153 
154  void ReRegisterAllServices();
155 
156  static const char RDNMET_SCOPE[];
157 
158  private:
159  typedef struct {
160  uint16_t lifetime;
161  ola::thread::timeout_id timeout;
162  } URLRegistrationState;
163  typedef std::map<string, URLRegistrationState> URLStateMap;
164 
165  typedef struct {
166  DiscoveryCallback *callback;
167  ola::thread::timeout_id timeout;
168  } DiscoveryState;
169  typedef std::map<string, DiscoveryState> DiscoveryStateMap;
170 
171  URLStateMap m_url_map;
172  DiscoveryStateMap m_discovery_callbacks;
173  bool m_init_ok;
174  unsigned int m_discovery_interval;
175 
176  // discovery methods
177  void AddDiscoveryCallback(string service, DiscoveryCallback *callback);
178  void StartDiscoveryProcess();
179  void RemoveDiscoveryTimeout(DiscoveryState *state);
180  void RunDiscoveryForService(const string service);
181  void ForceDiscovery(const string service);
182  void DiscoveryComplete(const string service, bool result,
183  const URLEntries &urls);
184  void RunDiscoveryCallback(DiscoveryCallback *callback, bool result,
185  const URLEntries *urls);
186  void DiscoveryTriggered(const string service);
187 
188  // register / deregister methods
189  void RegisterService(RegistrationCallback *callback, const string url,
190  uint16_t lifetime);
191  void RegistrationComplete(RegistrationCallback *callback, string url,
192  bool ok);
193  void DeRegisterService(RegistrationCallback *callback, const string url);
194  void ReRegisterService(string url);
195  void CompleteCallback(RegistrationCallback *callback, bool ok);
196 
197  // server info methods
198  void GetServerInfo(ServerInfoCallback *callback);
199  void HandleServerInfo(ServerInfoCallback *callback, bool ok,
200  const SLPThreadServerInfo &service_info);
201  void CompleteServerInfo(ServerInfoCallback *callback,
202  bool ok,
203  const SLPThreadServerInfo *server_info_ptr);
204 
205  // helper methods
206  static string GetDeviceURL(const IPV4Address& address, const UID &uid);
207  static string GetControllerURL(const IPV4Address& address);
208  static uint16_t ClampLifetime(const string &url, uint16_t lifetime);
209 
210  static const uint16_t MIN_SLP_LIFETIME;
211  static const uint16_t SA_REREGISTRATION_TIME;
212  static const char E133_DEVICE_SLP_SERVICE_NAME[];
213  static const char E133_CONTROLLER_SLP_SERVICE_NAME[];
214 
215  DISALLOW_COPY_AND_ASSIGN(BaseSLPThread);
216 };
217 
218 
223  public:
224  static BaseSLPThread* NewSLPThread(
226  unsigned int discovery_interval =
227  BaseSLPThread::DEFAULT_DISCOVERY_INTERVAL_SECONDS);
228 
229  private:
230  DISALLOW_COPY_AND_ASSIGN(SLPThreadFactory);
231 };
232 } // namespace e133
233 } // namespace ola
234 #endif // INCLUDE_OLA_E133_SLPTHREAD_H_