[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r2613: Give UPNPControlThread methods more well-defined return valu (in vidalia: . branches/upnp/src/vidalia branches/upnp/src/vidalia/config)



Author: edmanm
Date: 2008-05-26 19:56:33 -0400 (Mon, 26 May 2008)
New Revision: 2613

Modified:
   vidalia/
   vidalia/branches/upnp/src/vidalia/config/upnpcontrol.cpp
   vidalia/branches/upnp/src/vidalia/config/upnpcontrol.h
   vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.cpp
   vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.h
   vidalia/branches/upnp/src/vidalia/mainwindow.cpp
   vidalia/branches/upnp/src/vidalia/mainwindow.h
Log:
 r369@thebe:  edmanm | 2008-05-26 19:57:11 -0400
 Give UPNPControlThread methods more well-defined return values. Add a
 UPNPControl::error() signal emitted when port forwarding or IGD discovery
 fails. Add a slot to display a message box when the error() signal is emitted.



Property changes on: vidalia
___________________________________________________________________
 svk:merge ticket from /local/vidalia [r369] on 45a62a8a-8088-484c-baad-c7b3e776dd32

Modified: vidalia/branches/upnp/src/vidalia/config/upnpcontrol.cpp
===================================================================
--- vidalia/branches/upnp/src/vidalia/config/upnpcontrol.cpp	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/config/upnpcontrol.cpp	2008-05-26 23:56:33 UTC (rev 2613)
@@ -41,6 +41,7 @@
 {
   _forwardedORPort = 0;
   _forwardedDirPort = 0;
+  _error = UnknownError;
   mutex = new QMutex();
   controlThread = new UPNPControlThread(this);
   controlThread->start();
@@ -89,3 +90,48 @@
   controlThread->wakeup();
 }
 
+void
+UPNPControl::setError(UPNPError upnpError)
+{
+  mutex->lock();
+  _error = upnpError;
+  mutex->unlock();
+  
+  emit error(upnpError);
+}
+
+/** Returns the type of error that occurred last. */
+UPNPControl::UPNPError
+UPNPControl::error() const
+{
+  QMutexLocker locker(mutex);
+  return _error;
+}
+
+/** Returns a QString describing the type of error that occurred last. */
+QString
+UPNPControl::errorString() const
+{
+  UPNPError error = this->error();
+
+  switch (error) {
+    case Success:
+      return tr("Success");
+    case NoUPNPDevicesFound:
+      return tr("No UPnP-enabled devices found");
+    case NoValidIGDsFound:
+      return tr("No valid UPnP-enabled Internet gateway devices found");
+    case WSAStartupFailed:
+      return tr("WSAStartup failed");
+    case AddPortMappingFailed:
+      return tr("Failed to add a port mapping");
+    case GetPortMappingFailed:
+      return tr("Failed to retrieve a port mapping");
+    case DeletePortMappingFailed:
+      return tr("Failed to remove a port mapping");
+    default:
+      return tr("Unknown error");
+  }
+}
+
+

Modified: vidalia/branches/upnp/src/vidalia/config/upnpcontrol.h
===================================================================
--- vidalia/branches/upnp/src/vidalia/config/upnpcontrol.h	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/config/upnpcontrol.h	2008-05-26 23:56:33 UTC (rev 2613)
@@ -29,6 +29,18 @@
   Q_OBJECT
 
 public:
+  /** UPnP-related error values. */
+  enum UPNPError {
+    Success,
+    NoUPNPDevicesFound,
+    NoValidIGDsFound,
+    WSAStartupFailed,
+    AddPortMappingFailed,
+    GetPortMappingFailed,
+    DeletePortMappingFailed,
+    UnknownError
+  };
+
   /** Returns a pointer to this object's singleton instance. */
   static UPNPControl* Instance();
   /** Terminates the UPnP control thread and frees memory allocated to this
@@ -41,19 +53,34 @@
    * <b>desiredDirPort</b> and <b>desiredOrPort</b>, respectively. */
   void setDesiredState(quint16 desiredDirPort, quint16 desiredOrPort);
 
+  /** Returns the type of error that occurred last. */
+  UPNPError error() const;
+  /** Returns a QString describing the type of error that occurred last. */
+  QString errorString() const;
+
+signals:
+  /** Emitted when a UPnP error occurs. */
+  void error(UPNPError error);
+ 
 protected:
   /** Constructor. Initializes and starts a thread in which all blocking UPnP
    * operations will be performed. */
   UPNPControl();
   /** Destructor. cleanup() should be called before the object is destroyed. */
   ~UPNPControl();
-  
+
+  /** Sets the most recent UPnP-related error to <b>error</b>. */
+  void setError(UPNPError error);
+
 private:
   static UPNPControl* pInstance; /**< UPNPControl singleton instance. */
 
   quint16 _forwardedORPort; /**< Currently forwarded ORPort. */
   quint16 _forwardedDirPort; /**< Currently forwarded DirPort. */
   QMutex *mutex; /**< Mutex around variables shared with UPNPControlThread. */
+  UPNPError _error; /**< Most recent UPNP error. */
+
+  friend class UPNPControlThread;
   UPNPControlThread *controlThread; /**< Thread used for UPnP operations. */
 };
 

