[tor-commits] [vidalia/alpha] Display stream traffic in the Circuit list in the Network Map

chiiph at torproject.org chiiph at torproject.org
Sat Jun 30 00:54:41 UTC 2012


commit ece9744a678d5601fcf76a2cbb668a88422c75eb
Author: Tomás Touceda <chiiph at torproject.org>
Date:   Fri Jun 29 21:50:37 2012 -0300

    Display stream traffic in the Circuit list in the Network Map
---
 src/torcontrol/Stream.cpp                 |    4 +-
 src/torcontrol/Stream.h                   |    1 +
 src/torcontrol/TorControl.cpp             |    2 +
 src/torcontrol/TorControl.h               |    8 +++++
 src/torcontrol/TorEvents.cpp              |   26 ++++++++++++++++
 src/torcontrol/TorEvents.h                |   46 ++++++++++++++++++----------
 src/vidalia/network/CircuitListWidget.cpp |   19 ++++++++++-
 src/vidalia/network/CircuitListWidget.h   |    6 +++-
 src/vidalia/network/NetViewer.cpp         |    4 ++
 src/vidalia/network/NetViewer.ui          |   23 ++++++++++++--
 src/vidalia/network/StreamItem.cpp        |   34 +++++++++++++++++++++
 src/vidalia/network/StreamItem.h          |    7 ++++
 12 files changed, 154 insertions(+), 26 deletions(-)

diff --git a/src/torcontrol/Stream.cpp b/src/torcontrol/Stream.cpp
index 7322d48..6f75bc0 100644
--- a/src/torcontrol/Stream.cpp
+++ b/src/torcontrol/Stream.cpp
@@ -88,8 +88,8 @@ Stream::isValidStreamId(const StreamId &streamId)
     return false;
 
   for (int i = 0; i < length; i++) {
-    char c = streamId[i].toAscii();
-    if (c < '0' && c > '9' && c < 'A' && c > 'Z' && c < 'a' && c > 'z')
+    QChar c = streamId[i];
+    if (!c.isLower() and !c.isUpper() and !c.isNumber())
       return false;
   }
   return true;
diff --git a/src/torcontrol/Stream.h b/src/torcontrol/Stream.h
index f688391..8f1dfb0 100644
--- a/src/torcontrol/Stream.h
+++ b/src/torcontrol/Stream.h
@@ -26,6 +26,7 @@
 
 /** Stream IDs contains 1-16 alphanumeric ASCII characters. */
 typedef QString StreamId;
+Q_DECLARE_METATYPE(StreamId)
 
 
 class Stream
diff --git a/src/torcontrol/TorControl.cpp b/src/torcontrol/TorControl.cpp
index c9893ce..01bfb1d 100644
--- a/src/torcontrol/TorControl.cpp
+++ b/src/torcontrol/TorControl.cpp
@@ -41,6 +41,8 @@ TorControl::TorControl(ControlMethod::Method method)
   RELAY_SIGNAL(_eventHandler, SIGNAL(bandwidthUpdate(quint64, quint64)));
   RELAY_SIGNAL(_eventHandler, SIGNAL(circuitStatusChanged(Circuit)));
   RELAY_SIGNAL(_eventHandler, SIGNAL(streamStatusChanged(Stream)));
+  RELAY_SIGNAL(_eventHandler,
+               SIGNAL(streamBandwidthUpdate(StreamId, quint64, quint64)));
   RELAY_SIGNAL(_eventHandler, SIGNAL(newDescriptors(QStringList)));
   RELAY_SIGNAL(_eventHandler, SIGNAL(newConsensus()));
   RELAY_SIGNAL(_eventHandler, SIGNAL(logMessage(tc::Severity, QString)));
diff --git a/src/torcontrol/TorControl.h b/src/torcontrol/TorControl.h
index ec91679..3aa78d3 100644
--- a/src/torcontrol/TorControl.h
+++ b/src/torcontrol/TorControl.h
@@ -277,6 +277,14 @@ signals:
    */
   void circuitStatusChanged(const Circuit &circuit);
 
