1 /*****************************************************************
3 | Platinum - UPnP Engine
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
7 | http://www.plutinosoft.com
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.
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 | licensing@plutinosoft.com
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
33 ****************************************************************/
35 /*----------------------------------------------------------------------
37 +---------------------------------------------------------------------*/
39 #include "PltVersion.h"
41 #include "PltDeviceHost.h"
42 #include "PltCtrlPoint.h"
45 NPT_SET_LOCAL_LOGGER("platinum.core.upnp")
47 /*----------------------------------------------------------------------
48 | PLT_UPnP_CtrlPointStartIterator class
49 +---------------------------------------------------------------------*/
50 class PLT_UPnP_CtrlPointStartIterator
53 PLT_UPnP_CtrlPointStartIterator(PLT_SsdpListenTask
* listen_task
) :
54 m_ListenTask(listen_task
) {}
55 virtual ~PLT_UPnP_CtrlPointStartIterator() {}
57 NPT_Result
operator()(PLT_CtrlPointReference
& ctrl_point
) const {
58 NPT_CHECK_SEVERE(ctrl_point
->Start(m_ListenTask
));
63 PLT_SsdpListenTask
* m_ListenTask
;
66 /*----------------------------------------------------------------------
67 | PLT_UPnP_CtrlPointStopIterator class
68 +---------------------------------------------------------------------*/
69 class PLT_UPnP_CtrlPointStopIterator
72 PLT_UPnP_CtrlPointStopIterator(PLT_SsdpListenTask
* listen_task
) :
73 m_ListenTask(listen_task
) {}
74 virtual ~PLT_UPnP_CtrlPointStopIterator() {}
76 NPT_Result
operator()(PLT_CtrlPointReference
& ctrl_point
) const {
77 return ctrl_point
->Stop(m_ListenTask
);
82 PLT_SsdpListenTask
* m_ListenTask
;
85 /*----------------------------------------------------------------------
86 | PLT_UPnP_DeviceStartIterator class
87 +---------------------------------------------------------------------*/
88 class PLT_UPnP_DeviceStartIterator
91 PLT_UPnP_DeviceStartIterator(PLT_SsdpListenTask
* listen_task
) :
92 m_ListenTask(listen_task
) {}
93 virtual ~PLT_UPnP_DeviceStartIterator() {}
95 NPT_Result
operator()(PLT_DeviceHostReference
& device_host
) const {
97 // We should always increment the boot id on restart
98 // so it is used in place of boot id during initial announcement
99 device_host
->SetBootId(device_host
->GenerateNextBootId());
100 device_host
->SetNextBootId(0);
102 NPT_CHECK_SEVERE(device_host
->Start(m_ListenTask
));
107 PLT_SsdpListenTask
* m_ListenTask
;
110 /*----------------------------------------------------------------------
111 | PLT_UPnP_DeviceStopIterator class
112 +---------------------------------------------------------------------*/
113 class PLT_UPnP_DeviceStopIterator
116 PLT_UPnP_DeviceStopIterator(PLT_SsdpListenTask
* listen_task
) :
117 m_ListenTask(listen_task
) {}
118 virtual ~PLT_UPnP_DeviceStopIterator() {}
120 NPT_Result
operator()(PLT_DeviceHostReference
& device_host
) const {
121 return device_host
->Stop(m_ListenTask
);
126 PLT_SsdpListenTask
* m_ListenTask
;
129 /*----------------------------------------------------------------------
131 +---------------------------------------------------------------------*/
132 PLT_UPnP::PLT_UPnP() :
135 m_SsdpListenTask(NULL
),
136 m_IgnoreLocalUUIDs(true)
140 /*----------------------------------------------------------------------
141 | PLT_UPnP::~PLT_UPnP
142 +---------------------------------------------------------------------*/
143 PLT_UPnP::~PLT_UPnP()
147 m_CtrlPoints
.Clear();
151 /*----------------------------------------------------------------------
153 +---------------------------------------------------------------------*/
157 NPT_LOG_INFO("Starting UPnP...");
159 NPT_AutoLock
lock(m_Lock
);
161 if (m_Started
) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE
);
163 NPT_List
<NPT_IpAddress
> ips
;
164 PLT_UPnPMessageHelper::GetIPAddresses(ips
);
166 /* Create multicast socket and bind on 1900. If other apps didn't
167 play nicely by setting the REUSE_ADDR flag, this could fail */
168 NPT_Reference
<NPT_UdpMulticastSocket
> socket(new NPT_UdpMulticastSocket(NPT_SOCKET_FLAG_CANCELLABLE
));
169 NPT_CHECK_SEVERE(socket
->Bind(NPT_SocketAddress(NPT_IpAddress::Any
, 1900), true));
171 /* Join multicast group for every ip we found */
172 NPT_CHECK_SEVERE(ips
.ApplyUntil(PLT_SsdpInitMulticastIterator(socket
.AsPointer()),
173 NPT_UntilResultNotEquals(NPT_SUCCESS
)));
175 /* create the ssdp listener */
176 m_SsdpListenTask
= new PLT_SsdpListenTask(socket
.AsPointer());
178 NPT_Reference
<PLT_TaskManager
> taskManager(new PLT_TaskManager());
179 NPT_CHECK_SEVERE(taskManager
->StartTask(m_SsdpListenTask
));
181 /* start devices & ctrlpoints */
182 m_CtrlPoints
.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask
));
183 m_Devices
.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask
));
185 m_TaskManager
= taskManager
;
190 /*----------------------------------------------------------------------
192 +---------------------------------------------------------------------*/
196 NPT_AutoLock
lock(m_Lock
);
198 if (!m_Started
) NPT_CHECK_WARNING(NPT_ERROR_INVALID_STATE
);
200 NPT_LOG_INFO("Stopping UPnP...");
202 // Stop ctrlpoints and devices first
203 m_CtrlPoints
.Apply(PLT_UPnP_CtrlPointStopIterator(m_SsdpListenTask
));
204 m_Devices
.Apply(PLT_UPnP_DeviceStopIterator(m_SsdpListenTask
));
206 // stop remaining tasks
207 m_TaskManager
->Abort();
208 m_SsdpListenTask
= NULL
;
209 m_TaskManager
= NULL
;
215 /*----------------------------------------------------------------------
216 | PLT_UPnP::AddDevice
217 +---------------------------------------------------------------------*/
219 PLT_UPnP::AddDevice(PLT_DeviceHostReference
& device
)
221 NPT_AutoLock
lock(m_Lock
);
223 // tell all our controllers to ignore this device
224 if (m_IgnoreLocalUUIDs
) {
225 for (NPT_List
<PLT_CtrlPointReference
>::Iterator iter
=
226 m_CtrlPoints
.GetFirstItem();
229 (*iter
)->IgnoreUUID(device
->GetUUID());
234 NPT_LOG_INFO("Starting Device...");
235 NPT_CHECK_SEVERE(device
->Start(m_SsdpListenTask
));
238 m_Devices
.Add(device
);
242 /*----------------------------------------------------------------------
243 | PLT_UPnP::RemoveDevice
244 +---------------------------------------------------------------------*/
246 PLT_UPnP::RemoveDevice(PLT_DeviceHostReference
& device
)
248 NPT_AutoLock
lock(m_Lock
);
251 device
->Stop(m_SsdpListenTask
);
254 return m_Devices
.Remove(device
);
257 /*----------------------------------------------------------------------
258 | PLT_UPnP::AddCtrlPoint
259 +---------------------------------------------------------------------*/
261 PLT_UPnP::AddCtrlPoint(PLT_CtrlPointReference
& ctrl_point
)
263 NPT_AutoLock
lock(m_Lock
);
265 // tell the control point to ignore our own running devices
266 if (m_IgnoreLocalUUIDs
) {
267 for (NPT_List
<PLT_DeviceHostReference
>::Iterator iter
=
268 m_Devices
.GetFirstItem();
271 ctrl_point
->IgnoreUUID((*iter
)->GetUUID());
276 NPT_LOG_INFO("Starting Ctrlpoint...");
277 NPT_CHECK_SEVERE(ctrl_point
->Start(m_SsdpListenTask
));
280 m_CtrlPoints
.Add(ctrl_point
);
284 /*----------------------------------------------------------------------
285 | PLT_UPnP::RemoveCtrlPoint
286 +---------------------------------------------------------------------*/
288 PLT_UPnP::RemoveCtrlPoint(PLT_CtrlPointReference
& ctrl_point
)
290 NPT_AutoLock
lock(m_Lock
);
293 ctrl_point
->Stop(m_SsdpListenTask
);
296 return m_CtrlPoints
.Remove(ctrl_point
);