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

[vidalia-svn] r2511: Switch to using 'getinfo ns/all' instead of 'getinfo network (in vidalia/trunk: . src/torcontrol src/vidalia/network)



Author: edmanm
Date: 2008-04-12 18:02:27 -0400 (Sat, 12 Apr 2008)
New Revision: 2511

Modified:
   vidalia/trunk/
   vidalia/trunk/src/torcontrol/circuit.cpp
   vidalia/trunk/src/torcontrol/circuit.h
   vidalia/trunk/src/torcontrol/circuitevent.h
   vidalia/trunk/src/torcontrol/torcontrol.cpp
   vidalia/trunk/src/torcontrol/torcontrol.h
   vidalia/trunk/src/torcontrol/torevents.cpp
   vidalia/trunk/src/vidalia/network/circuititem.cpp
   vidalia/trunk/src/vidalia/network/circuititem.h
   vidalia/trunk/src/vidalia/network/circuitlistwidget.cpp
   vidalia/trunk/src/vidalia/network/circuitlistwidget.h
   vidalia/trunk/src/vidalia/network/netviewer.cpp
   vidalia/trunk/src/vidalia/network/netviewer.h
   vidalia/trunk/src/vidalia/network/routerlistwidget.cpp
   vidalia/trunk/src/vidalia/network/routerlistwidget.h
Log:
 r351@lysithea:  edmanm | 2008-04-12 18:00:15 -0400
 Switch to using 'getinfo ns/all' instead of 'getinfo network-status' to figure
 out which routers are running, and only add running routers to the big list on
 the left of the network map. Also add support for 'usefeature verbose_names'
 and use it by default.



Property changes on: vidalia/trunk
___________________________________________________________________
 svk:merge ticket from /local/vidalia/trunk [r351] on 90112fd6-a33b-4cea-8d39-48ff1d78625c

Modified: vidalia/trunk/src/torcontrol/circuit.cpp
===================================================================
--- vidalia/trunk/src/torcontrol/circuit.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/circuit.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -15,6 +15,7 @@
 */
 
 #include <QStringList>
+#include <QRegExp>
 
 #include "circuit.h"
 
@@ -22,71 +23,61 @@
 /** Default constructor. */
 Circuit::Circuit()
 {
-  _circId = 0;
-  _status = Unknown;
-  _path   = QString();
+  _circId  = 0;
+  _status  = Unknown;
+  _isValid = false;
 }
 
-/** Constructor */
-Circuit::Circuit(quint64 circId, Status status, QString path)
-{
-  _circId = circId;
-  _status = status;
-  _path   = path;
-}
-
-/** Constructor */
-Circuit::Circuit(quint64 circId, Status status, QStringList hops)
-{
-  _circId = circId;
-  _status = status;
-  _path   = hops.join(",");
-}
-
 /** Parses the string given in Tor control protocol format for a circuit. The
  * format is:
  * 
  *      CircuitID SP CircStatus [SP Path]
  *
- * If the status is "LAUNCHED", the Path is empty.
+ * If the status is "LAUNCHED", the Path is empty. Server names in the path
+ * must follow Tor's VERBOSE_NAMES format.
  */
-Circuit
-Circuit::fromString(QString circuit)
+Circuit::Circuit(const QString &circuit)
 {
+  _isValid = false;
+
   QStringList parts = circuit.split(" ");
   if (parts.size() >= 2) {
     /* Get the circuit ID */
-    quint64 circId = (quint64)parts.at(0).toULongLong();
+    _circId = (quint64)parts.at(0).toULongLong();
     /* Get the circuit status value */
-    Circuit::Status status = Circuit::toStatus(parts.at(1));
+    _status = Circuit::toStatus(parts.at(1));
+
     /* Get the circuit path (list of routers) */
-    QString path = (parts.size() > 2 ? parts.at(2) : "");
+    if (parts.size() > 2) {
+      foreach (QString hop, parts.at(2).split(",")) {
+        QStringList parts = hop.split(QRegExp("[=~]"));
+        if (parts.size() != 2)
+          return;
 
-    return Circuit(circId, status, path);
+        _ids   << parts.at(0).mid(1);
+        _names << parts.at(1);
+      }
+    }
+
+    _isValid = true;
   }
-  return Circuit();
 }
 
 /** Converts the circuit status string to its proper enum value */
 Circuit::Status
-Circuit::toStatus(QString strStatus)
+Circuit::toStatus(const QString &status)
 {
-  Status status;
-  strStatus = strStatus.toUpper();
-  if (strStatus == "LAUNCHED") {
-    status = Launched;
-  } else if (strStatus == "BUILT") {
-    status = Built;
-  } else if (strStatus == "EXTENDED") {
-    status = Extended;
-  } else if (strStatus == "FAILED") {
-    status = Failed;
-  } else if (strStatus == "CLOSED") {
-    status = Closed;
-  } else {
-    status = Unknown;
-  }
-  return status;
+  if (!status.compare("LAUNCHED", Qt::CaseInsensitive))
+    return Launched;
+  if (!status.compare("BUILT", Qt::CaseInsensitive))
+    return Built;
+  if (!status.compare("EXTENDED", Qt::CaseInsensitive))
+    return Extended;
+  if (!status.compare("FAILED", Qt::CaseInsensitive))
+    return Failed;
+  if (!status.compare("CLOSED", Qt::CaseInsensitive))
+    return Closed;
+  return Unknown;
 }
 
 /** Returns a string representation of the circuit's status. */
