diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltEvent.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,261 @@
+/*****************************************************************
+|
+|   Platinum - Control/Event
+|
+| Copyright (c) 2004-2008, 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.
+| 
+| 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
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltTaskManager.h"
+#include "PltEvent.h"
+#include "PltService.h"
+#include "PltUPnP.h"
+#include "PltDeviceData.h"
+#include "PltXmlHelper.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.event")
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::PLT_EventSubscriber
++---------------------------------------------------------------------*/
+PLT_EventSubscriber::PLT_EventSubscriber(PLT_TaskManager* task_manager, 
+                                         PLT_Service*     service,
+                                         const char*      sid,
+                                         int              timeout /* = -1 */) : 
+    m_TaskManager(task_manager), 
+    m_Service(service), 
+    m_EventKey(0),
+    m_SubscriberTask(NULL),
+    m_SID(sid)
+{
+    NPT_LOG_FINE_1("Creating new subscriber (%s)", m_SID.GetChars());
+    SetTimeout(timeout);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::~PLT_EventSubscriber
++---------------------------------------------------------------------*/
+PLT_EventSubscriber::~PLT_EventSubscriber() 
+{
+    NPT_LOG_FINE_1("Deleting subscriber (%s)", m_SID.GetChars());
+    if (m_SubscriberTask) {
+        m_SubscriberTask->Kill();
+        m_SubscriberTask = NULL;
+    }
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetService
++---------------------------------------------------------------------*/
+PLT_Service*
+PLT_EventSubscriber::GetService() 
+{
+    return m_Service;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetEventKey
++---------------------------------------------------------------------*/
+NPT_Ordinal
+PLT_EventSubscriber::GetEventKey() 
+{
+    return m_EventKey;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetEventKey
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetEventKey(NPT_Ordinal value) 
+{
+    m_EventKey = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetLocalIf
++---------------------------------------------------------------------*/
+NPT_SocketAddress
+PLT_EventSubscriber::GetLocalIf() 
+{
+    return m_LocalIf;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetLocalIf
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetLocalIf(NPT_SocketAddress value) 
+{
+    m_LocalIf = value;
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::GetExpirationTime
++---------------------------------------------------------------------*/
+// a TimeStamp of 0 means no expiration
+NPT_TimeStamp
+PLT_EventSubscriber::GetExpirationTime()
+{
+    return m_ExpirationTime;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::SetExpirationTime
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::SetTimeout(int timeout /* = -1 */) 
+{
+    NPT_LOG_FINE_2("subscriber (%s) expiring in %d seconds",
+        m_SID.GetChars(),
+        timeout);
+
+    // -1 means infinite so we set an expiration time of 0
+    if (timeout == -1) {
+        m_ExpirationTime = NPT_TimeStamp(0, 0);
+    } else {
+        NPT_System::GetCurrentTimeStamp(m_ExpirationTime);
+        m_ExpirationTime += NPT_TimeInterval(timeout, 0);
+    }
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::FindCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::FindCallbackURL(const char* callback_url) 
+{
+    NPT_String res;
+    return NPT_ContainerFind(m_CallbackURLs, 
+                             NPT_StringFinder(callback_url), 
+                             res);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::AddCallbackURL
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::AddCallbackURL(const char* callback_url) 
+{
+    NPT_CHECK_POINTER_FATAL(callback_url);
+
+    NPT_LOG_FINE_2("Adding callback \"%s\" to subscriber %s", 
+        callback_url, 
+        m_SID.GetChars());
+    return m_CallbackURLs.Add(callback_url);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriber::Notify
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_EventSubscriber::Notify(NPT_List<PLT_StateVariable*>& vars)
+{
+    // verify we have eventable variables
+    bool foundVars = false;
+    NPT_XmlElementNode* propertyset = new NPT_XmlElementNode("e", "propertyset");
+    NPT_CHECK_SEVERE(propertyset->SetNamespaceUri("e", "urn:schemas-upnp-org:event-1-0"));
+
+    NPT_List<PLT_StateVariable*>::Iterator var = vars.GetFirstItem();
+    while (var) {
+        if ((*var)->IsSendingEvents()) {
+            NPT_XmlElementNode* property = new NPT_XmlElementNode("e", "property");
+            propertyset->AddChild(property);
+            PLT_XmlHelper::AddChildText(property, (*var)->GetName(), (*var)->GetValue());
+            foundVars = true;
+        }
+        ++var;
+    }
+
+    // no eventable state variables found!
+    if (foundVars == false) {
+        delete propertyset;
+        return NPT_FAILURE;
+    }
+
+    // format the body with the xml
+    NPT_String xml;
+    if (NPT_FAILED(PLT_XmlHelper::Serialize(*propertyset, xml))) {
+        delete propertyset;
+        NPT_CHECK_FATAL(NPT_FAILURE);
+    }
+    delete propertyset;
+
+
+    // parse the callback url
+    NPT_HttpUrl url(m_CallbackURLs[0]);
+    if (!url.IsValid()) {
+        NPT_CHECK_FATAL(NPT_FAILURE);
+    }
+    // format request
+    NPT_HttpRequest* request = new NPT_HttpRequest(url,
+                                                   "NOTIFY",
+                                                   NPT_HTTP_PROTOCOL_1_0);
+    request->GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "keep-alive");
+
+    // add the extra headers
+    PLT_HttpHelper::SetContentType(*request, "text/xml");
+    PLT_UPnPMessageHelper::SetNT(*request, "upnp:event");
+    PLT_UPnPMessageHelper::SetNTS(*request, "upnp:propchange");
+    PLT_UPnPMessageHelper::SetSID(*request, m_SID);
+    PLT_UPnPMessageHelper::SetSeq(*request, m_EventKey);
+
+    // wrap around sequence to 1
+    if (++m_EventKey == 0) m_EventKey = 1;
+
+    PLT_HttpHelper::SetBody(*request, xml);
+
+    // start the task now if not started already
+    if (!m_SubscriberTask) {
+        m_SubscriberTask = new PLT_HttpClientSocketTask(request, true);
+        NPT_TimeInterval delay(0.5f);
+        // delay start to make sure ctrlpoint receives response to subscription
+        // before our first NOTIFY. Also make sure task is not auto-destroy
+        // since we want to destroy it ourselves when the subscriber goes away.
+        NPT_CHECK_FATAL(m_TaskManager->StartTask(m_SubscriberTask, &delay, false));
+    } else {
+        m_SubscriberTask->AddRequest(request);
+    }
+     
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_EventSubscriberFinderByService::operator()
++---------------------------------------------------------------------*/
+bool 
+PLT_EventSubscriberFinderByService::operator()(PLT_EventSubscriber* const & eventSub) const 
+{
+    return m_Service->GetDevice()->GetUUID().Compare(
+        eventSub->GetService()->GetDevice()->GetUUID(), true) ? false : true;
+}