aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/CMakeLists.txt4
-rw-r--r--src/modules/upnp/CMakeLists.txt30
-rw-r--r--src/modules/upnp/igdcontrolpoint.cpp190
-rw-r--r--src/modules/upnp/igdcontrolpoint.h100
-rw-r--r--src/modules/upnp/layer3forwardingservice.cpp137
-rw-r--r--src/modules/upnp/layer3forwardingservice.h84
-rw-r--r--src/modules/upnp/libkviupnp.cpp77
-rw-r--r--src/modules/upnp/manager.cpp154
-rw-r--r--src/modules/upnp/manager.h110
-rw-r--r--src/modules/upnp/rootservice.cpp281
-rw-r--r--src/modules/upnp/rootservice.h100
-rw-r--r--src/modules/upnp/service.cpp286
-rw-r--r--src/modules/upnp/service.h128
-rw-r--r--src/modules/upnp/ssdpconnection.cpp134
-rw-r--r--src/modules/upnp/ssdpconnection.h78
-rw-r--r--src/modules/upnp/wanconnectionservice.cpp192
-rw-r--r--src/modules/upnp/wanconnectionservice.h113
-rw-r--r--src/modules/upnp/xmlfunctions.cpp126
-rw-r--r--src/modules/upnp/xmlfunctions.h61
19 files changed, 2383 insertions, 2 deletions
diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt
index 7eb6aee5e..b6f617e87 100644
--- a/src/modules/CMakeLists.txt
+++ b/src/modules/CMakeLists.txt
@@ -36,7 +36,7 @@ SUBDIRS(
serverdb setup sharedfile sharedfileswindow
snd socketspy spaste str system
texticons term theme tip tmphighlight toolbar toolbareditor trayicon
- url
+ upnp url
window
# broken modules
@@ -54,4 +54,4 @@ SUBDIRS(
IF(NOT MINGW)
ADD_SUBDIRECTORY(rijndael)
-ENDIF() \ No newline at end of file
+ENDIF()
diff --git a/src/modules/upnp/CMakeLists.txt b/src/modules/upnp/CMakeLists.txt
new file mode 100644
index 000000000..9ca767097
--- /dev/null
+++ b/src/modules/upnp/CMakeLists.txt
@@ -0,0 +1,30 @@
+# CMakeLists for src/modules/upnp
+
+SET(kviupnp_SRCS
+ igdcontrolpoint.cpp
+ layer3forwardingservice.cpp
+ libkviupnp.cpp
+ manager.cpp
+ rootservice.cpp
+ service.cpp
+ ssdpconnection.cpp
+ wanconnectionservice.cpp
+ xmlfunctions.cpp
+)
+
+SET(kviupnp_MOC_HDRS
+ igdcontrolpoint.h
+ layer3forwardingservice.h
+ manager.h
+ rootservice.h
+ service.h
+ ssdpconnection.h
+ wanconnectionservice.h
+ xmlfunctions.h
+)
+
+# After this call, files will be moc'ed to moc_kvi_*.cpp
+QT4_WRAP_CPP(kviupnp_MOC_SRCS ${kviupnp_MOC_HDRS})
+
+SET(kvi_module_name kviupnp)
+INCLUDE(${CMAKE_SOURCE_DIR}/cmake/module.rules.txt)
diff --git a/src/modules/upnp/igdcontrolpoint.cpp b/src/modules/upnp/igdcontrolpoint.cpp
new file mode 100644
index 000000000..9c0dde69e
--- /dev/null
+++ b/src/modules/upnp/igdcontrolpoint.cpp
@@ -0,0 +1,190 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ igdcontrolpoint.cpp - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include <QDebug>
+
+#include "igdcontrolpoint.h"
+
+#include "rootservice.h"
+#include "layer3forwardingservice.h"
+#include "wanconnectionservice.h"
+
+namespace UPnP
+{
+
+#define InternetGatewayDeviceType "urn:schemas-upnp-org:device:InternetGatewayDevice:1"
+#define Layer3ForwardingType "urn:schemas-upnp-org:service:Layer3Forwarding:1"
+
+
+// The constructor
+IgdControlPoint::IgdControlPoint(const QString &hostname, int port, const QString &rootUrl)
+ : QObject()
+ , forwardingService_(0)
+ , gatewayAvailable_(false)
+ , igdPort_(0)
+ , rootService_(0)
+ , wanConnectionService_(0)
+{
+ qDebug() << "CREATED UPnP::IgdControlPoint: Created control point"
+ << " url='" << hostname << ":" << port << "/" << rootUrl << "'." << endl;
+ qDebug() << "UPnP::IgdControlPoint: querying services..." << endl;
+
+
+ // Store device url
+ igdHostname_ = hostname;
+ igdPort_ = port;
+
+ // Query the device for it's services
+ rootService_ = new RootService(igdHostname_, igdPort_, rootUrl);
+ connect(rootService_, SIGNAL(queryFinished(bool)), this, SLOT(slotDeviceQueried(bool)));
+}
+
+
+
+// The destructor
+IgdControlPoint::~IgdControlPoint()
+{
+ delete rootService_;
+ delete forwardingService_;
+ delete wanConnectionService_;
+
+ qDebug() << "DESTROYED UPnP::IgdControlPoint [host=" << igdHostname_ << ", port=" << igdPort_ << "]" << endl;
+}
+
+
+
+// Return the external IP address
+QString IgdControlPoint::getExternalIpAddress() const
+{
+ // Do not expose wanConnectionService_;
+ if(wanConnectionService_ != 0)
+ {
+ return wanConnectionService_->getExternalIpAddress();
+ }
+ else
+ {
+ return QString::null;
+ }
+}
+
+
+
+// Initialize the control point
+void IgdControlPoint::initialize()
+{
+ rootService_->queryDevice();
+}
+
+
+
+// Return true if a controlable gateway is available
+bool IgdControlPoint::isGatewayAvailable()
+{
+ return gatewayAvailable_;
+}
+
+
+
+// The IGD was queried for it's services
+void IgdControlPoint::slotDeviceQueried(bool error)
+{
+ if(! error)
+ {
+ // Get the Layer3ForwardingService from the retrieved service list
+ ServiceParameters params = rootService_->getServiceByType(Layer3ForwardingType);
+
+ if(! params.controlUrl.isNull())
+ {
+ qDebug() << "UPnP::IgdControlPoint: Services found, "
+ << "querying service '" << params.serviceId << "' for port mapping service..." << endl;
+
+ // Call the service
+ forwardingService_ = new Layer3ForwardingService(params);
+ connect(forwardingService_, SIGNAL(queryFinished(bool)), this, SLOT(slotWanConnectionFound(bool)));
+ forwardingService_->queryDefaultConnectionService();
+ }
+ else
+ {
+ // TODO: error
+ }
+ }
+}
+
+
+
+// A WAN connection service was found
+void IgdControlPoint::slotWanConnectionFound(bool error)
+{
+ if(! error)
+ {
+ // Get the retreived service description
+ QString deviceUrn = forwardingService_->getConnectionDeviceUdn();
+ QString serviceId = forwardingService_->getConnectionServiceId();
+ ServiceParameters params = rootService_->getServiceById(serviceId, deviceUrn);
+
+ if(! params.controlUrl.isNull())
+ {
+ qDebug() << "UPnP::IgdControlPoint: wan/ipconnection service found, "
+ << "querying service '" << params.serviceId << "' for external ip address..." << endl;
+
+ // Call the service
+ wanConnectionService_ = new WanConnectionService(params);
+ connect(wanConnectionService_, SIGNAL(queryFinished(bool)), this, SLOT(slotWanQueryFinished(bool)));
+ wanConnectionService_->queryExternalIpAddress();
+ }
+ }
+
+ // No longer need the forwarding service
+ forwardingService_->deleteLater();
+ forwardingService_ = 0;
+}
+
+
+
+// A WAN connection query was finished
+void IgdControlPoint::slotWanQueryFinished(bool error)
+{
+ if(! error)
+ {
+ qDebug() << "IgdControlPoint: UPnP Gateway Device found." << endl;
+ gatewayAvailable_ = true;
+ }
+ 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;
+ }
+}
+
+
+
+} // End of namespace
diff --git a/src/modules/upnp/igdcontrolpoint.h b/src/modules/upnp/igdcontrolpoint.h
new file mode 100644
index 000000000..d2df850d6
--- /dev/null
+++ b/src/modules/upnp/igdcontrolpoint.h
@@ -0,0 +1,100 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ igdcontrolpoint.cpp - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_IGDCONTROLPOINT_H
+#define UPNP_IGDCONTROLPOINT_H
+
+#include <qobject.h>
+
+namespace UPnP
+{
+
+class SsdpConnection;
+class RootService;
+class Layer3ForwardingService;
+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).
+ * It queries the device for its port mapping service (an instance of a WanIPConnection or WanPPPConnection service).
+ * Once the service is found, it can be used from the Manager class to configure port mappings.
+ *
+ * @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();
+
+ private slots:
+ // The IGD was queried for it's services
+ void slotDeviceQueried(bool error);
+ // A WAN connection service was found
+ void slotWanConnectionFound(bool error);
+ // A WAN connection query was finished
+ void slotWanQueryFinished(bool error);
+
+ private: // private attibutes
+ // The forwarding service
+ Layer3ForwardingService *forwardingService_;
+ // Is a gateway available?
+ bool gatewayAvailable_;
+ // The host of the gateway
+ QString igdHostname_;
+ // The port of the gateway
+ int igdPort_;
+ // The root service
+ RootService *rootService_;
+ // The wan connection service
+ WanConnectionService *wanConnectionService_;
+};
+
+
+}
+
+#endif
diff --git a/src/modules/upnp/layer3forwardingservice.cpp b/src/modules/upnp/layer3forwardingservice.cpp
new file mode 100644
index 000000000..bdd62d377
--- /dev/null
+++ b/src/modules/upnp/layer3forwardingservice.cpp
@@ -0,0 +1,137 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ layer3forwardingservice.cpp - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include <QDebug>
+#include <QStringList>
+
+#include "layer3forwardingservice.h"
+
+namespace UPnP
+{
+
+// The constructor
+Layer3ForwardingService::Layer3ForwardingService(const ServiceParameters &params)
+ : Service(params)
+{
+
+}
+
+
+// The destructor
+Layer3ForwardingService::~Layer3ForwardingService()
+{
+
+}
+
+
+
+// Get the device UDN of the default connection service
+QString Layer3ForwardingService::getConnectionDeviceUdn() const
+{
+ return connectionDeviceUdn_;
+}
+
+
+
+// Get the service ID of the default connection service
+QString Layer3ForwardingService::getConnectionServiceId() const
+{
+ return connectionServiceId_;
+}
+
+
+
+// The control point received a response to callAction()
+void Layer3ForwardingService::gotActionResponse(const QString &responseType, const QMap<QString,QString> &resultValues)
+{
+ qDebug() << "UPnP::Layer3ForwardingService: Got action response"
+ << " type='" << responseType << "'." << endl;
+
+ // Example:
+ //
+ // <m:GetDefaultConnectionServiceResponse xmlns:m="urn:schemas-upnp-org:service:Layer3Forwarding:1" >
+ // <NewDefaultConnectionService>
+ // (there is no white space between these parts!)
+ // uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F_WCDpppoa:WANConnectionDevice:1,
+ // urn:upnp-org:serviceId:wanpppc:pppoa
+ // </NewDefaultConnectionService>
+ // </m:GetDefaultConnectionServiceResponse>
+
+
+ if(responseType == "GetDefaultConnectionServiceResponse" )
+ {
+ QString newService = resultValues["NewDefaultConnectionService"];
+ QStringList serviceItems = QStringList::split(',', newService);
+ QString uuid;
+ QString urn;
+
+ // Extract the uuid and urn from the NewDefaultConnectionService value
+ for(uint i = 0; i < serviceItems.count(); i++)
+ {
+ QString type = serviceItems[i].section(':', 0, 0);
+ if(type == "uuid")
+ {
+ // format: uuid:<id>:<class>:<ver>
+ connectionDeviceUdn_ = serviceItems[i].section(':', 0, 1);
+ }
+ else if(type == "urn")
+ {
+ connectionServiceId_ = serviceItems[i];
+ }
+ else
+ {
+ qDebug() << "UPnP::Layer3ForwardingService - Unexpected section"
+ << " '" << type << "' encountered in NewDefaultConnectionService value." << endl;
+ }
+ }
+
+ qDebug() << "UPnP::Layer3ForwardingService:"
+ << " udn='" << connectionDeviceUdn_ << "'"
+ << " serviceid='" << connectionServiceId_ << "'." << endl;
+ }
+ else
+ {
+ qDebug() << "UPnP::Layer3ForwardingService - Unexpected response type"
+ << " '" << responseType << "' encountered." << endl;
+ }
+}
+
+
+
+// Query the Layer3Forwarding service for the default connection service
+void Layer3ForwardingService::queryDefaultConnectionService()
+{
+ callAction("GetDefaultConnectionService");
+}
+
+
+}
diff --git a/src/modules/upnp/layer3forwardingservice.h b/src/modules/upnp/layer3forwardingservice.h
new file mode 100644
index 000000000..18edde929
--- /dev/null
+++ b/src/modules/upnp/layer3forwardingservice.h
@@ -0,0 +1,84 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ layer3forwardingservice.h - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_LAYER3FORWARDINGSERVICE_H
+#define UPNP_LAYER3FORWARDINGSERVICE_H
+
+#include "service.h"
+
+namespace UPnP {
+
+/**
+ * The Layer3Forwarding service is used to query a Internet Gateway Device (router in UPnP terms)
+ * for it's WanConnection service. This can be an instance of the WanIPConnection or WanPPPConnection service,
+ * which is implemented by the WanConnectionService class.
+ * The WanIPConnection/WanPPPConnection service can be used to configure the external connection settings and port mappings of the router.
+ * The Layer3Forwarding service itself is resolved by the RootService class.
+ *
+ * @author Diederik van der Boor
+ * @ingroup NetworkUPnP
+ */
+class Layer3ForwardingService : public Service
+{
+ public: // public methods
+
+ // The constructor
+ Layer3ForwardingService(const ServiceParameters &params);
+ // The destructor
+ virtual ~Layer3ForwardingService();
+
+ // Get the device UDN of the default connection service
+ QString getConnectionDeviceUdn() const;
+ // Get the service ID of the default connection service
+ QString getConnectionServiceId() const;
+
+ // Query the Layer3Forwarding service for the default connection service
+ void queryDefaultConnectionService();
+
+
+ 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 device UDN of the default connection service
+ QString connectionServiceId_;
+ // The service ID of the default connection service
+ QString connectionDeviceUdn_;
+};
+
+}
+
+#endif
diff --git a/src/modules/upnp/libkviupnp.cpp b/src/modules/upnp/libkviupnp.cpp
new file mode 100644
index 000000000..99fa7a795
--- /dev/null
+++ b/src/modules/upnp/libkviupnp.cpp
@@ -0,0 +1,77 @@
+//=============================================================================
+//
+// File : libkviupnp.cpp
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This math is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+//=============================================================================
+
+#include "kvi_settings.h"
+#include "kvi_module.h"
+#include "kvi_string.h"
+
+#include "manager.h"
+
+UPnP::Manager* p_manager = 0;
+
+
+static bool upnp_kvs_fnc_getExternalIpAddress(KviKvsModuleFunctionCall * c)
+{
+ QString buffer;
+
+ if(p_manager)
+ buffer = p_manager->getExternalIpAddress();
+
+ c->returnValue()->setString(buffer);
+ return true;
+}
+
+static bool upnp_kvs_cmd_test(KviKvsModuleCommandCall * c)
+{
+ return true;
+}
+
+static bool upnp_module_init(KviModule * m)
+{
+ p_manager = UPnP::Manager::instance();
+ //p_manager->initialize();
+
+ KVSM_REGISTER_FUNCTION(m,"getExternalIpAddress",upnp_kvs_fnc_getExternalIpAddress);
+ KVSM_REGISTER_SIMPLE_COMMAND(m,"test",upnp_kvs_cmd_test);
+
+ return true;
+}
+
+static bool upnp_module_cleanup(KviModule *m)
+{
+ delete p_manager;
+ p_manager = 0;
+ return true;
+}
+
+KVIRC_MODULE(
+ "Upnp", // module name
+ "4.0.0", // module version
+ "Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net),",
+ "Universal Plug and Play",
+ upnp_module_init,
+ 0,
+ 0,
+ upnp_module_cleanup
+)
diff --git a/src/modules/upnp/manager.cpp b/src/modules/upnp/manager.cpp
new file mode 100644
index 000000000..127e0a7d9
--- /dev/null
+++ b/src/modules/upnp/manager.cpp
@@ -0,0 +1,154 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ manager.cpp - description
+ -------------------
+ begin : Fri Aug 05 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "manager.h"
+
+#include "igdcontrolpoint.h"
+#include "ssdpconnection.h"
+
+#include <QDebug>
+#include <QTimer>
+
+
+namespace UPnP
+{
+
+// Set the static variable
+Manager* Manager::instance_(0);
+
+
+// The constructor
+Manager::Manager()
+ : activeIgdControlPoint_(0)
+ , broadcastFailed_(false)
+ , ssdpConnection_(0)
+ , ssdpTimer_(0)
+{
+
+}
+
+
+
+// The destructor
+Manager::~Manager()
+{
+ delete ssdpTimer_;
+ delete ssdpConnection_;
+ instance_ = 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
+ ssdpConnection_ = new SsdpConnection();
+ connect(ssdpConnection_, SIGNAL( deviceFound(const QString&,int,const QString&) ) ,
+ this, SLOT( slotDeviceFound(const QString&,int,const QString&) ) );
+
+ // Create a timer
+ ssdpTimer_ = new QTimer(this);
+ connect(ssdpTimer_, SIGNAL(timeout()), this, SLOT(slotBroadcastTimeout()));
+
+ // Start a UPnP broadcast
+ broadcastFailed_ = false;
+ ssdpConnection_->queryDevices();
+ ssdpTimer_->start(2000, true);
+}
+
+
+
+// Return the instance of the manager class
+Manager * Manager::instance()
+{
+ // Create when it's required
+ if(instance_ == 0)
+ {
+ instance_ = new Manager();
+ instance_->initialize();
+ }
+
+ return instance_;
+}
+
+
+
+// Return the external IP address
+QString Manager::getExternalIpAddress() const
+{
+ // Do not expose activeIgd_;
+ return (activeIgdControlPoint_ != 0 ? activeIgdControlPoint_->getExternalIpAddress() : QString::null);
+}
+
+
+
+// Return true if a controlable gateway is available
+bool Manager::isGatewayAvailable()
+{
+ return (activeIgdControlPoint_ != 0 &&
+ activeIgdControlPoint_->isGatewayAvailable());
+}
+
+
+
+// The broadcast failed
+void Manager::slotBroadcastTimeout()
+{
+qDebug() << "UPnP::Manager: Timeout, no broadcast response received!" << endl;
+
+ broadcastFailed_ = 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;
+
+ IgdControlPoint *controlPoint = new IgdControlPoint(hostname, port, rootUrl);
+ igdControlPoints_.append(controlPoint);
+
+ if(activeIgdControlPoint_ == 0)
+ {
+ activeIgdControlPoint_ = controlPoint;
+ activeIgdControlPoint_->initialize();
+ }
+}
+
+
+
+} // end of namespace
diff --git a/src/modules/upnp/manager.h b/src/modules/upnp/manager.h
new file mode 100644
index 000000000..b42b1c9ef
--- /dev/null
+++ b/src/modules/upnp/manager.h
@@ -0,0 +1,110 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ manager.h - description
+ -------------------
+ begin : Fri Aug 05 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNPMANAGER_H
+#define UPNPMANAGER_H
+
+#include <QObject>
+#include "kvi_pointerlist.h"
+
+class QTimer;
+
+namespace UPnP
+{
+
+class IgdControlPoint;
+class SsdpConnection;
+
+
+/**
+ * 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.
+ * Underneath, the actual work is done by the SsdpConnection and IgdControlPoint classes.
+ *
+ * @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;
+
+ // Return the instance of the manager class
+ static Manager * instance();
+
+ // Return true if a controlable gateway is available
+ bool isGatewayAvailable();
+
+ 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: // 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 *activeIgdControlPoint_;
+ // True if the broadcast failed
+ bool broadcastFailed_;
+ // The instance of the singleton class
+ static Manager *instance_;
+ // A list of all detected gateway devices
+ KviPointerList<IgdControlPoint> igdControlPoints_;
+ // The SSDP connection to find all UPnP devices
+ SsdpConnection *ssdpConnection_;
+ // The timer to detect a broadcast timeout
+ QTimer *ssdpTimer_;
+};
+
+
+} // End of namespace
+
+#endif
diff --git a/src/modules/upnp/rootservice.cpp b/src/modules/upnp/rootservice.cpp
new file mode 100644
index 000000000..57de03b11
--- /dev/null
+++ b/src/modules/upnp/rootservice.cpp
@@ -0,0 +1,281 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ rootservice.cpp - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "rootservice.h"
+#include "xmlfunctions.h"
+
+#include <QDebug>
+
+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>
+
+
+// The contructor
+RootService::RootService(const QString &hostname, int port,
+ const QString &rootUrl)
+ : Service(hostname, port, rootUrl)
+ , hostname_(hostname)
+ , port_(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;
+
+ // Insert the given device node
+ // The "key" is the device/UDN tag, the value is a list of device/serviceList/service nodes
+ deviceServices_.insert(XmlFunctions::getNodeValue(device, "/UDN"),
+ device.namedItem("serviceList").childNodes());
+
+ // Find all embedded device nodes
+ QDomNodeList embeddedDevices = device.namedItem("deviceList").childNodes();
+ for(uint i = 0; i < embeddedDevices.count(); i++)
+ {
+ if(embeddedDevices.item(i).nodeName() != "device") continue;
+ addDeviceServices(embeddedDevices.item(i));
+ }
+}
+
+
+
+// Return the device type
+QString RootService::getDeviceType() const
+{
+ return deviceType_;
+}
+
+
+
+// Return a service from the cached root device entry
+ServiceParameters RootService::getServiceById(const QString &serviceId) const
+{
+ // Get a /root/device/serviceList/service/ tag
+ return getServiceById(serviceId, rootUdn_);
+}
+
+
+
+// Return a service from a cached embedded device entry
+ServiceParameters RootService::getServiceById(const QString &serviceId, const QString &deviceUdn) const
+{
+ // Get a /root/device/deviceList/device/.../serviceList/service/serviceId tag
+ QDomNode service = XmlFunctions::getNodeChildByKey( deviceServices_[deviceUdn], "serviceId", serviceId );
+
+ // Initialize a ServiceParameters struct
+ ServiceParameters params;
+
+ if(! service.isNull())
+ {
+ params.hostname = hostname_;
+ params.port = port_;
+ params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL");
+ params.scdpUrl = XmlFunctions::getNodeValue(service, "/SCDPURL");
+ params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId");
+ } else
+ {
+ qWarning() << "UPnP::RootService::getServiceById -"
+ << " id '" << serviceId << "' not found for device '" << deviceUdn << "'." << endl;
+ }
+
+ return params;
+}
+
+
+
+// Return a service from the cached root device entry
+ServiceParameters RootService::getServiceByType(const QString &serviceType) const
+{
+ // Get a /root/device/serviceList/service/ tag
+ return getServiceByType(serviceType, rootUdn_);
+}
+
+
+
+// Return a service from a cached embedded device entry
+ServiceParameters RootService::getServiceByType(const QString &serviceType, const QString &deviceUdn) const
+{
+ // Get a /root/device/deviceList/device/.../serviceList/service/serviceType tag
+ QDomNode service = XmlFunctions::getNodeChildByKey( deviceServices_[deviceUdn], "serviceType", serviceType );
+
+ // Initialize a ServiceParameters struct
+ ServiceParameters params;
+
+ if(! service.isNull())
+ {
+ params.hostname = hostname_;
+ params.port = port_;
+ params.controlUrl = XmlFunctions::getNodeValue(service, "/controlURL");
+ params.scdpUrl = XmlFunctions::getNodeValue(service, "/SCDPURL");
+ params.serviceId = XmlFunctions::getNodeValue(service, "/serviceId");
+ } else
+ {
+ qWarning() << "UPnP::RootService::getServiceByType -"
+ << " type '" << serviceType << "' not found for device '" << deviceUdn << "'." << endl;
+ }
+
+ return params;
+}
+
+
+
+// The control point received a response to callInformationUrl()
+void RootService::gotInformationResponse(const QDomNode &response)
+{
+ // Register all device UDN nodes for later
+ deviceServices_.clear();
+ addDeviceServices( XmlFunctions::getNode(response, "/device") );
+
+ // Fetch the required data
+ deviceType_ = XmlFunctions::getNodeValue(response, "/device/deviceType");
+ rootUdn_ = 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
new file mode 100644
index 000000000..ba2999478
--- /dev/null
+++ b/src/modules/upnp/rootservice.h
@@ -0,0 +1,100 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ rootservice.h - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_ROOTSERVICE_H
+#define UPNP_ROOTSERVICE_H
+
+#include "service.h"
+
+
+namespace UPnP
+{
+
+/**
+ * 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.
+ *
+ * @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
+ ServiceParameters getServiceById(const QString &serviceId, const QString &deviceUdn) 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
+ ServiceParameters getServiceByType(const QString &serviceType, const QString &deviceUdn) const;
+
+ // 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: // Private methods
+ // Recursively add all devices and embedded devices to the deviceServices_ map
+ void addDeviceServices(const QDomNode &device);
+
+
+ private:
+ // The device type
+ QString deviceType_;
+ // A collection of all services provided by the device
+ QMap<QString,QDomNodeList> deviceServices_;
+ // The hostname of the device
+ QString hostname_;
+ // The port of the device
+ int port_;
+ // The udn of the root device
+ QString rootUdn_;
+};
+
+}
+
+#endif
diff --git a/src/modules/upnp/service.cpp b/src/modules/upnp/service.cpp
new file mode 100644
index 000000000..055b968de
--- /dev/null
+++ b/src/modules/upnp/service.cpp
@@ -0,0 +1,286 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ service.cpp - description
+ -------------------
+ begin : Sun Jul 24 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "service.h"
+#include "xmlfunctions.h"
+
+#include <QDebug>
+#include <QHttp>
+#include <QByteArray>
+
+// This implementation was created with the help of the following documentation:
+// http://www.upnp.org/standardizeddcps/documents/UPnP_IGD_1.0.zip
+// http://zacbowling.com/upnp/
+// 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)
+ : informationUrl_(informationUrl)
+ , pendingRequests_(0)
+{
+ http_ = new QHttp(hostname, port);
+ connect(http_, SIGNAL( requestFinished(int,bool) ) ,
+ this, SLOT( slotRequestFinished(int,bool) ) );
+
+qDebug() << "UPnP::Service: Created information service url='" << informationUrl_ << "'." << endl;
+}
+
+
+// The constructor for action services
+Service::Service(const ServiceParameters &params)
+ : controlUrl_(params.controlUrl)
+ , informationUrl_(params.scdpUrl)
+ , pendingRequests_(0)
+ , serviceId_(params.serviceId)
+{
+ http_ = new QHttp(params.hostname, params.port);
+ connect(http_, SIGNAL( requestFinished(int,bool) ) ,
+ this, SLOT( slotRequestFinished(int,bool) ) );
+
+ qDebug() << "CREATED UPnP::Service: url='" << controlUrl_ << "' id='" << serviceId_ << "'." << endl;
+}
+
+
+
+// The destructor
+Service::~Service()
+{
+ qDebug() << "DESTROYED UPnP::Service [url=" << controlUrl_ << ", id=" << serviceId_ << "]" << endl;
+
+ delete http_;
+}
+
+
+
+// Makes a UPnP action request
+// TODO: rename to callMethod / callSoapMethod
+int Service::callAction(const QString &actionName)
+{
+ return callActionInternal(actionName, 0);
+}
+
+
+
+// Makes a UPnP action request
+int Service::callAction(const QString &actionName, const QMap<QString,QString> &arguments)
+{
+ return callActionInternal(actionName, &arguments);
+}
+
+
+
+// Makes a UPnP action request (keeps pointers from the external interface)
+int Service::callActionInternal(const QString &actionName, const QMap<QString,QString> *arguments)
+{
+ qDebug() << "UPnP::Service: calling remote prodecure '" << actionName << "'." << endl;
+
+ // Create the data message
+ QString soapMessage = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>"
+ "<u:" + actionName + " xmlns:u=\"" + serviceId_ + "\">";
+
+ // 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.data() + "</" + argumentName + ">";
+ }
+ }
+
+ // Add the closing tags
+ soapMessage += "</u:" + actionName + "></s:Body></s:Envelope>";
+
+ // Get an utf8 encoding string
+ QByteArray content = soapMessage.utf8();
+
+ // Create the HTTP header
+ QHttpRequestHeader header("POST", controlUrl_);
+ header.setContentType("text/xml; charset=\"utf-8\"");
+ header.setContentLength(content.size());
+ header.setValue("SoapAction", serviceId_ + "#" + actionName);
+
+ // Send the POST request
+ pendingRequests_++;
+ return http_->request(header, content);
+}
+
+
+
+// Makes a UPnP service request
+// TODO: rename to downloadFile()
+int Service::callInformationUrl()
+{
+ qDebug() << "UPnP::Service: requesting file '" << informationUrl_ << "'." << endl;
+
+ // Send the GET request
+ // TODO: User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows NT/5.1)
+ pendingRequests_++;
+ return http_->get(informationUrl_);
+}
+
+
+
+// Get the number of pending requests
+int Service::getPendingRequests() const
+{
+ return pendingRequests_;
+}
+
+
+// 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;
+}
+
+
+
+// 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;
+}
+
+
+
+// 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;
+}
+
+
+
+// The QHttp object retrieved data.
+void Service::slotRequestFinished(int /*id*/, bool error)
+{
+ qDebug() << "UPnP::Service: Got HTTP response." << endl;
+
+ if(! error)
+ {
+ // Not sure why this happens
+ if(http_->bytesAvailable() > 0)
+ {
+ // Get the XML content
+ QByteArray response = http_->readAll();
+ QDomDocument xml;
+
+ // TODO: handle 401 Authorisation required messages
+
+ // Parse the XML
+ QString errorMessage;
+ error = ! xml.setContent(response, false, &errorMessage);
+
+ if(! error)
+ {
+ // Determine how to process the data
+ if(xml.namedItem("s: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, "/s:Envelope/s:Body").firstChild();
+
+ error = (resultNode.nodeName() == "s:Fault");
+
+ if(! error)
+ {
+ if(resultNode.nodeName().startsWith("m:"))
+ {
+ 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(uint i = 0; i < children.count(); i++)
+ {
+ QString key = children.item(i).nodeName();
+ resultValues[ key ] = children.item(i).toElement().text();
+ }
+
+ // Call the gotActionResponse()
+ gotActionResponse(resultNode.nodeName().mid(2), resultValues);
+ }
+ }
+ else
+ {
+ qDebug() << "UPnP::Service: SOAP Error detected, calling gotActionResponse()." << endl;
+
+ // Action failed
+ gotActionErrorResponse(resultNode);
+ }
+ }
+ }
+ else
+ {
+ qWarning() << "UPnP::Service - XML Parsing failed: " << errorMessage << endl;
+ }
+
+ // Only emit when bytes>0
+ pendingRequests_--;
+ emit queryFinished(error);
+ }
+ }
+ else
+ {
+ qWarning() << "UPnP::Service - HTTP Request failed: " << http_->errorString() << endl;
+ pendingRequests_--;
+ emit queryFinished(error);
+ }
+
+}
+
+
+} // end of namespace
diff --git a/src/modules/upnp/service.h b/src/modules/upnp/service.h
new file mode 100644
index 000000000..9e9e72af6
--- /dev/null
+++ b/src/modules/upnp/service.h
@@ -0,0 +1,128 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ service.h - description
+ -------------------
+ begin : Sun Jul 24 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_CONTROLPOINT_H
+#define UPNP_CONTROLPOINT_H
+
+#include <qobject.h>
+#include <qdom.h>
+#include <qmap.h>
+#include <qstring.h>
+
+class QHttp;
+
+namespace UPnP
+{
+
+// A datablock to make the exchange
+// of service information easier
+struct ServiceParameters
+{
+ QString hostname;
+ int port;
+ QString scdpUrl;
+ QString controlUrl;
+ QString serviceId;
+};
+
+
+/**
+ * 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.
+ *
+ * This class different kind of calls.
+ * An information request queries the service for data with a HTTP GET.
+ * An action request issues a HTTP POST call to the given service.
+ *
+ * @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 &params);
+ // The destructor
+ virtual ~Service();
+
+ // Get the number of pending requests
+ int getPendingRequests() const;
+
+
+ protected: // Protected methods
+ // Makes a UPnP action request
+ int callAction(const QString &actionName);
+ // Makes a UPnP action request
+ int callAction(const QString &actionName, const QMap<QString,QString> &arguments);
+ // Makes a UPnP service request
+ int callInformationUrl();
+
+ // 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 slots:
+ // The QHttp object retrieved data.
+ void slotRequestFinished(int id, bool error);
+
+ private:
+ // Makes a UPnP action request (keeps pointers from the external interface)
+ int callActionInternal(const QString &actionName, const QMap<QString,QString> *arguments);
+
+ private:
+ // The URL to control the service
+ QString controlUrl_;
+ // The HTTP requester
+ QHttp *http_;
+ // The URL to request service information
+ QString informationUrl_;
+ // The number of pending queries/actions
+ int pendingRequests_;
+ // The ID of the service
+ QString serviceId_;
+
+ 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
new file mode 100644
index 000000000..1e9fd08a2
--- /dev/null
+++ b/src/modules/upnp/ssdpconnection.cpp
@@ -0,0 +1,134 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ ssdpconnection.cpp - description
+ -------------------
+ begin : Fri Jul 29 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "ssdpconnection.h"
+
+#include <QHostAddress>
+#include <QUdpSocket>
+
+#include <QByteArray>
+#include <QDebug>
+#include <QUrl>
+
+namespace UPnP
+{
+
+SsdpConnection::SsdpConnection()
+: QObject()
+{
+ socket_ = new QUdpSocket();
+ connect(socket_, SIGNAL(readyRead()), this, SLOT(slotDataReceived()));
+}
+
+SsdpConnection::~SsdpConnection()
+{
+ if(socket_ != 0)
+ {
+ socket_->close();
+ delete socket_;
+ }
+}
+
+
+
+// Data was received by the socket
+void SsdpConnection::slotDataReceived()
+{
+ qDebug() << "UPnP::SsdpConnection: received " << socket_->bytesAvailable() << " bytes." << endl;
+
+ // Get the HTTP-like content
+ // TODO: How to handle multiple packets arriving from different devices?
+ QByteArray response = socket_->readAll();
+
+ // Response from my 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
+ //
+
+ QString sspdResponse = QString::fromUtf8(response.data(), response.size());
+
+ // Find the location field manually, MimeMessage is not required
+ int locationStart = sspdResponse.find("LOCATION:",0,false); // case insensitive
+ int locationEnd = sspdResponse.find("\r\n",locationStart);
+
+ locationStart += 9; // length of field name
+ QString location = sspdResponse.mid(locationStart, locationEnd - locationStart);
+
+ // Parse the URL syntax using KURL
+ QUrl url(location);
+
+ // 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 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";
+
+ // Bind the socket to a certain port
+ bool success = socket_->bind(address, bindPort);
+ if(! success)
+ {
+ qDebug() << "UPnP::SsdpConnection: Failed to bind to port " << bindPort << "." << endl;
+ }
+
+ // Send the data
+ QByteArray dataBlock = data.utf8();
+ int bytesWritten = socket_->writeDatagram(dataBlock.data(), dataBlock.size(), address, 1900);
+
+ if(bytesWritten == -1)
+ {
+ qDebug() << "UPnP::SsdpConnection: Failed to send the UPnP broadcast packet." << endl;
+ }
+}
+
+
+
+} // end of namespace
diff --git a/src/modules/upnp/ssdpconnection.h b/src/modules/upnp/ssdpconnection.h
new file mode 100644
index 000000000..19ecddd09
--- /dev/null
+++ b/src/modules/upnp/ssdpconnection.h
@@ -0,0 +1,78 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ ssdpconnection.h - description
+ -------------------
+ begin : Fri Jul 29 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_SSDPCONNECTION_H
+#define UPNP_SSDPCONNECTION_H
+
+#include <QObject>
+
+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.
+ * Devices can respond with their location and root service name.
+ * The RootService class uses this information to query the device for
+ * it's meta information and service list.
+ *
+ * @author Diederik van der Boor
+ * @ingroup NetworkUPnP
+ */
+class SsdpConnection : public QObject
+{
+ Q_OBJECT
+
+ public:
+ SsdpConnection();
+ virtual ~SsdpConnection();
+
+ void queryDevices(int bindPort = 1500);
+
+ private slots:
+ // Data was received by the socket
+ void slotDataReceived();
+
+ private:
+ QUdpSocket *socket_;
+ signals:
+ // 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
new file mode 100644
index 000000000..3b61241d7
--- /dev/null
+++ b/src/modules/upnp/wanconnectionservice.cpp
@@ -0,0 +1,192 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ wanconnectionservice.cpp - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "wanconnectionservice.h"
+#include <QDebug>
+
+namespace UPnP
+{
+
+
+// The constructor
+WanConnectionService::WanConnectionService(const ServiceParameters &params)
+ : Service(params)
+ , natEnabled_(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)
+{
+ // TODO: this still needs to be tested
+ 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);
+}
+
+
+
+// Delete a port mapping
+void WanConnectionService::deletePortMapping(const QString &protocol, const QString &remoteHost, int externalPort)
+{
+ // TODO: this still needs to be tested
+ QMap<QString,QString> arguments;
+ arguments["NewProtocol"] = protocol;
+ arguments["NewRemoteHost"] = remoteHost;
+ arguments["NewExternalPort"] = QString::number(externalPort);
+ callAction("DeletePortMapping", arguments);
+}
+
+
+
+// Return the external IP address
+QString WanConnectionService::getExternalIpAddress() const
+{
+ return externalIpAddress_;
+}
+
+
+
+// Return true if NAT is enabled
+bool WanConnectionService::getNatEnabled() const
+{
+ return natEnabled_;
+}
+
+
+
+// Return the port mappings
+const KviPointerList<PortMapping>& WanConnectionService::getPortMappings() const
+{
+ return portMappings_;
+}
+
+
+
+// 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")
+ {
+ // Get the external IP address from the response
+ externalIpAddress_ = resultValues["NewExternalIPAddress"];
+
+ qDebug() << "UPnP::WanConnectionService: externalIp='" << externalIpAddress_ << "'." << endl;
+ }
+ else if(responseType == "GetNATRSIPStatusResponse")
+ {
+ // Get the nat status from the response
+ natEnabled_ = (resultValues["NewNATEnabled"] == "1");
+
+ qDebug() << "UPnP::WanConnectionService: natEnabled=" << natEnabled_ << "." << endl;
+ }
+ else if(responseType == "GetGenericPortMappingEntryResponse")
+ {
+ // 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
+ portMappings_.append(map);
+
+ qDebug() << "UPnP::WanConnectionService - Got mapping: " << map->protocol << " " << map->remoteHost << ":" << map->externalPort
+ << " to " << map->internalClient << ":" << map->internalPort
+ << " max " << map->leaseDuration << "s '" << map->description << "' " << (map->enabled ? "enabled" : "disabled") << endl;
+ }
+ else
+ {
+ qDebug() << "UPnP::WanConnectionService - Unexpected response type"
+ << " '" << responseType << "' encountered." << endl;
+ }
+}
+
+
+
+// Query for the external IP address
+void WanConnectionService::queryExternalIpAddress()
+{
+ callAction("GetExternalIPAddress");
+}
+
+
+
+// Query for the Nat status
+void WanConnectionService::queryNatEnabled()
+{
+ callAction("GetNATRSIPStatus");
+}
+
+
+
+// Query for a port mapping entry
+void WanConnectionService::queryPortMappingEntry(int index)
+{
+ QMap<QString,QString> arguments;
+ arguments["NewPortMappingIndex"] = QString::number(index);
+ callAction("GetGenericPortMappingEntry", arguments);
+}
+
+
+
+} // End of namespace
diff --git a/src/modules/upnp/wanconnectionservice.h b/src/modules/upnp/wanconnectionservice.h
new file mode 100644
index 000000000..4552f8ebc
--- /dev/null
+++ b/src/modules/upnp/wanconnectionservice.h
@@ -0,0 +1,113 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ wanconnectionservice.h - description
+ -------------------
+ begin : Mon Jul 25 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef UPNP_WANCONNECTIONSERVICE_H
+#define UPNP_WANCONNECTIONSERVICE_H
+
+#include "service.h"
+#include "kvi_pointerlist.h"
+
+namespace UPnP
+{
+
+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.
+ * This class implements the common actions both services support,
+ * which is sufficient to control the port mappings of the router.
+ *
+ * @author Diederik van der Boor
+ * @ingroup NetworkUPnP
+ */
+class WanConnectionService : public Service
+{
+ public: // public methods
+
+ // The constructor
+ WanConnectionService(const ServiceParameters &params);
+ // 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);
+
+
+ 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 externalIpAddress_;
+ // True if NAT is enabled
+ bool natEnabled_;
+ // The current port mappings
+ KviPointerList<PortMapping> portMappings_;
+};
+
+}
+
+#endif
diff --git a/src/modules/upnp/xmlfunctions.cpp b/src/modules/upnp/xmlfunctions.cpp
new file mode 100644
index 000000000..c311f4d97
--- /dev/null
+++ b/src/modules/upnp/xmlfunctions.cpp
@@ -0,0 +1,126 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ xmlfunctions.cpp - description
+ -------------------
+ begin : Sun Jul 24 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#include "xmlfunctions.h"
+
+#include <QStringList>
+
+
+// Helper function, get a specific node
+QDomNode XmlFunctions::getNode( const QDomNode &rootNode, const QString &path )
+{
+
+ QStringList pathItems = QStringList::split( "/", path, false );
+ QDomNode childNode = rootNode.namedItem( pathItems[0] ); // can be a null node
+
+ uint 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.
+ }
+
+ if( childNode.isNull() ) {
+ qDebug() << "XmlFunctions::getNode() - notice: node '" << pathItems[ i - 1 ] << "'"
+ << " does not exist (root=" << rootNode.nodeName() << " path=" << path << ")." << endl;
+ }
+
+ return childNode;
+}
+
+
+
+// Helper function, get the attribute text of a node
+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.
+}
+
+
+
+// Helper function, get a specific child node
+QDomNode XmlFunctions::getNodeChildByKey( const QDomNodeList &childNodes, const QString &keyTagName, const QString &keyValue )
+{
+
+ for( uint 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 );
+ }
+ }
+
+ // 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 )
+{
+
+ // 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::null;
+ }
+
+
+ // 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 source;
+ QTextStream textStream( &source, IO_WriteOnly );
+ node.save( textStream, indent );
+ return source;
+}
+
diff --git a/src/modules/upnp/xmlfunctions.h b/src/modules/upnp/xmlfunctions.h
new file mode 100644
index 000000000..b4680b3b9
--- /dev/null
+++ b/src/modules/upnp/xmlfunctions.h
@@ -0,0 +1,61 @@
+//=============================================================================
+//
+// Creation date : Fri Aug 08 18:00:00 2000 GMT by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2008 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Original Copyright following:
+//=============================================================================
+
+/***************************************************************************
+ xmlfunctions.cpp - description
+ -------------------
+ begin : Sun Jul 24 2005
+ copyright : (C) 2005 by Diederik van der Boor
+ email : vdboor --at-- codingdomain.com
+ ***************************************************************************/
+
+#ifndef XMLFUNCTIONS_H
+#define XMLFUNCTIONS_H
+
+#include <QDomNode>
+#include <QDebug>
+
+/**
+ * Some helper functions to make the handling of QDom easier.
+ *
+ * @author Diederik van der Boor
+ * @ingroup NetworkExtra
+ */
+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 );
+};
+
+#endif