+  /** Emitted when Tor sends a bandwidth usage update for a stream.
+   * <b>bytesReceived</b> is the number of bytes read on the stream over
+   * the previous second and <b>bytesWritten</b> is the number of bytes
+   * sent over the same interval.
+   */
+  void streamBandwidthUpdate(const StreamId &streamId,
+                             quint64 bytesReceived, quint64 bytesSent);
+
   /** Emitted when Tor has mapped the address <b>from</b> to the address
    * <b>to</b>. <b>expires</b> indicates the time at which when the address
    * mapping will no longer be considered valid.
diff --git a/src/torcontrol/TorEvents.cpp b/src/torcontrol/TorEvents.cpp
index db337e5..8b7c401 100644
--- a/src/torcontrol/TorEvents.cpp
+++ b/src/torcontrol/TorEvents.cpp
@@ -41,6 +41,7 @@ TorEvents::TorEvents(QObject *parent)
   qRegisterMetaType<BootstrapStatus>("BootstrapStatus");
   qRegisterMetaType<Circuit>("Circuit");
   qRegisterMetaType<Stream>("Stream");
+  qRegisterMetaType<StreamId>("StreamId");
 
   qRegisterMetaType<QHostAddress>("QHostAddress");
   qRegisterMetaType<QDateTime>("QDateTime");
@@ -66,6 +67,7 @@ TorEvents::toString(Event e)
     case ClientStatus:    event = "STATUS_CLIENT"; break;
     case ServerStatus:    event = "STATUS_SERVER"; break;
     case NewConsensus:    event = "NEWCONSENSUS"; break;
+    case StreamBandwidth: event = "STREAM_BW"; break;
     default: event = "UNKNOWN"; break;
   }
   return event;
@@ -104,6 +106,8 @@ TorEvents::toTorEvent(const QString &event)
     e = ServerStatus;
   } else if (event == "NEWCONSENSUS") {
     e = NewConsensus;
+  } else if (event == "STREAM_BW") {
+    e = StreamBandwidth;
   } else {
     e = Unknown;
   }
@@ -131,6 +135,7 @@ TorEvents::handleEvent(const ControlReply &reply)
       case Bandwidth:      handleBandwidthUpdate(line); break;
       case CircuitStatus:  handleCircuitStatus(line); break;
       case StreamStatus:   handleStreamStatus(line); break;
+      case StreamBandwidth:handleStreamBandwidthUpdate(line); break;
       case NewDescriptor:  handleNewDescriptor(line); break;
       case NewConsensus:   handleNewConsensus(line); break;
       case AddressMap:     handleAddressMap(line); break;
@@ -225,6 +230,27 @@ TorEvents::handleStreamStatus(const ReplyLine &line)
   }
 }
 
+/** Handle a stream bandwidth update event. The format of this message is:
+ *
+ *    "650" SP "STREAM_BW" SP StreamID SP BytesWritten SP BytesRead
+ *     BytesWritten = 1*DIGIT
+ *     BytesRead = 1*DIGIT
+ */
+void
+TorEvents::handleStreamBandwidthUpdate(const ReplyLine &line)
+{
+  QStringList msg = line.getMessage().split(" ");
+  if (msg.size() >= 4) {
+    StreamId streamId = msg.at(1);
+    quint64 bytesSent = (quint64)msg.at(2).toULongLong();
+    quint64 bytesReceived = (quint64)msg.at(3).toULongLong();
+
+    /* Post the event to each of the interested targets */
+    if (Stream::isValidStreamId(streamId))
+      emit streamBandwidthUpdate(streamId, bytesReceived, bytesSent);
+  }
+}
+
 /** Handle a log message event. The format of this message is:
  *  The syntax is:
  *
diff --git a/src/torcontrol/TorEvents.h b/src/torcontrol/TorEvents.h
index 832034d..4642a7e 100644
--- a/src/torcontrol/TorEvents.h
+++ b/src/torcontrol/TorEvents.h
@@ -25,6 +25,7 @@
 
 class Circuit;
 class Stream;
+typedef QString StreamId;
 class BootstrapStatus;
 class ControlReply;
 class ReplyLine;
@@ -41,25 +42,26 @@ class TorEvents : public QObject
 public:
   /** Asynchronous events sent from Tor to the controller */
   enum Event {
-    Unknown       = 0,
-    Bandwidth     = (1u << 0),
-    LogDebug      = (1u << 1),
-    LogInfo       = (1u << 2),
-    LogNotice     = (1u << 3),
-    LogWarn       = (1u << 4),
-    LogError      = (1u << 5),
-    CircuitStatus = (1u << 6),
-    StreamStatus  = (1u << 7),
-    OrConnStatus  = (1u << 8),
-    NewDescriptor = (1u << 9),
-    AddressMap    = (1u << 10),
-    GeneralStatus = (1u << 11),
-    ClientStatus  = (1u << 12),
-    ServerStatus  = (1u << 13),
-    NewConsensus  = (1u << 14),
+    Unknown         = 0,
+    Bandwidth       = (1u << 0),
+    LogDebug        = (1u << 1),
+    LogInfo         = (1u << 2),
+    LogNotice       = (1u << 3),
+    LogWarn         = (1u << 4),
+    LogError        = (1u << 5),
+    CircuitStatus   = (1u << 6),
+    StreamStatus    = (1u << 7),
+    OrConnStatus    = (1u << 8),
+    NewDescriptor   = (1u << 9),
+    AddressMap      = (1u << 10),
+    GeneralStatus   = (1u << 11),
+    ClientStatus    = (1u << 12),
+    ServerStatus    = (1u << 13),
+    NewConsensus    = (1u << 14),
+    StreamBandwidth = (1u << 15),
   };
   static const Event EVENT_MIN = TorEvents::Bandwidth;
