aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/upnp/Service.cpp
diff options
context:
space:
mode:
authorGravatar Alexey Sokolov2016-04-29 23:57:30 +0100
committerGravatar Alexey Sokolov2016-04-29 23:57:48 +0100
commit690dd7a33ddc90678367d73adf313533536e10f2 (patch)
tree2276fe7c384ebbc222b40a19c536d5c3c5606ce8 /src/modules/upnp/Service.cpp
parentAdd config for clang-format. (diff)
downloadKVIrc-690dd7a33ddc90678367d73adf313533536e10f2.tar.gz
KVIrc-690dd7a33ddc90678367d73adf313533536e10f2.tar.bz2
KVIrc-690dd7a33ddc90678367d73adf313533536e10f2.zip
Apply clang-format
Diffstat (limited to 'src/modules/upnp/Service.cpp')
-rw-r--r--src/modules/upnp/Service.cpp462
1 files changed, 219 insertions, 243 deletions
diff --git a/src/modules/upnp/Service.cpp b/src/modules/upnp/Service.cpp
index 747250531..e0547bfc2 100644
--- a/src/modules/upnp/Service.cpp
+++ b/src/modules/upnp/Service.cpp
@@ -45,304 +45,280 @@
// http://www.knoxscape.com/Upnp/NAT.htm
// http://www.artima.com/spontaneous/upnp_digihome2.html
-
namespace UPnP
{
-
-// The constructor for information services
-Service::Service(const QString &hostname, int port, const QString &informationUrl)
-: m_iPendingRequests(0)
-, m_szBaseXmlPrefix("s")
-, m_szHostname(hostname)
-, m_iPort(port)
-{
- m_szInformationUrl = informationUrl;
- qDebug() << "UPnP::Service: created information service url='" << m_szInformationUrl << "'." << endl;
-}
-
-
-// The constructor for action services
-Service::Service(const ServiceParameters &params)
-: m_szControlUrl(params.controlUrl)
-, m_szInformationUrl(params.scpdUrl)
-, m_iPendingRequests(0)
-, m_szServiceId(params.serviceId)
-, m_szServiceType(params.serviceType)
-, m_szBaseXmlPrefix("s")
-, m_szHostname(params.hostname)
-, m_iPort(params.port)
-{
- qDebug() << "CREATED UPnP::Service: url='" << m_szControlUrl << "' id='" << m_szServiceId << "'." << endl;
-}
-
-
-
-// The destructor
-Service::~Service()
-{
- qDebug() << "DESTROYED UPnP::Service [url=" << m_szControlUrl << ", id=" << m_szServiceId << "]" << endl;
-}
-
-
-
-// Makes a UPnP action request
-// TODO: rename to callMethod / callSoapMethod
-int Service::callAction(const QString &actionName, const QString &prefix)
-{
- return callActionInternal(actionName, 0, prefix);
-}
-
-
-
-// Makes a UPnP action request
-int Service::callAction(const QString &actionName, const QMap<QString,QString> &arguments, const QString &prefix)
-{
- return callActionInternal(actionName, &arguments, prefix);
-}
-
-
-
-// Makes a UPnP action request (keeps pointers from the external interface)
-int Service::callActionInternal(const QString &actionName, const QMap<QString,QString> *arguments, const QString &prefix)
-{
- qDebug() << "UPnP::Service: calling remote procedure '" << actionName << "'." << endl;
-
- // Create the data message
- //NOTE: we shouldm use serviceId_ instead of serviceType_, but it seems that my router
- // (and maybe others) are reporting wrong Ids, while they're gonna accepting only the
- // correct ones. This is a decoded reply from my Zyxel:
-
- // Service :
- // servicetype = urn:schemas-upnp-org:service:Layer3Forwarding:1
- // controlurl = /UD/act?0
- // eventsuburl = /?0
- // scpdurl = /L3Fwd.xml
- // serviceid = urn:upnp-org:serviceId:L3Forwarding1
-
- // this router wants us to use servicetype in the following requests
-
- QString soapMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
- "<" + m_szBaseXmlPrefix + ":Envelope xmlns:" + m_szBaseXmlPrefix + "=\"http://schemas.xmlsoap.org/soap/envelope/\""
- " " + m_szBaseXmlPrefix + ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
- " <" + m_szBaseXmlPrefix + ":Body>\n"
- " <" + prefix + ":" + actionName + " xmlns:" + prefix + "=\"" + m_szServiceType + "\">\n";
-
- // Do we have any arguments?
- if(arguments != 0)
+ // The constructor for information services
+ Service::Service(const QString & hostname, int port, const QString & informationUrl)
+ : m_iPendingRequests(0), m_szBaseXmlPrefix("s"), m_szHostname(hostname), m_iPort(port)
{
- // Add the arguments
- QMap<QString,QString>::const_iterator it;
- for(it = arguments->begin(); it != arguments->end(); ++it)
- {
- QString argumentName = it.key();
- soapMessage += "<" + argumentName + ">" + it.value() + "</" + argumentName + ">";
- }
+ m_szInformationUrl = informationUrl;
+ qDebug() << "UPnP::Service: created information service url='" << m_szInformationUrl << "'." << endl;
}
- // Add the closing tags
- soapMessage += " </" + prefix + ":" + actionName + ">\n </" + m_szBaseXmlPrefix + ":Body>\n</" + m_szBaseXmlPrefix + ":Envelope>\n";
-
- // Get an utf8 encoding string
- QByteArray content = soapMessage.toUtf8().data();
-
- // Create the HTTP header
- QNetworkRequest request;
- request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");
- request.setHeader(QNetworkRequest::ContentLengthHeader, content.size());
- request.setRawHeader("SOAPAction", QString("\"%1#%2\"").arg(m_szServiceType, actionName).toUtf8());
-
- QString port;
- port.setNum(m_iPort);
- request.setRawHeader("HOST", QString("%1:%2").arg(m_szHostname, port).toUtf8());
-
- QUrl url;
- url.setHost(m_szHostname);
- url.setPort(m_iPort);
- request.setUrl(url);
-
- // Send the POST request
- m_iPendingRequests++;
-
- QByteArray dummy;
- QNetworkReply * pReply = KviNetworkAccessManager::getInstance()->post(request, dummy);
- connect(pReply, SIGNAL(finished()), this, SLOT(slotRequestFinished()));
-
- return 0;
-}
-
+ // The constructor for action services
+ Service::Service(const ServiceParameters & params)
+ : m_szControlUrl(params.controlUrl), m_szInformationUrl(params.scpdUrl), m_iPendingRequests(0), m_szServiceId(params.serviceId), m_szServiceType(params.serviceType), m_szBaseXmlPrefix("s"), m_szHostname(params.hostname), m_iPort(params.port)
+ {
+ qDebug() << "CREATED UPnP::Service: url='" << m_szControlUrl << "' id='" << m_szServiceId << "'." << endl;
+ }
+ // The destructor
+ Service::~Service()
+ {
+ qDebug() << "DESTROYED UPnP::Service [url=" << m_szControlUrl << ", id=" << m_szServiceId << "]" << endl;
+ }
+ // Makes a UPnP action request
+ // TODO: rename to callMethod / callSoapMethod
+ int Service::callAction(const QString & actionName, const QString & prefix)
+ {
+ return callActionInternal(actionName, 0, prefix);
+ }
-// Makes a UPnP service request
-// TODO: rename to downloadFile()
-int Service::callInformationUrl()
-{
- qDebug() << "UPnP::Service: requesting file '" << m_szInformationUrl << "'." << endl;
+ // Makes a UPnP action request
+ int Service::callAction(const QString & actionName, const QMap<QString, QString> & arguments, const QString & prefix)
+ {
+ return callActionInternal(actionName, &arguments, prefix);
+ }
- // Send the GET request
- // TODO: User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1)
- m_iPendingRequests++;
+ // Makes a UPnP action request (keeps pointers from the external interface)
+ int Service::callActionInternal(const QString & actionName, const QMap<QString, QString> * arguments, const QString & prefix)
+ {
+ qDebug() << "UPnP::Service: calling remote procedure '" << actionName << "'." << endl;
- 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()));
+ // Create the data message
+ //NOTE: we shouldm use serviceId_ instead of serviceType_, but it seems that my router
+ // (and maybe others) are reporting wrong Ids, while they're gonna accepting only the
+ // correct ones. This is a decoded reply from my Zyxel:
- return 0;
-}
+ // Service :
+ // servicetype = urn:schemas-upnp-org:service:Layer3Forwarding:1
+ // controlurl = /UD/act?0
+ // eventsuburl = /?0
+ // scpdurl = /L3Fwd.xml
+ // serviceid = urn:upnp-org:serviceId:L3Forwarding1
+ // this router wants us to use servicetype in the following requests
+ QString soapMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<"
+ + m_szBaseXmlPrefix + ":Envelope xmlns:" + m_szBaseXmlPrefix + "=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " "
+ + m_szBaseXmlPrefix + ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
+ " <"
+ + m_szBaseXmlPrefix + ":Body>\n"
+ " <"
+ + prefix + ":" + actionName + " xmlns:" + prefix + "=\"" + m_szServiceType + "\">\n";
-// Get the number of pending requests
-int Service::getPendingRequests() const
-{
- return m_iPendingRequests;
-}
+ // Do we have any arguments?
+ if(arguments != 0)
+ {
+ // Add the arguments
+ QMap<QString, QString>::const_iterator it;
+ for(it = arguments->begin(); it != arguments->end(); ++it)
+ {
+ QString argumentName = it.key();
+ soapMessage += "<" + argumentName + ">" + it.value() + "</" + argumentName + ">";
+ }
+ }
+ // Add the closing tags
+ soapMessage += " </" + prefix + ":" + actionName + ">\n </" + m_szBaseXmlPrefix + ":Body>\n</" + m_szBaseXmlPrefix + ":Envelope>\n";
-// The control point received an action failure indication
-void Service::gotActionErrorResponse(const QDomNode &response)
-{
- QString faultString = XmlFunctions::getNodeValue(response, "/faultstring");
- QString errorCode = XmlFunctions::getNodeValue(response, "/detail/" + faultString + "/errorCode");
- QString errorDescription = XmlFunctions::getNodeValue(response, "/detail/" + faultString + "/errorDescription");
- qWarning() << "UPnP::Service - Action failed: " << errorCode << " " << errorDescription << endl;
-}
+ // Get an utf8 encoding string
+ QByteArray content = soapMessage.toUtf8().data();
+ // Create the HTTP header
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml");
+ request.setHeader(QNetworkRequest::ContentLengthHeader, content.size());
+ request.setRawHeader("SOAPAction", QString("\"%1#%2\"").arg(m_szServiceType, actionName).toUtf8());
+ QString port;
+ port.setNum(m_iPort);
+ request.setRawHeader("HOST", QString("%1:%2").arg(m_szHostname, port).toUtf8());
-// The control point received a response to callAction()
-void Service::gotActionResponse(const QString &responseType, const QMap<QString,QString> &/*resultValues*/)
-{
- qWarning() << "UPnP::Service - Action response '" << responseType << "' is not handled." << endl;
-}
+ QUrl url;
+ url.setHost(m_szHostname);
+ url.setPort(m_iPort);
+ request.setUrl(url);
+ // Send the POST request
+ m_iPendingRequests++;
+ QByteArray dummy;
+ QNetworkReply * pReply = KviNetworkAccessManager::getInstance()->post(request, dummy);
+ connect(pReply, SIGNAL(finished()), this, SLOT(slotRequestFinished()));
-// The control point received a response to callInformationUrl()
-void Service::gotInformationResponse(const QDomNode &response)
-{
- QString rootTagName = response.nodeName();
- qWarning() << "UPnP::Service - Service response (with root '" << rootTagName << "') is not handled." << endl;
-}
+ return 0;
+ }
+ // Makes a UPnP service request
+ // TODO: rename to downloadFile()
+ int Service::callInformationUrl()
+ {
+ qDebug() << "UPnP::Service: requesting file '" << m_szInformationUrl << "'." << endl;
+ // Send the GET request
+ // TODO: User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1)
+ m_iPendingRequests++;
-// The QHttp object retrieved data.
-void Service::slotRequestFinished()
-{
- QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
+ 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()));
- qDebug() << "UPnP::Service: received HTTP response for request " << endl;
+ return 0;
+ }
- if(!reply)
+ // Get the number of pending requests
+ int Service::getPendingRequests() const
{
- qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl;
- m_iPendingRequests--;
- emit queryFinished(true);
- return;
+ return m_iPendingRequests;
}
- if (reply->error() != QNetworkReply::NoError)
+ // The control point received an action failure indication
+ void Service::gotActionErrorResponse(const QDomNode & response)
{
- qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl;
- m_iPendingRequests--;
- emit queryFinished(true);
- reply->deleteLater();
- return;
+ QString faultString = XmlFunctions::getNodeValue(response, "/faultstring");
+ QString errorCode = XmlFunctions::getNodeValue(response, "/detail/" + faultString + "/errorCode");
+ QString errorDescription = XmlFunctions::getNodeValue(response, "/detail/" + faultString + "/errorDescription");
+ qWarning() << "UPnP::Service - Action failed: " << errorCode << " " << errorDescription << endl;
}
- // Get the XML content
- QByteArray response = reply->readAll();
- QDomDocument xml;
-
- qDebug() << "Response:\n" << response << "\n---\n";
+ // The control point received a response to callAction()
+ void Service::gotActionResponse(const QString & responseType, const QMap<QString, QString> & /*resultValues*/)
+ {
+ qWarning() << "UPnP::Service - Action response '" << responseType << "' is not handled." << endl;
+ }
- // Parse the XML
- QString errorMessage;
- bool error = ! xml.setContent(response, false, &errorMessage);
+ // The control point received a response to callInformationUrl()
+ void Service::gotInformationResponse(const QDomNode & response)
+ {
+ QString rootTagName = response.nodeName();
+ qWarning() << "UPnP::Service - Service response (with root '" << rootTagName << "') is not handled." << endl;
+ }
- if(!error)
+ // The QHttp object retrieved data.
+ void Service::slotRequestFinished()
{
- //extract the xml prefix used by the device; should be "s"
+ QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
- //this is the reply of my Zyxel:
- // <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" >
- // <SOAP-ENV:Body>
- // <u:GetDefaultConnectionServiceResponse xmlns:u="urn:schemas-upnp-org:service:Layer3Forwarding:1" >
- // <NewDefaultConnectionService>WANIPConnection</NewDefaultConnectionService>
- // </u:GetDefaultConnectionServiceResponse>
- // </SOAP-ENV:Body>
- // </SOAP-ENV:Envelope>
+ qDebug() << "UPnP::Service: received HTTP response for request " << endl;
- QString baseNamespace = xml.documentElement().tagName();
+ if(!reply)
+ {
+ qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl;
+ m_iPendingRequests--;
+ emit queryFinished(true);
+ return;
+ }
- if(baseNamespace.length() > 0)
+ if(reply->error() != QNetworkReply::NoError)
{
- int cutAt = baseNamespace.indexOf(':');
- if(cutAt > -1)
- {
- baseNamespace.truncate(cutAt);
- qDebug() << "Device is using " << baseNamespace << " as XML namespace" << endl;
- m_szBaseXmlPrefix = baseNamespace;
- }
+ qWarning() << "UPnP::Service - HTTP Request failed: " << reply->errorString() << endl;
+ m_iPendingRequests--;
+ emit queryFinished(true);
+ reply->deleteLater();
+ return;
}
- // Determine how to process the data
- if(xml.namedItem(m_szBaseXmlPrefix + ":Envelope").isNull())
+ // Get the XML content
+ QByteArray response = reply->readAll();
+ QDomDocument xml;
+
+ qDebug() << "Response:\n" << response << "\n---\n";
+
+ // Parse the XML
+ QString errorMessage;
+ bool error = !xml.setContent(response, false, &errorMessage);
+
+ if(!error)
{
- 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();
+ //extract the xml prefix used by the device; should be "s"
- error = (resultNode.nodeName() == m_szBaseXmlPrefix + ":Fault");
+ //this is the reply of my Zyxel:
+ // <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" >
+ // <SOAP-ENV:Body>
+ // <u:GetDefaultConnectionServiceResponse xmlns:u="urn:schemas-upnp-org:service:Layer3Forwarding:1" >
+ // <NewDefaultConnectionService>WANIPConnection</NewDefaultConnectionService>
+ // </u:GetDefaultConnectionServiceResponse>
+ // </SOAP-ENV:Body>
+ // </SOAP-ENV:Envelope>
- if(! error)
+ QString baseNamespace = xml.documentElement().tagName();
+
+ if(baseNamespace.length() > 0)
{
- if(resultNode.nodeName().startsWith("m:") || resultNode.nodeName().startsWith("u:"))
+ int cutAt = baseNamespace.indexOf(':');
+ if(cutAt > -1)
{
- qDebug() << "UPnP::Service: SOAP envelope detected, calling gotActionResponse()." << endl;
- // Action success, return SOAP body
- QMap<QString,QString> resultValues;
+ baseNamespace.truncate(cutAt);
+ qDebug() << "Device is using " << baseNamespace << " as XML namespace" << endl;
+ m_szBaseXmlPrefix = baseNamespace;
+ }
+ }
- // 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++)
+ // 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");
+
+ if(!error)
+ {
+ if(resultNode.nodeName().startsWith("m:") || resultNode.nodeName().startsWith("u:"))
{
- QString key = children.item(i).nodeName();
- resultValues[ key ] = children.item(i).toElement().text();
- }
+ qDebug() << "UPnP::Service: SOAP envelope detected, calling gotActionResponse()." << endl;
+ // Action success, return SOAP body
+ QMap<QString, QString> 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);
+ // Call the gotActionResponse()
+ gotActionResponse(resultNode.nodeName().mid(2), resultValues);
+ }
}
- } else {
- qDebug() << "UPnP::Service: SOAP error detected, calling gotActionResponse()." << endl;
+ else
+ {
+ qDebug() << "UPnP::Service: SOAP error detected, calling gotActionResponse()." << endl;
- // Action failed
- gotActionErrorResponse(resultNode);
+ // Action failed
+ gotActionErrorResponse(resultNode);
+ }
}
}
- } else {
- qWarning() << "UPnP::Service - XML parsing failed: " << errorMessage << endl;
- }
-
- // Only emit when bytes>0
- m_iPendingRequests--;
- emit queryFinished(error);
-}
+ else
+ {
+ qWarning() << "UPnP::Service - XML parsing failed: " << errorMessage << endl;
+ }
+ // Only emit when bytes>0
+ m_iPendingRequests--;
+ emit queryFinished(error);
+ }
} // end of namespace