MythTV  master
upnp.cpp
Go to the documentation of this file.
1 // Program Name: upnp.cpp
3 // Created : Oct. 24, 2005
4 //
5 // Purpose : UPnp Main Class
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 #include <QNetworkInterface>
14 
15 #include "mythcorecontext.h"
16 #include "upnptaskcache.h"
17 #include "mythlogging.h"
18 #include "serverpool.h"
19 #include "upnp.h"
20 
22 // Global/Class Static variables
24 
26 QList<QHostAddress> UPnp::g_IPAddrList;
27 
29 
32 //
33 // UPnp Class implementaion
34 //
37 
39 //
41 
43 {
44  LOG(VB_UPNP, LOG_DEBUG, "UPnp - Constructor");
45  // N.B. Ask for 5 second delay to send Bye Bye twice
46  // TODO Check whether we actually send Bye Bye twice:)
47  m_power = MythPower::AcquireRelease(this, true, 5);
48  if (m_power)
49  {
50  // NB We only listen for WillXXX signals which should give us time to send notifications
55  }
56 }
57 
59 //
61 
63 {
64  LOG(VB_UPNP, LOG_DEBUG, "UPnp - Destructor");
65  CleanUp();
66  if (m_power)
67  MythPower::AcquireRelease(this, false);
68 }
69 
71 //
73 
75 {
76  delete g_pConfig;
77  g_pConfig = pConfig;
78 }
79 
81 //
83 
85 {
86  // If someone is asking for a config and it's nullptr, create a
87  // new XmlConfiguration since we don't have database info yet.
88 
89  if (g_pConfig == nullptr)
90  g_pConfig = new XmlConfiguration( "config.xml" );
91 
92  return g_pConfig;
93 }
94 
96 //
98 
99 bool UPnp::Initialize( int nServicePort, HttpServer *pHttpServer )
100 {
101  QList<QHostAddress> sList = ServerPool::DefaultListen();
102  if (sList.contains(QHostAddress(QHostAddress::AnyIPv4)))
103  {
104  sList.removeAll(QHostAddress(QHostAddress::AnyIPv4));
105  sList.removeAll(QHostAddress(QHostAddress::AnyIPv6));
106  sList.append(QNetworkInterface::allAddresses());
107  }
108  return Initialize( sList, nServicePort, pHttpServer );
109 }
110 
112 //
114 
115 bool UPnp::Initialize( QList<QHostAddress> &sIPAddrList, int nServicePort, HttpServer *pHttpServer )
116 {
117  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Initialize - Begin");
118 
119  if (m_pHttpServer)
120  {
121  LOG(VB_GENERAL, LOG_ERR,
122  "UPnp::Initialize - Already initialized, programmer error.");
123  return false;
124  }
125 
126  if (g_pConfig == nullptr)
127  {
128  LOG(VB_GENERAL, LOG_ERR,
129  "UPnp::Initialize - Must call SetConfiguration.");
130  return false;
131  }
132 
133  if ((m_pHttpServer = pHttpServer) == nullptr)
134  {
135  LOG(VB_GENERAL, LOG_ERR,
136  "UPnp::Initialize - Invalid Parameter (pHttpServer == NULL)");
137  return false;
138  }
139 
140  g_IPAddrList = sIPAddrList;
141  bool ipv4 = gCoreContext->GetBoolSetting("IPv4Support",true);
142  bool ipv6 = gCoreContext->GetBoolSetting("IPv6Support",true);
143 
144  for (int it = 0; it < g_IPAddrList.size(); ++it)
145  {
146  // If IPV4 support is disabled and this is an IPV4 address,
147  // remove this address
148  // If IPV6 support is disabled and this is an IPV6 address,
149  // remove this address
150  if ((g_IPAddrList[it].protocol() == QAbstractSocket::IPv4Protocol
151  && ! ipv4)
152  ||(g_IPAddrList[it].protocol() == QAbstractSocket::IPv6Protocol
153  && ! ipv6))
154  g_IPAddrList.removeAt(it--);
155  }
156 
157  m_nServicePort = nServicePort;
158 
159  // ----------------------------------------------------------------------
160  // Register any HttpServerExtensions
161  // ----------------------------------------------------------------------
162 
165 
166  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Initialize - End");
167 
168  return true;
169 }
170 
172 // Delay startup of Discovery Threads until all Extensions are registered.
174 
176 {
177  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Enabling SSDP Notifications");
178  // ----------------------------------------------------------------------
179  // Turn on Device Announcements
180  // (this will also create/startup SSDP if not already done)
181  // ----------------------------------------------------------------------
182 
184 
185  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Returning");
186 }
187 
189 //
191 
193 {
194  LOG(VB_UPNP, LOG_INFO, "UPnp::CleanUp() - disabling SSDP notifications");
195 
197 
198  if (g_pConfig)
199  {
200  delete g_pConfig;
201  g_pConfig = nullptr;
202  }
203 
204 }
205 
207 //
209 
211 {
212  return UPnpDeviceDesc::Retrieve( sURL );
213 }
214 
216 //
218 
220 {
221  switch( eCode )
222  {
223  case UPnPResult_Success : return "Success";
224  case UPnPResult_InvalidAction : return "Invalid Action";
225  case UPnPResult_InvalidArgs : return "Invalid Args";
226  case UPnPResult_ActionFailed : return "Action Failed";
227  case UPnPResult_ArgumentValueInvalid : return "Argument Value Invalid";
228  case UPnPResult_ArgumentValueOutOfRange : return "Argument Value Out Of Range";
229  case UPnPResult_OptionalActionNotImplemented: return "Optional Action Not Implemented";
230  case UPnPResult_OutOfMemory : return "Out Of Memory";
231  case UPnPResult_HumanInterventionRequired : return "Human Intervention Required";
232  case UPnPResult_StringArgumentTooLong : return "String Argument Too Long";
233  case UPnPResult_ActionNotAuthorized : return "Action Not Authorized";
234  case UPnPResult_SignatureFailure : return "Signature Failure";
235  case UPnPResult_SignatureMissing : return "Signature Missing";
236  case UPnPResult_NotEncrypted : return "Not Encrypted";
237  case UPnPResult_InvalidSequence : return "Invalid Sequence";
238  case UPnPResult_InvalidControlURL : return "Invalid Control URL";
239  case UPnPResult_NoSuchSession : return "No Such Session";
240  case UPnPResult_MS_AccessDenied : return "Access Denied";
241 
242  case UPnPResult_CDS_NoSuchObject : return "No Such Object";
243  case UPnPResult_CDS_InvalidCurrentTagValue : return "Invalid CurrentTagValue";
244  case UPnPResult_CDS_InvalidNewTagValue : return "Invalid NewTagValue";
245  case UPnPResult_CDS_RequiredTag : return "Required Tag";
246  case UPnPResult_CDS_ReadOnlyTag : return "Read Only Tag";
247  case UPnPResult_CDS_ParameterMismatch : return "Parameter Mismatch";
248  case UPnPResult_CDS_InvalidSearchCriteria : return "Invalid Search Criteria";
249  case UPnPResult_CDS_InvalidSortCriteria : return "Invalid Sort Criteria";
250  case UPnPResult_CDS_NoSuchContainer : return "No Such Container";
251  case UPnPResult_CDS_RestrictedObject : return "Restricted Object";
252  case UPnPResult_CDS_BadMetadata : return "Bad Metadata";
253  case UPnPResult_CDS_ResrtictedParentObject : return "Resrticted Parent Object";
254  case UPnPResult_CDS_NoSuchSourceResource : return "No Such Source Resource";
255  case UPnPResult_CDS_ResourceAccessDenied : return "Resource Access Denied";
256  case UPnPResult_CDS_TransferBusy : return "Transfer Busy";
257  case UPnPResult_CDS_NoSuchFileTransfer : return "No Such File Transfer";
258  case UPnPResult_CDS_NoSuchDestRes : return "No Such Destination Resource";
259  case UPnPResult_CDS_DestResAccessDenied : return "Destination Resource Access Denied";
260  case UPnPResult_CDS_CannotProcessRequest : return "Cannot Process The Request";
261 
262  //case UPnPResult_CMGR_IncompatibleProtocol = 701,
263  //case UPnPResult_CMGR_IncompatibleDirections = 702,
264  //case UPnPResult_CMGR_InsufficientNetResources = 703,
265  //case UPnPResult_CMGR_LocalRestrictions = 704,
266  //case UPnPResult_CMGR_AccessDenied = 705,
267  //case UPnPResult_CMGR_InvalidConnectionRef = 706,
268  case UPnPResult_CMGR_NotInNetwork : return "Not In Network";
269  case UPnPResult_MythTV_NoNamespaceGiven: return "No Namespace Given";
270  case UPnPResult_MythTV_XmlParseError : return "XML Parse Error";
271  }
272 
273  return "Unknown";
274 }
275 
277 //
279 
281  UPnPResultCode eCode,
282  const QString &msg )
283 {
284  QString sMsg( msg );
285 
286  if (pRequest != nullptr)
287  {
288  QString sDetails = "";
289 
290  if (pRequest->m_bSOAPRequest)
291  sDetails = "<UPnPResult xmlns=\"urn:schemas-upnp-org:control-1-0\">";
292 
293  if (sMsg.length() == 0)
294  sMsg = GetResultDesc( eCode );
295 
296  sDetails += QString( "<errorCode>%1</errorCode>"
297  "<errorDescription>%2</errorDescription>" )
298  .arg( eCode )
299  .arg( HTTPRequest::Encode( sMsg ) );
300 
301  if (pRequest->m_bSOAPRequest)
302  sDetails += "</UPnPResult>";
303 
304 
305  pRequest->FormatErrorResponse ( true, // -=>TODO: Should make this dynamic
306  "UPnPResult",
307  sDetails );
308  }
309  else
310  LOG(VB_GENERAL, LOG_ERR, "Response not created - pRequest == NULL" );
311 }
312 
314 //
316 
318  const QString &hostName )
319 {
321  pRequest->m_nResponseStatus = 301;
322 
323  QStringList sItems = pRequest->m_sRawRequest.split( ' ' );
324  QString sUrl = "http://" + pRequest->m_mapHeaders[ "host" ] + sItems[1];
325  QUrl url( sUrl );
326  url.setHost( hostName );
327 
328  pRequest->m_mapRespHeaders[ "Location" ] = url.toString();
329 
330  LOG(VB_UPNP, LOG_INFO, QString("Sending http redirect to: %1")
331  .arg(url.toString()));
332 
333  pRequest->SendResponse();
334 }
335 
337 {
339 }
340 
341 void UPnp::EnableNotificatins(qint64 /*unused*/) const
342 {
344 }
UPnPResult_CDS_RequiredTag
@ UPnPResult_CDS_RequiredTag
Definition: upnp.h:60
UPnPResult_MythTV_NoNamespaceGiven
@ UPnPResult_MythTV_NoNamespaceGiven
Definition: upnp.h:87
MythPower::WokeUp
void WokeUp(qint64 SecondsAsleep)
UPnPResult_InvalidArgs
@ UPnPResult_InvalidArgs
Definition: upnp.h:41
UPnPResult_CMGR_NotInNetwork
@ UPnPResult_CMGR_NotInNetwork
Definition: upnp.h:83
HTTPRequest
Definition: httprequest.h:107
UPnPResult_CDS_InvalidSearchCriteria
@ UPnPResult_CDS_InvalidSearchCriteria
Definition: upnp.h:63
UPnpDeviceDesc::Retrieve
static UPnpDeviceDesc * Retrieve(QString &sURL)
Definition: upnpdevice.cpp:615
UPnPResult_CDS_BadMetadata
@ UPnPResult_CDS_BadMetadata
Definition: upnp.h:67
UPnp::Start
virtual void Start()
Definition: upnp.cpp:175
SSDPExtension
Definition: ssdp.h:141
HttpServer::RegisterExtension
void RegisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:321
UPnPResult_ArgumentValueOutOfRange
@ UPnPResult_ArgumentValueOutOfRange
Definition: upnp.h:44
UPnpDeviceDesc
Definition: upnpdevice.h:148
arg
arg(title).arg(filename).arg(doDelete))
UPnPResult_CDS_NoSuchDestRes
@ UPnPResult_CDS_NoSuchDestRes
Definition: upnp.h:73
UPnp::CleanUp
static void CleanUp()
Definition: upnp.cpp:192
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
UPnp::m_nServicePort
int m_nServicePort
Definition: upnp.h:108
MythPower::WillSuspend
void WillSuspend(uint MilliSeconds=0)
HTTPRequest::Encode
static QString Encode(const QString &sIn)
Definition: httprequest.cpp:1789
UPnPResult_OutOfMemory
@ UPnPResult_OutOfMemory
Definition: upnp.h:46
UPnp::FormatErrorResponse
static void FormatErrorResponse(HTTPRequest *pRequest, UPnPResultCode eCode, const QString &sMsg="")
Definition: upnp.cpp:280
XmlConfiguration
Definition: configuration.h:51
UPnp::Initialize
bool Initialize(int nServicePort, HttpServer *pHttpServer)
Definition: upnp.cpp:99
UPnPResult_CDS_TransferBusy
@ UPnPResult_CDS_TransferBusy
Definition: upnp.h:71
UPnPResult_SignatureMissing
@ UPnPResult_SignatureMissing
Definition: upnp.h:51
UPnPResult_HumanInterventionRequired
@ UPnPResult_HumanInterventionRequired
Definition: upnp.h:47
UPnp::m_power
MythPower * m_power
Definition: upnp.h:151
HTTPRequest::m_mapRespHeaders
QStringMap m_mapRespHeaders
Definition: httprequest.h:151
SSDP::Instance
static SSDP * Instance()
Definition: ssdp.cpp:54
upnp.h
HTTPRequest::m_nResponseStatus
long m_nResponseStatus
Definition: httprequest.h:150
UPnp::FormatRedirectResponse
static void FormatRedirectResponse(HTTPRequest *pRequest, const QString &hostName)
Definition: upnp.cpp:317
mythlogging.h
UPnPResult_NoSuchSession
@ UPnPResult_NoSuchSession
Definition: upnp.h:55
UPnp::GetDeviceDesc
static UPnpDeviceDesc * GetDeviceDesc(QString &sURL)
Definition: upnp.cpp:210
UPnPResult_CDS_NoSuchFileTransfer
@ UPnPResult_CDS_NoSuchFileTransfer
Definition: upnp.h:72
UPnPResult_CDS_NoSuchSourceResource
@ UPnPResult_CDS_NoSuchSourceResource
Definition: upnp.h:69
UPnPResult_OptionalActionNotImplemented
@ UPnPResult_OptionalActionNotImplemented
Definition: upnp.h:45
UPnp::g_pConfig
static Configuration * g_pConfig
Definition: upnp.h:105
UPnPResult_CDS_CannotProcessRequest
@ UPnPResult_CDS_CannotProcessRequest
Definition: upnp.h:75
UPnPResult_CDS_InvalidCurrentTagValue
@ UPnPResult_CDS_InvalidCurrentTagValue
Definition: upnp.h:58
UPnPResult_NotEncrypted
@ UPnPResult_NotEncrypted
Definition: upnp.h:52
ServerPool::DefaultListen
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:297
UPnPResult_SignatureFailure
@ UPnPResult_SignatureFailure
Definition: upnp.h:50
UPnPResult_MythTV_XmlParseError
@ UPnPResult_MythTV_XmlParseError
Definition: upnp.h:88
HTTPRequest::m_sRawRequest
QString m_sRawRequest
Definition: httprequest.h:121
uint
unsigned int uint
Definition: compat.h:140
UPnPResult_CDS_InvalidNewTagValue
@ UPnPResult_CDS_InvalidNewTagValue
Definition: upnp.h:59
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
UPnPResult_ActionNotAuthorized
@ UPnPResult_ActionNotAuthorized
Definition: upnp.h:49
ResponseTypeOther
@ ResponseTypeOther
Definition: httprequest.h:83
UPnPResult_CDS_NoSuchContainer
@ UPnPResult_CDS_NoSuchContainer
Definition: upnp.h:65
UPnPResult_ActionFailed
@ UPnPResult_ActionFailed
Definition: upnp.h:42
UPnPResult_InvalidAction
@ UPnPResult_InvalidAction
Definition: upnp.h:40
SSDP::DisableNotifications
void DisableNotifications()
Definition: ssdp.cpp:185
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:924
UPnPResult_CDS_ParameterMismatch
@ UPnPResult_CDS_ParameterMismatch
Definition: upnp.h:62
HTTPRequest::m_bSOAPRequest
bool m_bSOAPRequest
Definition: httprequest.h:142
HttpServer::GetSharePath
QString GetSharePath(void) const
Definition: httpserver.h:128
UPnPResult_CDS_RestrictedObject
@ UPnPResult_CDS_RestrictedObject
Definition: upnp.h:66
MythPower::AcquireRelease
static MythPower * AcquireRelease(void *Reference, bool Acquire, uint MinimumDelay=0)
Definition: mythpower.cpp:70
UPnPResult_CDS_InvalidSortCriteria
@ UPnPResult_CDS_InvalidSortCriteria
Definition: upnp.h:64
upnptaskcache.h
HTTPRequest::FormatErrorResponse
void FormatErrorResponse(bool bServerError, const QString &sFaultString, const QString &sDetails)
Definition: httprequest.cpp:715
mythcorecontext.h
Configuration
Definition: configuration.h:21
UPnPResult_CDS_ReadOnlyTag
@ UPnPResult_CDS_ReadOnlyTag
Definition: upnp.h:61
HTTPRequest::m_eResponseType
HttpResponseType m_eResponseType
Definition: httprequest.h:147
serverpool.h
UPnPResult_CDS_ResrtictedParentObject
@ UPnPResult_CDS_ResrtictedParentObject
Definition: upnp.h:68
UPnp::DisableNotifications
static void DisableNotifications(uint)
Definition: upnp.cpp:336
UPnPResult_CDS_NoSuchObject
@ UPnPResult_CDS_NoSuchObject
Definition: upnp.h:57
UPnp::UPnp
UPnp()
Definition: upnp.cpp:42
UPnPResult_StringArgumentTooLong
@ UPnPResult_StringArgumentTooLong
Definition: upnp.h:48
HTTPRequest::m_mapHeaders
QStringMap m_mapHeaders
Definition: httprequest.h:130
HttpServer
Definition: httpserver.h:112
UPnp::~UPnp
~UPnp() override
Definition: upnp.cpp:62
UPnPResult_ArgumentValueInvalid
@ UPnPResult_ArgumentValueInvalid
Definition: upnp.h:43
UPnp::GetConfiguration
static Configuration * GetConfiguration()
Definition: upnp.cpp:84
UPnPResult_InvalidControlURL
@ UPnPResult_InvalidControlURL
Definition: upnp.h:54
UPnp::m_pHttpServer
HttpServer * m_pHttpServer
Definition: upnp.h:107
UPnPResult_CDS_ResourceAccessDenied
@ UPnPResult_CDS_ResourceAccessDenied
Definition: upnp.h:70
UPnPResult_InvalidSequence
@ UPnPResult_InvalidSequence
Definition: upnp.h:53
SSDP::EnableNotifications
void EnableNotifications(int nServicePort)
Definition: ssdp.cpp:145
UPnPResult_Success
@ UPnPResult_Success
Definition: upnp.h:38
HTTPRequest::SendResponse
qint64 SendResponse(void)
Definition: httprequest.cpp:296
MythPower::WillRestart
void WillRestart(uint MilliSeconds=0)
UPnPResult_MS_AccessDenied
@ UPnPResult_MS_AccessDenied
Definition: upnp.h:85
UPnp::SetConfiguration
static void SetConfiguration(Configuration *pConfig)
Definition: upnp.cpp:74
MythPower::WillShutDown
void WillShutDown(uint MilliSeconds=0)
UPnp::g_UPnpDeviceDesc
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition: upnp.h:112
UPnp::g_IPAddrList
static QList< QHostAddress > g_IPAddrList
Definition: upnp.h:113
UPnp::EnableNotificatins
void EnableNotificatins(qint64) const
Definition: upnp.cpp:341
UPnPResult_CDS_DestResAccessDenied
@ UPnPResult_CDS_DestResAccessDenied
Definition: upnp.h:74
UPnPResultCode
UPnPResultCode
Definition: upnp.h:36
UPnp::GetResultDesc
static QString GetResultDesc(UPnPResultCode eCode)
Definition: upnp.cpp:219