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 }
46 
48 //
50 
52 {
53  LOG(VB_UPNP, LOG_DEBUG, "UPnp - Destructor");
54  CleanUp();
55 }
56 
58 //
60 
62 {
63  delete g_pConfig;
64  g_pConfig = pConfig;
65 }
66 
68 //
70 
72 {
73  // If someone is asking for a config and it's nullptr, create a
74  // new XmlConfiguration since we don't have database info yet.
75 
76  if (g_pConfig == nullptr)
77  g_pConfig = new XmlConfiguration( "config.xml" );
78 
79  return g_pConfig;
80 }
81 
83 //
85 
86 bool UPnp::Initialize( int nServicePort, HttpServer *pHttpServer )
87 {
88  QList<QHostAddress> sList = ServerPool::DefaultListen();
89  if (sList.contains(QHostAddress(QHostAddress::AnyIPv4)))
90  {
91  sList.removeAll(QHostAddress(QHostAddress::AnyIPv4));
92  sList.removeAll(QHostAddress(QHostAddress::AnyIPv6));
93  sList.append(QNetworkInterface::allAddresses());
94  }
95  return Initialize( sList, nServicePort, pHttpServer );
96 }
97 
99 //
101 
102 bool UPnp::Initialize( QList<QHostAddress> &sIPAddrList, int nServicePort, HttpServer *pHttpServer )
103 {
104  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Initialize - Begin");
105 
106  if (m_pHttpServer)
107  {
108  LOG(VB_GENERAL, LOG_ERR,
109  "UPnp::Initialize - Already initialized, programmer error.");
110  return false;
111  }
112 
113  if (g_pConfig == nullptr)
114  {
115  LOG(VB_GENERAL, LOG_ERR,
116  "UPnp::Initialize - Must call SetConfiguration.");
117  return false;
118  }
119 
120  if ((m_pHttpServer = pHttpServer) == nullptr)
121  {
122  LOG(VB_GENERAL, LOG_ERR,
123  "UPnp::Initialize - Invalid Parameter (pHttpServer == NULL)");
124  return false;
125  }
126 
127  g_IPAddrList = sIPAddrList;
128  int it;
129  bool ipv4 = gCoreContext->GetBoolSetting("IPv4Support",true);
130  bool ipv6 = gCoreContext->GetBoolSetting("IPv6Support",true);
131 
132  for (it = 0; it < g_IPAddrList.size(); ++it)
133  {
134  // If IPV4 support is disabled and this is an IPV4 address,
135  // remove this address
136  // If IPV6 support is disabled and this is an IPV6 address,
137  // remove this address
138  if ((g_IPAddrList[it].protocol() == QAbstractSocket::IPv4Protocol
139  && ! ipv4)
140  ||(g_IPAddrList[it].protocol() == QAbstractSocket::IPv6Protocol
141  && ! ipv6))
142  g_IPAddrList.removeAt(it--);
143  }
144 
145  m_nServicePort = nServicePort;
146 
147  // ----------------------------------------------------------------------
148  // Register any HttpServerExtensions
149  // ----------------------------------------------------------------------
150 
153 
154  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Initialize - End");
155 
156  return true;
157 }
158 
160 // Delay startup of Discovery Threads until all Extensions are registered.
162 
164 {
165  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Enabling SSDP Notifications");
166  // ----------------------------------------------------------------------
167  // Turn on Device Announcements
168  // (this will also create/startup SSDP if not already done)
169  // ----------------------------------------------------------------------
170 
172 
173  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Returning");
174 }
175 
177 //
179 
181 {
182  LOG(VB_UPNP, LOG_INFO, "UPnp::CleanUp() - disabling SSDP notifications");
183 
185 
186  if (g_pConfig)
187  {
188  delete g_pConfig;
189  g_pConfig = nullptr;
190  }
191 
192 }
193 
195 //
197 
199 {
200  return UPnpDeviceDesc::Retrieve( sURL );
201 }
202 
204 //
206 
208 {
209  switch( eCode )
210  {
211  case UPnPResult_Success : return "Success";
212  case UPnPResult_InvalidAction : return "Invalid Action";
213  case UPnPResult_InvalidArgs : return "Invalid Args";
214  case UPnPResult_ActionFailed : return "Action Failed";
215  case UPnPResult_ArgumentValueInvalid : return "Argument Value Invalid";
216  case UPnPResult_ArgumentValueOutOfRange : return "Argument Value Out Of Range";
217  case UPnPResult_OptionalActionNotImplemented: return "Optional Action Not Implemented";
218  case UPnPResult_OutOfMemory : return "Out Of Memory";
219  case UPnPResult_HumanInterventionRequired : return "Human Intervention Required";
220  case UPnPResult_StringArgumentTooLong : return "String Argument Too Long";
221  case UPnPResult_ActionNotAuthorized : return "Action Not Authorized";
222  case UPnPResult_SignatureFailure : return "Signature Failure";
223  case UPnPResult_SignatureMissing : return "Signature Missing";
224  case UPnPResult_NotEncrypted : return "Not Encrypted";
225  case UPnPResult_InvalidSequence : return "Invalid Sequence";
226  case UPnPResult_InvalidControlURL : return "Invalid Control URL";
227  case UPnPResult_NoSuchSession : return "No Such Session";
228  case UPnPResult_MS_AccessDenied : return "Access Denied";
229 
230  case UPnPResult_CDS_NoSuchObject : return "No Such Object";
231  case UPnPResult_CDS_InvalidCurrentTagValue : return "Invalid CurrentTagValue";
232  case UPnPResult_CDS_InvalidNewTagValue : return "Invalid NewTagValue";
233  case UPnPResult_CDS_RequiredTag : return "Required Tag";
234  case UPnPResult_CDS_ReadOnlyTag : return "Read Only Tag";
235  case UPnPResult_CDS_ParameterMismatch : return "Parameter Mismatch";
236  case UPnPResult_CDS_InvalidSearchCriteria : return "Invalid Search Criteria";
237  case UPnPResult_CDS_InvalidSortCriteria : return "Invalid Sort Criteria";
238  case UPnPResult_CDS_NoSuchContainer : return "No Such Container";
239  case UPnPResult_CDS_RestrictedObject : return "Restricted Object";
240  case UPnPResult_CDS_BadMetadata : return "Bad Metadata";
241  case UPnPResult_CDS_ResrtictedParentObject : return "Resrticted Parent Object";
242  case UPnPResult_CDS_NoSuchSourceResource : return "No Such Source Resource";
243  case UPnPResult_CDS_ResourceAccessDenied : return "Resource Access Denied";
244  case UPnPResult_CDS_TransferBusy : return "Transfer Busy";
245  case UPnPResult_CDS_NoSuchFileTransfer : return "No Such File Transfer";
246  case UPnPResult_CDS_NoSuchDestRes : return "No Such Destination Resource";
247  case UPnPResult_CDS_DestResAccessDenied : return "Destination Resource Access Denied";
248  case UPnPResult_CDS_CannotProcessRequest : return "Cannot Process The Request";
249 
250  //case UPnPResult_CMGR_IncompatibleProtocol = 701,
251  //case UPnPResult_CMGR_IncompatibleDirections = 702,
252  //case UPnPResult_CMGR_InsufficientNetResources = 703,
253  //case UPnPResult_CMGR_LocalRestrictions = 704,
254  //case UPnPResult_CMGR_AccessDenied = 705,
255  //case UPnPResult_CMGR_InvalidConnectionRef = 706,
256  case UPnPResult_CMGR_NotInNetwork : return "Not In Network";
257  case UPnPResult_MythTV_NoNamespaceGiven: return "No Namespace Given";
258  case UPnPResult_MythTV_XmlParseError : return "XML Parse Error";
259  }
260 
261  return "Unknown";
262 }
263 
265 //
267 
269  UPnPResultCode eCode,
270  const QString &msg )
271 {
272  QString sMsg( msg );
273 
274  if (pRequest != nullptr)
275  {
276  QString sDetails = "";
277 
278  if (pRequest->m_bSOAPRequest)
279  sDetails = "<UPnPResult xmlns=\"urn:schemas-upnp-org:control-1-0\">";
280 
281  if (sMsg.length() == 0)
282  sMsg = GetResultDesc( eCode );
283 
284  sDetails += QString( "<errorCode>%1</errorCode>"
285  "<errorDescription>%2</errorDescription>" )
286  .arg( eCode )
287  .arg( HTTPRequest::Encode( sMsg ) );
288 
289  if (pRequest->m_bSOAPRequest)
290  sDetails += "</UPnPResult>";
291 
292 
293  pRequest->FormatErrorResponse ( true, // -=>TODO: Should make this dynamic
294  "UPnPResult",
295  sDetails );
296  }
297  else
298  LOG(VB_GENERAL, LOG_ERR, "Response not created - pRequest == NULL" );
299 }
300 
302 //
304 
306  const QString &hostName )
307 {
309  pRequest->m_nResponseStatus = 301;
310 
311  QStringList sItems = pRequest->m_sRawRequest.split( ' ' );
312  QString sUrl = "http://" + pRequest->m_mapHeaders[ "host" ] + sItems[1];
313  QUrl url( sUrl );
314  url.setHost( hostName );
315 
316  pRequest->m_mapRespHeaders[ "Location" ] = url.toString();
317 
318  LOG(VB_UPNP, LOG_INFO, QString("Sending http redirect to: %1")
319  .arg(url.toString()));
320 
321  pRequest->SendResponse();
322 }
virtual ~UPnp()
Definition: upnp.cpp:51
static Configuration * g_pConfig
Definition: upnp.h:100
bool Initialize(int nServicePort, HttpServer *pHttpServer)
Definition: upnp.cpp:86
UPnPResultCode
Definition: upnp.h:31
static UPnpDeviceDesc * Retrieve(QString &sURL)
Definition: upnpdevice.cpp:620
QStringMap m_mapRespHeaders
Definition: httprequest.h:149
void RegisterExtension(HttpServerExtension *)
Definition: httpserver.cpp:325
int m_nServicePort
Definition: upnp.h:103
static QString Encode(const QString &sIn)
void EnableNotifications(int nServicePort)
Definition: ssdp.cpp:150
long m_nResponseStatus
Definition: httprequest.h:148
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void DisableNotifications()
Definition: ssdp.cpp:190
QString GetSharePath(void) const
Definition: httpserver.h:128
static QString GetResultDesc(UPnPResultCode eCode)
Definition: upnp.cpp:207
static void FormatErrorResponse(HTTPRequest *pRequest, UPnPResultCode eCode, const QString &sMsg="")
Definition: upnp.cpp:268
QString m_sRawRequest
Definition: httprequest.h:119
static Configuration * GetConfiguration()
Definition: upnp.cpp:71
HttpServer * m_pHttpServer
Definition: upnp.h:102
UPnp()
Definition: upnp.cpp:42
virtual void Start()
Definition: upnp.cpp:163
static void FormatRedirectResponse(HTTPRequest *pRequest, const QString &hostName)
Definition: upnp.cpp:305
static void SetConfiguration(Configuration *pConfig)
Definition: upnp.cpp:61
static UPnpDeviceDesc * GetDeviceDesc(QString &sURL)
Definition: upnp.cpp:198
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static SSDP * Instance()
Definition: ssdp.cpp:54
bool GetBoolSetting(const QString &key, bool defaultval=false)
bool m_bSOAPRequest
Definition: httprequest.h:140
HttpResponseType m_eResponseType
Definition: httprequest.h:145
qint64 SendResponse(void)
QStringMap m_mapHeaders
Definition: httprequest.h:128
void FormatErrorResponse(bool bServerError, const QString &sFaultString, const QString &sDetails)
void CleanUp()
Definition: upnp.cpp:180
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:289
static QList< QHostAddress > g_IPAddrList
Definition: upnp.h:108
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition: upnp.h:107