Modified: vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.cpp
===================================================================
--- vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.cpp	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.cpp	2008-05-26 23:56:33 UTC (rev 2613)
@@ -104,7 +104,7 @@
 UPNPControlThread::configurePorts() {
   quint16 desiredDirPort, desiredOrPort;
   bool force_init = false;
-  int retval = 0;
+  UPNPControl::UPNPError retval = UPNPControl::Success;
 
   vDebug("configurePorts()");
 
@@ -126,36 +126,31 @@
     /* Configure DirPort */
     if (desiredDirPort != _dirPort) {
       retval = updatePort(_dirPort, desiredDirPort);
-      if (!retval)
+      if (retval == UPNPControl::Success)
         _dirPort = desiredDirPort;
     }
     
     /* Configure ORPort */
     if (desiredOrPort != _orPort) {
       retval = updatePort(_orPort, desiredOrPort);
-      if (!retval)
+      if (retval == UPNPControl::Success)
         _orPort = desiredOrPort;
     }
   } else {
     /* Add the mapping even if they exist already */
     retval = updatePort(0, desiredDirPort);
-    if (!retval)
+    if (retval == UPNPControl::Success)
       _dirPort = desiredDirPort;
     
     retval = updatePort(0, desiredOrPort);
-    if (!retval)
+    if (retval == UPNPControl::Success)
       _orPort = desiredOrPort;
   }
 
   vInfo("configurePorts() result: %1").arg(retval);
-    
-  if (retval) {
-    QString message;
-    QTextStream(&message)
-      << "Failed to configure automatic port forwarding (status: " 
-      << retval << ")";
-    QMessageBox::warning(0, QString("Automatic port forwarding"), message);
-  }
+
+  if (retval != UPNPControl::Success)
+    UPNPControl::Instance()->setError(retval);
 }
 
 /** Terminates the UPnP control thread's run() loop.
@@ -193,33 +188,34 @@
 
 /** Updates the port mapping for <b>oldPort</b>, changing it to 
  * <b>newPort</b>. */
-int
+UPNPControl::UPNPError
 UPNPControlThread::updatePort(quint16 oldPort, quint16 newPort)
 {
-  int retval;
+  UPNPControl::UPNPError retval;
 
 #ifdef Q_OS_WIN32  
   // Workaround from http://trolltech.com/developer/knowledgebase/579
   WSAData wsadata;
   if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
-    vWarn("WSAStartup failure while disabling UPnP port forwarding");
+    vWarn("WSAStartup failure while updating UPnP port forwarding");
+    return UPNPControl::WSAStartupFailed;
   }
 #endif
 
   if (_upnpInitialized.isNull() && (oldPort != 0 || newPort != 0)) {
     retval = initializeUPNP();
-    if (0 == retval)
+    if (retval == UPNPControl::Success)
       _upnpInitialized = QTime::currentTime();
     else
       _upnpInitialized = QTime();
   } else {
-    retval = 0;
+    retval = UPNPControl::Success;
   }
 
