From 78916bba41cb9e0215a9c1c84eefcd2ad311f092 Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Wed, 28 Mar 2007 21:59:21 +0000 Subject: [PATCH] - Added debug in UPnP - Started to rewrite qBT's own UPnP support instead of using aMule CVS code : (not usable yet) --- TODO | 3 +- src/GUI.cpp | 8 ++--- src/UPnP.cpp | 89 +++++++++++++++++++++++------------------------- src/bittorrent.h | 1 + src/src.pro | 5 +-- src/upnp.cpp | 57 +++++++++++++++++++++++++++++++ src/upnp.h | 57 +++++++++++++++++++++++++++++++ 7 files changed, 166 insertions(+), 54 deletions(-) create mode 100644 src/upnp.cpp create mode 100644 src/upnp.h diff --git a/TODO b/TODO index e31720a73..a46b84940 100644 --- a/TODO +++ b/TODO @@ -43,4 +43,5 @@ - Use tooltips to explain options - Exit confirmation only if there are active downloads (display number of downloads) - SMARTER - Make use of QNetworkInterface (could be useful ?) -- Display more info in log (PeX, UPnP, DHT w/ ports...) \ No newline at end of file +- Display more info in log (PeX, UPnP, DHT w/ ports...) +- Possibility to disable the trayicon \ No newline at end of file diff --git a/src/GUI.cpp b/src/GUI.cpp index 8e7716af6..5fde3e21f 100644 --- a/src/GUI.cpp +++ b/src/GUI.cpp @@ -405,7 +405,7 @@ void GUI::updateDlList(bool force){ // No need to update if qBittorrent DL list is hidden return; } - qDebug("Updating download list"); +// qDebug("Updating download list"); LCD_UpSpeed->display(tmp); // UP LCD LCD_DownSpeed->display(tmp2); // DL LCD // browse handles @@ -485,7 +485,7 @@ void GUI::updateDlList(bool force){ continue; } } - qDebug("Updated Download list"); +// qDebug("Updated Download list"); } void GUI::sortDownloadListFloat(int index, Qt::SortOrder sortOrder){ @@ -1195,7 +1195,7 @@ void GUI::trackerAuthenticationRequired(torrent_handle& h){ // Check connection status and display right icon void GUI::checkConnectionStatus(){ - qDebug("Checking connection status"); +// qDebug("Checking connection status"); char tmp[MAX_CHAR_TMP]; session_status sessionStatus = BTSession.getSessionStatus(); // Update ratio info @@ -1232,7 +1232,7 @@ void GUI::checkConnectionStatus(){ connecStatusLblIcon->setToolTip(""+tr("Connection status:")+"
"+tr("Offline")+"
"+tr("No peers found...")+""); } } - qDebug("Connection status updated"); +// qDebug("Connection status updated"); } /***************************************************** diff --git a/src/UPnP.cpp b/src/UPnP.cpp index 3a9126d90..a0abba8b5 100644 --- a/src/UPnP.cpp +++ b/src/UPnP.cpp @@ -87,11 +87,8 @@ m_LibraryHandle(dlopen(libname, RTLD_LAZY)) std::ostringstream msg; if (!m_LibraryHandle) { qDebug("error(CDynamicLibHandle): Unable to dlopen the lib. Check PATH and LD_LIBRARY_PATH."); - //AddLogLineM(true, logUPnP, msg); -// throw CUPnPException(msg); } else { qDebug("Successfully opened the lib."); - //AddLogLineM(false, logUPnP, msg); } } @@ -104,11 +101,10 @@ CDynamicLibHandle::~CDynamicLibHandle() msg << "error(CDynamicLibHandle): Error closing " << m_libname << ": " << dlerror() << "."; -// AddLogLineM(true, logUPnP, msg); fprintf(stderr, "%s\n", msg.str().c_str()); } else { msg << "Successfully closed " << m_libname << "."; -// AddLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } } @@ -291,14 +287,14 @@ std::string CUPnPLib::processUPnPErrorMessage( errorString << "'."; } -// AddLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } else { msg << "Error: " << messsage << ": UPnP SDK error: " << GetUPnPErrorMessage(errorCode) << " (" << errorCode << ")."; -// AddLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } return msg.str(); @@ -326,7 +322,7 @@ void CUPnPLib::ProcessActionResponse( msg << "\n Empty response for action '" << actionName << "'."; } -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -510,7 +506,7 @@ m_relatedStateVariable(upnpLib.Element_GetChildValueByTag(argument, "relatedStat "\n direction: " << m_direction << "\n retval: " << m_retval << "\n relatedStateVariable: " << m_relatedStateVariable; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -527,7 +523,7 @@ m_name(upnpLib.Element_GetChildValueByTag(action, "name")) std::ostringstream msg; msg << "\n Action:" << "\n name: " << m_name; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -543,7 +539,7 @@ m_allowedValue(upnpLib.Element_GetTextValue(allowedValue)) std::ostringstream msg; msg << "\n AllowedValue:" << "\n allowedValue: " << m_allowedValue; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -566,7 +562,7 @@ m_sendEvents (upnpLib.Element_GetAttributeByTag (stateVariable, "sendEvents")) "\n dataType: " << m_dataType << "\n defaultValue: " << m_defaultValue << "\n sendEvents: " << m_sendEvents; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -629,7 +625,7 @@ m_SCPD(NULL) msg << "Error generating scpdURL from " << "|" << URLBase << "|" << m_SCPDURL << "|."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } else { m_absSCPDURL = scpdURL; } @@ -644,7 +640,7 @@ m_SCPD(NULL) msg << "Error generating controlURL from " << "|" << URLBase << "|" << m_controlURL << "|."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } else { m_absControlURL = controlURL; } @@ -659,7 +655,7 @@ m_SCPD(NULL) msg << "Error generating eventURL from " << "|" << URLBase << "|" << m_eventSubURL << "|."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } else { m_absEventSubURL = eventURL; } @@ -673,7 +669,7 @@ m_SCPD(NULL) "\n absControlURL: " << m_absControlURL << "\n eventSubURL: " << m_eventSubURL << "\n absEventSubURL: " << m_absEventSubURL; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); if ( m_serviceType == upnpLib.UPNP_SERVICE_WAN_IP_CONNECTION || m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION) { @@ -685,7 +681,7 @@ m_SCPD(NULL) msg.str(""); msg << "WAN Service Detected: '" << m_serviceType << "'."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); // Subscribe upnpLib.m_ctrlPoint.Subscribe(*this); #if 0 @@ -694,14 +690,14 @@ m_SCPD(NULL) msg << "WAN service detected again: '" << m_serviceType << "'. Will only use the first instance."; - AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } #endif } else { msg.str(""); msg << "Uninteresting service detected: '" << m_serviceType << "'. Ignoring."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } } @@ -723,7 +719,7 @@ bool CUPnPService::Execute( if (itAction == m_SCPD->GetActionList().end()) { msg << "Invalid action name '" << ActionName << "' for service '" << GetServiceType() << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } msgAction << ActionName << "("; @@ -737,7 +733,7 @@ bool CUPnPService::Execute( msg << "Invalid argument name '" << ArgValue[i].GetArgument() << "' for action '" << action.GetName() << "' for service '" << GetServiceType() << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } const CUPnPArgument &argument = *(itArg->second); @@ -747,7 +743,7 @@ bool CUPnPService::Execute( ArgValue[i].GetArgument() << "' for action '" << action.GetName() << "' for service '" << GetServiceType() << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } const std::string relatedStateVariableName = @@ -762,7 +758,7 @@ bool CUPnPService::Execute( "' for argument '" << argument.GetName() << "' for action '" << action.GetName() << "' for service '" << GetServiceType() << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } const CUPnPStateVariable &stateVariable = *(itSVT->second); @@ -774,7 +770,7 @@ bool CUPnPService::Execute( "' for argument '" << argument.GetName() << "' for action '" << action.GetName() << "' for service '" << GetServiceType() << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } } @@ -790,7 +786,7 @@ bool CUPnPService::Execute( "'"; } msgAction << ")"; -// AddDebugLogLineM(false, logUPnP, msgAction); + qDebug("UPnP: %s", msgAction.str().c_str()); // Everything is ok, make the action IXML_Document *ActionDoc = NULL; if (ArgValue.size()) { @@ -814,7 +810,7 @@ bool CUPnPService::Execute( 0, NULL); if (!ActionDoc) { msg << "Error: m_UpnpMakeAction returned NULL."; -// AddLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } } @@ -880,7 +876,7 @@ const std::string CUPnPService::GetStateVariable( "='" << StVarVal << "'."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return stdEmptyString; } @@ -919,7 +915,7 @@ m_presentationURL (upnpLib.Element_GetChildValueByTag(device, "presentationURL" msg << "Error generating presentationURL from " << "|" << URLBase << "|" << m_presentationURL << "|."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } else { m_presentationURL = presURL; } @@ -938,7 +934,7 @@ m_presentationURL (upnpLib.Element_GetChildValueByTag(device, "presentationURL" "\n UDN: " << m_UDN << "\n UPC: " << m_UPC << "\n presentationURL: " << m_presentationURL; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -964,7 +960,7 @@ m_expires(expires) "\n Fixed URLBase: " << FixedURLBase << "\n location: " << m_location << "\n expires: " << m_expires; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -1000,7 +996,7 @@ m_UPnPPort(udpPort) ipAddress = m_upnpLib.m_UpnpGetServerIpAddress(); msg << "bound to " << ipAddress << ":" << port << "."; -// AddLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); msg.str(""); ret = m_upnpLib.m_UpnpRegisterClient( static_cast(&CUPnPControlPoint::Callback), @@ -1045,7 +1041,7 @@ m_UPnPPort(udpPort) error: m_upnpLib.m_UpnpFinish(); msg << ret << ": " << m_upnpLib.GetUPnPErrorMessage(ret) << "."; -// throw CUPnPException(msg); + qDebug("UPnP: %s", msg.str().c_str()); } @@ -1071,7 +1067,7 @@ bool CUPnPControlPoint::AddPortMappings( msg << "UPnP Error: " "CUPnPControlPoint::AddPortMapping: " "Wan Service not detected."; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } @@ -1133,7 +1129,7 @@ bool CUPnPControlPoint::AddPortMappings( msg << "CUPnPControlPoint::DeletePortMappings: " "m_ActivePortMappingsMap.size() == " << m_ActivePortMappingsMap.size(); -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); // Not very good, must find a better test PortMappingNumberOfEntries.str( @@ -1207,7 +1203,7 @@ bool CUPnPControlPoint::DeletePortMappings( msg << "UPnP Error: " "CUPnPControlPoint::DeletePortMapping: " "Wan Service not detected."; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); return false; } @@ -1236,7 +1232,7 @@ bool CUPnPControlPoint::DeletePortMappings( "CUPnPControlPoint::DeletePortMapping: " "Mapping was not found in the active " "mapping map."; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } // Delete the port mapping @@ -1249,7 +1245,7 @@ bool CUPnPControlPoint::DeletePortMappings( msg << "CUPnPControlPoint::DeletePortMappings: " "m_ActivePortMappingsMap.size() == " << m_ActivePortMappingsMap.size(); -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); // Not very good, must find a better test PortMappingNumberOfEntries.str( @@ -1314,7 +1310,7 @@ upnpDiscovery: int ret; if (d_event->ErrCode != UPNP_E_SUCCESS) { msg << upnpCP->m_upnpLib.GetUPnPErrorMessage(d_event->ErrCode) << "."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } // Get the XML tree device description in doc ret = upnpCP->m_upnpLib.m_UpnpDownloadXmlDoc(d_event->Location, &doc); @@ -1322,7 +1318,7 @@ upnpDiscovery: msg << "Error retrieving device description from " << d_event->Location << ": " << upnpCP->m_upnpLib.GetUPnPErrorMessage(ret) << "."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } if (doc) { // Get the root node @@ -1365,7 +1361,7 @@ upnpDiscovery: //fprintf(stderr, "Callback: UPNP_DISCOVERY_SEARCH_TIMEOUT\n"); // Search timeout msg << "UPNP_DISCOVERY_SEARCH_TIMEOUT."; -// AddDebugLogLineM(false, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); // Unlock the search timeout mutex upnpCP->m_WaitForSearchTimeout.unlock(); @@ -1380,7 +1376,7 @@ upnpDiscovery: msg << "error(UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE): " << upnpCP->m_upnpLib.GetUPnPErrorMessage(dab_event->ErrCode) << "."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } std::string devType = dab_event->DeviceType; // Check for an InternetGatewayDevice and removes it from the list @@ -1540,7 +1536,7 @@ eventSubscriptionRequest: EventType); msg << "error(UPnP::Callback): Event not handled:'" << EventType << "'."; -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); fprintf(stderr, "%s\n", msg.str().c_str()); // Better not throw in the callback. Who would catch it? //throw CUPnPException(msg); @@ -1581,7 +1577,7 @@ void CUPnPControlPoint::OnEventReceived( } else { msg << "\n Empty property list."; } -// AddDebugLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); // Freeing that doc segfaults. Probably should not be freed. //m_upnpLib.m_ixmlDocument_free(ChangedVariablesDoc); } @@ -1646,7 +1642,7 @@ void CUPnPControlPoint::Subscribe(CUPnPService &service) msg << "Successfully subscribed to service " << service.GetServiceType() << ", absEventSubURL: " << service.GetAbsEventSubURL() << "."; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); IXML_Document *scpdDoc = NULL; errcode = m_upnpLib.m_UpnpDownloadXmlDoc( @@ -1662,7 +1658,7 @@ void CUPnPControlPoint::Subscribe(CUPnPService &service) msg.str(""); msg << "Error getting SCPD Document from " << service.GetAbsSCPDURL() << "."; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } } else { msg << "Error subscribing to service " << @@ -1676,8 +1672,7 @@ void CUPnPControlPoint::Subscribe(CUPnPService &service) // Error processing error: - return; -// AddLogLineM(true, logUPnP, msg); + qDebug("UPnP: %s", msg.str().c_str()); } diff --git a/src/bittorrent.h b/src/bittorrent.h index 19b93e3ba..eae9e7331 100644 --- a/src/bittorrent.h +++ b/src/bittorrent.h @@ -37,6 +37,7 @@ #include #include "deleteThread.h" +#include "upnp.h" class QTimer; class QString; diff --git a/src/src.pro b/src/src.pro index a942ca7a3..79aac610b 100644 --- a/src/src.pro +++ b/src/src.pro @@ -28,6 +28,7 @@ contains(DEBUG_MODE, 0){ QMAKE_CXXFLAGS_RELEASE += -fwrapv QMAKE_CXXFLAGS_DEBUG += -fwrapv #LIBS += -lcurl +LIBS += -lupnp #CONFIG += link_pkgconfig #PKGCONFIG += libtorrent QT += network @@ -129,8 +130,8 @@ SOURCES += GUI.cpp \ searchEngine.cpp !contains(DEFINES, NO_UPNP){ message(UPnP Enabled) - HEADERS += UPnP.h - SOURCES += UPnP.cpp + HEADERS += UPnP.h upnp.h + SOURCES += UPnP.cpp upnp.cpp }else{ message(UPnP Disabled) } diff --git a/src/upnp.cpp b/src/upnp.cpp new file mode 100644 index 000000000..3a3d71ba4 --- /dev/null +++ b/src/upnp.cpp @@ -0,0 +1,57 @@ +#include "upnp.h" + +int callBackCPRegister( Upnp_EventType EventType, void* Event, void* Cookie ){ + switch(EventType){ + case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: + case UPNP_DISCOVERY_SEARCH_RESULT: + { + struct Upnp_Discovery *d_event = (struct Upnp_Discovery*) Event; + IXML_Document *DescDoc=NULL; + int ret = UpnpDownloadXmlDoc(d_event->Location, &DescDoc); + if(ret != UPNP_E_SUCCESS){ + // silently ignore? + }else{ + ((UPnPHandler*)Cookie)->addUPnPDevice(d_event); +// TvCtrlPointAddDevice(DescDoc, d_event->Location, d_event->Expires); + } + if(DescDoc) ixmlDocument_free(DescDoc); +// TvCtrlPointPrintList(); + break; + } + case UPNP_DISCOVERY_SEARCH_TIMEOUT: + qDebug("UPnP devices discovery timed out..."); + break; + case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE: + { + struct Upnp_Discovery *d_event = (struct Upnp_Discovery*) Event; + ((UPnPHandler*)Cookie)->removeUPnPDevice(QString(d_event->DeviceId)); +// TvCtrlPointPrintList(); + break; + } + default: + qDebug("Debug: UPnP Unhandled event"); + } + return 0; +} + +void UPnPHandler::run(){ + // Initialize the SDK + int ret = UpnpInit(NULL, 0); + if(ret != UPNP_E_SUCCESS){ + qDebug("Fatal error: UPnP initialization failed"); + UpnpFinish(); + return; + } + qDebug("UPnP successfully initialized"); + qDebug("UPnP bind on IP %s:%d", UpnpGetServerIpAddress(), UpnpGetServerPort()); + // Register the UPnP control point + ret = UpnpRegisterClient(callBackCPRegister, this, &UPnPClientHandle); + if(ret != UPNP_E_SUCCESS){ + qDebug("Fatal error: UPnP control point registration failed"); + UpnpFinish(); + return; + } + qDebug("UPnP control point successfully registered"); + // Look for UPnP enabled routers (devices) + ret = UpnpSearchAsync(UPnPClientHandle, WAIT_TIMEOUT, "upnp:rootdevice", this); +} \ No newline at end of file diff --git a/src/upnp.h b/src/upnp.h new file mode 100644 index 000000000..8e6859e35 --- /dev/null +++ b/src/upnp.h @@ -0,0 +1,57 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2006 Christophe Dumez + * + * 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. + * + * Contact : chris@qbittorrent.org + */ +#ifndef __QBT_UPNP__ +#define __QBT_UPNP__ + +#include +#include + +#include + +#define WAIT_TIMEOUT 5 + +// Control point registration callback + +class UPnPHandler : public QThread { + Q_OBJECT + + private: + UpnpClient_Handle UPnPClientHandle; + QHash UPnPDevices; + + public: + UPnPHandler(){} + ~UPnPHandler(){} + + public slots: + void addUPnPDevice(struct Upnp_Discovery* device){ + + } + + void removeUPnPDevice(QString device_id){ + + } + + private: + void run(); +}; + +#endif