@@ -105,10 +96,3 @@
   return status;
 }
 
-/** Returns true if all fields in this Circuit object are empty. */
-bool
-Circuit::isEmpty() const
-{
-  return (!_circId && (_status == Unknown));
-}
-

Modified: vidalia/trunk/src/torcontrol/circuit.h
===================================================================
--- vidalia/trunk/src/torcontrol/circuit.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/circuit.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -19,7 +19,6 @@
 
 #include <QCoreApplication>
 #include <QStringList>
-#include <QString>
 
 
 class Circuit
@@ -39,18 +38,11 @@
 
   /** Default constructor. */
   Circuit();
-  /** Constructor */
-  Circuit(quint64 circId, Status status, QString path);
-  /** Constructor */
-  Circuit(quint64 circId, Status status, QStringList hops);
-
-  /** Parses the given string (in Tor's control protocol format) */
-  static Circuit fromString(QString circuit);
-  /** Converts a string description of a circuit's status to an enum value */
-  static Status toStatus(QString strStatus);
+  /** Constructor. */  
+  Circuit(const QString &circuit);
   
-  /** Returns true if all fields in this Circuit are empty. */
-  bool isEmpty() const;
+  /** Returns true if this circuit is valid. */
+  bool isValid() const { return _isValid; }
   
   /** Returns the ID for this circuit */
   quint64 id() const { return _circId; }
@@ -58,19 +50,26 @@
   Status status() const { return _status; }
   /** Returns a string representation of the status of this circuit. */
   QString statusString() const;
-  /** Returns the path chosen for this circuit */
-  QString path() const { return _path; }
   /** Returns the length of the circuit's path. */
-  uint length() const { return hops().size(); }
-  /** Returns a list of hops on the path. */
-  QStringList hops() const { return _path.isEmpty() ? QStringList() 
-                                                    : _path.split(","); }
+  uint length() const { return _ids.size(); }
+  /** Returns the circuit's path as an ordered list of router nicknames. */
+  QStringList routerNames() const { return _names; }
+  /** Returns the circuit's path as an ordered list of router fingerprints. */
+  QStringList routerIDs() const { return _ids; }
 
+  /** Converts a string description of a circuit's status to an enum value */
+  static Status toStatus(const QString &strStatus);
+
 private:
   quint64 _circId; /**< Circuit ID. */
   Status _status;  /**< Circuit status. */
-  QString _path;   /**< Circuit path. */
+  QStringList _names;  /**< Nicknames of the routers in the circuit. */
+  QStringList _ids;    /**< IDs of the routers in the circuit. */
+  bool _isValid;
 };
 
+/** A collection of circuits. */
+typedef QList<Circuit> CircuitList;
+
 #endif
 

Modified: vidalia/trunk/src/torcontrol/circuitevent.h
===================================================================
--- vidalia/trunk/src/torcontrol/circuitevent.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/circuitevent.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -37,8 +37,10 @@
   quint64 id() const { return _circuit.id(); }
   /** Returns the status of this circuit event. */
   Circuit::Status status() const { return _circuit.status(); }
-  /** Returns the path chosen for this circuit event.  */
-  QString path() const { return _circuit.path(); }
+  /** Returns the names of the routers in the path for this circuit event. */
+  QStringList routerNames() const { return _circuit.routerNames(); }
+  /** Returns the IDs of the routers in the path for this circuit event. */
+  QStringList routerIDs() const { return _circuit.routerIDs(); }
   
 private:
   /** Circuit object for this event. */

Modified: vidalia/trunk/src/torcontrol/torcontrol.cpp
===================================================================
--- vidalia/trunk/src/torcontrol/torcontrol.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/torcontrol.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -280,7 +280,9 @@
   /* The version of Tor isn't going to change while we're connected to it, so
    * save it for later. */
   getInfo("version", _torVersion);
-  
+  /* We want to use verbose names in events and GETINFO results. */
+  useFeature("VERBOSE_NAMES");
+
   /* The control socket is connected, so we can stop reading from stdout */
   if (_torProcess)
     _torProcess->closeStdout();
@@ -332,6 +334,16 @@
   return pi;
 }
 
+/** Tells Tor the controller wants to enable <b>feature</b> via the
+ * USEFEATURE control command. Returns true if the given feature was
+ * successfully enabled. */
+bool
+TorControl::useFeature(const QString &feature, QString *errmsg)
+{
+  ControlCommand cmd("USEFEATURE", feature);
+  return send(cmd, errmsg); 
+}
+
 /** Returns true if Tor either has an open circuit or (on Tor >=
  * 0.2.0.1-alpha) has previously decided it's able to establish a circuit. */
 bool
@@ -347,7 +359,7 @@
 
   /* Either Tor was too old or our getinfo failed, so try to get a list of all
    * circuits and check their statuses. */
