summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Platinum/Source/Core/PltService.h
blob: ebca19542c67da44589f93de729ba4d99644354c (plain)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
/*****************************************************************
|
|   Platinum - Service
|
| Copyright (c) 2004-2010, Plutinosoft, LLC.
| All rights reserved.
| http://www.plutinosoft.com
|
| This program is free software; you can redistribute it and/or
| modify it under the terms of the GNU General Public License
| as published by the Free Software Foundation; either version 2
| of the License, or (at your option) any later version.
|
| OEMs, ISVs, VARs and other distributors that combine and 
| distribute commercially licensed software with Platinum software
| and do not wish to distribute the source code for the commercially
| licensed software under version 2, or (at your option) any later
| version, of the GNU General Public License (the "GPL") must enter
| into a commercial license agreement with Plutinosoft, LLC.
| licensing@plutinosoft.com
|  
| This program 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 General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with this program; see the file LICENSE.txt. If not, write to
| the Free Software Foundation, Inc., 
| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
| http://www.gnu.org/licenses/gpl-2.0.html
|
****************************************************************/

/** @file
 UPnP Service
 */

#ifndef _PLT_SERVICE_H_
#define _PLT_SERVICE_H_

/*----------------------------------------------------------------------
|    includes
+---------------------------------------------------------------------*/
#include "Neptune.h"
#include "PltEvent.h"
#include "PltArgument.h"
#include "PltStateVariable.h"
#include "PltAction.h"

/*----------------------------------------------------------------------
|    forward declarations
+---------------------------------------------------------------------*/
class PLT_DeviceData;

/*----------------------------------------------------------------------
|    PLT_Service class
+---------------------------------------------------------------------*/
/**
 UPnP Service.
 The PLT_Service class holds information about a UPnP service of a given device.
 It maintains a list of actions and state variables. A PLT_DeviceData instance can own 
 one or more PLT_Service instances. When a PLT_Service is advertised as part of a
 a UPnP Device (PLT_DeviceHost), it also maintains a list of subscribers to nofify when
 state variables change.
 */
class PLT_Service
{
public:
    // methods
    /**
     Create an instance of a UPnP Service either hosted or discovered.
     @param device Pointer to the PLT_DeviceData the service is associated to
     @param type String representing the UPnP service type
     @param id String representing the UPnP service id
     @param name A String to create unique service SCPD, control and eventing urls
     @param last_change_namespace A String for the LastChange state variable namespace if any
     */
    PLT_Service(PLT_DeviceData* device,
                const char*     type, 
                const char*     id,
                const char*     name,
                const char*     last_change_namespace = NULL);
    virtual ~PLT_Service();
    
    // methods
    /**
     When service is hosted by a PLT_DeviceHost, this setups the SCPD, control and event urls.
     @param service_name the service name used to format unique urls
     */
    NPT_Result InitURLs(const char* service_name);
    
    /**
     Verify the service has been properly initialized or is a valid discovered service.
     @return true if valid.
     */
    bool IsValid() {  return (m_ActionDescs.GetItemCount() > 0); }
    
    /**
     When a PLT_DeviceHost needs to change more than one state variables at a time
     but would rather send only one event with all state variable changes, this can be 
     used to pause and resume the automatic eventing.
     @param pause Flag to indicate if eventing should be paused or resumed 
     */
    NPT_Result PauseEventing(bool pause = true);

    // class methods
    static bool IsTrue(const NPT_String& value) {
        if (value.Compare("1", true)    && 
            value.Compare("true", true) && 
            value.Compare("yes", true)) {
            return false;
        }
        return true;
    }

    // accessor methods
    /**
     Set the SCPD url for control points to be able to fetch the SCPD xml document.
     @param url relative path of SCPD url
     */
    NPT_Result SetSCPDURL(const char* url)     { m_SCPDURL = url; return NPT_SUCCESS; }
    
    /*
     Set the Service Control url for control points to be able to invoke actions.
     @param url relative path of control url
     */
    NPT_Result SetControlURL(const char* url)  { m_ControlURL = url; return NPT_SUCCESS; };
    
    /**
     Set the Service Event subscription url for control points to be able to subscribe
     to events.
     @param url relative path of even url
     */
    NPT_Result SetEventSubURL(const char* url) { m_EventSubURL = url; return NPT_SUCCESS; };
    
    /**
     Return the SCPD url associated with this service.
     @param absolute flag to indicate if absolute url including ip and port should
     be returned
     @return SCPD url
     */
    NPT_String GetSCPDURL(bool absolute = false);
    
    /**
     Return the Control url associated with this service.
     @param absolute flag to indicate if absolute url including ip and port should
     be returned
     @return Control url
     */
    NPT_String GetControlURL(bool absolute = false);
    
    /**
     Return the Event subscription url associated with this service.
     @param absolute flag to indicate if absolute url including ip and port should
     be returned
     @return Event url
     */
    NPT_String GetEventSubURL(bool absolute = false);
    
