From 36ba1c05543a5ea8c338a2d2018e7124030e88c6 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Tue, 2 Oct 2012 20:10:18 +0000 Subject: Porting of the upnp module to KviNetworkAccessManager (needs some testing) git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@6264 17fca916-40b9-46aa-a4ea-0a15b648b75c --- src/modules/upnp/Service.cpp | 228 ++++++++++++++++++++++--------------------- 1 file changed, 116 insertions(+), 112 deletions(-) (limited to 'src/modules/upnp/Service.cpp') diff --git a/src/modules/upnp/Service.cpp b/src/modules/upnp/Service.cpp index 3a889465b..0edfd340d 100644 --- a/src/modules/upnp/Service.cpp +++ b/src/modules/upnp/Service.cpp @@ -34,14 +34,11 @@ #include "Service.h" #include "XmlFunctions.h" -#warning upnp/Service uses QHttp, it must be either ported or dropped - #include -#if (QT_VERSION < 0x050000) -#include -#endif #include +#include "KviNetworkAccessManager.h" + // This implementation was created with the help of the following documentation: // http://www.upnp.org/standardizeddcps/documents/UPnP_IGD_1.0.zip // http://zacbowling.com/upnp/ @@ -61,10 +58,6 @@ Service::Service(const QString &hostname, int port, const QString &informationUr , m_iPort(port) { m_szInformationUrl = informationUrl; -#if (QT_VERSION < 0x050000) - m_pHttp = new QHttp(hostname, port); - connect(m_pHttp, SIGNAL( requestFinished(int,bool) ), this, SLOT( slotRequestFinished(int,bool) ) ); -#endif qDebug() << "UPnP::Service: Created information service url='" << m_szInformationUrl << "'." << endl; } @@ -80,10 +73,6 @@ Service::Service(const ServiceParameters ¶ms) , m_szHostname(params.hostname) , m_iPort(params.port) { -#if (QT_VERSION < 0x050000) - m_pHttp = new QHttp(params.hostname, params.port); - connect(m_pHttp, SIGNAL( requestFinished(int,bool) ), this, SLOT( slotRequestFinished(int,bool) ) ); -#endif qDebug() << "CREATED UPnP::Service: url='" << m_szControlUrl << "' id='" << m_szServiceId << "'." << endl; } @@ -93,9 +82,6 @@ Service::Service(const ServiceParameters ¶ms) Service::~Service() { qDebug() << "DESTROYED UPnP::Service [url=" << m_szControlUrl << ", id=" << m_szServiceId << "]" << endl; -#if (QT_VERSION < 0x050000) - delete m_pHttp; -#endif } @@ -121,7 +107,6 @@ int Service::callAction(const QString &actionName, const QMap & int Service::callActionInternal(const QString &actionName, const QMap *arguments, const QString &prefix) { qDebug() << "UPnP::Service: calling remote procedure '" << actionName << "'." << endl; -#if (QT_VERSION < 0x050000) // Create the data message //NOTE: we shouldm use serviceId_ instead of serviceType_, but it seems that my router @@ -162,21 +147,28 @@ int Service::callActionInternal(const QString &actionName, const QMappost(request, dummy); + connect(pReply, SIGNAL(finished()), this, SLOT(slotRequestFinished())); - return m_pHttp->request(header, content); -#endif + return 0; } @@ -191,9 +183,18 @@ int Service::callInformationUrl() // Send the GET request // TODO: User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1) m_iPendingRequests++; -#if (QT_VERSION < 0x050000) - return m_pHttp->get(m_szInformationUrl); -#endif + + QNetworkRequest request; + QByteArray dummy; + QUrl url; + url.setHost(m_szHostname); + url.setPort(m_iPort); + url.setPath(m_szInformationUrl); + request.setUrl(url); + QNetworkReply * pReply = KviNetworkAccessManager::getInstance()->post(request, dummy); + connect(pReply, SIGNAL(finished()), this, SLOT(slotRequestFinished())); + + return 0; } @@ -234,110 +235,113 @@ void Service::gotInformationResponse(const QDomNode &response) // The QHttp object retrieved data. -void Service::slotRequestFinished(int id, bool error) +void Service::slotRequestFinished() { -#if (QT_VERSION < 0x050000) - qDebug() << "UPnP::Service: Got HTTP response for request #"<< id << ", state: " << m_pHttp->state() << ", " << m_pHttp->bytesAvailable() << " bytes." << endl; + QNetworkReply *reply = qobject_cast(sender()); - if(! error) + qDebug() << "UPnP::Service: Got HTTP response for request " << endl; + + if(!reply) { - // an answer with 0 bytes is probably an error - if(m_pHttp->bytesAvailable() > 0) - { - // Get the XML content - QByteArray response = m_pHttp->readAll(); - QDomDocument xml; + qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl; + m_iPendingRequests--; + emit queryFinished(true); + return; + } - qDebug() << "Response:\n" << response << "\n---\n"; + if (reply->error() != QNetworkReply::NoError) + { + qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl; + m_iPendingRequests--; + emit queryFinished(true); + reply->deleteLater(); + return; + } - // Parse the XML - QString errorMessage; - error = ! xml.setContent(response, false, &errorMessage); + // Get the XML content + QByteArray response = reply->readAll(); + QDomDocument xml; - if(! error) - { - //extract the xml prefix used by the device; should be "s" + qDebug() << "Response:\n" << response << "\n---\n"; - //this is the reply of my Zyxel: - // - // - // - // WANIPConnection - // - // - // + // Parse the XML + QString errorMessage; + bool error = ! xml.setContent(response, false, &errorMessage); - QString baseNamespace = xml.documentElement().tagName(); + if(!error) + { + //extract the xml prefix used by the device; should be "s" - if(baseNamespace.length() > 0) - { - int cutAt = baseNamespace.indexOf(':'); - if(cutAt > -1) - { - baseNamespace.truncate(cutAt); - qDebug() << "Device is using " << baseNamespace << " as xml namespace" << endl; - m_szBaseXmlPrefix = baseNamespace; - } - } + //this is the reply of my Zyxel: + // + // + // + // WANIPConnection + // + // + // - // Determine how to process the data - if(xml.namedItem(m_szBaseXmlPrefix + ":Envelope").isNull()) - { - qDebug() << "UPnP::Service: Plain XML detected, calling gotInformationResponse()." << endl; - // No SOAP envelope found, this is a normal response to callService() - gotInformationResponse( xml.lastChild() ); - } else { - qDebug() << xml.toString() << endl; - // Got a SOAP message response to callAction() - QDomNode resultNode = XmlFunctions::getNode(xml, "/" + m_szBaseXmlPrefix + ":Envelope/" + m_szBaseXmlPrefix + ":Body").firstChild(); + QString baseNamespace = xml.documentElement().tagName(); + + if(baseNamespace.length() > 0) + { + int cutAt = baseNamespace.indexOf(':'); + if(cutAt > -1) + { + baseNamespace.truncate(cutAt); + qDebug() << "Device is using " << baseNamespace << " as xml namespace" << endl; + m_szBaseXmlPrefix = baseNamespace; + } + } + + // Determine how to process the data + if(xml.namedItem(m_szBaseXmlPrefix + ":Envelope").isNull()) + { + qDebug() << "UPnP::Service: Plain XML detected, calling gotInformationResponse()." << endl; + // No SOAP envelope found, this is a normal response to callService() + gotInformationResponse( xml.lastChild() ); + } else { + qDebug() << xml.toString() << endl; + // Got a SOAP message response to callAction() + QDomNode resultNode = XmlFunctions::getNode(xml, "/" + m_szBaseXmlPrefix + ":Envelope/" + m_szBaseXmlPrefix + ":Body").firstChild(); - error = (resultNode.nodeName() == m_szBaseXmlPrefix + ":Fault"); + error = (resultNode.nodeName() == m_szBaseXmlPrefix + ":Fault"); - if(! error) + if(! error) + { + if(resultNode.nodeName().startsWith("m:") || resultNode.nodeName().startsWith("u:")) + { + qDebug() << "UPnP::Service: SOAP Envelope detected, calling gotActionResponse()." << endl; + // Action success, return SOAP body + QMap resultValues; + + // Parse all parameters + // It's possible to pass the entire QDomNode object to the gotActionResponse() + // function, but this is somewhat nicer, and reduces code boat in the subclasses + QDomNodeList children = resultNode.childNodes(); + for(int i = 0; i < children.count(); i++) { - if(resultNode.nodeName().startsWith("m:") || resultNode.nodeName().startsWith("u:")) - { - qDebug() << "UPnP::Service: SOAP Envelope detected, calling gotActionResponse()." << endl; - // Action success, return SOAP body - QMap resultValues; - - // Parse all parameters - // It's possible to pass the entire QDomNode object to the gotActionResponse() - // function, but this is somewhat nicer, and reduces code boat in the subclasses - QDomNodeList children = resultNode.childNodes(); - for(int i = 0; i < children.count(); i++) - { - QString key = children.item(i).nodeName(); - resultValues[ key ] = children.item(i).toElement().text(); - } - - // Call the gotActionResponse() - gotActionResponse(resultNode.nodeName().mid(2), resultValues); - } - } else { - qDebug() << "UPnP::Service: SOAP Error detected, calling gotActionResponse()." << endl; - - // Action failed - gotActionErrorResponse(resultNode); + QString key = children.item(i).nodeName(); + resultValues[ key ] = children.item(i).toElement().text(); } + + // Call the gotActionResponse() + gotActionResponse(resultNode.nodeName().mid(2), resultValues); } } else { - qWarning() << "UPnP::Service - XML Parsing failed: " << errorMessage << endl; - } + qDebug() << "UPnP::Service: SOAP Error detected, calling gotActionResponse()." << endl; - // Only emit when bytes>0 - m_iPendingRequests--; - emit queryFinished(error); - } else { - QHttpResponseHeader header = m_pHttp->lastResponse(); - qDebug() << "Received zero-bytes HTTP response! Status: " << header.statusCode() << "; reason: " << header.reasonPhrase() << endl; + // Action failed + gotActionErrorResponse(resultNode); + } } } else { - qWarning() << "UPnP::Service - HTTP Request failed: " << m_pHttp->errorString() << endl; - m_iPendingRequests--; - emit queryFinished(error); + qWarning() << "UPnP::Service - XML Parsing failed: " << errorMessage << endl; } -#endif + + // Only emit when bytes>0 + m_iPendingRequests--; + emit queryFinished(error); } -- cgit v1.3.1-10-gc9f91