/*************************************************************************** * Copyright (C) 2005 by Joris Guisson * * joris.guisson@gmail.com * * * * 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 option) 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., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KTUPNPROUTER_H #define KTUPNPROUTER_H #include #include #include #include "exitoperation.h" #include #include #include #include "portlist.h" #include "forwardportlist.h" using bt::Uint16; namespace bt { /** * @author Joris Guisson * * Job to wait for a certain amount of time or until one or more ExitOperation's have * finished. */ class WaitJob : public KIO::Job { Q_OBJECT public: WaitJob(Uint32 millis); virtual ~WaitJob(); virtual void kill(bool quietly=true); /** * Add an ExitOperation; * @param op The operation */ void addExitOperation(kt::ExitOperation* op); /** * Execute a WaitJob * @param job The Job */ static void execute(WaitJob* job); /// Are there any ExitOperation's we need to wait for bool needToWait() const {return exit_ops.count() > 0;} private slots: void timerDone(); void operationFinished(kt::ExitOperation* op); private: QTimer timer; QValueList exit_ops; }; void SynchronousWait(Uint32 millis); } namespace bt { class HTTPRequest; class WaitJob; } namespace net { class ForwardPortList; } namespace KIO { class Job; } namespace kt { /** * Structure describing a UPnP service found in an xml file. */ struct UPnPService { QString serviceid; QString servicetype; QString controlurl; QString eventsuburl; QString scpdurl; UPnPService(); UPnPService(const UPnPService & s); /** * Set a property of the service. * @param name Name of the property (matches to variable names) * @param value Value of the property */ void setProperty(const QString & name,const QString & value); /** * Set all strings to empty. */ void clear(); /// Print the data of this service void debugPrintData(); /** * Assignment operator * @param s The service to copy * @return *this */ UPnPService & operator = (const UPnPService & s); }; /** * Struct to hold the description of a device */ struct UPnPDeviceDescription { QString friendlyName; QString manufacturer; QString modelDescription; QString modelName; QString modelNumber; /** * Set a property of the description * @param name Name of the property (matches to variable names) * @param value Value of the property */ void setProperty(const QString & name,const QString & value); }; /** * @author Joris Guisson * * Class representing a UPnP enabled router. This class is also used to communicate * with the router. */ class UPnPRouter : public QObject { Q_OBJECT public: struct Forwarding { net::Port extport; net::Port intport; bt::HTTPRequest* pending_req; UPnPService* service; }; struct ForwardingRequest { net::Port extport; net::Port intport; bt::HTTPRequest* pending_req; }; private: QString server; QString tmp_file; KURL location; UPnPDeviceDescription desc; QValueList services; QValueList fwds; QValueList fwdreqs; QValueList active_reqs; net::ForwardPortList* forwardedPortList; public: /** * Construct a router. * @param server The name of the router * @param location The location of it's xml description file * @param verbose Print lots of debug info */ UPnPRouter(const QString & server,const KURL & location,bool verbose = false); virtual ~UPnPRouter(); /// Get the name of the server QString getServer() const {return server;} /// Get the location of it's xml description KURL getLocation() const {return location;} /// Get the device description UPnPDeviceDescription & getDescription() {return desc;} /// Get the device description (const version) const UPnPDeviceDescription & getDescription() const {return desc;} /** * Download the XML File of the router. */ void downloadXMLFile(); /** * Add a service to the router. * @param s The service */ void addService(const UPnPService & s); #if 0 /** * See if a port is forwarded * @param port The Port */ void isPortForwarded(const net::Port & port); /** * Get the external IP address. */ void getExternalIP(); #endif /** * Forward a local port * @param port The local port to forward */ void forward(const net::Port & externalport, const net::Port & internalport = net::Port::Port(), bool force = false); /** * Undo forwarding * @param port The port * @param waitjob When this is set the jobs needs to be added to the waitjob, * so we can wait for their completeion at exit */ void undoForward(const net::Port & externalport,const net::Port & internalport, bt::WaitJob* waitjob = 0); void debugPrintData(); QValueList::iterator beginReqMappings() {return fwdreqs.begin();} QValueList::iterator endReqMappings() {return fwdreqs.end();} QValueList::iterator beginPortMappings() {return fwds.begin();} QValueList::iterator endPortMappings() {return fwds.end();} net::ForwardPortList* forwardedPorts() {return forwardedPortList;} private slots: void onReplyOK(bt::HTTPRequest* r,const QString &,bool); void onReplyError(bt::HTTPRequest* r,const QString &,bool); void onError(bt::HTTPRequest* r,bool); void downloadFinished(KIO::Job* j); signals: /** * Tell the GUI that it needs to be updated. */ void updateGUI(); /** * Signal which indicates that the XML was downloaded successfully or not. * @param r The router which emitted the signal * @param success Wether or not it succeeded */ void xmlFileDownloaded(UPnPRouter* r,bool success); void replyOK(kt::UPnPRouter*,bt::HTTPRequest* ,const QString &,bool); void replyError(kt::UPnPRouter*,bt::HTTPRequest* ,const QString &,bool); private: QValueList::iterator findPortForwardingService(); bt::HTTPRequest* sendSoapQuery(const QString & query,const QString & soapact,const QString & controlurl,bool fwd, bool at_exit = false ); bool verbose; void forward(UPnPService* srv,const net::Port & externalport,const net::Port & internalport = net::Port::Port()); void undoForward(UPnPService* srv,const net::Port & externalport,const net::Port & internalport,bt::WaitJob* waitjob); void httpRequestDone(bt::HTTPRequest* r,bool erase_fwd); }; } #endif