-  QList<Circuit> circs = getCircuits();
+  CircuitList circs = getCircuits();
   foreach (Circuit circ, circs) {
     if (circ.status() == Circuit::Built)
       return true;
@@ -848,170 +860,69 @@
   return resetConf(QStringList() << key, errmsg);
 }
 
-/** Gets the descriptor for the specified router name. */
+/** Returns the descriptor for the router whose fingerprint matches
+ * <b>id</b>. If <b>id</b> is invalid or the router's descriptor cannot
+ * be parsed, then an invalid RouterDescriptor is returned. */
 RouterDescriptor
-TorControl::getDescriptorByName(QString name, QString *errmsg)
+TorControl::getRouterDescriptor(const QString &id, QString *errmsg)
 {
-  QList<RouterDescriptor> rdlist;
-  RouterDescriptor rd;
-  
-  rdlist = getDescriptorListByName(QStringList() << name, errmsg);
-  if (!rdlist.isEmpty()) {
-    rd = (RouterDescriptor)rdlist.takeFirst();
-    return rd;
-  }
-  return RouterDescriptor();
+  QStringList descriptor = getInfo("desc/id/" + id, errmsg).toStringList();
+  return RouterDescriptor(descriptor);
 }
 
-/** Gets the descriptor for the specified ID. */
-RouterDescriptor
-TorControl::getDescriptorById(QString id, QString *errmsg)
+/** Returns the status of the router whose fingerprint matches <b>id</b>. If
+ * <b>id</b> is invalid or the router's status cannot be parsed, then an
+ * invalid RouterStatus is returned. */
+RouterStatus
+TorControl::getRouterStatus(const QString &id, QString *errmsg)
 {
-  QList<RouterDescriptor> rdlist;
-  RouterDescriptor rd;
-  
-  rdlist = getDescriptorListById(QStringList() << id, errmsg);
-  if (!rdlist.isEmpty()) {
-    rd = (RouterDescriptor)rdlist.takeFirst();
-    return rd;
-  }
-  return RouterDescriptor();
+  QStringList status = getInfo("ns/id/" + id, errmsg).toStringList();
+  return RouterStatus(status);
 }
 