-  static const Event EVENT_MAX = TorEvents::NewConsensus;
+  static const Event EVENT_MAX = TorEvents::StreamBandwidth;
   Q_DECLARE_FLAGS(Events, Event);
 
   /** Default Constructor */
@@ -92,6 +94,14 @@ signals:
    */
   void circuitStatusChanged(const Circuit &circuit);
 
+  /** Emitted when Tor sends a bandwidth usage update for a stream.
+   * <b>bytesReceived</b> is the number of bytes read on the stream over
+   * the previous second and <b>bytesWritten</b> is the number of bytes
+   * sent over the same interval.
+   */
+  void streamBandwidthUpdate(const StreamId &streamId,
+                             quint64 bytesReceived, quint64 bytesSent);
+
   /** Emitted when Tor has mapped the address <b>from</b> to the address
    * <b>to</b>. <b>expires</b> indicates the time at which when the address
    * mapping will no longer be considered valid.
@@ -227,6 +237,8 @@ private:
   void handleCircuitStatus(const ReplyLine &line);
   /** Handle a stream status event */
   void handleStreamStatus(const ReplyLine &line);
+  /** Handle a stream bandwidth event */
+  void handleStreamBandwidthUpdate(const ReplyLine &line);
   /** Handle a log message event */
   void handleLogMessage(const ReplyLine &line);
   /** Handle an OR connection status event. */
diff --git a/src/vidalia/network/CircuitListWidget.cpp b/src/vidalia/network/CircuitListWidget.cpp
index 4773d9b..a92ad9c 100644
--- a/src/vidalia/network/CircuitListWidget.cpp
+++ b/src/vidalia/network/CircuitListWidget.cpp
@@ -34,7 +34,7 @@ CircuitListWidget::CircuitListWidget(QWidget *parent)
 : QTreeWidget(parent)
 {
   /* Create and initialize columns */
-  setHeaderLabels(QStringList() << tr("Connection") << tr("Status"));
+  setHeaderLabels(QStringList() << tr("Connection") << tr("Status") << tr("Traffic"));
 
   /* Find out when a circuit has been selected */
   connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
@@ -52,13 +52,14 @@ CircuitListWidget::CircuitListWidget(QWidget *parent)
 void
 CircuitListWidget::retranslateUi()
 {
-  setHeaderLabels(QStringList() << tr("Connection") << tr("Status"));
+  setHeaderLabels(QStringList() << tr("Connection") << tr("Status") << tr("Traffic"));
   for (int i = 0; i < topLevelItemCount(); i++) {
     CircuitItem *circuitItem = dynamic_cast<CircuitItem *>(topLevelItem(i));
     circuitItem->update(circuitItem->circuit());
 
     foreach (StreamItem *streamItem, circuitItem->streams()) {
       streamItem->update(streamItem->stream());
+      streamItem->setTraffic(streamItem->bytesReceived(), streamItem->bytesSent());
     }
   }
 }
@@ -197,6 +198,20 @@ CircuitListWidget::addStream(const Stream &stream)
   }
 }
 