    /**
     Return the service id.
     @return service id
     */
    const NPT_String& GetServiceID() const { return m_ServiceID;   }
    
    /**
     Return the service type.
     @return service type
     */
    const NPT_String& GetServiceType() const { return m_ServiceType; }

    /**
     Return the service friendly name.
     @return service name
     */
    const NPT_String& GetServiceName() const { return m_ServiceName; } 

    /**
     Return the PLT_DeviceData* the service is associated with.
     @return PLT_DeviceData pointer
     */
    PLT_DeviceData* GetDevice() { return m_Device;      }
    
    /**
     When a control point discover a new service with a higher version number
     than it can work with, a lower version can be set to force backward 
     compatibility.
     @param version Integer specifying the version to use
     */
    NPT_Result ForceVersion(NPT_Cardinal version);

    /**
     Return the service SCPD xml document.
     @param xml String to receive document
     */
    NPT_Result GetSCPDXML(NPT_String& xml);
    
    /**
     Set the service SCPD xml document.
     @param xml String SCPD xml document
     */
    NPT_Result SetSCPDXML(const char* xml);
    
    /**
     Populate the UPnP Device description document with service information.
     @param parent XML Element where to insert the service XML Element
     @param service Pointer to service XML Element node newly created so it can be
     extended with additional non standard information.
     */
    NPT_Result GetDescription(NPT_XmlElementNode* parent, NPT_XmlElementNode** service = NULL);

    /**
     Set a new value for a given state variable. The service keeps track of which
     state variables have changed and events are being triggered by a PLT_ServiceEventTask
     when necessary.
     @param name state variable name
     @param value new State Variable value.
     @param clearonsend whether the State Variable should clear immediatly in ::OnSendingCompleted
     */
    NPT_Result SetStateVariable(const char* name, const char* value, const bool clearonsend = false);
    
    /**
     Certain state variables notifications must not be sent faster than a certain 
     rate according to the UPnP specs. This sets the rate for a given state variable.
     @param name state variable name
     @param rate a time interval specifying the minimum interval allowed between
     notifications.
     */
    NPT_Result SetStateVariableRate(const char* name, NPT_TimeInterval rate);
    
    /**
     Certain state variables require extra xml attributes when serialized.
     @param name state variable name
     @param key the attribute name
     @param value the attribute value
     */
	NPT_Result SetStateVariableExtraAttribute(const char* name, const char* key, const char* value);
    
    /**
     Helper function to increment a state variable representing a number.
     @param name state variable name
     */
    NPT_Result IncStateVariable(const char* name);
    
    /**
     Return the PLT_StateVariable pointer given a state variable name.
     @param name state variable name
     @return PLT_StateVariable pointer
     */
    PLT_StateVariable* FindStateVariable(const char* name);
    
    /**
     Return the state variable value given a state variable name.
     @param name state variable name
     @param value state variable value output
     */
    NPT_Result GetStateVariableValue(const char* name, NPT_String& value);
    
    /**
     Return whether a service is capable of sending events.
     @return true if sending events
     */
    bool IsSubscribable();
    
    /**
     Return the list of state variables.
     @return list of state variable pointers.
     */
    const NPT_List<PLT_StateVariable*>& GetStateVariables() const { return m_StateVars; }

    /**
     Return the PLT_ActionDesc given an action name
     @param name action name
     @return PLT_ActioDesc pointer
     */
    PLT_ActionDesc* FindActionDesc(const char* name);
    
    /**
     Return an array of actions descriptions PLT_ActionDesc.
     @return array of PLT_ActionDesc pointers.
     */
    const NPT_Array<PLT_ActionDesc*>& GetActionDescs() const { return m_ActionDescs; }

private:    
    /**
     A task to send events.
     The PLT_ServiceEventTask is started when receiving a first subscription. It
     monitors if some state variables have changed and sends events to all
     subscribers if so.
     */
    class PLT_ServiceEventTask : public PLT_ThreadTask {
    public:
        PLT_ServiceEventTask(PLT_Service* service) : m_Service(service) {}
        
        void DoRun() override { 
            while (!IsAborting(100)) m_Service->NotifyChanged();
        }
        
    private:
        PLT_Service* m_Service;
    };
    
    // methods
    void Cleanup();
    
    /**
     Called by a PLT_StateVariable to keep track of what events need to be 
     sent by the PLT_ServiceEventTask task.
     @param var PLT_StateVariable pointer
     */
    NPT_Result AddChanged(PLT_StateVariable* var);
    
    /**
     Certain UPnP services combine state variable changes into one single
     state variable called "LastChange". This function updates the LastChange
     state variable by looking through the list passed for state variables that
     are not individually evented.
     */
    NPT_Result UpdateLastChange(NPT_List<PLT_StateVariable*>& vars);
    
    /**
     Send state variable change events to all subscribers.
     */
    NPT_Result NotifyChanged();