-  if (!retval && oldPort != 0)
+  if (retval == UPNPControl::Success && oldPort != 0)
     retval = disablePort(oldPort);
 
-  if (!retval && newPort != 0)
+  if (retval == UPNPControl::Success && newPort != 0)
     retval = forwardPort(newPort);
 
 #ifdef Q_OS_WIN32
@@ -232,7 +228,7 @@
 /** Discovers UPnP-enabled IGDs on the network. Based on 
  * http://miniupnp.free.fr/files/download.php?file=xchat-upnp20061022.patch
  * This method will block for UPNPCONTROL_DISCOVER_TIMEOUT milliseconds. */
-int
+UPNPControl::UPNPError
 UPNPControlThread::initializeUPNP()
 {
   struct UPNPDev *devlist;
@@ -244,7 +240,7 @@
   devlist = upnpDiscover(UPNPCONTROL_DISCOVER_TIMEOUT, NULL, NULL);
   if (NULL == devlist) {
     vWarn("upnpDiscover returned: NULL");
-    return 5;
+    return UPNPControl::NoUPNPDevicesFound;
   }
 
   retval = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
@@ -254,14 +250,14 @@
   freeUPNPDevlist(devlist);
 
   if (retval != 1 && retval != 2)
-    return 6;
+    return UPNPControl::NoValidIGDsFound;
 
-  return 0;
+  return UPNPControl::Success;
 }
 
 /** Adds a port forwarding mapping from external:<b>port</b> to
  * internal:<b>port</b>. Returns 0 on success, or non-zero on failure. */
-int
+UPNPControl::UPNPError
 UPNPControlThread::forwardPort(quint16 port)
 {
   int retval;
@@ -276,11 +272,11 @@
 
   // Add the port mapping of external:port -> internal:port
   retval = UPNP_AddPortMapping(urls.controlURL, data.servicetype,
-                               sPort, sPort, lanaddr, "Tor server", "TCP");
+                               sPort, sPort, lanaddr, "Tor relay", "TCP");
   if(UPNPCOMMAND_SUCCESS != retval) {
     vWarn("AddPortMapping(%1, %2, %3) failed with code %4")
             .arg(sPort).arg(sPort).arg(lanaddr).arg(retval);
-    return 1;
+    return UPNPControl::AddPortMappingFailed;
   }
   
   // Check if the port mapping was accepted
@@ -288,23 +284,23 @@
                                             sPort, "TCP", intClient, intPort);
   if(UPNPCOMMAND_SUCCESS != retval) {
     vWarn("GetSpecificPortMappingEntry() failed with code %1").arg(retval);
-    return 2;
+    return UPNPControl::GetPortMappingFailed;
   }
   
   if(! intClient[0]) {
     vWarn("GetSpecificPortMappingEntry failed.");
-    return 3;
+    return UPNPControl::GetPortMappingFailed;
   }
   
   // Output the mapping
   vInfo("(external):%1 -> %2:%3").arg(sPort).arg(intClient).arg(intPort);
 
-  return 0;
+  return UPNPControl::Success;
 }
 
 /** Removes the port mapping for <b>port</b>. Returns 0 on success or non-zero
  * on failure. */
-int
+UPNPControl::UPNPError
 UPNPControlThread::disablePort(quint16 port)
 {
   char sPort[6];
@@ -317,12 +313,12 @@
                                       sPort, "TCP");
   if(UPNPCOMMAND_SUCCESS != retval) {
     vWarn("DeletePortMapping() failed with code %1").arg(retval);
-    return 4;
+    return UPNPControl::DeletePortMappingFailed;
   }
   
   // Output the cancelled mapping
   vInfo("(external):%1 -> <>").arg(sPort);
   
-  return 0;
+  return UPNPControl::Success;
 }
 

Modified: vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.h
===================================================================
--- vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.h	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/config/upnpcontrolthread.h	2008-05-26 23:56:33 UTC (rev 2613)
@@ -21,16 +21,14 @@
 #include <QMutex>
 #include <QWaitCondition>
 #include <QTime>
