MythTV
master
libs
libmythupnp
upnptasknotify.cpp
Go to the documentation of this file.
1
// Program Name: upnptasknotify.cpp
3
// Created : Oct. 24, 2005
4
//
5
// Purpose : UPnp Task to send Notification messages
6
//
7
// Copyright (c) 2005 David Blain <dblain@mythtv.org>
8
//
9
// Licensed under the GPL v2 or later, see COPYING for details
10
//
12
13
// ANSI C headers
14
#include <cstdlib>
15
16
#include <chrono>
// for milliseconds
17
#include <thread>
// for sleep_for
18
19
// Qt headers
20
#include <QStringList>
21
#include <QUuid>
22
#include <QFile>
23
24
// MythTV headers
25
#include "
mmulticastsocketdevice.h
"
26
#include "
mythlogging.h
"
27
#include "
mythversion.h
"
28
#include "
mythmiscutil.h
"
29
#include "
upnp.h
"
30
33
//
34
// UPnpNotifyTask Implementation
35
//
38
40
//
42
43
UPnpNotifyTask::UPnpNotifyTask
(
int
nServicePort ) :
44
Task
(
"UPnpNotifyTask"
)
45
{
46
m_nServicePort
= nServicePort;
47
48
m_nMaxAge
=
UPnp::GetConfiguration
()->
GetDuration
<std::chrono::seconds>(
"UPnP/SSDP/MaxAge"
, 1h );
49
}
50
52
//
54
55
void
UPnpNotifyTask::SendNotifyMsg
( MSocketDevice *pSocket,
56
const
QString& sNT,
57
const
QString& sUDN )
58
{
59
QString sUSN;
60
61
if
( sUDN.length() > 0)
62
sUSN = sUDN +
"::"
+ sNT;
63
else
64
sUSN = sNT;
65
66
QString sData = QString (
"Server: %1\r\n"
67
"NTS: %3\r\n"
68
"NT: %4\r\n"
69
"USN: %5\r\n"
70
"CACHE-CONTROL: max-age=%6\r\n"
71
"Content-Length: 0\r\n\r\n"
)
72
.arg(
HttpServer::GetServerVersion
() )
73
.arg(
GetNTSString
() )
74
.arg( sNT )
75
.arg( sUSN )
76
.arg(
m_nMaxAge
.count() );
77
78
LOG
(VB_UPNP, LOG_INFO,
79
QString(
"UPnpNotifyTask::SendNotifyMsg : %1:%2 : %3 : %4"
)
80
.
arg
(pSocket->address().toString()) .arg(pSocket->port())
81
.arg(sNT) .arg(sUSN));
82
83
QMutexLocker qml(&
m_mutex
);
// for addressList
84
85
// -------------------------------------------------------------------
86
// Refresh IP Address List in case of changes
87
// -------------------------------------------------------------------
88
89
QList<QHostAddress> addressList =
UPnp::g_IPAddrList
;
90
91
for
(
const
auto
& addr : qAsConst(addressList))
92
{
93
if
(addr.toString().isEmpty())
94
{
95
LOG
(VB_GENERAL, LOG_ERR,
96
"UPnpNotifyTask::SendNotifyMsg - NULL in address list"
);
97
continue
;
98
}
99
100
QHostAddress ip = addr;
101
// Descope the Link Local address. The scope is only valid
102
// on the server sending the announcement, not the clients
103
// that receive it
104
ip.setScopeId(QString());
105
106
QString ipaddress = ip.toString();
107
108
// If this looks like an IPv6 address, then enclose it in []'s
109
if
(ipaddress.contains(
":"
))
110
ipaddress =
"["
+ ipaddress +
"]"
;
111
112
QString sHeader = QString(
"NOTIFY * HTTP/1.1\r\n"
113
"HOST: %1:%2\r\n"
114
"LOCATION: http://%3:%4/getDeviceDesc\r\n"
)
115
.arg(pSocket->address().toString()) .arg(pSocket->port())
116
.arg(ipaddress) .arg(
m_nServicePort
);
117
118
QString sPacket = sHeader + sData;
119
QByteArray scPacket = sPacket.toUtf8();
120
121
// ---------------------------------------------------------------
122
// Send Packet to Socket (Send same packet twice)
123
// ---------------------------------------------------------------
124
125
pSocket->writeBlock( scPacket, scPacket.length(),
126
pSocket->address(), pSocket->port() );
127
std::this_thread::sleep_for(std::chrono::milliseconds(
MythRandom
() % 250));
128
pSocket->writeBlock( scPacket, scPacket.length(),
129
pSocket->address(), pSocket->port() );
130
}
131
}
132
134
//
136
137
void
UPnpNotifyTask::Execute
(
TaskQueue
*pQueue )
138
{
139
MSocketDevice *pMulticast =
new
MMulticastSocketDevice
(
140
SSDP_GROUP
,
SSDP_PORT
);
141
142
// ----------------------------------------------------------------------
143
// Must send rootdevice Notification for first device.
144
// ----------------------------------------------------------------------
145
146
UPnpDevice
&device =
UPnp::g_UPnpDeviceDesc
.
m_rootDevice
;
147
148
SendNotifyMsg
( pMulticast,
"upnp:rootdevice"
, device.
GetUDN
() );
149
150
// ----------------------------------------------------------------------
151
// Process rest of notifications
152
// ----------------------------------------------------------------------
153
154
ProcessDevice
( pMulticast, &device );
155
156
// ----------------------------------------------------------------------
157
// Clean up and reshedule task if needed (timeout = m_nMaxAge / 2).
158
// ----------------------------------------------------------------------
159
160
delete
pMulticast;
161
162
pMulticast =
nullptr
;
163
164
m_mutex
.lock();
165
166
if
(
m_eNTS
==
NTS_alive
)
167
pQueue->
AddTask
( (
m_nMaxAge
/ 2), (
Task
*)
this
);
168
169
m_mutex
.unlock();
170
171
}
172
174
//
176
177
void
UPnpNotifyTask::ProcessDevice
(
178
MSocketDevice *pSocket,
UPnpDevice
*pDevice)
179
{
180
// ----------------------------------------------------------------------
181
// Loop for each device and send the 2 required messages
182
//
183
// -=>TODO: Need to add support to only notify
184
// Version 1 of a service.
185
// ----------------------------------------------------------------------
186
187
SendNotifyMsg
( pSocket, pDevice->
GetUDN
(),
""
);
188
SendNotifyMsg
( pSocket, pDevice->
m_sDeviceType
, pDevice->
GetUDN
() );
189
190
// ------------------------------------------------------------------
191
// Loop for each service in this device and send the 1 required message
192
// ------------------------------------------------------------------
193
194
for
(
auto
sit = pDevice->
m_listServices
.cbegin(); sit != pDevice->
m_listServices
.cend(); ++sit)
195
SendNotifyMsg
( pSocket, (*sit)->m_sServiceType, pDevice->
GetUDN
() );
196
197
// ----------------------------------------------------------------------
198
// Process any Embedded Devices
199
// ----------------------------------------------------------------------
200
201
for
(
const
auto
& dev : qAsConst(pDevice->
m_listDevices
))
202
ProcessDevice
( pSocket, dev);
203
}
Configuration::GetDuration
std::enable_if< std::chrono::__is_duration< T >::value, T >::type GetDuration(const QString &sSetting, T defaultval=T::zero())
Definition:
configuration.h:41
HttpServer::GetServerVersion
static QString GetServerVersion(void)
Definition:
httpserver.cpp:285
UPnpDevice::m_listServices
UPnpServiceList m_listServices
Definition:
upnpdevice.h:123
SSDP_PORT
#define SSDP_PORT
Definition:
ssdp.h:27
MMulticastSocketDevice
Definition:
mmulticastsocketdevice.h:47
arg
arg(title).arg(filename).arg(doDelete))
UPnpNotifyTask::m_mutex
QMutex m_mutex
Definition:
upnptasknotify.h:56
UPnpDevice::m_sDeviceType
QString m_sDeviceType
Definition:
upnpdevice.h:103
NTS_alive
@ NTS_alive
Definition:
upnptasknotify.h:40
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition:
mythlogging.h:23
TaskQueue
Definition:
taskqueue.h:81
UPnpNotifyTask::m_eNTS
UPnpNotifyNTS m_eNTS
Definition:
upnptasknotify.h:62
mythversion.h
UPnpDeviceDesc::m_rootDevice
UPnpDevice m_rootDevice
Definition:
upnpdevice.h:152
upnp.h
mythlogging.h
Task
Definition:
taskqueue.h:53
UPnpDevice::m_listDevices
UPnpDeviceList m_listDevices
Definition:
upnpdevice.h:124
UPnpDevice
Definition:
upnpdevice.h:99
UPnpNotifyTask::m_nMaxAge
std::chrono::seconds m_nMaxAge
Definition:
upnptasknotify.h:60
UPnpNotifyTask::SendNotifyMsg
void SendNotifyMsg(MSocketDevice *pSocket, const QString &sNT, const QString &sUDN)
Definition:
upnptasknotify.cpp:55
UPnpNotifyTask::UPnpNotifyTask
UPnpNotifyTask(int nServicePort)
Definition:
upnptasknotify.cpp:43
MythRandom
MBASE_PUBLIC uint32_t MythRandom()
Definition:
mythmiscutil.h:24
UPnpNotifyTask::ProcessDevice
void ProcessDevice(MSocketDevice *pSocket, UPnpDevice *pDevice)
Definition:
upnptasknotify.cpp:177
mythmiscutil.h
TaskQueue::AddTask
void AddTask(std::chrono::milliseconds msec, Task *pTask)
Add a task to run in the future.
Definition:
taskqueue.cpp:171
UPnpNotifyTask::m_nServicePort
int m_nServicePort
Definition:
upnptasknotify.h:59
mmulticastsocketdevice.h
UPnp::GetConfiguration
static Configuration * GetConfiguration()
Definition:
upnp.cpp:84
SSDP_GROUP
#define SSDP_GROUP
Definition:
ssdp.h:26
UPnpDevice::GetUDN
QString GetUDN(void) const
Definition:
upnpdevice.cpp:766
UPnpNotifyTask::Execute
void Execute(TaskQueue *pQueue) override
Definition:
upnptasknotify.cpp:137
UPnp::g_UPnpDeviceDesc
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition:
upnp.h:112
UPnp::g_IPAddrList
static QList< QHostAddress > g_IPAddrList
Definition:
upnp.h:113
UPnpNotifyTask::GetNTSString
QString GetNTSString()
Definition:
upnptasknotify.h:82
Generated on Wed Jan 27 2021 03:17:02 for MythTV by
1.8.17