comparison deps/Platinum/Source/Core/PltEvent.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*****************************************************************
2 |
3 | Platinum - Control/Event
4 |
5 | Copyright (c) 2004-2008, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
8 |
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
13 |
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 |
21 | This program is distributed in the hope that it will be useful,
22 | but WITHOUT ANY WARRANTY; without even the implied warranty of
23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 | GNU General Public License for more details.
25 |
26 | You should have received a copy of the GNU General Public License
27 | along with this program; see the file LICENSE.txt. If not, write to
28 | the Free Software Foundation, Inc.,
29 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 | http://www.gnu.org/licenses/gpl-2.0.html
31 |
32 ****************************************************************/
33
34 /*----------------------------------------------------------------------
35 | includes
36 +---------------------------------------------------------------------*/
37 #include "PltTaskManager.h"
38 #include "PltEvent.h"
39 #include "PltService.h"
40 #include "PltUPnP.h"
41 #include "PltDeviceData.h"
42 #include "PltXmlHelper.h"
43
44 NPT_SET_LOCAL_LOGGER("platinum.core.event")
45
46 /*----------------------------------------------------------------------
47 | PLT_EventSubscriber::PLT_EventSubscriber
48 +---------------------------------------------------------------------*/
49 PLT_EventSubscriber::PLT_EventSubscriber(PLT_TaskManager* task_manager,
50 PLT_Service* service,
51 const char* sid,
52 int timeout /* = -1 */) :
53 m_TaskManager(task_manager),
54 m_Service(service),
55 m_EventKey(0),
56 m_SubscriberTask(NULL),
57 m_SID(sid)
58 {
59 NPT_LOG_FINE_1("Creating new subscriber (%s)", m_SID.GetChars());
60 SetTimeout(timeout);
61 }
62
63 /*----------------------------------------------------------------------
64 | PLT_EventSubscriber::~PLT_EventSubscriber
65 +---------------------------------------------------------------------*/
66 PLT_EventSubscriber::~PLT_EventSubscriber()
67 {
68 NPT_LOG_FINE_1("Deleting subscriber (%s)", m_SID.GetChars());
69 if (m_SubscriberTask) {
70 m_SubscriberTask->Kill();
71 m_SubscriberTask = NULL;
72 }
73 }
74
75 /*----------------------------------------------------------------------
76 | PLT_EventSubscriber::GetService
77 +---------------------------------------------------------------------*/
78 PLT_Service*
79 PLT_EventSubscriber::GetService()
80 {
81 return m_Service;
82 }
83
84 /*----------------------------------------------------------------------
85 | PLT_EventSubscriber::GetEventKey
86 +---------------------------------------------------------------------*/
87 NPT_Ordinal
88 PLT_EventSubscriber::GetEventKey()
89 {
90 return m_EventKey;
91 }
92
93 /*----------------------------------------------------------------------
94 | PLT_EventSubscriber::SetEventKey
95 +---------------------------------------------------------------------*/
96 NPT_Result
97 PLT_EventSubscriber::SetEventKey(NPT_Ordinal value)
98 {
99 m_EventKey = value;
100 return NPT_SUCCESS;
101 }
102
103 /*----------------------------------------------------------------------
104 | PLT_EventSubscriber::GetLocalIf
105 +---------------------------------------------------------------------*/
106 NPT_SocketAddress
107 PLT_EventSubscriber::GetLocalIf()
108 {
109 return m_LocalIf;
110 }
111
112 /*----------------------------------------------------------------------
113 | PLT_EventSubscriber::SetLocalIf
114 +---------------------------------------------------------------------*/
115 NPT_Result
116 PLT_EventSubscriber::SetLocalIf(NPT_SocketAddress value)
117 {
118 m_LocalIf = value;
119 return NPT_SUCCESS;
120 }
121
122 /*----------------------------------------------------------------------
123 | PLT_EventSubscriber::GetExpirationTime
124 +---------------------------------------------------------------------*/
125 // a TimeStamp of 0 means no expiration
126 NPT_TimeStamp
127 PLT_EventSubscriber::GetExpirationTime()
128 {
129 return m_ExpirationTime;
130 }
131
132 /*----------------------------------------------------------------------
133 | PLT_EventSubscriber::SetExpirationTime
134 +---------------------------------------------------------------------*/
135 NPT_Result
136 PLT_EventSubscriber::SetTimeout(int timeout /* = -1 */)
137 {
138 NPT_LOG_FINE_2("subscriber (%s) expiring in %d seconds",
139 m_SID.GetChars(),
140 timeout);
141
142 // -1 means infinite so we set an expiration time of 0
143 if (timeout == -1) {
144 m_ExpirationTime = NPT_TimeStamp(0, 0);
145 } else {
146 NPT_System::GetCurrentTimeStamp(m_ExpirationTime);
147 m_ExpirationTime += NPT_TimeInterval(timeout, 0);
148 }
149 return NPT_SUCCESS;
150 }
151
152 /*----------------------------------------------------------------------
153 | PLT_EventSubscriber::FindCallbackURL
154 +---------------------------------------------------------------------*/
155 NPT_Result
156 PLT_EventSubscriber::FindCallbackURL(const char* callback_url)
157 {
158 NPT_String res;
159 return NPT_ContainerFind(m_CallbackURLs,
160 NPT_StringFinder(callback_url),
161 res);
162 }
163
164 /*----------------------------------------------------------------------
165 | PLT_EventSubscriber::AddCallbackURL
166 +---------------------------------------------------------------------*/
167 NPT_Result
168 PLT_EventSubscriber::AddCallbackURL(const char* callback_url)
169 {
170 NPT_CHECK_POINTER_FATAL(callback_url);
171
172 NPT_LOG_FINE_2("Adding callback \"%s\" to subscriber %s",
173 callback_url,
174 m_SID.GetChars());
175 return m_CallbackURLs.Add(callback_url);
176 }
177
178 /*----------------------------------------------------------------------
179 | PLT_EventSubscriber::Notify
180 +---------------------------------------------------------------------*/
181 NPT_Result
182 PLT_EventSubscriber::Notify(NPT_List<PLT_StateVariable*>& vars)
183 {
184 // verify we have eventable variables
185 bool foundVars = false;
186 NPT_XmlElementNode* propertyset = new NPT_XmlElementNode("e", "propertyset");
187 NPT_CHECK_SEVERE(propertyset->SetNamespaceUri("e", "urn:schemas-upnp-org:event-1-0"));
188
189 NPT_List<PLT_StateVariable*>::Iterator var = vars.GetFirstItem();
190 while (var) {
191 if ((*var)->IsSendingEvents()) {
192 NPT_XmlElementNode* property = new NPT_XmlElementNode("e", "property");
193 propertyset->AddChild(property);
194 PLT_XmlHelper::AddChildText(property, (*var)->GetName(), (*var)->GetValue());
195 foundVars = true;
196 }
197 ++var;
198 }
199
200 // no eventable state variables found!
201 if (foundVars == false) {
202 delete propertyset;
203 return NPT_FAILURE;
204 }
205
206 // format the body with the xml
207 NPT_String xml;
208 if (NPT_FAILED(PLT_XmlHelper::Serialize(*propertyset, xml))) {
209 delete propertyset;
210 NPT_CHECK_FATAL(NPT_FAILURE);
211 }
212 delete propertyset;
213
214
215 // parse the callback url
216 NPT_HttpUrl url(m_CallbackURLs[0]);
217 if (!url.IsValid()) {
218 NPT_CHECK_FATAL(NPT_FAILURE);
219 }
220 // format request
221 NPT_HttpRequest* request = new NPT_HttpRequest(url,
222 "NOTIFY",
223 NPT_HTTP_PROTOCOL_1_0);
224 request->GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "keep-alive");
225
226 // add the extra headers
227 PLT_HttpHelper::SetContentType(*request, "text/xml");
228 PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
229 PLT_UPnPMessageHelper::SetNTS(*request, "upnp:propchange");
230 PLT_UPnPMessageHelper::SetSID(*request, m_SID);
231 PLT_UPnPMessageHelper::SetSeq(*request, m_EventKey);
232
233 // wrap around sequence to 1
234 if (++m_EventKey == 0) m_EventKey = 1;
235
236 PLT_HttpHelper::SetBody(*request, xml);
237
238 // start the task now if not started already
239 if (!m_SubscriberTask) {
240 m_SubscriberTask = new PLT_HttpClientSocketTask(request, true);
241 NPT_TimeInterval delay(0.5f);
242 // delay start to make sure ctrlpoint receives response to subscription
243 // before our first NOTIFY. Also make sure task is not auto-destroy
244 // since we want to destroy it ourselves when the subscriber goes away.
245 NPT_CHECK_FATAL(m_TaskManager->StartTask(m_SubscriberTask, &delay, false));
246 } else {
247 m_SubscriberTask->AddRequest(request);
248 }
249
250 return NPT_SUCCESS;
251 }
252
253 /*----------------------------------------------------------------------
254 | PLT_EventSubscriberFinderByService::operator()
255 +---------------------------------------------------------------------*/
256 bool
257 PLT_EventSubscriberFinderByService::operator()(PLT_EventSubscriber* const & eventSub) const
258 {
259 return m_Service->GetDevice()->GetUUID().Compare(
260 eventSub->GetService()->GetDevice()->GetUUID(), true) ? false : true;
261 }