Browse Source

- Added UPnP support (experimental) - taken from aMule CVS

adaptive-webui-19844
Christophe Dumez 18 years ago
parent
commit
fd2d2ddc0b
  1. 3
      Changelog
  2. 2
      TODO
  3. 89
      configure
  4. 3
      qbittorrent.qc
  5. 61
      qcm/libupnp.qcm
  6. 5
      src/GUI.cpp
  7. 1
      src/GUI.h
  8. 1691
      src/UPnP.cpp
  9. 694
      src/UPnP.h
  10. 33
      src/bittorrent.cpp
  11. 15
      src/bittorrent.h
  12. 9
      src/src.pro

3
Changelog

@ -1,3 +1,6 @@
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v0.10.0
- FEATURE: Added UPnP port forwarding support
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v0.9.0 * Unknown - Christophe Dumez <chris@qbittorrent.org> - v0.9.0
- FEATURE: Based on libtorrent v0.12 - FEATURE: Based on libtorrent v0.12
- FEATURE: Based on Qt4.2 - FEATURE: Based on Qt4.2

2
TODO

@ -34,5 +34,5 @@
- Allow to edit the trackers for a torrent - Allow to edit the trackers for a torrent
- Improve torrent creation dialog (look & features) - Improve torrent creation dialog (look & features)
- Add IPv6 support (at least start working on it) - Add IPv6 support (at least start working on it)
- UPnP support? - UPnP support? (debug, sync with aMule, option entry)
- Allow user to change application style (WinXP, MacOS, CleanLooks...) : app.setStyle(new QCleanlooksStyle()); - Allow user to change application style (WinXP, MacOS, CleanLooks...) : app.setStyle(new QCleanlooksStyle());

89
configure vendored