    // Events
    /**
     Called by PLT_DeviceHost when it receives a request for a new subscription.
     */
    NPT_Result ProcessNewSubscription(
        PLT_TaskManagerReference task_manager,
        const NPT_SocketAddress& addr, 
        const NPT_String&        callback_urls, 
        int                      timeout, 
        NPT_HttpResponse&        response);
    
    /**
     Called by PLT_DeviceHost when it receives a request renewing an existing
     subscription.
     */
    NPT_Result ProcessRenewSubscription(
        const NPT_SocketAddress& addr, 
        const NPT_String&        sid, 
        int                      timeout,
        NPT_HttpResponse&        response);
    
    /**
     Called by PLT_DeviceHost when it receives a request to cancel an existing
     subscription.
     */
    NPT_Result ProcessCancelSubscription(
        const NPT_SocketAddress& addr, 
        const NPT_String&        sid, 
        NPT_HttpResponse&        response);


protected:
    // friends that need to call private functions
    friend class PLT_StateVariable; // AddChanged
    friend class PLT_DeviceHost;    // ProcessXXSubscription
    
    //members
    PLT_DeviceData*                         m_Device;
    NPT_String                              m_ServiceType;
    NPT_String                              m_ServiceID;
	NPT_String                              m_ServiceName;
    NPT_String                              m_SCPDURL;
    NPT_String                              m_ControlURL;
    NPT_String                              m_EventSubURL;
    PLT_ServiceEventTask*                   m_EventTask;
    NPT_Array<PLT_ActionDesc*>              m_ActionDescs;
    NPT_List<PLT_StateVariable*>            m_StateVars;
    NPT_Mutex                               m_Lock;
    NPT_List<PLT_StateVariable*>            m_StateVarsChanged;
    NPT_List<PLT_StateVariable*>            m_StateVarsToPublish;
    NPT_List<PLT_EventSubscriberReference>  m_Subscribers;
    bool                                    m_EventingPaused;
    NPT_String                              m_LastChangeNamespace;
};

/*----------------------------------------------------------------------
|    PLT_ServiceSCPDURLFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceSCPDURLFinder class returns an instance of a PLT_Service given a 
 service SCPD url.
 */
class PLT_ServiceSCPDURLFinder
{
public:
    // methods
    PLT_ServiceSCPDURLFinder(const char* url) : m_URL(url) {}
    virtual ~PLT_ServiceSCPDURLFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_URL;
};

/*----------------------------------------------------------------------
|    PLT_ServiceControlURLFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceControlURLFinder class returns an instance of a PLT_Service 
 given a service control url.
 */
class PLT_ServiceControlURLFinder
{
public:
    // methods
    PLT_ServiceControlURLFinder(const char* url) : m_URL(url) {}
    virtual ~PLT_ServiceControlURLFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_URL;
};

/*----------------------------------------------------------------------
|    PLT_ServiceEventSubURLFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceEventSubURLFinder class returns an instance of a PLT_Service 
 given a service event subscription url.
 */
class PLT_ServiceEventSubURLFinder
{
public:
    // methods
    PLT_ServiceEventSubURLFinder(const char* url) : m_URL(url) {}
    virtual ~PLT_ServiceEventSubURLFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_URL;
};

/*----------------------------------------------------------------------
|    PLT_ServiceIDFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceIDFinder class returns an instance of a PLT_Service given a 
 service id.
 */
class PLT_ServiceIDFinder
{
public:
    // methods
    PLT_ServiceIDFinder(const char* id) : m_Id(id) {}
    virtual ~PLT_ServiceIDFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_Id;
};

/*----------------------------------------------------------------------
|    PLT_ServiceTypeFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceTypeFinder class returns an instance of a PLT_Service given a 
 service type.
 */
class PLT_ServiceTypeFinder
{
public:
    // methods
    PLT_ServiceTypeFinder(const char* type) : m_Type(type) {}
    virtual ~PLT_ServiceTypeFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_Type;
};

/*----------------------------------------------------------------------
|    PLT_ServiceNameFinder
+---------------------------------------------------------------------*/
/** 
 The PLT_ServiceNameFinder class returns an instance of a PLT_Service given a 
 service name.
 */
class PLT_ServiceNameFinder
{
public:
    // methods
    PLT_ServiceNameFinder(const char* name) : m_Name(name) {}
    virtual ~PLT_ServiceNameFinder() {}
    bool operator()(PLT_Service* const & service) const;

private:
    // members
    NPT_String m_Name;
};

/*----------------------------------------------------------------------
|    PLT_LastChangeXMLIterator
+---------------------------------------------------------------------*/
/**
 The PLT_LastChangeXMLIterator class is used to serialize the LastChange variable
 changes into xml given a list of state variables.
 */
class PLT_LastChangeXMLIterator
{
public:
    // methods
    PLT_LastChangeXMLIterator(NPT_XmlElementNode* node) : m_Node(node) {}
    virtual ~PLT_LastChangeXMLIterator() {}

    NPT_Result operator()(PLT_StateVariable* const & var) const;

private:
    NPT_XmlElementNode* m_Node;
};

#endif /* _PLT_SERVICE_H_ */