-/** Gets router descriptors for all names in <b>nameList</b>. */
-QList<RouterDescriptor>
-TorControl::getDescriptorListByName(QStringList nameList, QString *errmsg)
+/** Returns a RouterStatus object for every known router in the network. If
+ * the network status document cannot be parsed, then an empty NetworkStatus
+ * is returned. */
+NetworkStatus
+TorControl::getNetworkStatus(QString *errmsg)
 {
-  ControlCommand cmd("GETINFO");
-  ControlReply reply;
-  QList<RouterDescriptor> rdlist;
+  QStringList networkStatusLines = getInfo("ns/all", errmsg).toStringList();
+  QList<RouterStatus> networkStatus;
+  int len = networkStatusLines.size();
+  int i = 0;
   
-  /* If there are no IDs in the list, then return now. */
-  if (nameList.isEmpty()) {
-    return QList<RouterDescriptor>();
+  while (i < len) {
+    /* Extract the "r", "s", and whatever other status lines */
+    QStringList routerStatusLines;
+    do {
+      routerStatusLines << networkStatusLines.at(i);
+    } while (++i < len && ! networkStatusLines.at(i).startsWith("r "));
+    
+    /* Create a new RouterStatus object and add it to the network status, if
+     * it's valid. */
+    RouterStatus routerStatus(routerStatusLines);
+    if (routerStatus.isValid())
+      networkStatus << routerStatus;
   }
-  
-  /* Build up the the getinfo arguments from the list of names */
-  foreach (QString name, nameList) {
-    cmd.addArgument("desc/name/"+ name);
-  }
-  
-  /* Request the list of router descriptors */
-  if (send(cmd, reply, errmsg)) {
-    foreach (ReplyLine line, reply.getLines()) {
-      /* Check if we got a "250 OK" and descriptor data. */
-      if (line.getStatus() == "250" && !line.getData().isEmpty()) {
-        /* Parse the router descriptor data */
-        rdlist << RouterDescriptor(line.getData());
-      }
-    }
-  }
-  return rdlist;
+  return networkStatus;
 }
 
-/** Gets router descriptors for all IDs in <b>idlist</b>. */
-QList<RouterDescriptor>
-TorControl::getDescriptorListById(QStringList idlist, QString *errmsg)
-{
-  ControlCommand cmd("GETINFO");
-  ControlReply reply;
-  QHash<QString,bool> offline;
-  QList<RouterDescriptor> rdlist;
-  
-  /* If there are no IDs in the list, then return now. */
-  if (idlist.isEmpty()) {
-    return QList<RouterDescriptor>();
-  }
-  
-  /* Build up the the getinfo arguments fromthe list of IDs */
-  foreach (QString id, idlist) {
-    if (id.startsWith("!")) {
-      /* The ! means this router is offline. Save a list of the offline
-       * routers for easy lookup after we get all descriptors from Tor */
-      id = id.remove("!");
-      offline.insert(id, true);
-    }
-    cmd.addArgument("desc/id/"+ id);
-  }
-  
-  /* Request the list of router descriptors */
-  if (send(cmd, reply, errmsg)) {
-    foreach (ReplyLine line, reply.getLines()) {
-      /* Check if we got a "250 OK" and descriptor data. */
-      if (line.getStatus() == "250" && !line.getData().isEmpty()) {
-        /* Parse the router descriptor data */
-        RouterDescriptor rd(line.getData());
-        rd.setOffline(!offline.isEmpty() && offline.contains(rd.id()));
-        rdlist << rd;
-      }
-    }
-  }
-  return rdlist;
-}
-
-/** Gets a list of RouterDescriptor objects for all routers that Tor currently
- * knows about. */
-QList<RouterDescriptor>
-TorControl::getRouterList(QString *errmsg)
-{
-  /* Get a list of all router IDs Tor currently know about */
-  QStringList idList = getRouterIDList(errmsg);
-  /* Get descriptors for each of those routers */
-  return getDescriptorListById(idList, errmsg);
-}
-
-/** Gets a list of router IDs for all routers Tor knows about. */
-QStringList
-TorControl::getRouterIDList(QString *errmsg)
-{
-  ControlCommand cmd("GETINFO", "network-status");
-  ControlReply reply;
-  QStringList idList;
-
-  if (send(cmd, reply, errmsg)) {
-    QString routerIDs = reply.getMessage().remove(0,qstrlen("network-status="));
-
-    /* Split the list of router IDs up */
-    QStringList routers = routerIDs.split(" ");
-    foreach (QString router, routers) {
-      /* A router ID may be of the form <name>=$<ID>, $<ID>, or <ID> */
-      QString id = router.mid(router.indexOf("=")+1);
-      id = id.replace("$", "");
-      /* A "!" before <name> or <ID> means "unresponsive" */
-      if (router.startsWith("!") && !id.startsWith("!")) {
-        id.prepend("!");
-      }
-      /* Add this router ID to the list. */
-      idList << id;
-    }
-  }
-  return idList;
-}
-
 /** Gets a list of current circuits. */
 QList<Circuit>
 TorControl::getCircuits(QString *errmsg)
 {
   ControlCommand cmd("GETINFO", "circuit-status");
   ControlReply reply;
-  QList<Circuit> circuits;
-  Circuit c;
+  CircuitList circuits;
   
-  if (send(cmd, reply, errmsg)) {
-    /* Sometimes there is a circuit on the first message line */
-    QString msg = reply.getMessage();
-    c = Circuit::fromString(msg.mid(msg.indexOf("=")+1));
-    if (!c.isEmpty()) {
-      circuits << c;
-    }
+  if (!send(cmd, reply, errmsg))
+    return CircuitList();
 
-    /* The rest of the circuits just come as data, one per line */
-    foreach(QString line, reply.getData()) {
-      c = Circuit::fromString(line);
-      if (!c.isEmpty()) {
-        circuits << Circuit::fromString(line);
-      }
-    }
+  /* The rest of the circuits just come as data, one per line */
+  foreach(QString line, reply.getData()) {
+    Circuit circ(line);
+    if (circ.isValid())
+      circuits << circ;
   }
   return circuits;
 }

Modified: vidalia/trunk/src/torcontrol/torcontrol.h
===================================================================
--- vidalia/trunk/src/torcontrol/torcontrol.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/torcontrol.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -28,6 +28,7 @@
 #include "torevents.h"
 #include "torsignal.h"
 #include "routerdescriptor.h"
+#include "routerstatus.h"
 #include "addressmap.h"
 #include "protocolinfo.h"
 
@@ -155,23 +156,24 @@
   /** Tells Tor to reset a configuration key back to its default value. */
   bool resetConf(QString key, QString *errmsg = 0);
 
-  /** Gets a descriptor for the given router name. */
-  RouterDescriptor getDescriptorByName(QString name, QString *errmsg = 0);
-  /** Gets a descriptor for the given router ID. */
-  RouterDescriptor getDescriptorById(QString id, QString *errmsg = 0);
-  /** Gets descriptors for the given list of router names. */
-  QList<RouterDescriptor> getDescriptorListByName(QStringList names, QString *errmsg = 0);
-  /** Gets descriptors for the given list of router IDs. */
-  QList<RouterDescriptor> getDescriptorListById(QStringList ids, QString *errmsg = 0);
-  /** Gets a list of descriptors for all routers Tor knows about. */
-  QList<RouterDescriptor> getRouterList(QString *errmsg = 0);
-  /** Gets a list of router IDs for all routers Tor knows about. */
-  QStringList getRouterIDList(QString *errmsg = 0);
+  /** Returns the descriptor for the router whose fingerprint matches
+   * <b>id</b>. If <b>id</b> is invalid or the router's descriptor cannot be
+   * parsed, then an invalid RouterDescriptor is returned. */
+  RouterDescriptor getRouterDescriptor(const QString &id, QString *errmsg = 0);
+  /** Returns the status of the router whose fingerprint matches <b>id</b>. If
+   * <b>id</b> is invalid or the router's status cannot be parsed, then an
+   * invalid RouterStatus is returned. */
+  RouterStatus getRouterStatus(const QString &id, QString *errmsg = 0);
+  /** Returns a RouterStatus object for every known router in the network. If
+   * the network status document cannot be parsed, then an empty NetworkStatus
+   * is returned. */
+  NetworkStatus getNetworkStatus(QString *errmsg = 0);
 
+
   /** Gets a list of current circuits. */
-  QList<Circuit> getCircuits(QString *errmsg = 0);
+  CircuitList getCircuits(QString *errmsg = 0);
   /** Gets a list of current streams. */
-  QList<Stream> getStreams(QString *errmsg = 0);
+  StreamList getStreams(QString *errmsg = 0);
   
   /** Gets a list of address mappings of the type specified by <b>type</b>
    * (defaults to <i>AddressMapAll</i>. */
@@ -224,7 +226,11 @@
   bool send(ControlCommand cmd, ControlReply &reply, QString *errmsg = 0);
   /** Send a message to Tor and discard the response */
   bool send(ControlCommand cmd, QString *errmsg = 0);
-  
+  /** Tells Tor the controller wants to enable <b>feature</b> via the
+   * USEFEATURE control command. Returns true if the given feature was
+   * successfully enabled. */
+  bool useFeature(const QString &feature, QString *errmsg = 0);
+
 /* The slots below simply relay signals from the appropriate member objects */
 private slots:
   void onStarted();

Modified: vidalia/trunk/src/torcontrol/torevents.cpp
===================================================================
--- vidalia/trunk/src/torcontrol/torevents.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/torcontrol/torevents.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -245,7 +245,9 @@
   int i = msg.indexOf(" ") + 1;
   if (i > 0) {
     /* Post the event to each of the interested targets */
-    dispatch(CircuitStatus, new CircuitEvent(Circuit::fromString(msg.mid(i))));
+    Circuit circ(msg.mid(i));
+    if (circ.isValid())
+      dispatch(CircuitStatus, new CircuitEvent(circ));
   }
 }
 

Modified: vidalia/trunk/src/vidalia/network/circuititem.cpp
===================================================================
--- vidalia/trunk/src/vidalia/network/circuititem.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/circuititem.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -19,23 +19,24 @@
 
 
 /** Constructor */
-CircuitItem::CircuitItem(Circuit circuit, QString displayedPath)
+CircuitItem::CircuitItem(const Circuit &circuit)
 {
   /* Update the displayed text */
-  update(circuit, displayedPath);
+  update(circuit);
 }
 
 /** Updates the status and path of this circuit item. */
 void
-CircuitItem::update(Circuit circuit, QString displayedPath)
+CircuitItem::update(const Circuit &circuit)
 {
+  QString displayedPath;
+
   /* Save the Circuit object */
   _circuit = circuit;
   
   /* Use a semi-meaningful value if the path is empty */
-  if (displayedPath.isEmpty()) {
-    displayedPath = tr("<Path Empty>");
-  }
+  displayedPath = circuit.length() > 0 ? circuit.routerNames().join(",")
+                                       : tr("<Path Empty>");
 
   /* Update the column fields */
   setText(CircuitListWidget::ConnectionColumn, displayedPath);

Modified: vidalia/trunk/src/vidalia/network/circuititem.h
===================================================================
--- vidalia/trunk/src/vidalia/network/circuititem.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/circuititem.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -31,14 +31,14 @@
 
 public:
   /** Default constructor */
-  CircuitItem(Circuit circuit, QString displayedPath);
+  CircuitItem(const Circuit &circuit);
  
   /** Adds a stream to this circuit item */
   void addStream(StreamItem *stream);
   /** Removes the stream item from the list and frees its memory. */
   void removeStream(StreamItem *stream);
   /** Updates the status of this circuit item using the given circuit. */
-  void update(Circuit circuit, QString displayedPath);
+  void update(const Circuit &circuit);
   /** Returns the ID for this circuit. */
   quint64 id() { return _circuit.id(); }
   /** Returns the Circuit object for this item. */

Modified: vidalia/trunk/src/vidalia/network/circuitlistwidget.cpp
===================================================================
--- vidalia/trunk/src/vidalia/network/circuitlistwidget.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/circuitlistwidget.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -121,22 +121,21 @@
   }
 }
 