@ -22,6 +22,9 @@ Dependency options:
--with-libtorrent-lib=[path] Path to libtorrent library files --with-libtorrent-lib=[path] Path to libtorrent library files
--with-libcurl-inc=[path] Path to libcurl include files --with-libcurl-inc=[path] Path to libcurl include files
--with-libcurl-lib=[path] Path to libcurl library files --with-libcurl-lib=[path] Path to libcurl library files
--disable-libupnp Disable use of libupnp
--disable-upnp disable UPnP support
--with-libupnp-inc=[path] Path to libupnp include files
EOT EOT
} }
@ -158,6 +161,21 @@ while [ $# -gt 0 ]; do
shift shift
;; ;;
--disable-libupnp)
QC_DISABLE_libupnp="Y"
shift
;;
--disable-upnp)
QC_DISABLE_UPNP="Y"
shift
;;
--with-libupnp-inc=*)
QC_WITH_LIBUPNP_INC=$optarg
shift
;;
--verbose) --verbose)
QC_DEBUG="Y" QC_DEBUG="Y"
shift shift
@ -183,6 +201,9 @@ echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
echo QC_DISABLE_libupnp=$QC_DISABLE_libupnp
echo QC_DISABLE_UPNP=$QC_DISABLE_UPNP
echo QC_WITH_LIBUPNP_INC=$QC_WITH_LIBUPNP_INC
echo echo
fi fi
@ -447,6 +468,68 @@ public:
return false; return false;
} }
}; };
#line 1 "libupnp.qcm"
/*
-----BEGIN QCMOD-----
name: libupnp
arg: disable-upnp, disable UPnP support
arg: with-libupnp-inc=[path], Path to libupnp include files
-----END QCMOD-----
*/
class qc_libupnp : public ConfObj
{
public:
qc_libupnp(Conf *c) : ConfObj(c) {}
QString name() const { return "libupnp"; }
QString shortname() const { return "libupnp"; }
bool exec(){
QString s;
s = conf->getenv("QC_DISABLE_UPNP");
if(!s.isEmpty()){
conf->addDefine("NO_UPNP");
return false;
}
s = conf->getenv("QC_WITH_LIBUPNP_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "upnp/upnp.h")) {
//qWarning("libupnp includes not found!");
conf->addDefine("NO_UPNP");
return false;
}
conf->addIncludePath(s);
}else{
QStringList sl;
sl += "/usr/include";
sl += "/usr/local/include";
if(!conf->findHeader("upnp/upnp.h", sl, &s)) {
//qWarning("libupnp includes not found!");
conf->addDefine("NO_UPNP");
return false;
}
conf->addIncludePath(s);
}
/*s = conf->getenv("QC_WITH_LIBUPNP_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "upnp")) {
qWarning("libupnp library not found!");
return false;
}
conf->addLib(QString("-L") + s);
}else{
if(!conf->findLibrary("upnp", &s)) {
qWarning("libupnp library not found!");
return false;
}
if (!s.isEmpty())
conf->addLib(QString("-L") + s);
}
conf->addLib("-lupnp");*/
return true;
}
};
EOT EOT
cat >$1/modules_new.cpp <<EOT cat >$1/modules_new.cpp <<EOT
@ -465,6 +548,9 @@ cat >$1/modules_new.cpp <<EOT
o = new qc_python(conf); o = new qc_python(conf);
o->required = true; o->required = true;
o->disabled = false; o->disabled = false;
o = new qc_libupnp(conf);
o->required = false;
o->disabled = false;
EOT EOT
cat >$1/conf4.h <<EOT cat >$1/conf4.h <<EOT
@ -1395,6 +1481,9 @@ export QC_WITH_LIBTORRENT_INC
export QC_WITH_LIBTORRENT_LIB export QC_WITH_LIBTORRENT_LIB
export QC_WITH_LIBCURL_INC export QC_WITH_LIBCURL_INC
export QC_WITH_LIBCURL_LIB export QC_WITH_LIBCURL_LIB
export QC_DISABLE_libupnp
export QC_DISABLE_UPNP
export QC_WITH_LIBUPNP_INC
export QC_DEBUG export QC_DEBUG
rm -rf .qconftemp rm -rf .qconftemp
( (

3
qbittorrent.qc

@ -17,4 +17,7 @@
<dep type='python'> <dep type='python'>
<required/> <required/>
</dep> </dep>
<dep type='libupnp'>
<optional/>
</dep>
</qconf> </qconf>

61
qcm/libupnp.qcm

@ -0,0 +1,61 @@
/*
-----BEGIN QCMOD-----
name: libupnp
arg: disable-upnp, disable UPnP support
arg: with-libupnp-inc=[path], Path to libupnp include files
-----END QCMOD-----
*/
class qc_libupnp : public ConfObj
{
public:
qc_libupnp(Conf *c) : ConfObj(c) {}
QString name() const { return "libupnp"; }
QString shortname() const { return "libupnp"; }
bool exec(){
QString s;
s = conf->getenv("QC_DISABLE_UPNP");
if(!s.isEmpty()){
conf->addDefine("NO_UPNP");
return false;
}
s = conf->getenv("QC_WITH_LIBUPNP_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "upnp/upnp.h")) {
//qWarning("libupnp includes not found!");
conf->addDefine("NO_UPNP");
return false;
}
conf->addIncludePath(s);
}else{
QStringList sl;
sl += "/usr/include";
sl += "/usr/local/include";
if(!conf->findHeader("upnp/upnp.h", sl, &s)) {
//qWarning("libupnp includes not found!");
conf->addDefine("NO_UPNP");
return false;
}
conf->addIncludePath(s);
}
/*s = conf->getenv("QC_WITH_LIBUPNP_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "upnp")) {
qWarning("libupnp library not found!");
return false;
}
conf->addLib(QString("-L") + s);
}else{
if(!conf->findLibrary("upnp", &s)) {
qWarning("libupnp library not found!");
return false;
}
if (!s.isEmpty())
conf->addLib(QString("-L") + s);
}
conf->addLib("-lupnp");*/
return true;
}
};

5
src/GUI.cpp

@ -1172,6 +1172,11 @@ void GUI::configureSession(bool deleteOptions){
}else{ }else{
BTSession.disableDHT(); BTSession.disableDHT();
} }
#ifndef NO_UPNP
// Upnp
BTSession.enableUPnP();
#endif
// PeX
if(!options->isPeXDisabled()){ if(!options->isPeXDisabled()){
qDebug("Enabling Peer eXchange (PeX)"); qDebug("Enabling Peer eXchange (PeX)");
BTSession.enablePeerExchange(); BTSession.enablePeerExchange();

1
src/GUI.h

@ -45,7 +45,6 @@
#include "trackerLogin.h" #include "trackerLogin.h"
#include "bittorrent.h" #include "bittorrent.h"
#define TIME_TRAY_BALLOON 5000 #define TIME_TRAY_BALLOON 5000
class createtorrent; class createtorrent;

1691
src/UPnP.cpp

File diff suppressed because it is too large Load Diff

694
src/UPnP.h

@ -0,0 +1,694 @@
//
// This file is part of the aMule Project.
//
// Copyright (c) 2006 Marcelo Roberto Jimenez ( phoenix@amule.org )
// Copyright (c) 2006 aMule Team ( admin@amule.org / http://www.amule.org )
//
// Any parts of this program derived from the xMule, lMule or eMule project,
// or contributed by third-party developers are copyrighted by their
// respective authors.
//
// 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 St, Fifth Floor, Boston, MA 02110-1301, USA
//
// This define must not conflict with the one in the standard header
#ifndef AMULE_UPNP_H
#define AMULE_UPNP_H
#include <map>
#include <string>
#include <sstream>
#include <vector>
#include <upnp/upnp.h>
#include <QMutex>
#ifdef UPNP_C
std::string stdEmptyString;
#else // UPNP_C
extern std::string stdEmptyString;
#endif // UPNP_C
/**
* Case insensitive std::string comparison
*/
bool stdStringIsEqualCI(
const std::string &s1,
const std::string &s2);
class CUPnPPortMapping
{
private:
std::string m_port;
std::string m_protocol;
std::string m_enabled;
std::string m_description;
std::string m_key;
public:
CUPnPPortMapping(
int port = 0,
const std::string &protocol = stdEmptyString,
bool enabled = false,
const std::string &description = stdEmptyString);
~CUPnPPortMapping() {}
const std::string &getPort() const
{ return m_port; }
const std::string &getProtocol() const
{ return m_protocol; }
const std::string &getEnabled() const
{ return m_enabled; }
const std::string &getDescription() const
{ return m_description; }
const std::string &getKey() const
{ return m_key; }
};
class CDynamicLibHandle
{
private:
std::string m_libname;
void *const m_LibraryHandle;
CDynamicLibHandle(const CDynamicLibHandle &);
CDynamicLibHandle &operator=(const CDynamicLibHandle &);
public:
CDynamicLibHandle(const char *libname);
~CDynamicLibHandle();
void *Get() const { return m_LibraryHandle; }
};
class CUPnPControlPoint;
class CUPnPLib
{
public:
static const std::string &UPNP_ROOT_DEVICE;
static const std::string &UPNP_DEVICE_IGW;
static const std::string &UPNP_DEVICE_WAN;
static const std::string &UPNP_DEVICE_WAN_CONNECTION;
static const std::string &UPNP_DEVICE_LAN;
static const std::string &UPNP_SERVICE_LAYER3_FORWARDING;
static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG;
static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION;
static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION;
CUPnPControlPoint &m_ctrlPoint;
private:
// dlopen stuff
static const int NUM_LIB_IXML_SYMBOLS = 8;
static const char *s_LibIXMLSymbols[NUM_LIB_IXML_SYMBOLS];
static const int NUM_LIB_UPNP_SYMBOLS = 17;
static const char *s_LibUPnPSymbols[NUM_LIB_UPNP_SYMBOLS];
CDynamicLibHandle m_LibIXMLHandle;
CDynamicLibHandle m_LibUPnPHandle;
public:
CUPnPLib(CUPnPControlPoint &ctrlPoint);
~CUPnPLib() {}
// Convenience function so we don't have to write explicit calls
// to char2unicode every time
std::string GetUPnPErrorMessage(int code) const;
// Convenience function to avoid repetitive processing of error
// messages
std::string processUPnPErrorMessage(
const std::string &messsage,
int code,
const DOMString errorString,
IXML_Document *doc) const;
// Processing response to actions
void ProcessActionResponse(
IXML_Document *RespDoc,
const std::string &actionName) const;
// IXML_Element
IXML_Element *Element_GetRootElement(
IXML_Document *doc) const;
IXML_Element *Element_GetFirstChild(
IXML_Element *parent) const;
IXML_Element *Element_GetNextSibling(
IXML_Element *child) const;
const DOMString Element_GetTag(
IXML_Element *element) const;
const std::string Element_GetTextValue(
IXML_Element *element) const;
const std::string Element_GetChildValueByTag(
IXML_Element *element,
const DOMString tag) const;
IXML_Element *Element_GetFirstChildByTag(
IXML_Element *element,
const DOMString tag) const;
IXML_Element *Element_GetNextSiblingByTag(
IXML_Element *element,
const DOMString tag) const;
const std::string Element_GetAttributeByTag(
IXML_Element *element,
const DOMString tag) const;
// ixml api
IXML_Node *(*m_ixmlNode_getFirstChild)(IXML_Node *nodeptr);
IXML_Node *(*m_ixmlNode_getNextSibling)(IXML_Node *nodeptr);
const DOMString (*m_ixmlNode_getNodeName)(IXML_Node *nodeptr);
const DOMString (*m_ixmlNode_getNodeValue)(IXML_Node *nodeptr);
IXML_NamedNodeMap *(*m_ixmlNode_getAttributes)(IXML_Node *nodeptr);
void (*m_ixmlDocument_free)(IXML_Document *doc);
IXML_Node *(*m_ixmlNamedNodeMap_getNamedItem)(
IXML_NamedNodeMap *nnMap, const DOMString name);
void (*m_ixmlNamedNodeMap_free)(IXML_NamedNodeMap *nnMap);
// upnp api
// 1 - Initialization and Registration
int (*m_UpnpInit)(const char *IPAddress, int Port);
void (*m_UpnpFinish)();
unsigned short (*m_UpnpGetServerPort)();
char *(*m_UpnpGetServerIpAddress)();
int (*m_UpnpRegisterClient)(Upnp_FunPtr Callback,
const void *Cookie, UpnpClient_Handle *Hnd);
int (*m_UpnpUnRegisterClient)(UpnpClient_Handle Hnd);
// 2 - Discovery
int (*m_UpnpSearchAsync)(UpnpClient_Handle Hnd, int Mx,
const char *Target, const void *Cookie);
// 3 - Control
int (*m_UpnpGetServiceVarStatus)(UpnpClient_Handle Hnd, const char *ActionURL,
const char *VarName, DOMString *StVarVal);
int (*m_UpnpSendAction)(UpnpClient_Handle Hnd, const char *ActionURL,
const char *ServiceType, const char *DevUDN, IXML_Document *Action,
IXML_Document **RespNode);
int (*m_UpnpSendActionAsync)(UpnpClient_Handle Hnd, const char *ActionURL,
const char *ServiceType, const char *DevUDN, IXML_Document *Action,
Upnp_FunPtr Callback, const void *Cookie);
// 4 - Eventing
int (*m_UpnpSubscribe)(UpnpClient_Handle Hnd,
const char *PublisherUrl, int *TimeOut, Upnp_SID SubsId);
int (*m_UpnpUnSubscribe)(UpnpClient_Handle Hnd, Upnp_SID SubsId);
// 5 - HTTP
int (*m_UpnpDownloadXmlDoc)(const char *url, IXML_Document **xmlDoc);
// 6 - Optional Tools API
int (*m_UpnpResolveURL)(const char *BaseURL,
const char *RelURL, char *AbsURL);
IXML_Document *(*m_UpnpMakeAction)(
const char *ActionName, const char *ServType, int NumArg,
const char *Arg, ...);
int (*m_UpnpAddToAction)(
IXML_Document **ActionDoc, const char *ActionName,
const char *ServType, const char *ArgName, const char *ArgVal);
const char *(*m_UpnpGetErrorMessage)(int ErrorCode);
};
class CUPnPControlPoint;
/*
* Even though we can retrieve the upnpLib handler from the upnpControlPoint,
* we must pass it separetly at this point, because the class CUPnPControlPoint
* must be declared after.
*
* CUPnPLib can only be removed from the constructor once we agree to link to
* UPnPLib explicitly, making this dlopen() stuff unnecessary.
*/
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
class CXML_List : public std::map<const std::string, T *>
{
public:
CXML_List(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *parent,
const std::string &url);
~CXML_List();
};
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::CXML_List(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *parent,
const std::string &url)
{
IXML_Element *elementList =
upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME);
unsigned int i = 0;
for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME);
element;
element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) {
// Add a new element to the element list
T *upnpElement = new T(upnpControlPoint, upnpLib, element, url);
(*this)[upnpElement->GetKey()] = upnpElement;
++i;
}
std::ostringstream msg;
msg << "\n " << XML_LIST_NAME << ": " <<
i << " " << XML_ELEMENT_NAME << "s.";
//AddDebugLogLineM(false, logUPnP, msg);
}
template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::~CXML_List()
{
typename CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::iterator it;
for(it = this->begin(); it != this->end(); ++it) {
delete (*it).second;
}
}
#ifdef UPNP_C
char s_argument[] = "argument";
char s_argumentList[] = "argumentList";
char s_action[] = "action";
char s_actionList[] = "actionList";
char s_allowedValue[] = "allowedValue";
char s_allowedValueList[] = "allowedValueList";
char s_stateVariable[] = "stateVariable";
char s_serviceStateTable[] = "serviceStateTable";
char s_service[] = "service";
char s_serviceList[] = "serviceList";
char s_device[] = "device";
char s_deviceList[] = "deviceList";
#else // UPNP_C
extern char s_argument[];
extern char s_argumentList[];
extern char s_action[];
extern char s_actionList[];
extern char s_allowedValue[];
extern char s_allowedValueList[];
extern char s_stateVariable[];
extern char s_serviceStateTable[];
extern char s_service[];
extern char s_serviceList[];
extern char s_device[];
extern char s_deviceList[];
#endif // UPNP_C
class CUPnPArgument;
typedef CXML_List<CUPnPArgument, s_argument, s_argumentList> ArgumentList;
class CUPnPAction;
typedef CXML_List<CUPnPAction, s_action, s_actionList> ActionList;
class CUPnPStateVariable;
typedef CXML_List<CUPnPStateVariable, s_stateVariable, s_serviceStateTable> ServiceStateTable;
class CUPnPAllowedValue;
typedef CXML_List<CUPnPAllowedValue, s_allowedValue, s_allowedValueList> AllowedValueList;
class CUPnPService;
typedef CXML_List<CUPnPService, s_service, s_serviceList> ServiceList;
class CUPnPDevice;
typedef CXML_List<CUPnPDevice, s_device, s_deviceList> DeviceList;
class CUPnPError
{
private:
IXML_Element *m_root;
const std::string m_ErrorCode;
const std::string m_ErrorDescription;
public:
CUPnPError(
const CUPnPLib &upnpLib,
IXML_Document *errorDoc);
~CUPnPError() {}
const std::string &getErrorCode() const
{ return m_ErrorCode; }
const std::string &getErrorDescription() const
{ return m_ErrorDescription; }
};
class CUPnPArgument
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
const std::string m_name;
const std::string m_direction;
bool m_retval;
const std::string m_relatedStateVariable;
public:
CUPnPArgument(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *argument,
const std::string &SCPDURL);
~CUPnPArgument() {}
const std::string &GetName() const
{ return m_name; }
const std::string &GetDirection() const
{ return m_direction; }
bool GetRetVal() const
{ return m_retval; }
const std::string &GetRelatedStateVariable() const
{ return m_relatedStateVariable; }
const std::string &GetKey() const
{ return m_name; }
};
class CUPnPAction
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
ArgumentList m_ArgumentList;
const std::string m_name;
public:
CUPnPAction(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *action,
const std::string &SCPDURL);
~CUPnPAction() {}
const std::string &GetName() const
{ return m_name; }
const std::string &GetKey() const
{ return m_name; }
const ArgumentList &GetArgumentList() const
{ return m_ArgumentList; }
};
class CUPnPAllowedValue
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
const std::string m_allowedValue;
public:
CUPnPAllowedValue(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *allowedValue,
const std::string &SCPDURL);
~CUPnPAllowedValue() {}
const std::string &GetAllowedValue() const
{ return m_allowedValue; }
const std::string &GetKey() const
{ return m_allowedValue; }
};
class CUPnPStateVariable
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
AllowedValueList m_AllowedValueList;
const std::string m_name;
const std::string m_dataType;
const std::string m_defaultValue;
const std::string m_sendEvents;
public:
CUPnPStateVariable(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *stateVariable,
const std::string &URLBase);
~CUPnPStateVariable() {}
const std::string &GetNname() const
{ return m_name; }
const std::string &GetDataType() const
{ return m_dataType; }
const std::string &GetDefaultValue() const
{ return m_defaultValue; }
const std::string &GetKey() const
{ return m_name; }
const AllowedValueList &GetAllowedValueList() const
{ return m_AllowedValueList; }
};
class CUPnPSCPD
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
ActionList m_ActionList;
ServiceStateTable m_ServiceStateTable;
const std::string m_SCPDURL;
public:
CUPnPSCPD(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *scpd,
const std::string &SCPDURL);
~CUPnPSCPD() {}
const ActionList &GetActionList() const
{ return m_ActionList; }
const ServiceStateTable &GetServiceStateTable() const
{ return m_ServiceStateTable; }
};
class CUPnPArgumentValue
{
private:
std::string m_argument;
std::string m_value;
public:
CUPnPArgumentValue();
CUPnPArgumentValue(const std::string &argument, const std::string &value);
~CUPnPArgumentValue() {}
const std::string &GetArgument() const { return m_argument; }
const std::string &GetValue() const { return m_value; }
const std::string &SetArgument(const std::string& argument) { return m_argument = argument; }
const std::string &SetValue(const std::string &value) { return m_value = value; }
};
class CUPnPService
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
CUPnPLib &m_upnpLib;
const std::string m_serviceType;
const std::string m_serviceId;
const std::string m_SCPDURL;
const std::string m_controlURL;
const std::string m_eventSubURL;
std::string m_absSCPDURL;
std::string m_absControlURL;
std::string m_absEventSubURL;
int m_timeout;
Upnp_SID m_SID;
std::auto_ptr<CUPnPSCPD> m_SCPD;
public:
CUPnPService(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *service,
const std::string &URLBase);
~CUPnPService();
const std::string &GetServiceType() const
{ return m_serviceType; }
const std::string &GetServiceId() const
{ return m_serviceId; }
const std::string &GetSCPDURL() const
{ return m_SCPDURL; }
const std::string &GetAbsSCPDURL() const
{ return m_absSCPDURL; }
const std::string &GetControlURL() const
{ return m_controlURL; }
const std::string &GetEventSubURL() const
{ return m_eventSubURL; }
const std::string &GetAbsControlURL() const
{ return m_absControlURL; }
const std::string &GetAbsEventSubURL() const
{ return m_absEventSubURL; }
int GetTimeout() const
{ return m_timeout; }
void SetTimeout(int t)
{ m_timeout = t; }
int *GetTimeoutAddr()
{ return &m_timeout; }
char *GetSID()
{ return m_SID; }
void SetSID(const char *s)
{ memcpy(m_SID, s, sizeof(Upnp_SID)); }
const std::string &GetKey() const
{ return m_serviceId; }
bool IsSubscribed() const
{ return m_SCPD.get() != NULL; }
void SetSCPD(CUPnPSCPD *SCPD)
{ m_SCPD.reset(SCPD); }
bool Execute(
const std::string &ActionName,
const std::vector<CUPnPArgumentValue> &ArgValue) const;
const std::string GetStateVariable(
const std::string &stateVariableName) const;
};
class CUPnPDevice
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
// Please, lock these lists before use
DeviceList m_DeviceList;
ServiceList m_ServiceList;
const std::string m_deviceType;
const std::string m_friendlyName;
const std::string m_manufacturer;
const std::string m_manufacturerURL;
const std::string m_modelDescription;
const std::string m_modelName;
const std::string m_modelNumber;
const std::string m_modelURL;
const std::string m_serialNumber;
const std::string m_UDN;
const std::string m_UPC;
std::string m_presentationURL;
public:
CUPnPDevice(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *device,
const std::string &URLBase);
~CUPnPDevice() {}
const std::string &GetUDN() const
{ return m_UDN; }
const std::string &GetDeviceType() const
{ return m_deviceType; }
const std::string &GetFriendlyName() const
{ return m_friendlyName; }
const std::string &GetPresentationURL() const
{ return m_presentationURL; }
const std::string &GetKey() const
{ return m_UDN; }
};
class CUPnPRootDevice : public CUPnPDevice
{
private:
const CUPnPControlPoint &m_UPnPControlPoint;
const std::string m_URLBase;
const std::string m_location;
int m_expires;
public:
CUPnPRootDevice(
const CUPnPControlPoint &upnpControlPoint,
CUPnPLib &upnpLib,
IXML_Element *rootDevice,
const std::string &OriginalURLBase,
const std::string &FixedURLBase,
const char *location,
int expires);
~CUPnPRootDevice() {}
const std::string &GetURLBase() const
{ return m_URLBase; }
const std::string &GetLocation() const
{ return m_location; }
int GetExpires() const
{ return m_expires; }
void SetExpires(int expires)
{ m_expires = expires; }
};
typedef std::map<const std::string, CUPnPRootDevice *> RootDeviceMap;
typedef std::map<const std::string, CUPnPService *> ServiceMap;
typedef std::map<const std::string, CUPnPPortMapping> PortMappingMap;
class CUPnPControlPoint
{
private:
static CUPnPControlPoint *s_CtrlPoint;
// upnp stuff
CUPnPLib m_upnpLib;
UpnpClient_Handle m_UPnPClientHandle;
RootDeviceMap m_RootDeviceMap;
ServiceMap m_ServiceMap;
PortMappingMap m_ActivePortMappingsMap;
QMutex m_RootDeviceListMutex;
bool m_IGWDeviceDetected;
CUPnPService *m_WanService;
QMutex m_WaitForSearchTimeout;
public:
CUPnPControlPoint(unsigned short udpPort);
~CUPnPControlPoint();
void Subscribe(CUPnPService &service);
void Unsubscribe(CUPnPService &service);
bool AddPortMappings(
std::vector<CUPnPPortMapping> &upnpPortMapping);
bool DeletePortMappings(
std::vector<CUPnPPortMapping> &upnpPortMapping);
UpnpClient_Handle GetUPnPClientHandle() const
{ return m_UPnPClientHandle; }
bool GetIGWDeviceDetected() const
{ return m_IGWDeviceDetected; }
void SetIGWDeviceDetected(bool b)
{ m_IGWDeviceDetected = b; }
bool WanServiceDetected() const
{ return !m_ServiceMap.empty(); }
void SetWanService(CUPnPService *service)
{ m_WanService = service; }
// Callback function
static int Callback(
Upnp_EventType EventType,
void* Event,
void* Cookie);
private:
void OnEventReceived(
const std::string &Sid,
int EventKey,
IXML_Document *ChangedVariables);
void AddRootDevice(
IXML_Element *rootDevice,
const std::string &urlBase,
const char *location,
int expires);
void RemoveRootDevice(
const char *udn);
void RefreshPortMappings();
bool PrivateAddPortMapping(
CUPnPPortMapping &upnpPortMapping);
bool PrivateDeletePortMapping(
CUPnPPortMapping &upnpPortMapping);
};
#endif /* AMULE_UPNP_H */
// File_checked_for_headers

