Open Lighting Architecture
 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/thread/Thread.h>
40 #include <ola/io/SelectServer.h>
41 #include <ola/network/Socket.h>
42 #include <ola/network/IPV4Address.h>
43 #include <ola/rdm/UID.h>
44 #include <ola/thread/ExecutorInterface.h>
45 #include <ola/slp/SLPClient.h>
46 #include <ola/slp/URLEntry.h>
47 
48 #include <map>
49 #include <string>
50 #include <vector>
51 
52 namespace ola {
53 namespace e133 {
54 
55 using std::string;
56 using ola::rdm::UID;
58 using ola::slp::URLEntries;
59 
61  public:
62  string backend_type;
63 
64  SLPThreadServerInfo() : ServerInfo() {}
65 
66  SLPThreadServerInfo(const SLPThreadServerInfo &server_info)
67  : ServerInfo(server_info),
68  backend_type(server_info.backend_type) {
69  }
70 
71  explicit SLPThreadServerInfo(const ola::slp::ServerInfo &server_info)
72  : ServerInfo(server_info) {
73  }
74 };
75 
80  public:
86 
87  // Ownership is not transferred.
88  explicit BaseSLPThread(
90  unsigned int discovery_interval = DEFAULT_DISCOVERY_INTERVAL_SECONDS);
91  virtual ~BaseSLPThread();
92 
93  // These must be called before Init(); Once Initialized the callbacks can't
94  // be changed. Ownership of the callback is transferred.
95  bool SetNewControllerCallback(DiscoveryCallback *callback);
96  bool SetNewDeviceCallback(DiscoveryCallback *callback);
97 
98  void RegisterDevice(RegistrationCallback *callback,
99  const IPV4Address &address,
100  const UID &uid,
101  uint16_t lifetime);
102 
103  void RegisterController(RegistrationCallback *callback,
104  const IPV4Address &address,
105  uint16_t lifetime);
106 
107  void DeRegisterDevice(RegistrationCallback *callback,
108  const IPV4Address &address,
109  const UID &uid);
110 
111  void DeRegisterController(RegistrationCallback *callback,
112  const IPV4Address &address);
113 
114  void ServerInfo(ServerInfoCallback *callback);
115 
116  void RunDeviceDiscoveryNow();
117 
118  virtual bool Init();
119  bool Start();
120  bool Join(void *ptr = NULL);
121  virtual void Cleanup() = 0;
122 
123  static const unsigned int DEFAULT_DISCOVERY_INTERVAL_SECONDS;
124 
125  protected:
128 
130  ola::thread::ExecutorInterface *m_executor;
131 
132  void *Run();
133  void RunCallbackInExecutor(RegistrationCallback *callback, bool ok);
134 
135  // The sub class provides these, they are allowed to block.
136  virtual void RunDiscovery(InternalDiscoveryCallback *callback,
137  const string &service) = 0;
138  virtual void RegisterSLPService(RegistrationCallback *callback,
139  const string& url,
140  uint16_t lifetime) = 0;
141  virtual void DeRegisterSLPService(RegistrationCallback *callback,
142  const string& url) = 0;
143  virtual void SLPServerInfo(ServerInfoCallback *callback) = 0;
144 
145  // Called after the SelectServer has finished and just before the thread
146  // completes.
147  virtual void ThreadStopping() {}
148 
149  // This enables us to limit the refresh-time, 0 means the implementation
150  // doesn't have a min-refresh-time.
151  virtual uint16_t MinRefreshTime() { return 0; }
152 
153  void ReRegisterAllServices();
154 
155  static const char RDNMET_SCOPE[];
156 
157  private:
158  typedef struct {
159  uint16_t lifetime;
160  ola::thread::timeout_id timeout;
161  } URLRegistrationState;
162  typedef std::map<string, URLRegistrationState> URLStateMap;
163 
164  typedef struct {
165  DiscoveryCallback *callback;
166  ola::thread::timeout_id timeout;
167  } DiscoveryState;
168  typedef std::map<string, DiscoveryState> DiscoveryStateMap;
169 
170  URLStateMap m_url_map;
171  DiscoveryStateMap m_discovery_callbacks;
172  bool m_init_ok;
173  unsigned int m_discovery_interval;
174 
175  // discovery methods
176  void AddDiscoveryCallback(string service, DiscoveryCallback *callback);
177  void StartDiscoveryProcess();
178  void RemoveDiscoveryTimeout(DiscoveryState *state);
179  void RunDiscoveryForService(const string service);
180  void ForceDiscovery(const string service);
181  void DiscoveryComplete(const string service, bool result,
182  const URLEntries &urls);
183  void RunDiscoveryCallback(DiscoveryCallback *callback, bool result,
184  const URLEntries *urls);
185  void DiscoveryTriggered(const string service);
186 
187  // register / deregister methods
188  void RegisterService(RegistrationCallback *callback, const string url,
189  uint16_t lifetime);
190  void RegistrationComplete(RegistrationCallback *callback, string url,
191  bool ok);
192  void DeRegisterService(RegistrationCallback *callback, const string url);
193  void ReRegisterService(string url);
194  void CompleteCallback(RegistrationCallback *callback, bool ok);
195 
196  // server info methods
197  void GetServerInfo(ServerInfoCallback *callback);
198  void HandleServerInfo(ServerInfoCallback *callback, bool ok,
199  const SLPThreadServerInfo &service_info);
200  void CompleteServerInfo(ServerInfoCallback *callback,
201  bool ok,
202  const SLPThreadServerInfo *server_info_ptr);
203 
204  // helper methods
205  static string GetDeviceURL(const IPV4Address& address, const UID &uid);
206  static string GetControllerURL(const IPV4Address& address);
207  static uint16_t ClampLifetime(const string &url, uint16_t lifetime);
208 
209  static const uint16_t MIN_SLP_LIFETIME;
210  static const uint16_t SA_REREGISTRATION_TIME;
211  static const char E133_DEVICE_SLP_SERVICE_NAME[];
212  static const char E133_CONTROLLER_SLP_SERVICE_NAME[];
213 };
214 
215 
220  public:
221  static BaseSLPThread* NewSLPThread(
223  unsigned int discovery_interval =
224  BaseSLPThread::DEFAULT_DISCOVERY_INTERVAL_SECONDS);
225 
226  private:
228  SLPThreadFactory& operator=(const SLPThreadFactory&);
229 };
230 } // namespace e133
231 } // namespace ola
232 #endif // INCLUDE_OLA_E133_SLPTHREAD_H_