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  bool ipv4 = gCoreContext->GetBoolSetting("IPv4Support",true);
129  bool ipv6 = gCoreContext->GetBoolSetting("IPv6Support",true);
130 
131  for (int it = 0; it < g_IPAddrList.size(); ++it)
132  {
133  // If IPV4 support is disabled and this is an IPV4 address,
134  // remove this address
135  // If IPV6 support is disabled and this is an IPV6 address,
136  // remove this address
137  if ((g_IPAddrList[it].protocol() == QAbstractSocket::IPv4Protocol
138  && ! ipv4)
139  ||(g_IPAddrList[it].protocol() == QAbstractSocket::IPv6Protocol
140  && ! ipv6))
141  g_IPAddrList.removeAt(it--);
142  }
143 
144  m_nServicePort = nServicePort;
145 
146  // ----------------------------------------------------------------------
147  // Register any HttpServerExtensions
148  // ----------------------------------------------------------------------
149 
152 
153  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Initialize - End");
154 
155  return true;
156 }
157 
159 // Delay startup of Discovery Threads until all Extensions are registered.
161 
163 {
164  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Enabling SSDP Notifications");
165  // ----------------------------------------------------------------------
166  // Turn on Device Announcements
167  // (this will also create/startup SSDP if not already done)
168  // ----------------------------------------------------------------------
169 
171 
172  LOG(VB_UPNP, LOG_DEBUG, "UPnp::Start - Returning");
173 }
174 
176 //
178 
180 {
181  LOG(VB_UPNP, LOG_INFO, "UPnp::CleanUp() - disabling SSDP notifications");
182 
184 
185  if (g_pConfig)
186  {
187  delete g_pConfig;
188  g_pConfig = nullptr;
189  }
190 
191 }
192 
194 //
196 
198 {
199  return UPnpDeviceDesc::Retrieve( sURL );
200 }
201 
203 //
205 
207 {
208  switch( eCode )
209  {
210  case UPnPResult_Success : return "Success";
211  case UPnPResult_InvalidAction : return "Invalid Action";
212  case UPnPResult_InvalidArgs : return "Invalid Args";
213  case UPnPResult_ActionFailed : return "Action Failed";
214  case UPnPResult_ArgumentValueInvalid : return "Argument Value Invalid";
215  case UPnPResult_ArgumentValueOutOfRange : return "Argument Value Out Of Range";
216  case UPnPResult_OptionalActionNotImplemented: return "Optional Action Not Implemented";
217  case UPnPResult_OutOfMemory : return "Out Of Memory";
218  case UPnPResult_HumanInterventionRequired : return "Human Intervention Required";
219  case UPnPResult_StringArgumentTooLong : return "String Argument Too Long";
220  case UPnPResult_ActionNotAuthorized : return "Action Not Authorized";
221  case UPnPResult_SignatureFailure : return "Signature Failure";
222  case UPnPResult_SignatureMissing : return "Signature Missing";
223  case UPnPResult_NotEncrypted : return "Not Encrypted";
224  case UPnPResult_InvalidSequence : return "Invalid Sequence";
225  case UPnPResult_InvalidControlURL : return "Invalid Control URL";
226  case UPnPResult_NoSuchSession : return "No Such Session";
227  case UPnPResult_MS_AccessDenied : return "Access Denied";
228 
229  case UPnPResult_CDS_NoSuchObject : return "No Such Object";
230  case UPnPResult_CDS_InvalidCurrentTagValue : return "Invalid CurrentTagValue";
231  case UPnPResult_CDS_InvalidNewTagValue : return "Invalid NewTagValue";
232  case UPnPResult_CDS_RequiredTag : return "Required Tag";
233  case UPnPResult_CDS_ReadOnlyTag : return "Read Only Tag";
234  case UPnPResult_CDS_ParameterMismatch : return "Parameter Mismatch";
235  case UPnPResult_CDS_InvalidSearchCriteria : return "Invalid Search Criteria";
236  case UPnPResult_CDS_InvalidSortCriteria : return "Invalid Sort Criteria";
237  case UPnPResult_CDS_NoSuchContainer : return "No Such Container";
238  case UPnPResult_CDS_RestrictedObject : return "Restricted Object";
239  case UPnPResult_CDS_BadMetadata : return "Bad Metadata";
240  case UPnPResult_CDS_ResrtictedParentObject : return "Resrticted Parent Object";
241  case UPnPResult_CDS_NoSuchSourceResource : return "No Such Source Resource";
242  case UPnPResult_CDS_ResourceAccessDenied : return "Resource Access Denied";
243  case UPnPResult_CDS_TransferBusy : return "Transfer Busy";
244  case UPnPResult_CDS_NoSuchFileTransfer : return "No Such File Transfer";
245  case UPnPResult_CDS_NoSuchDestRes : return "No Such Destination Resource";
246  case UPnPResult_CDS_DestResAccessDenied : return "Destination Resource Access Denied";
247  case UPnPResult_CDS_CannotProcessRequest : return "Cannot Process The Request";
248 
249  //case UPnPResult_CMGR_IncompatibleProtocol = 701,
250  //case UPnPResult_CMGR_IncompatibleDirections = 702,
251  //case UPnPResult_CMGR_InsufficientNetResources = 703,
252  //case UPnPResult_CMGR_LocalRestrictions = 704,
253  //case UPnPResult_CMGR_AccessDenied = 705,
254  //case UPnPResult_CMGR_InvalidConnectionRef = 706,
255  case UPnPResult_CMGR_NotInNetwork : return "Not In Network";
256  case UPnPResult_MythTV_NoNamespaceGiven: return "No Namespace Given";
257  case UPnPResult_MythTV_XmlParseError : return "XML Parse Error";
258  }
259 
260  return "Unknown";
261 }
262 
264 //
266 
268  UPnPResultCode eCode,
269  const QString &msg )
270 {
271  QString sMsg( msg );
272 
273  if (pRequest != nullptr)
274  {
275  QString sDetails = "";
276 
277  if (pRequest->m_bSOAPRequest)
278  sDetails = "<UPnPResult xmlns=\"urn:schemas-upnp-org:control-1-0\">";
279 
280  if (sMsg.length() == 0)
281  sMsg = GetResultDesc( eCode );
282 
283  sDetails += QString( "<errorCode>%1</errorCode>"
284  "<errorDescription>%2</errorDescription>" )
285  .arg( eCode )
286  .arg( HTTPRequest::Encode( sMsg ) );
287 
288  if (pRequest->m_bSOAPRequest)
289  sDetails += "</UPnPResult>";
290 
291 
292  pRequest->FormatErrorResponse ( true, // -=>TODO: Should make this dynamic
293  "UPnPResult",
294  sDetails );
295  }
296  else
297  LOG(VB_GENERAL, LOG_ERR, "Response not created - pRequest == NULL" );
298 }
299 
301 //
303 
305  const QString &hostName )
306 {
308  pRequest->m_nResponseStatus = 301;
309 
310  QStringList sItems = pRequest->m_sRawRequest.split( ' ' );
311  QString sUrl = "http://" + pRequest->m_mapHeaders[ "host" ] + sItems[1];
312  QUrl url( sUrl );
313  url.setHost( hostName );
314 
315  pRequest->m_mapRespHeaders[ "Location" ] = url.toString();
316 
317  LOG(VB_UPNP, LOG_INFO, QString("Sending http redirect to: %1")
318  .arg(url.toString()));
319 
320  pRequest->SendResponse();
321 }
virtual ~UPnp()
Definition: upnp.cpp:51
static Configuration * g_pConfig
Definition: upnp.h:99
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:147
void RegisterExtension(HttpServerExtension *)
Definition: httpserver.cpp:321
int m_nServicePort
Definition: upnp.h:102
static QString Encode(const QString &sIn)
void EnableNotifications(int nServicePort)
Definition: ssdp.cpp:150
long m_nResponseStatus
Definition: httprequest.h:146
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:206
static void FormatErrorResponse(HTTPRequest *pRequest, UPnPResultCode eCode, const QString &sMsg="")
Definition: upnp.cpp:267
QString m_sRawRequest
Definition: httprequest.h:117
static Configuration * GetConfiguration()
Definition: upnp.cpp:71
HttpServer * m_pHttpServer
Definition: upnp.h:101
UPnp()
Definition: upnp.cpp:42
virtual void Start()
Definition: upnp.cpp:162
static void FormatRedirectResponse(HTTPRequest *pRequest, const QString &hostName)
Definition: upnp.cpp:304
static void SetConfiguration(Configuration *pConfig)
Definition: upnp.cpp:61
static UPnpDeviceDesc * GetDeviceDesc(QString &sURL)
Definition: upnp.cpp:197
#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:138
HttpResponseType m_eResponseType
Definition: httprequest.h:143
qint64 SendResponse(void)
QStringMap m_mapHeaders
Definition: httprequest.h:126
void FormatErrorResponse(bool bServerError, const QString &sFaultString, const QString &sDetails)
static void CleanUp()
Definition: upnp.cpp:179
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:289
static QList< QHostAddress > g_IPAddrList
Definition: upnp.h:107
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition: upnp.h:106