+#include "upnpcontrol.h"
 
 #define STATICLIB
 #include <miniupnpc/miniwget.h>
 #include <miniupnpc/miniupnpc.h>
 #include <miniupnpc/upnpcommands.h>
 
-/* Forward declaration to make it build */
-class UPNPControl;
 
-
 class UPNPControlThread : public QThread
 {
   Q_OBJECT
@@ -60,16 +58,16 @@
   void configurePorts();
   /** Discovers UPnP-enabled IGDs on the network.  This method will block for
    * UPNPCONTROL_DISCOVER_TIMEOUT milliseconds. */
-  int initializeUPNP();
+  UPNPControl::UPNPError initializeUPNP();
   /** Updates the port mapping for <b>oldPort</b>, changing it to 
    * <b>newPort</b>. */
-  int updatePort(quint16 oldPort, quint16 newPort);
+  UPNPControl::UPNPError updatePort(quint16 oldPort, quint16 newPort);
   /** Adds a port forwarding mapping from external:<b>port</b> to
    * internal:<b>port</b>. Returns 0 on success, or non-zero on failure. */
-  int forwardPort(quint16 port);
+  UPNPControl::UPNPError forwardPort(quint16 port);
   /** Removes the port mapping for <b>port</b>. Returns 0 on success or
    * non-zero on failure. */
-  int disablePort(quint16 port);
+  UPNPControl::UPNPError disablePort(quint16 port);
   
   QTime _upnpInitialized; /**< Time at which the UPnP state was last set. */
   bool _keepRunning; /**< True if the control thread should keep running. */

Modified: vidalia/branches/upnp/src/vidalia/mainwindow.cpp
===================================================================
--- vidalia/branches/upnp/src/vidalia/mainwindow.cpp	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/mainwindow.cpp	2008-05-26 23:56:33 UTC (rev 2613)
@@ -141,7 +141,11 @@
   /* Catch signals when the application is running or shutting down */
   connect(vApp, SIGNAL(running()), this, SLOT(running()));
   connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
- 
+
+  /* Catch UPnP-related signals */
+  connect(UPNPControl::Instance(), SIGNAL(error(UPNPControl::UPNPError)),
+         this, SLOT(upnpError(UPNPControl::UPNPError)));
+
   if (TrayIcon::isTrayIconSupported()) {
     /* Make the tray icon visible */
     _trayIcon.show();
@@ -1173,4 +1177,16 @@
   return "Unknown";
 }
 
+/** Called when a UPnP error occurs. */
+void
+MainWindow::upnpError(UPNPControl::UPNPError error)
+{
+  Q_UNUSED(error);
 
+  VMessageBox::warning(this,
+    tr("Port Forwarding Failed"),
+    p(tr("Vidalia was unable to configure automatic port forwarding."))
+      + p(UPNPControl::Instance()->errorString()),
+    VMessageBox::Ok);
+}
+

Modified: vidalia/branches/upnp/src/vidalia/mainwindow.h
===================================================================
--- vidalia/branches/upnp/src/vidalia/mainwindow.h	2008-05-26 23:20:52 UTC (rev 2612)
+++ vidalia/branches/upnp/src/vidalia/mainwindow.h	2008-05-26 23:56:33 UTC (rev 2613)
@@ -26,6 +26,7 @@
 #include "log/messagelog.h"
 #include "bwgraph/bwgraph.h"
 #include "config/configdialog.h"
+#include "config/upnpcontrol.h"
 #include "help/browser/helpbrowser.h"
 #include "network/netviewer.h"
 #include "ui_mainwindow.h"
@@ -103,7 +104,9 @@
   void onBrowserFailed(QString errmsg);
   /** Called when the proxy server fails to start */
   void onProxyFailed(QString errmsg);
-  
+  /** Called when a UPnP error occurs. */
+  void upnpError(UPNPControl::UPNPError error);
+
 private:
   enum TorStatus {
     Unset,      /**< Tor's status has not yet been set. */