-/** Adds a circuit to the list. If the circuit already exists in the list, the
- * status and path will be updated. <b>displayedPath</b> contains a
- * description of the circuit's path suitable for humans to read. */
+/** Adds a <b>circuit</b> to the list. If the circuit already exists in the
+ * list, the status and path will be updated. */
 void
-CircuitListWidget::addCircuit(Circuit circuit, QString displayedPath)
+CircuitListWidget::addCircuit(const Circuit &circuit)
 {
   /* Check to see if the circuit already exists in the tree */
   CircuitItem *item = findCircuitItem(circuit.id());
   
   if (!item) {
     /* Add the new circuit */
-    item = new CircuitItem(circuit, displayedPath);
+    item = new CircuitItem(circuit);
     addTopLevelItem(item);
   } else {
     /* Circuit already exists, so update its status and path */
-    item->update(circuit, displayedPath);
+    item->update(circuit);
   }
 
   /* If the circuit is closed or dead, schedule it for removal */
@@ -151,7 +150,7 @@
 /** Adds a stream to the list. If the stream already exists in the list, the
  * status and path will be updated. */
 void
-CircuitListWidget::addStream(Stream stream)
+CircuitListWidget::addStream(const Stream &stream)
 {
   /* Check to see if the stream already exists in the tree */
   StreamItem *item = findStreamItem(stream.id());
@@ -326,18 +325,16 @@
     }
 
     /* If this circuit has a path, then emit it so we can highlight it */
-    if (circuit.length() > 0) {
-      emit circuitSelected(circuit);
-    }
+    emit circuitSelected(circuit);
   }
 }
 
 /** Returns a list of circuits currently in the widget. */
