summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp')
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp b/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp
new file mode 100644
index 0000000..e0b1e8b
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltUPnP.cpp
@@ -0,0 +1,298 @@
+/*****************************************************************
+|
+| Platinum - UPnP Engine
+|
+| 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
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include "PltVersion.h"
+#include "PltUPnP.h"
+#include "PltDeviceHost.h"
+#include "PltCtrlPoint.h"
+#include "PltSsdp.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.core.upnp")
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_CtrlPointStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStartIterator
+{
+public:
+ PLT_UPnP_CtrlPointStartIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_CtrlPointStartIterator() {}
+
+ NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+ NPT_CHECK_SEVERE(ctrl_point->Start(m_ListenTask));
+ return NPT_SUCCESS;
+ }
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_CtrlPointStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_CtrlPointStopIterator
+{
+public:
+ PLT_UPnP_CtrlPointStopIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_CtrlPointStopIterator() {}
+
+ NPT_Result operator()(PLT_CtrlPointReference& ctrl_point) const {
+ return ctrl_point->Stop(m_ListenTask);
+ }
+
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_DeviceStartIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStartIterator
+{
+public:
+ PLT_UPnP_DeviceStartIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_DeviceStartIterator() {}
+
+ NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+
+ // We should always increment the boot id on restart
+ // so it is used in place of boot id during initial announcement
+ device_host->SetBootId(device_host->GenerateNextBootId());
+ device_host->SetNextBootId(0);
+
+ NPT_CHECK_SEVERE(device_host->Start(m_ListenTask));
+ return NPT_SUCCESS;
+ }
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP_DeviceStopIterator class
++---------------------------------------------------------------------*/
+class PLT_UPnP_DeviceStopIterator
+{
+public:
+ PLT_UPnP_DeviceStopIterator(PLT_SsdpListenTask* listen_task) :
+ m_ListenTask(listen_task) {}
+ virtual ~PLT_UPnP_DeviceStopIterator() {}
+
+ NPT_Result operator()(PLT_DeviceHostReference& device_host) const {
+ return device_host->Stop(m_ListenTask);
+ }
+
+
+private:
+ PLT_SsdpListenTask* m_ListenTask;
+};
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::PLT_UPnP() :
+ m_TaskManager(NULL),
+ m_Started(false),
+ m_SsdpListenTask(NULL),
+ m_IgnoreLocalUUIDs(true)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::~PLT_UPnP
++---------------------------------------------------------------------*/
+PLT_UPnP::~PLT_UPnP()
+{
+ Stop();
+
+ m_CtrlPoints.Clear();
+ m_Devices.Clear();
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::Start()
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Start()
+{
+ NPT_LOG_INFO("Starting UPnP...");
+
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_List<NPT_IpAddress> ips;
+ PLT_UPnPMessageHelper::GetIPAddresses(ips);
+
+ /* Create multicast socket and bind on 1900. If other apps didn't
+ play nicely by setting the REUSE_ADDR flag, this could fail */
+ NPT_Reference<NPT_UdpMulticastSocket> socket(new NPT_UdpMulticastSocket(NPT_SOCKET_FLAG_CANCELLABLE));
+ NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true));
+
+ /* Join multicast group for every ip we found */
+ NPT_CHECK_SEVERE(ips.ApplyUntil(PLT_SsdpInitMulticastIterator(socket.AsPointer()),
+ NPT_UntilResultNotEquals(NPT_SUCCESS)));
+
+ /* create the ssdp listener */
+ m_SsdpListenTask = new PLT_SsdpListenTask(socket.AsPointer());
+ socket.Detach();
+ NPT_Reference<PLT_TaskManager> taskManager(new PLT_TaskManager());
+ NPT_CHECK_SEVERE(taskManager->StartTask(m_SsdpListenTask));
+
+ /* start devices & ctrlpoints */
+ m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask));
+ m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask));
+
+ m_TaskManager = taskManager;
+ m_Started = true;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::Stop
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::Stop()
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (!m_Started) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE);
+
+ NPT_LOG_INFO("Stopping UPnP...");
+
+ // Stop ctrlpoints and devices first
+ m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStopIterator(m_SsdpListenTask));
+ m_Devices.Apply(PLT_UPnP_DeviceStopIterator(m_SsdpListenTask));
+
+ // stop remaining tasks
+ m_TaskManager->Abort();
+ m_SsdpListenTask = NULL;
+ m_TaskManager = NULL;
+
+ m_Started = false;
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::AddDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddDevice(PLT_DeviceHostReference& device)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // tell all our controllers to ignore this device
+ if (m_IgnoreLocalUUIDs) {
+ for (NPT_List<PLT_CtrlPointReference>::Iterator iter =
+ m_CtrlPoints.GetFirstItem();
+ iter;
+ iter++) {
+ (*iter)->IgnoreUUID(device->GetUUID());
+ }
+ }
+
+ if (m_Started) {
+ NPT_LOG_INFO("Starting Device...");
+ NPT_CHECK_SEVERE(device->Start(m_SsdpListenTask));
+ }
+
+ m_Devices.Add(device);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::RemoveDevice
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveDevice(PLT_DeviceHostReference& device)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) {
+ device->Stop(m_SsdpListenTask);
+ }
+
+ return m_Devices.Remove(device);
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::AddCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::AddCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ // tell the control point to ignore our own running devices
+ if (m_IgnoreLocalUUIDs) {
+ for (NPT_List<PLT_DeviceHostReference>::Iterator iter =
+ m_Devices.GetFirstItem();
+ iter;
+ iter++) {
+ ctrl_point->IgnoreUUID((*iter)->GetUUID());
+ }
+ }
+
+ if (m_Started) {
+ NPT_LOG_INFO("Starting Ctrlpoint...");
+ NPT_CHECK_SEVERE(ctrl_point->Start(m_SsdpListenTask));
+ }
+
+ m_CtrlPoints.Add(ctrl_point);
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_UPnP::RemoveCtrlPoint
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_UPnP::RemoveCtrlPoint(PLT_CtrlPointReference& ctrl_point)
+{
+ NPT_AutoLock lock(m_Lock);
+
+ if (m_Started) {
+ ctrl_point->Stop(m_SsdpListenTask);
+ }
+
+ return m_CtrlPoints.Remove(ctrl_point);
+}
+