+/** Updates the traffic totals for a stream with the given delta values. */
+void
+CircuitListWidget::onStreamBandwidthUpdate(const StreamId &streamId,
+                                           quint64 bytesReceived,
+                                           quint64 bytesSent)
+{
+  StreamItem *item = findStreamItem(streamId);
+  if (item) {
+    item->setTraffic(
+      item->bytesReceived() + bytesReceived,
+      item->bytesSent() + bytesSent);
+  }
+}
+
 /** Schedules the given circuit to be removed after the specified timeout. */
 void
 CircuitListWidget::scheduleCircuitRemoval(CircuitItem *circuit, int delay)
diff --git a/src/vidalia/network/CircuitListWidget.h b/src/vidalia/network/CircuitListWidget.h
index 1405b17..7fb4d5e 100644
--- a/src/vidalia/network/CircuitListWidget.h
+++ b/src/vidalia/network/CircuitListWidget.h
@@ -34,7 +34,8 @@ public:
   /** Circuit list columns. */
   enum Columns {
     ConnectionColumn = 0, /**< Column for either the circuit or stream */
-    StatusColumn = 1      /**< Status of the connection. */
+    StatusColumn = 1,     /**< Status of the connection. */
+    TrafficColumn = 2,    /**< Amount of data received and sent by the stream. */
   };
 
   /** Default constructor */
@@ -66,6 +67,9 @@ signals:
 public slots:
   /** Clears all circuits and streams from the list. */
   void clearCircuits();
+  /** Updates the traffic totals for a stream with the given delta values. */
+  void onStreamBandwidthUpdate(const StreamId &streamId,
+                               quint64 bytesReceived, quint64 bytesSent);
 
 private slots:
   /** Removes the first circuit scheduled to be removed.*/
diff --git a/src/vidalia/network/NetViewer.cpp b/src/vidalia/network/NetViewer.cpp
index 2747cd6..475a35e 100644
--- a/src/vidalia/network/NetViewer.cpp
+++ b/src/vidalia/network/NetViewer.cpp
@@ -103,6 +103,10 @@ NetViewer::NetViewer(QWidget *parent)
   connect(_torControl, SIGNAL(streamStatusChanged(Stream)),
           this, SLOT(addStream(Stream)));
 
+  _torControl->setEvent(TorEvents::StreamBandwidth);
+  connect(_torControl, SIGNAL(streamBandwidthUpdate(StreamId, quint64, quint64)),
+          ui.treeCircuitList, SLOT(onStreamBandwidthUpdate(StreamId, quint64, quint64)));
+
   _torControl->setEvent(TorEvents::AddressMap);
   connect(_torControl, SIGNAL(addressMapped(QString, QString, QDateTime)),
           this, SLOT(addressMapped(QString, QString, QDateTime)));
diff --git a/src/vidalia/network/NetViewer.ui b/src/vidalia/network/NetViewer.ui
index 7994fb9..9d8dc87 100644
--- a/src/vidalia/network/NetViewer.ui
+++ b/src/vidalia/network/NetViewer.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>740</width>
-    <height>786</height>
+    <height>752</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -224,7 +224,7 @@
               <bool>false</bool>
              </property>
              <property name="columnCount">
-              <number>2</number>
+              <number>3</number>
              </property>
              <column>
               <property name="text">
@@ -236,6 +236,11 @@
                <string>Status</string>
               </property>
              </column>