33
src/bittorrent.cpp

@ -21,6 +21,7 @@
#include "bittorrent.h" #include "bittorrent.h"
#include "misc.h" #include "misc.h"
#include "downloadThread.h" #include "downloadThread.h"
#include "UPnP.h"
#include <QDir> #include <QDir>
#include <QTime> #include <QTime>
@ -36,6 +37,9 @@ bittorrent::bittorrent(){
s->set_severity_level(alert::info); s->set_severity_level(alert::info);
// DHT (Trackerless), disabled until told otherwise // DHT (Trackerless), disabled until told otherwise
DHTEnabled = false; DHTEnabled = false;
#ifndef NO_UPNP
UPnPEnabled = false;
#endif
// Enabling metadata plugin // Enabling metadata plugin
s->add_extension(&create_metadata_plugin); s->add_extension(&create_metadata_plugin);
timerAlerts = new QTimer(this); timerAlerts = new QTimer(this);
@ -54,6 +58,9 @@ void bittorrent::resumeUnfinishedTorrents(){
// Main destructor // Main destructor
bittorrent::~bittorrent(){ bittorrent::~bittorrent(){
disableDirectoryScanning(); disableDirectoryScanning();
#ifndef NO_UPNP
disableUPnP();
#endif
delete timerAlerts; delete timerAlerts;
delete downloader; delete downloader;
delete s; delete s;
@ -64,6 +71,32 @@ torrent_handle bittorrent::getTorrentHandle(const QString& hash) const{
return s->find_torrent(misc::fromString<sha1_hash>((hash.toStdString()))); return s->find_torrent(misc::fromString<sha1_hash>((hash.toStdString())));
} }
#ifndef NO_UPNP
void bittorrent::enableUPnP(){
if(!UPnPEnabled){
qDebug("Enabling UPnP");
UPnPEnabled = true;
m_upnpMappings.resize(1);
m_upnpMappings[0] = CUPnPPortMapping(
getListenPort(),
"TCP",
true,
"qBittorrent");
m_upnp = new CUPnPControlPoint(50000);
m_upnp->AddPortMappings(m_upnpMappings);
}
}
void bittorrent::disableUPnP(){
if(UPnPEnabled){
qDebug("Disabling UPnP");
UPnPEnabled = false;
m_upnp->DeletePortMappings(m_upnpMappings);
delete m_upnp;
}
}
#endif
// Return true if the torrent corresponding to the // Return true if the torrent corresponding to the
// hash is paused // hash is paused
bool bittorrent::isPaused(const QString& hash) const{ bool bittorrent::isPaused(const QString& hash) const{

15
src/bittorrent.h

@ -47,6 +47,10 @@ using namespace libtorrent;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
class downloadThread; class downloadThread;
#ifndef NO_UPNP
class CUPnPControlPoint;
class CUPnPPortMapping;
#endif
class bittorrent : public QObject{ class bittorrent : public QObject{
Q_OBJECT Q_OBJECT
@ -54,12 +58,19 @@ class bittorrent : public QObject{
private: private:
session *s; session *s;
bool DHTEnabled; bool DHTEnabled;
#ifndef NO_UPNP
bool UPnPEnabled;
#endif
QString scan_dir; QString scan_dir;
QTimer *timerScan; QTimer *timerScan;
QTimer *timerAlerts; QTimer *timerAlerts;
downloadThread *downloader; downloadThread *downloader;
QStringList supported_preview_extensions; QStringList supported_preview_extensions;
QString defaultSavePath; QString defaultSavePath;
#ifndef NO_UPNP
CUPnPControlPoint* m_upnp;
std::vector<CUPnPPortMapping> m_upnpMappings;
#endif
protected: protected:
QString getSavePath(const QString& hash); QString getSavePath(const QString& hash);
@ -109,6 +120,10 @@ class bittorrent : public QObject{
void setDHTPort(int dht_port); void setDHTPort(int dht_port);
void setSessionSettings(session_settings sessionSettings); void setSessionSettings(session_settings sessionSettings);
void setDefaultSavePath(const QString& savepath); void setDefaultSavePath(const QString& savepath);
#ifndef NO_UPNP
void enableUPnP();
void disableUPnP();
#endif
protected slots: protected slots:
void cleanDeleter(deleteThread* deleter); void cleanDeleter(deleteThread* deleter);

9
src/src.pro

@ -8,10 +8,10 @@ DEBUG_MODE = 1
# Global # Global
TEMPLATE = app TEMPLATE = app
TARGET = qbittorrent TARGET = qbittorrent
CONFIG += qt thread x11 CONFIG += qt thread x11 network
# Update this VERSION for each release # Update this VERSION for each release
DEFINES += VERSION=\\\"v0.10.0alpha1\\\" DEFINES += VERSION=\\\"v0.10.0alpha2\\\"
DEFINES += VERSION_MAJOR=0 DEFINES += VERSION_MAJOR=0
DEFINES += VERSION_MINOR=10 DEFINES += VERSION_MINOR=10
DEFINES += VERSION_BUGFIX=0 DEFINES += VERSION_BUGFIX=0
@ -74,6 +74,7 @@ contains(DEBUG_MODE, 0){
# Windows # Windows
win32 { win32 {
DEFINES += NO_UPNP
LIBS += -lcurl -ltorrent LIBS += -lcurl -ltorrent
} }
@ -123,4 +124,8 @@ SOURCES += GUI.cpp \
properties_imp.cpp \ properties_imp.cpp \
createtorrent_imp.cpp \ createtorrent_imp.cpp \
bittorrent.cpp bittorrent.cpp
!contains(DEFINES, NO_UPNP){
HEADERS += UPnP.h
SOURCES += UPnP.cpp
}

Loading…
Cancel
Save