-QList<Circuit>
+CircuitList
 CircuitListWidget::circuits()
 {
   int numCircs = topLevelItemCount();
-  QList<Circuit> circs;
+  CircuitList circs;
   
   for (int i = 0; i < numCircs; i++) {
     CircuitItem *circ = (CircuitItem *)topLevelItem(i);

Modified: vidalia/trunk/src/vidalia/network/circuitlistwidget.h
===================================================================
--- vidalia/trunk/src/vidalia/network/circuitlistwidget.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/circuitlistwidget.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -43,10 +43,10 @@
 
   /** Adds a circuit to the list. If the circuit already exists in the list,
    * the status and path will be updated. */
-  void addCircuit(Circuit circuit, QString displayedPath);
+  void addCircuit(const Circuit &circuit);
   /** Adds a stream to the list. If the stream already exists in the list, the
    * status and path will be updated. */
-  void addStream(Stream stream);
+  void addStream(const Stream &stream);
   /** Returns a list of circuits currently in the widget. */
   QList<Circuit> circuits();
 

Modified: vidalia/trunk/src/vidalia/network/netviewer.cpp
===================================================================
--- vidalia/trunk/src/vidalia/network/netviewer.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/netviewer.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -154,7 +154,7 @@
   if (type == CustomEventType::NewDescriptorEvent) {
     /* New router descriptor, so load it and add it to the list */
     NewDescriptorEvent *nde = (NewDescriptorEvent *)event;
-    loadDescriptors(nde->descriptorIDs());
+    newDescriptors(nde->descriptorIDs());
   } else if (type == CustomEventType::CircuitEvent) {
     /* New or updated circuit information */
     CircuitEvent *ce = (CircuitEvent *)event;
@@ -185,7 +185,7 @@
   clear();
 
   /* Load router information */
-  loadDescriptors(_torControl->getRouterIDList());
+  loadNetworkStatus();
   /* Load existing address mappings */
   loadAddressMap();
   /* Load Circuits and Streams information */
@@ -227,12 +227,12 @@
 NetViewer::loadConnections()
 {
   /* Load all circuits */
-  QList<Circuit> circuits = _torControl->getCircuits();
+  CircuitList circuits = _torControl->getCircuits();
   foreach (Circuit circuit, circuits) {
     addCircuit(circuit);
   }
   /* Now load all streams */
-  QList<Stream> streams = _torControl->getStreams();
+  StreamList streams = _torControl->getStreams();
   foreach (Stream stream, streams) {
     addStream(stream);
   }
@@ -243,20 +243,17 @@
 
 /** Adds <b>circuit</b> to the map and the list */
 void
-NetViewer::addCircuit(Circuit circuit)
+NetViewer::addCircuit(const Circuit &circuit)
 {
-  /* Circuits displayed to the user always use nicknames */
-  Circuit circNames = circuitPathNames(circuit);
-  /* Circuits on the map always use keyids */
-  Circuit circIds   = circuitPathIDs(circuit);
-
-  ui.treeCircuitList->addCircuit(circuit, circNames.path());
-  _map->addCircuit(circuit.id(), circIds.hops());
+  /* Add the circuit to the list of all current circuits */
+  ui.treeCircuitList->addCircuit(circuit);
+  /* Plot the circuit on the map */
+  _map->addCircuit(circuit.id(), circuit.routerIDs());
 }
 
 /** Adds <b>stream</b> to its associated circuit on the list of all circuits. */
 void
-NetViewer::addStream(Stream stream)
+NetViewer::addStream(const Stream &stream)
 {
   QString target = stream.targetAddress();
   QHostAddress addr(target);
@@ -266,10 +263,12 @@
   if (!addr.isNull() && _addressMap.isMapped(target)) {
     /* Replace the IP address in the stream event with the original 
      * hostname */
-    stream = Stream(stream.id(), stream.status(), stream.circuitId(),
-                    _addressMap.mappedTo(target), stream.targetPort());
+    ui.treeCircuitList->addStream(
+      Stream(stream.id(), stream.status(), stream.circuitId(),
+             _addressMap.mappedTo(target), stream.targetPort()));
+  } else {
+    ui.treeCircuitList->addStream(stream);
   }
-  ui.treeCircuitList->addStream(stream);
 }
 
 /** Called when the user selects the "Help" action from the toolbar. */
@@ -279,35 +278,46 @@
   emit helpRequested("netview");
 }
 
-/** Loads a list of new descriptors from the given IDs. */
+/** Retrieves a list of all running routers from Tor and their descriptors,
+ * and adds them to the RouterListWidget. */
 void
-NetViewer::loadDescriptors(QStringList ids)
+NetViewer::loadNetworkStatus()
 {
-  /* Get descriptors for all the given IDs */
-  QList<RouterDescriptor> rds = _torControl->getDescriptorListById(ids);
-  
-  vInfo("Loading %1 relay descriptors for the network map.")
-                                             .arg(rds.size());
-  foreach (RouterDescriptor rd, rds) {
-    /* Load the router descriptor and add it to the router list. */
-    if (!rd.isEmpty()) {
+  NetworkStatus networkStatus = _torControl->getNetworkStatus();
+  foreach (RouterStatus rs, networkStatus) {
+    if (!rs.isRunning())
+      continue;
+
+    RouterDescriptor rd = _torControl->getRouterDescriptor(rs.id());
+    if (!rd.isEmpty())
       addRouter(rd);
-    }
   }
 }
 
 /** Adds a router to our list of servers and retrieves geographic location
  * information for the server. */
 void
-NetViewer::addRouter(RouterDescriptor rd)
+NetViewer::addRouter(const RouterDescriptor &rd)
 {
   /* Add the descriptor to the list of server */
   ui.treeRouterList->addRouter(rd);
-
   /* Add this IP to a list whose geographic location we'd like to find. */
   addToResolveQueue(rd.ip(), rd.id());
 }
 
+/** Called when a NEWDESC event arrives. Retrieves new router descriptors
+ * for the router identities given in <b>ids</b> and updates the router
+ * list and network map. */
+void
+NetViewer::newDescriptors(const QStringList &ids)
+{
+  foreach (QString id, ids) {
+    RouterDescriptor rd = _torControl->getRouterDescriptor(id);
+    if (!rd.isEmpty())
+      addRouter(rd); /* Updates the existing entry */
+  }
+}
+
 /** Adds an IP address to the resolve queue and updates the queue timers. */
 void
 NetViewer::addToResolveQueue(QHostAddress ip, QString id)
@@ -350,14 +360,11 @@
 
   QList<RouterDescriptor> routers;
 
-  foreach (QString router, circuit.hops()) {
+  foreach (QString id, circuit.routerIDs()) {
     /* Try to find and select each router in the path */
-    RouterListItem *item = (router.startsWith("$") ? 
-                ui.treeRouterList->findRouterById(router.mid(1))
-              : ui.treeRouterList->findRouterByName(router));
-    if (item) {
+    RouterListItem *item = ui.treeRouterList->findRouterById(id);
+    if (item)
       routers.append(item->descriptor());
-    }
   }
 
   ui.textRouterInfo->display(routers);
@@ -426,88 +433,10 @@
 
   /* Update the circuit lines */
   foreach (Circuit circuit, ui.treeCircuitList->circuits()) {
-    _map->addCircuit(circuit.id(), circuitPathIDs(circuit).hops());
+    _map->addCircuit(circuit.id(), circuit.routerIDs());
   }
-  
+
   /* Repaint the map */
   _map->update();
 }
 
-/** Convert all hops in <b>circ</b>'s path to server identities. <b>circ</b>'s
- * status and circuit ID will be preserved. If no ID can be found for a
- * router name, the name will be left in the circuit's path. */
-Circuit
-NetViewer::circuitPathIDs(Circuit circ)
-{
-  QStringList path = circ.hops();
-  QStringList ids;
-  RouterDescriptor rd;
-  quint32 torVersion;
-
-  torVersion = _torControl->getTorVersion();
-  foreach (QString hop, path) {
-    if (hop.startsWith("$")) {
-      /* This hop is already specified as a keyid, so just strip the "$" */
-      hop.remove(0,1);
-    } else {
-      if (torVersion < 0x00010202) {
-        /* Tor versions earlier than 0.1.2.2 have a bug where they will tell
-         * you a server's nickname in a circuit, even if that server is
-         * non-Named. If we requested the descriptor by name for a non-Named server
-         * from Tor, the user's log could be filled with warnings. So, just
-         * try to look it up from our own router list first. */
-        RouterListItem *item = ui.treeRouterList->findRouterByName(hop);
-        if (item) {
-          rd = item->descriptor();
-        } else {
-          /* We don't know about the router, so try to get it by name even
-           * though Tor will probably yell at us. We can't help it. */
-          rd = _torControl->getDescriptorByName(hop);
-          if (!rd.isEmpty()) {
-            /* Add this router to the list of those we know about */
-            addRouter(rd);
-          }
-        }
-      } else {
-        /* Ask Tor for the descriptor for the given router name */
-        rd = _torControl->getDescriptorByName(hop);
-      }
-      hop = (rd.isEmpty() ? hop : rd.id());
-    }
-    ids << hop;
-  }
-  return Circuit(circ.id(), circ.status(), ids);
-}
-
-/** Convert all hops in <b>circ</b>'s path to server names. <b>circ</b>'s
- * status and circuit ID will be preserved. If no name can be found for a
- * server identity, the ID will be left in the circuit's path. */
-Circuit
-NetViewer::circuitPathNames(Circuit circ)
-{
-  QStringList path = circ.hops();
-  QStringList names;
-  RouterDescriptor rd;
-  
-  foreach (QString hop, path) {
-    if (hop.startsWith("$")) {
-      /* Check if we already have a descriptor for this server identity. */
-      RouterListItem *item =  ui.treeRouterList->findRouterById(hop.mid(1));
-      if (item) {
-        rd = item->descriptor();
-      } else {
-        /* A router with the current hop ID does not exist in our router list,
-         * so ask Tor for its descriptor */
-        rd = _torControl->getDescriptorById(hop);
-        if (!rd.isEmpty()) {
-          /* This is a fine time to add this new router to our list */
-          addRouter(rd);
-        }
-      }
-      hop = (rd.isEmpty() ? hop : rd.name());
-    }
-    names << hop;
-  }
-  return Circuit(circ.id(), circ.status(), names);
-}
-

Modified: vidalia/trunk/src/vidalia/network/netviewer.h
===================================================================
--- vidalia/trunk/src/vidalia/network/netviewer.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/netviewer.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -44,10 +44,10 @@
   /** Loads a list of current circuits and streams. */
   void loadConnections();
   /** Adds <b>circuit</b> to the list and the map */
-  void addCircuit(Circuit circuit);
+  void addCircuit(const Circuit &circuit);
   /** Adds <b>stream</b> to the list of circuits, under the appropriate
    * circuit. */
-  void addStream(Stream stream);
+  void addStream(const Stream &stream);
   /** Clears all known information */
   void clear();
 
@@ -76,19 +76,18 @@
 private:
   /** Adds an IP address to the resolve queue and updates the queue timers. */
   void addToResolveQueue(QHostAddress ip, QString id);
-  /** Loads a list of router descriptors from the list of IDs. */
-  void loadDescriptors(QStringList ids);
+  /** Retrieves a list of all running routers from Tor and their descriptors,
+   * and adds them to the RouterListWidget. */
+  void loadNetworkStatus();
   /** Loads a list of address mappings from Tor. */
   void loadAddressMap();
   /** Adds a router to our list of servers and retrieves geographic location
    * information for the server. */
-  void addRouter(RouterDescriptor rd);
-  /** Convert all hops in <b>circ</b>'s path to server identities.
-  * <b>circ</b>'s status and circuit ID will be preserved. */
-  Circuit circuitPathIDs(Circuit circ);
-  /** Convert all hops in <b>circ</b>'s path to server names. <b>circ</b>'s
-   * status and circuit ID will be preserved. */
-  Circuit circuitPathNames(Circuit circ);
+  void addRouter(const RouterDescriptor &rd);
+  /** Called when a NEWDESC event arrives. Retrieves new router descriptors
+   * for the router identities given in <b>ids</b> and updates the router list
+   * and network map. */
+  void newDescriptors(const QStringList &ids);
 
   /** TorControl object used to talk to Tor. */
   TorControl* _torControl;

Modified: vidalia/trunk/src/vidalia/network/routerlistwidget.cpp
===================================================================
--- vidalia/trunk/src/vidalia/network/routerlistwidget.cpp	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/routerlistwidget.cpp	2008-04-12 22:02:27 UTC (rev 2511)
@@ -25,8 +25,6 @@
 RouterListWidget::RouterListWidget(QWidget *parent)
 : QTreeWidget(parent)
 {
-  _onlineRouterCount = 0;
-  
   /* Create and initialize columns */
   setHeaderLabels(QStringList() << QString("")
                                 << QString("")
@@ -81,8 +79,8 @@
 RouterListWidget::clearRouters()
 {
   _idmap.clear();
-  _onlineRouterCount = 0;
   QTreeWidget::clear();
+  setStatusTip(tr("%1 relays online").arg(0));
 }
 
 /** Called when the user selects a router from the list. This will search the
@@ -159,8 +157,6 @@
 
   RouterListItem *item = findRouterById(id);
   if (item) {
-    if (item->descriptor().online())
-      _onlineRouterCount--;
     item->update(rd);
   } else {
     item = new RouterListItem(this, rd);
@@ -169,10 +165,7 @@
   }
 
   /* Set our status tip to the number of servers in the list */
-  if (rd.online())
-    _onlineRouterCount++;
-  setStatusTip(tr("%1 relays online (%2 total)").arg(_onlineRouterCount)
-                                                .arg(topLevelItemCount()));
+  setStatusTip(tr("%1 relays online").arg(topLevelItemCount()));
 }
 
 /** Called when the selected items have changed. This emits the 

Modified: vidalia/trunk/src/vidalia/network/routerlistwidget.h
===================================================================
--- vidalia/trunk/src/vidalia/network/routerlistwidget.h	2008-04-12 22:02:24 UTC (rev 2510)
+++ vidalia/trunk/src/vidalia/network/routerlistwidget.h	2008-04-12 22:02:27 UTC (rev 2511)
@@ -81,7 +81,6 @@
 private:
   /** Maps a server ID to that server's list item. */
   QHash<QString,RouterListItem*> _idmap;
-  quint32  _onlineRouterCount; /**< Number of online routers. */
 };
 
 #endif