diff options
| author | 2016-04-29 23:57:30 +0100 | |
|---|---|---|
| committer | 2016-04-29 23:57:48 +0100 | |
| commit | 690dd7a33ddc90678367d73adf313533536e10f2 (patch) | |
| tree | 2276fe7c384ebbc222b40a19c536d5c3c5606ce8 /src/modules/upnp | |
| parent | Add config for clang-format. (diff) | |
| download | KVIrc-690dd7a33ddc90678367d73adf313533536e10f2.tar.gz KVIrc-690dd7a33ddc90678367d73adf313533536e10f2.tar.bz2 KVIrc-690dd7a33ddc90678367d73adf313533536e10f2.zip | |
Apply clang-format
Diffstat (limited to 'src/modules/upnp')
| -rw-r--r-- | src/modules/upnp/Manager.cpp | 190 | ||||
| -rw-r--r-- | src/modules/upnp/Manager.h | 99 | ||||
| -rw-r--r-- | src/modules/upnp/RootService.cpp | 453 | ||||
| -rw-r--r-- | src/modules/upnp/RootService.h | 82 | ||||
| -rw-r--r-- | src/modules/upnp/Service.cpp | 462 | ||||
| -rw-r--r-- | src/modules/upnp/Service.h | 131 | ||||
| -rw-r--r-- | src/modules/upnp/SsdpConnection.cpp | 164 | ||||
| -rw-r--r-- | src/modules/upnp/SsdpConnection.h | 28 | ||||
| -rw-r--r-- | src/modules/upnp/WanConnectionService.cpp | 245 | ||||
| -rw-r--r-- | src/modules/upnp/WanConnectionService.h | 102 | ||||
| -rw-r--r-- | src/modules/upnp/XmlFunctions.cpp | 110 | ||||
| -rw-r--r-- | src/modules/upnp/XmlFunctions.h | 24 | ||||
| -rw-r--r-- | src/modules/upnp/igdcontrolpoint.cpp | 190 | ||||
| -rw-r--r-- | src/modules/upnp/igdcontrolpoint.h | 81 | ||||
| -rw-r--r-- | src/modules/upnp/libkviupnp.cpp | 54 |
15 files changed, 1142 insertions, 1273 deletions
diff --git a/src/modules/upnp/Manager.cpp b/src/modules/upnp/Manager.cpp index 4bb41969b..db3e8d503 100644 --- a/src/modules/upnp/Manager.cpp +++ b/src/modules/upnp/Manager.cpp @@ -39,137 +39,115 @@ #include <QDebug> #include <QTimer> - namespace UPnP { -// Set the static variable -Manager* Manager::m_pInstance(0); - - -// The constructor -Manager::Manager() -: m_pActiveIgdControlPoint(0) -, m_bBroadcastFailed(false) -, m_bBroadcastFoundIt(false) -, m_pSsdpConnection(0) -, m_pSsdpTimer(0) -{ - -} - - - -// The destructor -Manager::~Manager() -{ - delete m_pSsdpTimer; - delete m_pSsdpConnection; - m_pInstance = 0; // Unregister the instance -} - + // Set the static variable + Manager * Manager::m_pInstance(0); + // The constructor + Manager::Manager() + : m_pActiveIgdControlPoint(0), m_bBroadcastFailed(false), m_bBroadcastFoundIt(false), m_pSsdpConnection(0), m_pSsdpTimer(0) + { + } -// Initialize the manager, detect all devices -void Manager::initialize() -{ - qDebug() << "UPnP::Manager: initiating a broadcast to detect UPnP devices..." << endl; + // The destructor + Manager::~Manager() + { + delete m_pSsdpTimer; + delete m_pSsdpConnection; + m_pInstance = 0; // Unregister the instance + } + // Initialize the manager, detect all devices + void Manager::initialize() + { + qDebug() << "UPnP::Manager: initiating a broadcast to detect UPnP devices..." << endl; - // Create the SSDP object to detect devices - m_pSsdpConnection = new SsdpConnection(); - connect(m_pSsdpConnection, SIGNAL( deviceFound(const QString&,int,const QString&) ), - this, SLOT( slotDeviceFound(const QString&,int,const QString&) ) ); + // Create the SSDP object to detect devices + m_pSsdpConnection = new SsdpConnection(); + connect(m_pSsdpConnection, SIGNAL(deviceFound(const QString &, int, const QString &)), + this, SLOT(slotDeviceFound(const QString &, int, const QString &))); - // Create a timer - m_pSsdpTimer = new QTimer(this); - connect(m_pSsdpTimer, SIGNAL(timeout()), this, SLOT(slotBroadcastTimeout())); + // Create a timer + m_pSsdpTimer = new QTimer(this); + connect(m_pSsdpTimer, SIGNAL(timeout()), this, SLOT(slotBroadcastTimeout())); - // Start a UPnP broadcast - m_bBroadcastFailed = false; - m_bBroadcastFoundIt = false; - m_pSsdpConnection->queryDevices(); - m_pSsdpTimer->setSingleShot(true); - m_pSsdpTimer->start(2000); -} + // Start a UPnP broadcast + m_bBroadcastFailed = false; + m_bBroadcastFoundIt = false; + m_pSsdpConnection->queryDevices(); + m_pSsdpTimer->setSingleShot(true); + m_pSsdpTimer->start(2000); + } + // Return the instance of the manager class + Manager * Manager::instance() + { + // Create when it's required + if(m_pInstance == 0) + { + m_pInstance = new Manager(); + m_pInstance->initialize(); + } + return m_pInstance; + } -// Return the instance of the manager class -Manager * Manager::instance() -{ - // Create when it's required - if(m_pInstance == 0) + // Return the external IP address + QString Manager::getExternalIpAddress() const { - m_pInstance = new Manager(); - m_pInstance->initialize(); + // Do not expose activeIgd_; + return (m_pActiveIgdControlPoint != 0 ? m_pActiveIgdControlPoint->getExternalIpAddress() : QString()); } - return m_pInstance; -} - - - -// Return the external IP address -QString Manager::getExternalIpAddress() const -{ - // Do not expose activeIgd_; - return (m_pActiveIgdControlPoint != 0 ? m_pActiveIgdControlPoint->getExternalIpAddress() : QString()); -} - - - -// Return true if a controlable gateway is available -bool Manager::isGatewayAvailable() -{ - return (m_pActiveIgdControlPoint != 0 && m_pActiveIgdControlPoint->isGatewayAvailable()); -} + // Return true if a controlable gateway is available + bool Manager::isGatewayAvailable() + { + return (m_pActiveIgdControlPoint != 0 && m_pActiveIgdControlPoint->isGatewayAvailable()); + } // Add a port mapping -void Manager::addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort, const QString &internalClient, int internalPort, const QString &description, bool enabled, int leaseDuration) -{ - if(m_pActiveIgdControlPoint != 0) - m_pActiveIgdControlPoint->addPortMapping(protocol, remoteHost, externalPort, internalClient, internalPort, description, enabled, leaseDuration); -} - -// Delete a port mapping -void Manager::deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort) -{ - if(m_pActiveIgdControlPoint != 0) - m_pActiveIgdControlPoint->deletePortMapping(protocol, remoteHost, externalPort); -} - -// The broadcast failed -void Manager::slotBroadcastTimeout() -{ - if(!m_bBroadcastFoundIt) + void Manager::addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, const QString & internalClient, int internalPort, const QString & description, bool enabled, int leaseDuration) { - qDebug() << "UPnP::Manager: timeout, no broadcast response received!" << endl; + if(m_pActiveIgdControlPoint != 0) + m_pActiveIgdControlPoint->addPortMapping(protocol, remoteHost, externalPort, internalClient, internalPort, description, enabled, leaseDuration); + } - m_bBroadcastFailed = true; + // Delete a port mapping + void Manager::deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort) + { + if(m_pActiveIgdControlPoint != 0) + m_pActiveIgdControlPoint->deletePortMapping(protocol, remoteHost, externalPort); } -} + // The broadcast failed + void Manager::slotBroadcastTimeout() + { + if(!m_bBroadcastFoundIt) + { + qDebug() << "UPnP::Manager: timeout, no broadcast response received!" << endl; + m_bBroadcastFailed = true; + } + } -// A device was discovered by the SSDP broadcast -void Manager::slotDeviceFound(const QString &hostname, int port, const QString &rootUrl) -{ - qDebug() << "UPnP::Manager: device found, initializing IgdControlPoint to query it." << endl; + // A device was discovered by the SSDP broadcast + void Manager::slotDeviceFound(const QString & hostname, int port, const QString & rootUrl) + { + qDebug() << "UPnP::Manager: device found, initializing IgdControlPoint to query it." << endl; - // this blocks the action of our timeout timer - m_bBroadcastFoundIt = true; + // this blocks the action of our timeout timer + m_bBroadcastFoundIt = true; - IgdControlPoint *controlPoint = new IgdControlPoint(hostname, port, rootUrl); - m_lIgdControlPoints.append(controlPoint); + IgdControlPoint * controlPoint = new IgdControlPoint(hostname, port, rootUrl); + m_lIgdControlPoints.append(controlPoint); - if(m_pActiveIgdControlPoint == 0) - { - m_pActiveIgdControlPoint = controlPoint; - m_pActiveIgdControlPoint->initialize(); + if(m_pActiveIgdControlPoint == 0) + { + m_pActiveIgdControlPoint = controlPoint; + m_pActiveIgdControlPoint->initialize(); + } } -} - - -} // end of namespace +} // end of namespace diff --git a/src/modules/upnp/Manager.h b/src/modules/upnp/Manager.h index 43af04818..69fd14ed5 100644 --- a/src/modules/upnp/Manager.h +++ b/src/modules/upnp/Manager.h @@ -44,7 +44,7 @@ namespace UPnP { -/** + /** * The manager class is the public interface used by other networking classes. * It's implemented as singleton to provide easy access by other classes. * Devices are automatically detected at start-up, and maintained by this class. @@ -53,64 +53,61 @@ namespace UPnP * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class Manager : public QObject -{ - Q_OBJECT - -public: // public methods - - // The destructor - virtual ~Manager(); - - // Return the external IP address - QString getExternalIpAddress() const; + class Manager : public QObject + { + Q_OBJECT - // Return the instance of the manager class - static Manager * instance(); + public: // public methods + // The destructor + virtual ~Manager(); - // Return true if a controlable gateway is available - bool isGatewayAvailable(); + // Return the external IP address + QString getExternalIpAddress() const; - // Add a port mapping - void addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort, const QString &internalClient, int internalPort, const QString &description, bool enabled = true, int leaseDuration = 0); - // Delete a port mapping - void deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort); + // Return the instance of the manager class + static Manager * instance(); -private slots: - // The broadcast failed - void slotBroadcastTimeout(); - // A device was discovered by the SSDP broadcast - void slotDeviceFound(const QString &hostname, int port, const QString &rootUrl); + // Return true if a controlable gateway is available + bool isGatewayAvailable(); + // Add a port mapping + void addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, const QString & internalClient, int internalPort, const QString & description, bool enabled = true, int leaseDuration = 0); + // Delete a port mapping + void deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort); -private: // private methods - // The constructor (it's a singleton) - Manager(); - // Disable the copy constructor - Manager(const Manager &); - // Disable the assign operator - Manager& operator=(const Manager&); - // Initialize the manager, detect all devices - void initialize(); + private slots: + // The broadcast failed + void slotBroadcastTimeout(); + // A device was discovered by the SSDP broadcast + void slotDeviceFound(const QString & hostname, int port, const QString & rootUrl); -private: - // The active control point we're working with - IgdControlPoint *m_pActiveIgdControlPoint; - // True if the broadcast failed (false during the discovery process) - bool m_bBroadcastFailed; - // True if the broadcast found a device (false during the discovery process) - bool m_bBroadcastFoundIt; - // The instance of the singleton class - static Manager *m_pInstance; - // A list of all detected gateway devices - KviPointerList<IgdControlPoint> m_lIgdControlPoints; - // The SSDP connection to find all UPnP devices - SsdpConnection *m_pSsdpConnection; - // The timer to detect a broadcast timeout - QTimer *m_pSsdpTimer; -}; + private: // private methods + // The constructor (it's a singleton) + Manager(); + // Disable the copy constructor + Manager(const Manager &); + // Disable the assign operator + Manager & operator=(const Manager &); + // Initialize the manager, detect all devices + void initialize(); + private: + // The active control point we're working with + IgdControlPoint * m_pActiveIgdControlPoint; + // True if the broadcast failed (false during the discovery process) + bool m_bBroadcastFailed; + // True if the broadcast found a device (false during the discovery process) + bool m_bBroadcastFoundIt; + // The instance of the singleton class + static Manager * m_pInstance; + // A list of all detected gateway devices + KviPointerList<IgdControlPoint> m_lIgdControlPoints; + // The SSDP connection to find all UPnP devices + SsdpConnection * m_pSsdpConnection; + // The timer to detect a broadcast timeout + QTimer * m_pSsdpTimer; + }; -} // End of namespace +} // End of namespace #endif diff --git a/src/modules/upnp/RootService.cpp b/src/modules/upnp/RootService.cpp index abf945da8..81cd7b23a 100644 --- a/src/modules/upnp/RootService.cpp +++ b/src/modules/upnp/RootService.cpp @@ -43,274 +43,259 @@ namespace UPnP { - // Example message result: - // - // <root xmlns="urn:schemas-upnp-org:device-1-0" > - // <specVersion> - // <major>1</major> - // <minor>0</minor> - // </specVersion> - // <URLBase>http://10.0.0.138</URLBase> - // <device> - // <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType> - // <friendlyName>SpeedTouch 510 (0313QZ6S2)</friendlyName> - // <manufacturer>THOMSON multimedia</manufacturer> - // <manufacturerURL>http://www.thomson-multimedia.com</manufacturerURL> - // <modelDescription>DSL Internet Gateway</modelDescription> - // <modelName>SpeedTouch</modelName> - // <modelNumber>510</modelNumber> - // <modelURL>http://www.speedtouch.com</modelURL> - // <serialNumber>0313QZ6S2</serialNumber> - // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F</UDN> - // <presentationURL>/index.htm</presentationURL> - // <serviceList> - // <service> - // <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType> - // <serviceId>urn:upnp-org:serviceId:layer3f</serviceId> - // <controlURL>/upnp/control/layer3f</controlURL> - // <eventSubURL>/upnp/event/layer3f</eventSubURL> - // <SCPDURL>/Layer3Forwarding.xml</SCPDURL> - // </service> - // </serviceList> - // <deviceList> - // <device> - // <deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType> - // <friendlyName>LANDevice</friendlyName> - // <manufacturer>THOMSON multimedia</manufacturer> - // <modelName>SpeedTouch</modelName> - // <serialNumber>0313QZ6S2</serialNumber> - // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_LD</UDN> - // <serviceList> - // <service> - // <serviceType>urn:schemas-upnp-org:service:LANHostConfigManagement:1</serviceType> - // <serviceId>urn:upnp-org:serviceId:lanhcm</serviceId> - // <controlURL>/upnp/control/lanhcm</controlURL> - // <eventSubURL>/upnp/event/lanhcm</eventSubURL> - // <SCPDURL>/LANHostConfigManagement.xml</SCPDURL> - // </service> - // </serviceList> - // </device> - // <device> - // <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType> - // <friendlyName>WANDevice</friendlyName> - // <manufacturer>THOMSON multimedia</manufacturer> - // <modelName>SpeedTouch</modelName> - // <serialNumber>0313QZ6S2</serialNumber> - // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_WD</UDN> - // <serviceList> - // <service> - // <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType> - // <serviceId>urn:upnp-org:serviceId:wancic</serviceId> - // <controlURL>/upnp/control/wancic</controlURL> - // <eventSubURL>/upnp/event/wancic</eventSubURL> - // <SCPDURL>/WANCommonInterfaceConfig.xml</SCPDURL> - // </service> - // </serviceList> - // <deviceList> - // <device> - // <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType> - // <friendlyName>WANConnectionDevice</friendlyName> - // <manufacturer>THOMSON multimedia</manufacturer> - // <modelName>SpeedTouch</modelName> - // <serialNumber>0313QZ6S2</serialNumber> - // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_WCDpppoa</UDN> - // <serviceList> - // <service> - // <serviceType>urn:schemas-upnp-org:service:WANDSLLinkConfig:1</serviceType> - // <serviceId>urn:upnp-org:serviceId:wandsllc:pppoa</serviceId> - // <controlURL>/upnp/control/wandsllcpppoa</controlURL> - // <eventSubURL>/upnp/event/wandsllcpppoa</eventSubURL> - // <SCPDURL>/WANDSLLinkConfig.xml</SCPDURL> - // </service> - // <service> - // <serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType> - // <serviceId>urn:upnp-org:serviceId:wanpppc:pppoa</serviceId> - // <controlURL>/upnp/control/wanpppcpppoa</controlURL> - // <eventSubURL>/upnp/event/wanpppcpppoa</eventSubURL> - // <SCPDURL>/WANPPPConnection.xml</SCPDURL> - // </service> - // </serviceList> - // </device> - // </deviceList> - // </device> - // </deviceList> - // </device> - // </root> + // Example message result: + // + // <root xmlns="urn:schemas-upnp-org:device-1-0" > + // <specVersion> + // <major>1</major> + // <minor>0</minor> + // </specVersion> + // <URLBase>http://10.0.0.138</URLBase> + // <device> + // <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType> + // <friendlyName>SpeedTouch 510 (0313QZ6S2)</friendlyName> + // <manufacturer>THOMSON multimedia</manufacturer> + // <manufacturerURL>http://www.thomson-multimedia.com</manufacturerURL> + // <modelDescription>DSL Internet Gateway</modelDescription> + // <modelName>SpeedTouch</modelName> + // <modelNumber>510</modelNumber> + // <modelURL>http://www.speedtouch.com</modelURL> + // <serialNumber>0313QZ6S2</serialNumber> + // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F</UDN> + // <presentationURL>/index.htm</presentationURL> + // <serviceList> + // <service> + // <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType> + // <serviceId>urn:upnp-org:serviceId:layer3f</serviceId> + // <controlURL>/upnp/control/layer3f</controlURL> + // <eventSubURL>/upnp/event/layer3f</eventSubURL> + // <SCPDURL>/Layer3Forwarding.xml</SCPDURL> + // </service> + // </serviceList> + // <deviceList> + // <device> + // <deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType> + // <friendlyName>LANDevice</friendlyName> + // <manufacturer>THOMSON multimedia</manufacturer> + // <modelName>SpeedTouch</modelName> + // <serialNumber>0313QZ6S2</serialNumber> + // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_LD</UDN> + // <serviceList> + // <service> + // <serviceType>urn:schemas-upnp-org:service:LANHostConfigManagement:1</serviceType> + // <serviceId>urn:upnp-org:serviceId:lanhcm</serviceId> + // <controlURL>/upnp/control/lanhcm</controlURL> + // <eventSubURL>/upnp/event/lanhcm</eventSubURL> + // <SCPDURL>/LANHostConfigManagement.xml</SCPDURL> + // </service> + // </serviceList> + // </device> + // <device> + // <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType> + // <friendlyName>WANDevice</friendlyName> + // <manufacturer>THOMSON multimedia</manufacturer> + // <modelName>SpeedTouch</modelName> + // <serialNumber>0313QZ6S2</serialNumber> + // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_WD</UDN> + // <serviceList> + // <service> + // <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType> + // <serviceId>urn:upnp-org:serviceId:wancic</serviceId> + // <controlURL>/upnp/control/wancic</controlURL> + // <eventSubURL>/upnp/event/wancic</eventSubURL> + // <SCPDURL>/WANCommonInterfaceConfig.xml</SCPDURL> + // </service> + // </serviceList> + // <deviceList> + // <device> + // <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType> + // <friendlyName>WANConnectionDevice</friendlyName> + // <manufacturer>THOMSON multimedia</manufacturer> + // <modelName>SpeedTouch</modelName> + // <serialNumber>0313QZ6S2</serialNumber> + // <UDN>uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_WCDpppoa</UDN> + // <serviceList> + // <service> + // <serviceType>urn:schemas-upnp-org:service:WANDSLLinkConfig:1</serviceType> + // <serviceId>urn:upnp-org:serviceId:wandsllc:pppoa</serviceId> + // <controlURL>/upnp/control/wandsllcpppoa</controlURL> + // <eventSubURL>/upnp/event/wandsllcpppoa</eventSubURL> + // <SCPDURL>/WANDSLLinkConfig.xml</SCPDURL> + // </service> + // <service> + // <serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType> + // <serviceId>urn:upnp-org:serviceId:wanpppc:pppoa</serviceId> + // <controlURL>/upnp/control/wanpppcpppoa</controlURL> + // <eventSubURL>/upnp/event/wanpppcpppoa</eventSubURL> + // <SCPDURL>/WANPPPConnection.xml</SCPDURL> + // </service> + // </serviceList> + // </device> + // </deviceList> + // </device> + // </deviceList> + // </device> + // </root> - -// The contructor -RootService::RootService(const QString &hostname, int port, const QString &rootUrl) -: Service(hostname, port, rootUrl) -, m_szHostname(hostname) -, m_iPort(port) -{ - -} - - -// The destructor -RootService::~RootService() -{ - -} - - -// Recursively add all devices and embedded devices to the deviceServices_ map -void RootService::addDeviceServices(const QDomNode &device) -{ - qDebug() << "UPnP discovered device " << XmlFunctions::getNodeValue(device, "/UDN") << endl; - - if(XmlFunctions::getNodeValue(device, "/deviceType") == InternetGatewayDeviceType) + // The contructor + RootService::RootService(const QString & hostname, int port, const QString & rootUrl) + : Service(hostname, port, rootUrl), m_szHostname(hostname), m_iPort(port) { - QString description; - description = XmlFunctions::getNodeValue(device, "/friendlyName"); - if(description.isNull()) - description = XmlFunctions::getNodeValue(device, "/modelDescription"); - if(description.isNull()) - description = XmlFunctions::getNodeValue(device, "/modelName") + " " + XmlFunctions::getNodeValue(device, "/modelNumber"); - if(description.isNull()) - description = __tr2qs("Unknown"); - - qDebug() << "Model: " << description << endl; - - g_pApp->activeConsole()->output(KVI_OUT_GENERICSTATUS,__tr2qs_ctx("[UPNP]: found gateway device: %s","upnp"), description.toUtf8().data()); - - } - // Insert the given device node - // The "key" is the device/UDN tag, the value is a list of device/serviceList/service nodes - m_deviceServices.insert(XmlFunctions::getNodeValue(device, "/UDN"), - device.namedItem("serviceList").childNodes()); - // Find all embedded device nodes - QDomNodeList embeddedDevices = device.namedItem("deviceList").childNodes(); - for(int i = 0; i < embeddedDevices.count(); i++) + // The destructor + RootService::~RootService() { - if(embeddedDevices.item(i).nodeName() != "device") continue; - addDeviceServices(embeddedDevices.item(i)); } -} + // Recursively add all devices and embedded devices to the deviceServices_ map + void RootService::addDeviceServices(const QDomNode & device) + { + qDebug() << "UPnP discovered device " << XmlFunctions::getNodeValue(device, "/UDN") << endl; + if(XmlFunctions::getNodeValue(device, "/deviceType") == InternetGatewayDeviceType) + { + QString description; + description = XmlFunctions::getNodeValue(device, "/friendlyName"); + if(description.isNull()) + description = XmlFunctions::getNodeValue(device, "/modelDescription"); + if(description.isNull()) + description = XmlFunctions::getNodeValue(device, "/modelName") + " " + XmlFunctions::getNodeValue(device, "/modelNumber"); + if(description.isNull()) + description = __tr2qs("Unknown"); -// Return the device type -QString RootService::getDeviceType() const -{ - return m_szDeviceType; -} + qDebug() << "Model: " << description << endl; + g_pApp->activeConsole()->output(KVI_OUT_GENERICSTATUS, __tr2qs_ctx("[UPNP]: found gateway device: %s", "upnp"), description.toUtf8().data()); + } + // Insert the given device node + // The "key" is the device/UDN tag, the value is a list of device/serviceList/service nodes + m_deviceServices.insert(XmlFunctions::getNodeValue(device, "/UDN"), + device.namedItem("serviceList").childNodes()); -// Return a service from the cached root device entry -ServiceParameters RootService::getServiceById(const QString &serviceId) const -{ - // Get a /root/device/serviceList/service/ tag - - ServiceParameters params; - QMap<QString,QDomNodeList>::const_iterator i = m_deviceServices.constBegin(); - while (i != m_deviceServices.constEnd()) { - if(getServiceById(serviceId, i.key(), params)) - return params; - ++i; + // Find all embedded device nodes + QDomNodeList embeddedDevices = device.namedItem("deviceList").childNodes(); + for(int i = 0; i < embeddedDevices.count(); i++) + { + if(embeddedDevices.item(i).nodeName() != "device") + continue; + addDeviceServices(embeddedDevices.item(i)); + } } - //calling function check this field to understand if the struct is null - params.controlUrl = QString(); - return params; -} - -// Return a service from a cached embedded device entry -bool RootService::getServiceById(const QString &serviceId, const QString &deviceUdn, ServiceParameters ¶ms) const -{ - // Get a /root/device/deviceList/device/.../serviceList/service/serviceId tag - QDomNode service = XmlFunctions::getNodeChildByKey( m_deviceServices[deviceUdn], "serviceId", serviceId ); - - if(! service.isNull()) + // Return the device type + QString RootService::getDeviceType() const { - params.hostname = m_szHostname; - params.port = m_iPort; - params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL"); - params.scpdUrl = XmlFunctions::getNodeValue(service, "/SCPDURL"); - params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId"); - params.serviceType = XmlFunctions::getNodeValue(service, "/serviceType"); - - return true; - } else { - return false; + return m_szDeviceType; } -} + // Return a service from the cached root device entry + ServiceParameters RootService::getServiceById(const QString & serviceId) const + { + // Get a /root/device/serviceList/service/ tag -// Return a service from the cached root device entry -ServiceParameters RootService::getServiceByType(const QString &serviceType) const -{ - // Get a /root/device/serviceList/service/ tag + ServiceParameters params; + QMap<QString, QDomNodeList>::const_iterator i = m_deviceServices.constBegin(); + while(i != m_deviceServices.constEnd()) + { + if(getServiceById(serviceId, i.key(), params)) + return params; + ++i; + } - ServiceParameters params; - QMap<QString,QDomNodeList>::const_iterator i = m_deviceServices.constBegin(); - while (i != m_deviceServices.constEnd()) { - if(getServiceByType(serviceType, i.key(), params)) - return params; - ++i; + //calling function check this field to understand if the struct is null + params.controlUrl = QString(); + return params; } - //calling function check this field to understand if the struct is null - params.controlUrl = QString(); - return params; - -} - + // Return a service from a cached embedded device entry + bool RootService::getServiceById(const QString & serviceId, const QString & deviceUdn, ServiceParameters & params) const + { + // Get a /root/device/deviceList/device/.../serviceList/service/serviceId tag + QDomNode service = XmlFunctions::getNodeChildByKey(m_deviceServices[deviceUdn], "serviceId", serviceId); + if(!service.isNull()) + { + params.hostname = m_szHostname; + params.port = m_iPort; + params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL"); + params.scpdUrl = XmlFunctions::getNodeValue(service, "/SCPDURL"); + params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId"); + params.serviceType = XmlFunctions::getNodeValue(service, "/serviceType"); -// Return a service from a cached embedded device entry -bool RootService::getServiceByType(const QString &serviceType, const QString &deviceUdn, ServiceParameters ¶ms) const -{ - // Get a /root/device/deviceList/device/.../serviceList/service/serviceType tag - QDomNode service = XmlFunctions::getNodeChildByKey( m_deviceServices[deviceUdn], "serviceType", serviceType ); + return true; + } + else + { + return false; + } + } - if(! service.isNull()) + // Return a service from the cached root device entry + ServiceParameters RootService::getServiceByType(const QString & serviceType) const { - params.hostname = m_szHostname; - params.port = m_iPort; - params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL"); - params.scpdUrl = XmlFunctions::getNodeValue(service, "/SCPDURL"); - params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId"); - params.serviceType = serviceType; + // Get a /root/device/serviceList/service/ tag - return true; - } else { - qWarning() << "UPnP::RootService::getServiceByType -" - << " type '" << serviceType << "' not found for device '" << deviceUdn << "'." << endl; + ServiceParameters params; + QMap<QString, QDomNodeList>::const_iterator i = m_deviceServices.constBegin(); + while(i != m_deviceServices.constEnd()) + { + if(getServiceByType(serviceType, i.key(), params)) + return params; + ++i; + } - return false; + //calling function check this field to understand if the struct is null + params.controlUrl = QString(); + return params; } -} + // Return a service from a cached embedded device entry + bool RootService::getServiceByType(const QString & serviceType, const QString & deviceUdn, ServiceParameters & params) const + { + // Get a /root/device/deviceList/device/.../serviceList/service/serviceType tag + QDomNode service = XmlFunctions::getNodeChildByKey(m_deviceServices[deviceUdn], "serviceType", serviceType); + if(!service.isNull()) + { + params.hostname = m_szHostname; + params.port = m_iPort; + params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL"); + params.scpdUrl = XmlFunctions::getNodeValue(service, "/SCPDURL"); + params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId"); + params.serviceType = serviceType; -// The control point received a response to callInformationUrl() -void RootService::gotInformationResponse(const QDomNode &response) -{ - // Register all device UDN nodes for later - m_deviceServices.clear(); - addDeviceServices( XmlFunctions::getNode(response, "/device") ); - - // Fetch the required data - m_szDeviceType = XmlFunctions::getNodeValue(response, "/device/deviceType"); - m_szRootUdn = XmlFunctions::getNodeValue(response, "/device/UDN"); - - // The rootUdn_ is used to retrieve - // the /root/device/serviceList/service - // nodes from the deviceServices_ map -} + return true; + } + else + { + qWarning() << "UPnP::RootService::getServiceByType -" + << " type '" << serviceType << "' not found for device '" << deviceUdn << "'." << endl; + return false; + } + } + // The control point received a response to callInformationUrl() + void RootService::gotInformationResponse(const QDomNode & response) + { + // Register all device UDN nodes for later + m_deviceServices.clear(); + addDeviceServices(XmlFunctions::getNode(response, "/device")); -// Query the device for its service list -void RootService::queryDevice() -{ - callInformationUrl(); -} + // Fetch the required data + m_szDeviceType = XmlFunctions::getNodeValue(response, "/device/deviceType"); + m_szRootUdn = XmlFunctions::getNodeValue(response, "/device/UDN"); + // The rootUdn_ is used to retrieve + // the /root/device/serviceList/service + // nodes from the deviceServices_ map + } + // Query the device for its service list + void RootService::queryDevice() + { + callInformationUrl(); + } } // end of namespae diff --git a/src/modules/upnp/RootService.h b/src/modules/upnp/RootService.h index 750ce5a9f..971e86be2 100644 --- a/src/modules/upnp/RootService.h +++ b/src/modules/upnp/RootService.h @@ -36,13 +36,12 @@ #include "Service.h" - namespace UPnP { #define InternetGatewayDeviceType "urn:schemas-upnp-org:device:InternetGatewayDevice:1" -/** + /** * The services of a device can be retrieved using the device root service. * The URL of the root service is returned by an SSDP broadcast. * The root service returns the meta information and list of services the device supports. @@ -50,54 +49,49 @@ namespace UPnP * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class RootService : public Service -{ -public: // public methods - - // The constructor - RootService(const QString &hostname, int port, const QString &rootUrl); - // The destructor - virtual ~RootService(); - - // Return the device type - QString getDeviceType() const; - - // Return a service from the cached root device entry - ServiceParameters getServiceById(const QString &serviceId) const; - // Return a service from a cached embedded device entry - bool getServiceById(const QString &serviceId, const QString &deviceUdn, ServiceParameters ¶ms) const; - // Return a service from the cached root device entry - ServiceParameters getServiceByType(const QString &serviceType) const; - // Return a service from a cached embedded device entry - bool getServiceByType(const QString &serviceType, const QString &deviceUdn, ServiceParameters ¶ms) const; - - // Query the device for its service list - void queryDevice(); - + class RootService : public Service + { + public: // public methods + // The constructor + RootService(const QString & hostname, int port, const QString & rootUrl); + // The destructor + virtual ~RootService(); -protected: // Protected methods - // The control point received a response to callInformationUrl() - virtual void gotInformationResponse(const QDomNode &response); + // Return the device type + QString getDeviceType() const; + // Return a service from the cached root device entry + ServiceParameters getServiceById(const QString & serviceId) const; + // Return a service from a cached embedded device entry + bool getServiceById(const QString & serviceId, const QString & deviceUdn, ServiceParameters & params) const; + // Return a service from the cached root device entry + ServiceParameters getServiceByType(const QString & serviceType) const; + // Return a service from a cached embedded device entry + bool getServiceByType(const QString & serviceType, const QString & deviceUdn, ServiceParameters & params) const; -private: // Private methods - // Recursively add all devices and embedded devices to the deviceServices_ map - void addDeviceServices(const QDomNode &device); + // Query the device for its service list + void queryDevice(); + protected: // Protected methods + // The control point received a response to callInformationUrl() + virtual void gotInformationResponse(const QDomNode & response); -private: - // The device type - QString m_szDeviceType; - // A collection of all services provided by the device - QMap<QString,QDomNodeList> m_deviceServices; - // The hostname of the device - QString m_szHostname; - // The port of the device - int m_iPort; - // The udn of the root device - QString m_szRootUdn; -}; + private: // Private methods + // Recursively add all devices and embedded devices to the deviceServices_ map + void addDeviceServices(const QDomNode & device); + private: + // The device type + QString m_szDeviceType; + // A collection of all services provided by the device + QMap<QString, QDomNodeList> m_deviceServices; + // The hostname of the device + QString m_szHostname; + // The port of the device + int m_iPort; + // The udn of the root device + QString m_szRootUdn; + }; } #endif 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 ¶ms) -: 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 diff --git a/src/modules/upnp/Service.h b/src/modules/upnp/Service.h index a4d77bf84..de81a5ee6 100644 --- a/src/modules/upnp/Service.h +++ b/src/modules/upnp/Service.h @@ -42,20 +42,19 @@ namespace UPnP { -// A datablock to make the exchange -// of service information easier -struct ServiceParameters -{ - QString hostname; - int port; - QString scpdUrl; - QString controlUrl; - QString serviceId; - QString serviceType; -}; - + // A datablock to make the exchange + // of service information easier + struct ServiceParameters + { + QString hostname; + int port; + QString scpdUrl; + QString controlUrl; + QString serviceId; + QString serviceType; + }; -/** + /** * This base class to implement calls to a UPnP-enabled device. * In UPnP terminology, a client is called a Control Point, and a service is a UPnP device. * @@ -66,68 +65,66 @@ struct ServiceParameters * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class Service : public QObject -{ - Q_OBJECT - -public: // public methods - // The constructor for the root service - Service(const QString &hostname, int port, const QString &informationUrl); - // The constructor for action services - Service(const ServiceParameters ¶ms); - // The destructor - virtual ~Service(); - - // Get the number of pending requests - int getPendingRequests() const; + class Service : public QObject + { + Q_OBJECT + public: // public methods + // The constructor for the root service + Service(const QString & hostname, int port, const QString & informationUrl); + // The constructor for action services + Service(const ServiceParameters & params); + // The destructor + virtual ~Service(); -protected: // Protected methods - // Makes a UPnP action request - int callAction(const QString &actionName, const QString &prefix); - // Makes a UPnP action request - int callAction(const QString &actionName, const QMap<QString,QString> &arguments, const QString &prefix); - // Makes a UPnP service request - int callInformationUrl(); + // Get the number of pending requests + int getPendingRequests() const; - // The control point received an action failure indication - virtual void gotActionErrorResponse(const QDomNode &response); - // The control point received a response to callAction() - virtual void gotActionResponse(const QString &responseType, const QMap<QString,QString> &resultValues); - // The control point received a response to callInformationUrl() - virtual void gotInformationResponse(const QDomNode &response); + protected: // Protected methods + // Makes a UPnP action request + int callAction(const QString & actionName, const QString & prefix); + // Makes a UPnP action request + int callAction(const QString & actionName, const QMap<QString, QString> & arguments, const QString & prefix); + // Makes a UPnP service request + int callInformationUrl(); -private slots: - // The QHttp object retrieved data. - void slotRequestFinished(); + // The control point received an action failure indication + virtual void gotActionErrorResponse(const QDomNode & response); + // The control point received a response to callAction() + virtual void gotActionResponse(const QString & responseType, const QMap<QString, QString> & resultValues); + // The control point received a response to callInformationUrl() + virtual void gotInformationResponse(const QDomNode & response); -private: - // Makes a UPnP action request (keeps pointers from the external interface) - int callActionInternal(const QString &actionName, const QMap<QString,QString> *arguments, const QString &prefix); + private slots: + // The QHttp object retrieved data. + void slotRequestFinished(); -private: - // The URL to control the service - QString m_szControlUrl; - // The URL to request service information - QString m_szInformationUrl; - // The number of pending queries/actions - int m_iPendingRequests; - // The ID of the service - QString m_szServiceId; - // The Type of the service - QString m_szServiceType; - // The xml prefix used by the router - QString m_szBaseXmlPrefix; - // hostname - QString m_szHostname; - //port - int m_iPort; + private: + // Makes a UPnP action request (keeps pointers from the external interface) + int callActionInternal(const QString & actionName, const QMap<QString, QString> * arguments, const QString & prefix); -signals: - // Called when a query completed - void queryFinished(bool error); -}; + private: + // The URL to control the service + QString m_szControlUrl; + // The URL to request service information + QString m_szInformationUrl; + // The number of pending queries/actions + int m_iPendingRequests; + // The ID of the service + QString m_szServiceId; + // The Type of the service + QString m_szServiceType; + // The xml prefix used by the router + QString m_szBaseXmlPrefix; + // hostname + QString m_szHostname; + //port + int m_iPort; + signals: + // Called when a query completed + void queryFinished(bool error); + }; } #endif diff --git a/src/modules/upnp/SsdpConnection.cpp b/src/modules/upnp/SsdpConnection.cpp index 7440d10d1..11a316ce6 100644 --- a/src/modules/upnp/SsdpConnection.cpp +++ b/src/modules/upnp/SsdpConnection.cpp @@ -43,110 +43,104 @@ namespace UPnP { -SsdpConnection::SsdpConnection() -: QObject() -{ - m_pSocket = new QUdpSocket(); - connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(slotDataReceived())); -} - -SsdpConnection::~SsdpConnection() -{ - if(m_pSocket != 0) + SsdpConnection::SsdpConnection() + : QObject() { - m_pSocket->close(); - delete m_pSocket; + m_pSocket = new QUdpSocket(); + connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(slotDataReceived())); } -} - - -// Data was received by the socket -void SsdpConnection::slotDataReceived() -{ - qDebug() << "UPnP::SsdpConnection: received " << m_pSocket->bytesAvailable() << " bytes." << endl; - - // Response from Diederik's Acatel router: - // - // HTTP/1.1 200 OK - // CACHE-CONTROL:max-age=1800 - // EXT: - // LOCATION:http://10.0.0.138:80/IGD.xml - // SERVER:SpeedTouch 510 4.0.2.0.0 UPnP/1.0 (0313QZ6S2) - // ST:upnp:rootdevice - // USN:uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F::upnp:rootdevice - // + SsdpConnection::~SsdpConnection() + { + if(m_pSocket != 0) + { + m_pSocket->close(); + delete m_pSocket; + } + } - // This is from a Zyxel router: - // - // HTTP/1.1 200 OK - // ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1 - // USN:uuid:11111111-%04x-c0a8-fcb30002cf618c::urn:schemas-upnp-org:device:InternetGatewayDevice:1 - // Location:http://192.168.252.179:80/DeviceDescription.xml - // Cache-Control: max-age=480 - // Server: ZyXEL-RomPlug/4.51 UPnP/1.0 IGD/1.00 - // Ext: + // Data was received by the socket + void SsdpConnection::slotDataReceived() + { + qDebug() << "UPnP::SsdpConnection: received " << m_pSocket->bytesAvailable() << " bytes." << endl; - while (m_pSocket->hasPendingDatagrams()) { - QByteArray datagram; - datagram.resize(m_pSocket->pendingDatagramSize()); - m_pSocket->readDatagram(datagram.data(), datagram.size()); + // Response from Diederik's Acatel router: + // + // HTTP/1.1 200 OK + // CACHE-CONTROL:max-age=1800 + // EXT: + // LOCATION:http://10.0.0.138:80/IGD.xml + // SERVER:SpeedTouch 510 4.0.2.0.0 UPnP/1.0 (0313QZ6S2) + // ST:upnp:rootdevice + // USN:uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F::upnp:rootdevice + // - qDebug("Received datagram: %s\n",datagram.data()); + // This is from a Zyxel router: + // + // HTTP/1.1 200 OK + // ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1 + // USN:uuid:11111111-%04x-c0a8-fcb30002cf618c::urn:schemas-upnp-org:device:InternetGatewayDevice:1 + // Location:http://192.168.252.179:80/DeviceDescription.xml + // Cache-Control: max-age=480 + // Server: ZyXEL-RomPlug/4.51 UPnP/1.0 IGD/1.00 + // Ext: - QString sspdResponse = QString::fromUtf8(datagram.data(), datagram.size()); + while(m_pSocket->hasPendingDatagrams()) + { + QByteArray datagram; + datagram.resize(m_pSocket->pendingDatagramSize()); + m_pSocket->readDatagram(datagram.data(), datagram.size()); - // Find the location field manually, MimeMessage is not required - int locationStart = sspdResponse.indexOf("LOCATION:",0,Qt::CaseInsensitive); - int locationEnd = sspdResponse.indexOf("\r\n",locationStart,Qt::CaseSensitive); + qDebug("Received datagram: %s\n", datagram.data()); - locationStart += 9; // length of field name - QString location = sspdResponse.mid(locationStart, locationEnd - locationStart); + QString sspdResponse = QString::fromUtf8(datagram.data(), datagram.size()); - // Parse the URL syntax using KURL - QUrl url(location.trimmed()); + // Find the location field manually, MimeMessage is not required + int locationStart = sspdResponse.indexOf("LOCATION:", 0, Qt::CaseInsensitive); + int locationEnd = sspdResponse.indexOf("\r\n", locationStart, Qt::CaseSensitive); - qDebug("Found internet gateway: %s\n", location.toUtf8().data()); - // Emit success - emit deviceFound(url.host(), url.port(), url.path()); + locationStart += 9; // length of field name + QString location = sspdResponse.mid(locationStart, locationEnd - locationStart); + // Parse the URL syntax using KURL + QUrl url(location.trimmed()); + qDebug("Found internet gateway: %s\n", location.toUtf8().data()); + // Emit success + emit deviceFound(url.host(), url.port(), url.path()); + } } -} + // Send a broadcast to detect all devices + void SsdpConnection::queryDevices(int bindPort) + { + qDebug() << "UPnP::SsdpConnection: sending broadcast packet." << endl; -// Send a broadcast to detect all devices -void SsdpConnection::queryDevices(int bindPort) -{ - qDebug() << "UPnP::SsdpConnection: sending broadcast packet." << endl; + // Send a packet to a broadcast address + QHostAddress address("239.255.255.250"); - // Send a packet to a broadcast address - QHostAddress address("239.255.255.250"); + QString data = "M-SEARCH * HTTP/1.1\r\n" + "Host:239.255.255.250:1900\r\n" + "ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" + "Man:\"ssdp:discover\"\r\n" + "MX:3\r\n" + "\r\n"; - QString data = "M-SEARCH * HTTP/1.1\r\n" - "Host:239.255.255.250:1900\r\n" - "ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" - "Man:\"ssdp:discover\"\r\n" - "MX:3\r\n" - "\r\n"; + // Bind the socket to a certain port + bool success = m_pSocket->bind(bindPort); + if(!success) + { + qDebug() << "UPnP::SsdpConnection: failed to bind to port " << bindPort << "." << endl; + } - // Bind the socket to a certain port - bool success = m_pSocket->bind(bindPort); - if(! success) - { - qDebug() << "UPnP::SsdpConnection: failed to bind to port " << bindPort << "." << endl; - } + // Send the data + QByteArray dataBlock = data.toUtf8(); + int bytesWritten = m_pSocket->writeDatagram(dataBlock.data(), dataBlock.size(), address, 1900); - // Send the data - QByteArray dataBlock = data.toUtf8(); - int bytesWritten = m_pSocket->writeDatagram(dataBlock.data(), dataBlock.size(), address, 1900); - - if(bytesWritten == -1) - { - qDebug() << "UPnP::SsdpConnection: failed to send the UPnP broadcast packet." << endl; + if(bytesWritten == -1) + { + qDebug() << "UPnP::SsdpConnection: failed to send the UPnP broadcast packet." << endl; + } } -} - - -} // end of namespace +} // end of namespace diff --git a/src/modules/upnp/SsdpConnection.h b/src/modules/upnp/SsdpConnection.h index d9a279060..0068f2f25 100644 --- a/src/modules/upnp/SsdpConnection.h +++ b/src/modules/upnp/SsdpConnection.h @@ -41,8 +41,7 @@ class QUdpSocket; namespace UPnP { - -/** + /** * The Simple Service Discovery Protocol allows UPnP clients * to discover UPnP devices on a network. * This is achieved by broadcasting a HTTP-like message over UDP. @@ -53,27 +52,26 @@ namespace UPnP * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class SsdpConnection : public QObject -{ - Q_OBJECT + class SsdpConnection : public QObject + { + Q_OBJECT public: - SsdpConnection(); - virtual ~SsdpConnection(); + SsdpConnection(); + virtual ~SsdpConnection(); - void queryDevices(int bindPort = 1500); + void queryDevices(int bindPort = 1500); private slots: - // Data was received by the socket - void slotDataReceived(); + // Data was received by the socket + void slotDataReceived(); private: - QUdpSocket *m_pSocket; + QUdpSocket * m_pSocket; signals: - // Called when a query completed - void deviceFound(const QString &hostname, int port, const QString &rootUrl); -}; - + // Called when a query completed + void deviceFound(const QString & hostname, int port, const QString & rootUrl); + }; } #endif diff --git a/src/modules/upnp/WanConnectionService.cpp b/src/modules/upnp/WanConnectionService.cpp index 9073bb89a..8fa5f1753 100644 --- a/src/modules/upnp/WanConnectionService.cpp +++ b/src/modules/upnp/WanConnectionService.cpp @@ -37,163 +37,138 @@ namespace UPnP { - -// The constructor -WanConnectionService::WanConnectionService(const ServiceParameters ¶ms) -: Service(params) -, m_bNatEnabled(false) -{ - -} - - -// The destructor -WanConnectionService::~WanConnectionService() -{ - -} - - - -// Add a port mapping -void WanConnectionService::addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort, - const QString &internalClient, int internalPort, const QString &description, - bool enabled, int leaseDuration) -{ - QMap<QString,QString> arguments; - arguments["NewProtocol"] = protocol; - arguments["NewRemoteHost"] = remoteHost; - arguments["NewExternalPort"] = QString::number(externalPort); - arguments["NewInternalClient"] = internalClient; - arguments["NewInternalPort"] = QString::number(internalPort); - arguments["NewPortMappingDescription"] = description; - arguments["NewEnabled"] = QString::number(enabled ? 1 : 0); - arguments["NewLeaseDuration"] = QString::number(leaseDuration); - callAction("AddPortMapping", arguments, "m"); -} - - - -// Delete a port mapping -void WanConnectionService::deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort) -{ - QMap<QString,QString> arguments; - arguments["NewProtocol"] = protocol; - arguments["NewRemoteHost"] = remoteHost; - arguments["NewExternalPort"] = QString::number(externalPort); - callAction("DeletePortMapping", arguments, "m"); -} - - - -// Return the external IP address -QString WanConnectionService::getExternalIpAddress() const -{ - return m_szExternalIpAddress; -} - - - -// Return true if NAT is enabled -bool WanConnectionService::getNatEnabled() const -{ - return m_bNatEnabled; -} - - - -// Return the port mappings -const KviPointerList<PortMapping>& WanConnectionService::getPortMappings() const -{ - return m_lPortMappings; -} - - - -// The control point received a response to callAction() -void WanConnectionService::gotActionResponse(const QString &responseType, const QMap<QString,QString> &resultValues) -{ - qDebug() << "UPnP::WanConnectionService: parsing action response:" - << " type='" << responseType << "'." << endl; - - // Check the message type - if(responseType == "GetExternalIPAddressResponse") + // The constructor + WanConnectionService::WanConnectionService(const ServiceParameters & params) + : Service(params), m_bNatEnabled(false) { - // Get the external IP address from the response - m_szExternalIpAddress = resultValues["NewExternalIPAddress"]; - - qDebug() << "UPnP::WanConnectionService: externalIp='" << m_szExternalIpAddress << "'." << endl; } - else if(responseType == "GetNATRSIPStatusResponse") - { - // Get the nat status from the response - m_bNatEnabled = (resultValues["NewNATEnabled"] == "1"); - qDebug() << "UPnP::WanConnectionService: natEnabled=" << m_bNatEnabled << "." << endl; - } - else if(responseType == "GetGenericPortMappingEntryResponse") + // The destructor + WanConnectionService::~WanConnectionService() { - // Find a place to store the data - PortMapping *map = new PortMapping; - - // Get the port mapping data from the response - map->enabled = (resultValues["NewEnabled"] == "1"); - map->externalPort = resultValues["NewExternalPort"].toInt(); - map->internalClient = resultValues["NewInternalClient"]; - map->internalPort = resultValues["NewInternalPort"].toInt(); - map->leaseDuration = resultValues["NewLeaseDuration"].toInt(); - map->description = resultValues["NewPortMappingDescription"]; - map->protocol = resultValues["NewProtocol"]; - map->remoteHost = resultValues["NewRemoteHost"]; - - // Register the mapping - m_lPortMappings.append(map); + } - qDebug() << "UPnP::WanConnectionService - Received mapping: " << map->protocol << " " << map->remoteHost << ":" << map->externalPort - << " to " << map->internalClient << ":" << map->internalPort - << " max " << map->leaseDuration << "s '" << map->description << "' " << (map->enabled ? "enabled" : "disabled") << endl; + // Add a port mapping + void WanConnectionService::addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, + const QString & internalClient, int internalPort, const QString & description, + bool enabled, int leaseDuration) + { + QMap<QString, QString> arguments; + arguments["NewProtocol"] = protocol; + arguments["NewRemoteHost"] = remoteHost; + arguments["NewExternalPort"] = QString::number(externalPort); + arguments["NewInternalClient"] = internalClient; + arguments["NewInternalPort"] = QString::number(internalPort); + arguments["NewPortMappingDescription"] = description; + arguments["NewEnabled"] = QString::number(enabled ? 1 : 0); + arguments["NewLeaseDuration"] = QString::number(leaseDuration); + callAction("AddPortMapping", arguments, "m"); } - else if(responseType == "AddPortMappingResponse") + + // Delete a port mapping + void WanConnectionService::deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort) { - qDebug() << "UPnP::WanConnectionService - Received mapping enabled" << endl; + QMap<QString, QString> arguments; + arguments["NewProtocol"] = protocol; + arguments["NewRemoteHost"] = remoteHost; + arguments["NewExternalPort"] = QString::number(externalPort); + callAction("DeletePortMapping", arguments, "m"); } - else if(responseType == "DeletePortMappingResponse") + + // Return the external IP address + QString WanConnectionService::getExternalIpAddress() const { - qDebug() << "UPnP::WanConnectionService - Received mapping disabled" << endl; + return m_szExternalIpAddress; } - else + + // Return true if NAT is enabled + bool WanConnectionService::getNatEnabled() const { - qDebug() << "UPnP::WanConnectionService - Unexpected response type" - << " '" << responseType << "' encountered." << endl; + return m_bNatEnabled; } -} + // Return the port mappings + const KviPointerList<PortMapping> & WanConnectionService::getPortMappings() const + { + return m_lPortMappings; + } + // The control point received a response to callAction() + void WanConnectionService::gotActionResponse(const QString & responseType, const QMap<QString, QString> & resultValues) + { + qDebug() << "UPnP::WanConnectionService: parsing action response:" + << " type='" << responseType << "'." << endl; -// Query for the external IP address -void WanConnectionService::queryExternalIpAddress() -{ - callAction("GetExternalIPAddress", "u"); -} + // Check the message type + if(responseType == "GetExternalIPAddressResponse") + { + // Get the external IP address from the response + m_szExternalIpAddress = resultValues["NewExternalIPAddress"]; + qDebug() << "UPnP::WanConnectionService: externalIp='" << m_szExternalIpAddress << "'." << endl; + } + else if(responseType == "GetNATRSIPStatusResponse") + { + // Get the nat status from the response + m_bNatEnabled = (resultValues["NewNATEnabled"] == "1"); + qDebug() << "UPnP::WanConnectionService: natEnabled=" << m_bNatEnabled << "." << endl; + } + else if(responseType == "GetGenericPortMappingEntryResponse") + { + // Find a place to store the data + PortMapping * map = new PortMapping; -// Query for the Nat status -void WanConnectionService::queryNatEnabled() -{ - callAction("GetNATRSIPStatus", "u"); -} + // Get the port mapping data from the response + map->enabled = (resultValues["NewEnabled"] == "1"); + map->externalPort = resultValues["NewExternalPort"].toInt(); + map->internalClient = resultValues["NewInternalClient"]; + map->internalPort = resultValues["NewInternalPort"].toInt(); + map->leaseDuration = resultValues["NewLeaseDuration"].toInt(); + map->description = resultValues["NewPortMappingDescription"]; + map->protocol = resultValues["NewProtocol"]; + map->remoteHost = resultValues["NewRemoteHost"]; + // Register the mapping + m_lPortMappings.append(map); + qDebug() << "UPnP::WanConnectionService - Received mapping: " << map->protocol << " " << map->remoteHost << ":" << map->externalPort + << " to " << map->internalClient << ":" << map->internalPort + << " max " << map->leaseDuration << "s '" << map->description << "' " << (map->enabled ? "enabled" : "disabled") << endl; + } + else if(responseType == "AddPortMappingResponse") + { + qDebug() << "UPnP::WanConnectionService - Received mapping enabled" << endl; + } + else if(responseType == "DeletePortMappingResponse") + { + qDebug() << "UPnP::WanConnectionService - Received mapping disabled" << endl; + } + else + { + qDebug() << "UPnP::WanConnectionService - Unexpected response type" + << " '" << responseType << "' encountered." << endl; + } + } -// Query for a port mapping entry -void WanConnectionService::queryPortMappingEntry(int index) -{ - QMap<QString,QString> arguments; - arguments["NewPortMappingIndex"] = QString::number(index); - callAction("GetGenericPortMappingEntry", arguments, "m"); -} + // Query for the external IP address + void WanConnectionService::queryExternalIpAddress() + { + callAction("GetExternalIPAddress", "u"); + } + // Query for the Nat status + void WanConnectionService::queryNatEnabled() + { + callAction("GetNATRSIPStatus", "u"); + } + // Query for a port mapping entry + void WanConnectionService::queryPortMappingEntry(int index) + { + QMap<QString, QString> arguments; + arguments["NewPortMappingIndex"] = QString::number(index); + callAction("GetGenericPortMappingEntry", arguments, "m"); + } } // End of namespace diff --git a/src/modules/upnp/WanConnectionService.h b/src/modules/upnp/WanConnectionService.h index c39c06a85..24e306dff 100644 --- a/src/modules/upnp/WanConnectionService.h +++ b/src/modules/upnp/WanConnectionService.h @@ -40,20 +40,19 @@ namespace UPnP { -struct PortMapping -{ - QString protocol; - QString remoteHost; - int externalPort; - QString internalClient; - int internalPort; - int leaseDuration; - QString description; - bool enabled; -}; - + struct PortMapping + { + QString protocol; + QString remoteHost; + int externalPort; + QString internalClient; + int internalPort; + int leaseDuration; + QString description; + bool enabled; + }; -/** + /** * The Wan(IP/PPP)Connection service controls the connection and port forwarding settings of a router. * The Layer3ForwardingService result either defines a WanIPConnection or WanPPPConnection service. * Which one is returned depends on the external connection type. @@ -63,52 +62,47 @@ struct PortMapping * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class WanConnectionService : public Service -{ -public: // public methods - - // The constructor - WanConnectionService(const ServiceParameters ¶ms); - // The destructor - virtual ~WanConnectionService(); - - // Add a port mapping - void addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort, - const QString &internalClient, int internalPort, const QString &description, - bool enabled = true, int leaseDuration = 0); - // Delete a port mapping - void deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort); - - // Return the external IP address - QString getExternalIpAddress() const; - // Return true if NAT is enabled - bool getNatEnabled() const; - // Return the port mappings - const KviPointerList<PortMapping>& getPortMappings() const; - - // Query for the external IP address - void queryExternalIpAddress(); - // Query for the Nat status - void queryNatEnabled(); - // Query for a port mapping entry - void queryPortMappingEntry(int index); - + class WanConnectionService : public Service + { + public: // public methods + // The constructor + WanConnectionService(const ServiceParameters & params); + // The destructor + virtual ~WanConnectionService(); -protected: // protected methods + // Add a port mapping + void addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, + const QString & internalClient, int internalPort, const QString & description, + bool enabled = true, int leaseDuration = 0); + // Delete a port mapping + void deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort); - // The control point received a response to callAction() - virtual void gotActionResponse(const QString &responseType, const QMap<QString,QString> &resultValues); + // Return the external IP address + QString getExternalIpAddress() const; + // Return true if NAT is enabled + bool getNatEnabled() const; + // Return the port mappings + const KviPointerList<PortMapping> & getPortMappings() const; + // Query for the external IP address + void queryExternalIpAddress(); + // Query for the Nat status + void queryNatEnabled(); + // Query for a port mapping entry + void queryPortMappingEntry(int index); -private: // private attributes - // The external IP address - QString m_szExternalIpAddress; - // True if NAT is enabled - bool m_bNatEnabled; - // The current port mappings - KviPointerList<PortMapping> m_lPortMappings; -}; + protected: // protected methods + // The control point received a response to callAction() + virtual void gotActionResponse(const QString & responseType, const QMap<QString, QString> & resultValues); + private: // private attributes + // The external IP address + QString m_szExternalIpAddress; + // True if NAT is enabled + bool m_bNatEnabled; + // The current port mappings + KviPointerList<PortMapping> m_lPortMappings; + }; } #endif diff --git a/src/modules/upnp/XmlFunctions.cpp b/src/modules/upnp/XmlFunctions.cpp index 39927fe74..c2d7caf6b 100644 --- a/src/modules/upnp/XmlFunctions.cpp +++ b/src/modules/upnp/XmlFunctions.cpp @@ -35,92 +35,84 @@ #include <QStringList> - // Helper function, get a specific node -QDomNode XmlFunctions::getNode( const QDomNode &rootNode, const QString &path ) +QDomNode XmlFunctions::getNode(const QDomNode & rootNode, const QString & path) { - QStringList pathItems = path.split( "/", QString::SkipEmptyParts ); - QDomNode childNode = rootNode.namedItem( pathItems[0] ); // can be a null node + QStringList pathItems = path.split("/", QString::SkipEmptyParts); + QDomNode childNode = rootNode.namedItem(pathItems[0]); // can be a null node - int i = 1; - while( i < pathItems.count() ) - { - if( childNode.isNull() ) - { - break; - } + int i = 1; + while(i < pathItems.count()) + { + if(childNode.isNull()) + { + break; + } - childNode = childNode.namedItem( pathItems[ i ] ); - i++; // not using for loop so i is always correct for kdDebug() below. - } + childNode = childNode.namedItem(pathItems[i]); + i++; // not using for loop so i is always correct for kdDebug() below. + } - if( childNode.isNull() ) { - qDebug() << "XmlFunctions::getNode() - Notice: node '" << pathItems[ i - 1 ] << "'" - << " does not exist (root=" << rootNode.nodeName() << " path=" << path << ")." << endl; - } + if(childNode.isNull()) + { + qDebug() << "XmlFunctions::getNode() - Notice: node '" << pathItems[i - 1] << "'" + << " does not exist (root=" << rootNode.nodeName() << " path=" << path << ")." << endl; + } - return childNode; + return childNode; } - - // Helper function, get the attribute text of a node -QString XmlFunctions::getNodeAttribute( const QDomNode &node, const QString &attribute ) +QString XmlFunctions::getNodeAttribute(const QDomNode & node, const QString & attribute) { - // Writing this is not funny - return node.attributes().namedItem( attribute ).toAttr().value(); -// node.toElement().attribute( attribute ); does not work for const nodes. + // Writing this is not funny + return node.attributes().namedItem(attribute).toAttr().value(); + // node.toElement().attribute( attribute ); does not work for const nodes. } - - // Helper function, get a specific child node -QDomNode XmlFunctions::getNodeChildByKey( const QDomNodeList &childNodes, const QString &keyTagName, const QString &keyValue ) +QDomNode XmlFunctions::getNodeChildByKey(const QDomNodeList & childNodes, const QString & keyTagName, const QString & keyValue) { - for( int i = 0; i < childNodes.count(); i++ ) - { -// kdDebug() << "node " << childNodes.item(i).nodeName() << "/" << keyTagName -// << "=" << childNodes.item(i).namedItem(keyTagName).toElement().text() << " == " << keyValue << "?" << endl; + for(int i = 0; i < childNodes.count(); i++) + { + // kdDebug() << "node " << childNodes.item(i).nodeName() << "/" << keyTagName + // << "=" << childNodes.item(i).namedItem(keyTagName).toElement().text() << " == " << keyValue << "?" << endl; - // If the node has an childname with a certain value... e.g. <childNodes> <item><name>value</name></item> .. </childNodes> - if( childNodes.item( i ).namedItem( keyTagName ).toElement().text() == keyValue) - { - // Return the node - return childNodes.item( i ); - } - } + // If the node has an childname with a certain value... e.g. <childNodes> <item><name>value</name></item> .. </childNodes> + if(childNodes.item(i).namedItem(keyTagName).toElement().text() == keyValue) + { + // Return the node + return childNodes.item(i); + } + } - // Return a null node (is there a better way?) - return childNodes.item( childNodes.count() ); + // Return a null node (is there a better way?) + return childNodes.item(childNodes.count()); } - - // Helper function, get the text value of a node -QString XmlFunctions::getNodeValue( const QDomNode &rootNode, const QString &path ) +QString XmlFunctions::getNodeValue(const QDomNode & rootNode, const QString & path) { - // Added code to avoid more assertion errors, and trace the cause. - if( rootNode.isNull() ) - { - qWarning() << "XmlFunctions::getNodeValue: attempted to request '" << path << "' on null root node." << endl; - return QString(); - } + // Added code to avoid more assertion errors, and trace the cause. + if(rootNode.isNull()) + { + qWarning() << "XmlFunctions::getNodeValue: attempted to request '" << path << "' on null root node." << endl; + return QString(); + } - - // Because writing node.namedItem("childItem").namedItem("child2").toElement().text() is not funny. - return getNode( rootNode, path ).toElement().text(); + // Because writing node.namedItem("childItem").namedItem("child2").toElement().text() is not funny. + return getNode(rootNode, path).toElement().text(); } - // Helper function, get the source XML of a node. -QString XmlFunctions::getSource( const QDomNode &node, int indent ) +QString XmlFunctions::getSource(const QDomNode & node, int indent) { - QString source; - QTextStream textStream( &source, QIODevice::WriteOnly ); - node.save( textStream, indent ); - return source; + QString source; + QTextStream textStream(&source, QIODevice::WriteOnly); + node.save(textStream, indent); + return source; } diff --git a/src/modules/upnp/XmlFunctions.h b/src/modules/upnp/XmlFunctions.h index b57361b2d..0d435b859 100644 --- a/src/modules/upnp/XmlFunctions.h +++ b/src/modules/upnp/XmlFunctions.h @@ -45,18 +45,18 @@ */ class XmlFunctions { - public: - // Helper function, get a specific node - static QDomNode getNode(const QDomNode &rootNode, const QString &path); - // Helper function, get the attribute text of a node - static QString getNodeAttribute(const QDomNode &node, const QString &attribute); - // Helper function, get a specific child node - static QDomNode getNodeChildByKey(const QDomNodeList &childNodes, - const QString &keyTagName, const QString &keyValue); - // Helper function, get the text value of a node - static QString getNodeValue(const QDomNode &rootNode, const QString &path); - // Helper function, get the source XML of a node. - static QString getSource( const QDomNode &node, int indent = 0 ); +public: + // Helper function, get a specific node + static QDomNode getNode(const QDomNode & rootNode, const QString & path); + // Helper function, get the attribute text of a node + static QString getNodeAttribute(const QDomNode & node, const QString & attribute); + // Helper function, get a specific child node + static QDomNode getNodeChildByKey(const QDomNodeList & childNodes, + const QString & keyTagName, const QString & keyValue); + // Helper function, get the text value of a node + static QString getNodeValue(const QDomNode & rootNode, const QString & path); + // Helper function, get the source XML of a node. + static QString getSource(const QDomNode & node, int indent = 0); }; #endif diff --git a/src/modules/upnp/igdcontrolpoint.cpp b/src/modules/upnp/igdcontrolpoint.cpp index 7ed70ed92..686d576ca 100644 --- a/src/modules/upnp/igdcontrolpoint.cpp +++ b/src/modules/upnp/igdcontrolpoint.cpp @@ -41,132 +41,124 @@ namespace UPnP { -#define WanIpConnectionType "urn:schemas-upnp-org:service:WANIPConnection:1" -#define WanPPPConnectionType "urn:schemas-upnp-org:service:WANPPPConnection:1" +#define WanIpConnectionType "urn:schemas-upnp-org:service:WANIPConnection:1" +#define WanPPPConnectionType "urn:schemas-upnp-org:service:WANPPPConnection:1" -// The constructor -IgdControlPoint::IgdControlPoint(const QString &hostname, int port, const QString &rootUrl) -: QObject() -, m_bGatewayAvailable(false) -, m_iIgdPort(0) -, m_pRootService(0) -, m_pWanConnectionService(0) -{ - qDebug() << "CREATED UPnP::IgdControlPoint: created control point" - << " url='" << hostname << ":" << port << "/" << rootUrl << "'." << endl; - - qDebug() << "UPnP::IgdControlPoint: querying services..." << endl; - - // Store device url - m_szIgdHostname = hostname; - m_iIgdPort = port; - - // Query the device for it's services - m_pRootService = new RootService(m_szIgdHostname, m_iIgdPort, rootUrl); - connect(m_pRootService, SIGNAL(queryFinished(bool)), this, SLOT(slotDeviceQueried(bool))); -} + // The constructor + IgdControlPoint::IgdControlPoint(const QString & hostname, int port, const QString & rootUrl) + : QObject(), m_bGatewayAvailable(false), m_iIgdPort(0), m_pRootService(0), m_pWanConnectionService(0) + { + qDebug() << "CREATED UPnP::IgdControlPoint: created control point" + << " url='" << hostname << ":" << port << "/" << rootUrl << "'." << endl; + qDebug() << "UPnP::IgdControlPoint: querying services..." << endl; + // Store device url + m_szIgdHostname = hostname; + m_iIgdPort = port; -// The destructor -IgdControlPoint::~IgdControlPoint() -{ - delete m_pRootService; - delete m_pWanConnectionService; - - qDebug() << "DESTROYED UPnP::IgdControlPoint [host=" << m_szIgdHostname << ", port=" << m_iIgdPort << "]" << endl; -} + // Query the device for it's services + m_pRootService = new RootService(m_szIgdHostname, m_iIgdPort, rootUrl); + connect(m_pRootService, SIGNAL(queryFinished(bool)), this, SLOT(slotDeviceQueried(bool))); + } + // The destructor + IgdControlPoint::~IgdControlPoint() + { + delete m_pRootService; + delete m_pWanConnectionService; + qDebug() << "DESTROYED UPnP::IgdControlPoint [host=" << m_szIgdHostname << ", port=" << m_iIgdPort << "]" << endl; + } -// Return the external IP address -QString IgdControlPoint::getExternalIpAddress() const -{ - // Do not expose wanConnectionService_; - if(m_pWanConnectionService != 0) + // Return the external IP address + QString IgdControlPoint::getExternalIpAddress() const { - return m_pWanConnectionService->getExternalIpAddress(); - } else { - return QString(); + // Do not expose wanConnectionService_; + if(m_pWanConnectionService != 0) + { + return m_pWanConnectionService->getExternalIpAddress(); + } + else + { + return QString(); + } } -} - - -// Initialize the control point -void IgdControlPoint::initialize() -{ - m_pRootService->queryDevice(); -} - - - -// Return true if a controlable gateway is available -bool IgdControlPoint::isGatewayAvailable() -{ - return m_bGatewayAvailable; -} + // Initialize the control point + void IgdControlPoint::initialize() + { + m_pRootService->queryDevice(); + } + // Return true if a controlable gateway is available + bool IgdControlPoint::isGatewayAvailable() + { + return m_bGatewayAvailable; + } -// The IGD was queried for it's services -void IgdControlPoint::slotDeviceQueried(bool error) -{ - if(! error) + // The IGD was queried for it's services + void IgdControlPoint::slotDeviceQueried(bool error) { - ServiceParameters params = m_pRootService->getServiceByType(WanIpConnectionType); + if(!error) + { + ServiceParameters params = m_pRootService->getServiceByType(WanIpConnectionType); - if(params.controlUrl.isNull()) - params = m_pRootService->getServiceByType(WanPPPConnectionType); + if(params.controlUrl.isNull()) + params = m_pRootService->getServiceByType(WanPPPConnectionType); - if(! params.controlUrl.isNull()) - { + if(!params.controlUrl.isNull()) + { - m_bGatewayAvailable = true; + m_bGatewayAvailable = true; - qDebug() << "UPnP::IgdControlPoint: WAN/IP connection service found, " - << "querying service '" << params.serviceId << "' for external IP address..." << endl; + qDebug() << "UPnP::IgdControlPoint: WAN/IP connection service found, " + << "querying service '" << params.serviceId << "' for external IP address..." << endl; - // Call the service - m_pWanConnectionService = new WanConnectionService(params); - connect(m_pWanConnectionService, SIGNAL(queryFinished(bool)), this, SLOT(slotWanQueryFinished(bool))); - m_pWanConnectionService->queryExternalIpAddress(); - } else { - qDebug() << "UPnP::IgdControlPoint: no PPP/IP connection service found :(" << endl; + // Call the service + m_pWanConnectionService = new WanConnectionService(params); + connect(m_pWanConnectionService, SIGNAL(queryFinished(bool)), this, SLOT(slotWanQueryFinished(bool))); + m_pWanConnectionService->queryExternalIpAddress(); + } + else + { + qDebug() << "UPnP::IgdControlPoint: no PPP/IP connection service found :(" << endl; + } } } -} - -// A WAN connection query was finished -void IgdControlPoint::slotWanQueryFinished(bool error) -{ - if(! error) + // A WAN connection query was finished + void IgdControlPoint::slotWanQueryFinished(bool error) { - qDebug() << "IgdControlPoint: UPnP gateway device found." << endl; - } else { - // Just started, the request for the external IP failed. This should succeed, abort portation - qDebug() << "Requesting external IP address failed, leaving UPnP gateway device untouched." << endl; + if(!error) + { + qDebug() << "IgdControlPoint: UPnP gateway device found." << endl; + } + else + { + // Just started, the request for the external IP failed. This should succeed, abort portation + qDebug() << "Requesting external IP address failed, leaving UPnP gateway device untouched." << endl; + } } -} -// Return the external IP address -void IgdControlPoint::addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort,const QString &internalClient, int internalPort, const QString &description, bool enabled, int leaseDuration) -{ - // Do not expose wanConnectionService_; - if(m_pWanConnectionService != 0) + // Return the external IP address + void IgdControlPoint::addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, const QString & internalClient, int internalPort, const QString & description, bool enabled, int leaseDuration) { - m_pWanConnectionService->addPortMapping(protocol, remoteHost, externalPort, internalClient, internalPort, description, enabled, leaseDuration); + // Do not expose wanConnectionService_; + if(m_pWanConnectionService != 0) + { + m_pWanConnectionService->addPortMapping(protocol, remoteHost, externalPort, internalClient, internalPort, description, enabled, leaseDuration); + } } -} -// Delete a port mapping -void IgdControlPoint::deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort) -{ - // Do not expose wanConnectionService_; - if(m_pWanConnectionService != 0) + // Delete a port mapping + void IgdControlPoint::deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort) { - m_pWanConnectionService->deletePortMapping(protocol, remoteHost, externalPort); + // Do not expose wanConnectionService_; + if(m_pWanConnectionService != 0) + { + m_pWanConnectionService->deletePortMapping(protocol, remoteHost, externalPort); + } } -} -} // End of namespace +} // End of namespace diff --git a/src/modules/upnp/igdcontrolpoint.h b/src/modules/upnp/igdcontrolpoint.h index 7968aa949..91c46e1e4 100644 --- a/src/modules/upnp/igdcontrolpoint.h +++ b/src/modules/upnp/igdcontrolpoint.h @@ -39,11 +39,11 @@ namespace UPnP { -class SsdpConnection; -class RootService; -class WanConnectionService; + class SsdpConnection; + class RootService; + class WanConnectionService; -/** + /** * A control point is a UPnP term for "client". * It's the host that controls the UPnP device. * This control point specifically handles Internet Gateway Devices (routers in UPnP terminology). @@ -53,49 +53,46 @@ class WanConnectionService; * @author Diederik van der Boor * @ingroup NetworkUPnP */ -class IgdControlPoint : public QObject -{ - Q_OBJECT - -public: // public methods - - // The constructor - IgdControlPoint(const QString &hostname, int port, const QString &rootUrl); - // The destructor - virtual ~IgdControlPoint(); - - // Return the external IP address - QString getExternalIpAddress() const; - // Initialize the control point - void initialize(); - // Return true if a controlable gateway is available - bool isGatewayAvailable(); + class IgdControlPoint : public QObject + { + Q_OBJECT - // Add a port mapping - void addPortMapping(const QString &protocol, const QString &remoteHost, int externalPort, const QString &internalClient, int internalPort, const QString &description, bool enabled = true, int leaseDuration = 0); - // Delete a port mapping - void deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort); + public: // public methods + // The constructor + IgdControlPoint(const QString & hostname, int port, const QString & rootUrl); + // The destructor + virtual ~IgdControlPoint(); -private slots: - // The IGD was queried for it's services - void slotDeviceQueried(bool error); - // A WAN connection query was finished - void slotWanQueryFinished(bool error); + // Return the external IP address + QString getExternalIpAddress() const; + // Initialize the control point + void initialize(); + // Return true if a controlable gateway is available + bool isGatewayAvailable(); -private: // private attibutes - // Is a gateway available? - bool m_bGatewayAvailable; - // The host of the gateway - QString m_szIgdHostname; - // The port of the gateway - int m_iIgdPort; - // The root service - RootService *m_pRootService; - // The wan connection service - WanConnectionService *m_pWanConnectionService; -}; + // Add a port mapping + void addPortMapping(const QString & protocol, const QString & remoteHost, int externalPort, const QString & internalClient, int internalPort, const QString & description, bool enabled = true, int leaseDuration = 0); + // Delete a port mapping + void deletePortMapping(const QString & protocol, const QString & remoteHost, int externalPort); + private slots: + // The IGD was queried for it's services + void slotDeviceQueried(bool error); + // A WAN connection query was finished + void slotWanQueryFinished(bool error); + private: // private attibutes + // Is a gateway available? + bool m_bGatewayAvailable; + // The host of the gateway + QString m_szIgdHostname; + // The port of the gateway + int m_iIgdPort; + // The root service + RootService * m_pRootService; + // The wan connection service + WanConnectionService * m_pWanConnectionService; + }; } #endif diff --git a/src/modules/upnp/libkviupnp.cpp b/src/modules/upnp/libkviupnp.cpp index bd04abf84..880b1b70c 100644 --- a/src/modules/upnp/libkviupnp.cpp +++ b/src/modules/upnp/libkviupnp.cpp @@ -31,7 +31,7 @@ // Please use our common variable naming conventions and coding style :) // Let's be so:) -UPnP::Manager* g_pManager = 0; +UPnP::Manager * g_pManager = 0; /* @doc: upnp.getExternalIpAddress @@ -55,12 +55,11 @@ static bool upnp_kvs_fnc_getExternalIpAddress(KviKvsModuleFunctionCall * c) { if(g_pManager) { - c->returnValue()->setString(g_pManager->getExternalIpAddress()); + c->returnValue()->setString(g_pManager->getExternalIpAddress()); } return true; } - /* @doc: upnp.isGatewayAvailable @type: @@ -77,10 +76,10 @@ static bool upnp_kvs_fnc_getExternalIpAddress(KviKvsModuleFunctionCall * c) */ static bool upnp_kvs_fnc_isGatewayAvailable(KviKvsModuleFunctionCall * c) { - if (g_pManager) - { - c->returnValue()->setBoolean(g_pManager->isGatewayAvailable()); - } + if(g_pManager) + { + c->returnValue()->setBoolean(g_pManager->isGatewayAvailable()); + } return true; } @@ -114,13 +113,15 @@ static bool upnp_kvs_cmd_addPortMapping(KviKvsModuleCommandCall * c) KviKvsVariant * pSw; KVSM_PARAMETERS_BEGIN(c) - KVSM_PARAMETER("port",KVS_PT_INT,0,iPort) + KVSM_PARAMETER("port", KVS_PT_INT, 0, iPort) KVSM_PARAMETERS_END(c) - if( (pSw = c->switches()->find('a',"fake-address")) ) + if((pSw = c->switches()->find('a', "fake-address"))) { pSw->asString(szLocalIp); - } else { + } + else + { kvi_getLocalHostAddress(szLocalIp); } @@ -151,7 +152,7 @@ static bool upnp_kvs_cmd_delPortMapping(KviKvsModuleCommandCall * c) kvs_int_t iPort; QString tmp; KVSM_PARAMETERS_BEGIN(c) - KVSM_PARAMETER("port",KVS_PT_INT,0,iPort) + KVSM_PARAMETER("port", KVS_PT_INT, 0, iPort) KVSM_PARAMETERS_END(c) g_pManager->deletePortMapping("TCP", "", iPort); @@ -185,7 +186,7 @@ static bool upnp_kvs_cmd_refresh(KviKvsModuleCommandCall *) return true; } -static bool upnp_module_init(KviModule *m) +static bool upnp_module_init(KviModule * m) { if(g_pManager) delete g_pManager; @@ -193,11 +194,11 @@ static bool upnp_module_init(KviModule *m) g_pManager = UPnP::Manager::instance(); - KVSM_REGISTER_FUNCTION(m,"isGatewayAvailable",upnp_kvs_fnc_isGatewayAvailable); - KVSM_REGISTER_FUNCTION(m,"getExternalIpAddress",upnp_kvs_fnc_getExternalIpAddress); - KVSM_REGISTER_SIMPLE_COMMAND(m,"addPortMapping",upnp_kvs_cmd_addPortMapping); - KVSM_REGISTER_SIMPLE_COMMAND(m,"delPortMapping",upnp_kvs_cmd_delPortMapping); - KVSM_REGISTER_SIMPLE_COMMAND(m,"refresh",upnp_kvs_cmd_refresh); + KVSM_REGISTER_FUNCTION(m, "isGatewayAvailable", upnp_kvs_fnc_isGatewayAvailable); + KVSM_REGISTER_FUNCTION(m, "getExternalIpAddress", upnp_kvs_fnc_getExternalIpAddress); + KVSM_REGISTER_SIMPLE_COMMAND(m, "addPortMapping", upnp_kvs_cmd_addPortMapping); + KVSM_REGISTER_SIMPLE_COMMAND(m, "delPortMapping", upnp_kvs_cmd_delPortMapping); + KVSM_REGISTER_SIMPLE_COMMAND(m, "refresh", upnp_kvs_cmd_refresh); return true; } @@ -216,13 +217,12 @@ static bool upnp_module_can_unload(KviModule *) } KVIRC_MODULE( - "UPnP", // module name - "4.0.0", // module version - "Copyright (C) 2008 Fabio Bas (ctrlaltca at gmail dot com),", - "Universal Plug and Play", - upnp_module_init, - upnp_module_can_unload, - 0, - upnp_module_cleanup, - 0 -) + "UPnP", // module name + "4.0.0", // module version + "Copyright (C) 2008 Fabio Bas (ctrlaltca at gmail dot com),", + "Universal Plug and Play", + upnp_module_init, + upnp_module_can_unload, + 0, + upnp_module_cleanup, + 0) |