+             <column>
+              <property name="text">
+               <string>Traffic</string>
+              </property>
+             </column>
             </widget>
            </item>
           </layout>
@@ -279,7 +284,7 @@
               <bool>false</bool>
              </property>
              <property name="columnCount">
-              <number>2</number>
+              <number>3</number>
              </property>
              <column>
               <property name="text">
@@ -291,6 +296,11 @@
                <string>Status</string>
               </property>
              </column>
+             <column>
+              <property name="text">
+               <string>Traffic</string>
+              </property>
+             </column>
             </widget>
            </item>
           </layout>
@@ -334,7 +344,7 @@
               <bool>false</bool>
              </property>
              <property name="columnCount">
-              <number>2</number>
+              <number>3</number>
              </property>
              <column>
               <property name="text">
@@ -346,6 +356,11 @@
                <string>Status</string>
               </property>
              </column>
+             <column>
+              <property name="text">
+               <string>Traffic</string>
+              </property>
+             </column>
             </widget>
            </item>
           </layout>
diff --git a/src/vidalia/network/StreamItem.cpp b/src/vidalia/network/StreamItem.cpp
index 5083b81..6d77afe 100644
--- a/src/vidalia/network/StreamItem.cpp
+++ b/src/vidalia/network/StreamItem.cpp
@@ -19,6 +19,7 @@
 
 /** Constructor */
 StreamItem::StreamItem(const Stream &stream)
+  : _bytesReceived(0), _bytesSent(0)
 {
   /* Set the stream's displayed target information */
   setText(CircuitListWidget::ConnectionColumn, stream.target());
@@ -37,3 +38,36 @@ StreamItem::update(const Stream &stream)
   setToolTip(CircuitListWidget::StatusColumn, stream.statusString());
 }
 
+/** Formats a count of bytes appropriately as bytes, kilobytes,
+ * megabytes, or gigabytes. */
+static
+QString formatBytes(quint64 bytes) {
+  const int K = 1024, M = K * K, G = K * M;
+  double d = bytes;
+  /*if (bytes < 1 * K) return QString("%1 B").arg(bytes);*/
+  if (bytes < 10 * K) return QString("%1 KB").arg(d / K, 0, 'f', 1);
+  if (bytes < 1 * M) return QString("%1 KB").arg(d / K, 0, 'f', 0);
+  if (bytes < 100 * M) return QString("%1 MB").arg(d / M, 0, 'f', 1);
+  if (bytes < 1 * G) return QString("%1 MB").arg(d / M, 0, 'f', 0);
+  return QString("%1 GB").arg(d / G, 0, 'f', 1);
+}
+
+/** Updates the traffic totals of this stream item. */
+void
+StreamItem::setTraffic(quint64 bytesReceived, quint64 bytesSent)
+{
+  _bytesReceived = bytesReceived;
+  _bytesSent = bytesSent;
+
+  QString str;
+  if (bytesReceived | bytesSent) {
+    str = QString("%1 down / %2 up").arg(
+      formatBytes(bytesReceived),
+      formatBytes(bytesSent));
+  } else {
+    str = QString();
+  }
+
+  setText(CircuitListWidget::TrafficColumn, str);
+  setToolTip(CircuitListWidget::TrafficColumn, str);
+}
diff --git a/src/vidalia/network/StreamItem.h b/src/vidalia/network/StreamItem.h
index ea8d906..1521d03 100644
--- a/src/vidalia/network/StreamItem.h
+++ b/src/vidalia/network/StreamItem.h
@@ -33,8 +33,15 @@ public:
   /** Returns the ID of the stream associated with this tree item. */
   StreamId id() const { return _stream.id(); }
 
+  /** Updates the traffic totals of this stream item. */
+  void setTraffic(quint64 bytesReceived, quint64 bytesSent);
+  quint64 bytesReceived() const { return _bytesReceived; }
+  quint64 bytesSent() const { return _bytesSent; }
+
 private:
   Stream _stream;
+  quint64 _bytesReceived;
+  quint64 _bytesSent;
 };
 
 #endif





More information about the tor-commits mailing list