[tor-commits] [stem/master] Adding support for TB_EMPTY events

atagar at torproject.org atagar at torproject.org
Mon Nov 4 07:29:15 UTC 2013


commit d6a95bf778e6b90d9de9ea46aefcfce2f9103e68
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Nov 3 23:22:32 2013 -0800

    Adding support for TB_EMPTY events
    
    Last event type from...
    
    https://gitweb.torproject.org/torspec.git/commitdiff/6f2919a
---
 docs/change_log.rst          |    1 +
 stem/__init__.py             |   18 +++++++++++++++++
 stem/response/events.py      |   44 ++++++++++++++++++++++++++++++++++++++++++
 stem/version.py              |    2 ++
 test/unit/response/events.py |   41 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 106 insertions(+)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 5c6fed2..7b71c47 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -45,6 +45,7 @@ The following are only available within stem's `git repository
   * Added `support for CONN_BW events <api/response.html#stem.response.events.ConnectionBandwidthEvent>`_ (:spec:`6f2919a`)
   * Added `support for CIRC_BW events <api/response.html#stem.response.events.CircuitBandwidthEvent>`_ (:spec:`6f2919a`)
   * Added `support for CELL_STATS events <api/response.html#stem.response.events.CellStatsEvent>`_ (:spec:`6f2919a`)
+  * Added `support for TB_EMPTY events <api/response.html#stem.response.events.TokenBucketEmptyEvent>`_ (:spec:`6f2919a`)
 
 .. _version_1.1:
 
diff --git a/stem/__init__.py b/stem/__init__.py
index 182428f..9710d24 100644
--- a/stem/__init__.py
+++ b/stem/__init__.py
@@ -380,6 +380,18 @@ Library for working with the tor process.
   **DIR**         fetching or sending tor descriptor data
   **EXIT**        carrying traffic between the tor network and an external destination
   =============== ===========
+
+.. data:: TokenBucket (enum)
+
+  Bucket categories of TB_EMPTY events.
+
+  =============== ===========
+  TokenBucket     Description
+  =============== ===========
+  **GLOBAL**      global token bucket
+  **RELAY**       relay token bucket
+  **ORCONN**      bucket used for OR connections
+  =============== ===========
 """
 
 __version__ = '1.1.0-dev'
@@ -718,3 +730,9 @@ ConnectionType = stem.util.enum.UppercaseEnum(
   "DIR",
   "EXIT",
 )
+
+TokenBucket = stem.util.enum.UppercaseEnum(
+  "GLOBAL",
+  "RELAY",
+  "ORCONN",
+)
diff --git a/stem/response/events.py b/stem/response/events.py
index 616bbfc..19e1680 100644
--- a/stem/response/events.py
+++ b/stem/response/events.py
@@ -1069,6 +1069,49 @@ class CellStatsEvent(Event):
     self.outbound_time = _parse_cell_type_mapping(self.outbound_time)
 
 
+class TokenBucketEmptyEvent(Event):
+  """
+  Event emitted when refilling an empty token bucket. **These events are only
+  emitted if TestingTorNetwork is set.**
+
+  The TB_EMPTY event was introduced in tor version 0.2.5.2-alpha.
+
+  .. versionadded:: 1.1.0-dev
+
+  :var stem.TokenBucket bucket: bucket being refilled
+  :var str id: connection identifier
+  :var int read: time in milliseconds since the read bucket was last refilled
+  :var int written: time in milliseconds since the write bucket was last refilled
+  :var int last_refill: time in milliseconds the bucket has been empty since last refilled
+  """
+
+  _POSITIONAL_ARGS = ("bucket",)
+  _KEYWORD_ARGS = {
+    "ID": "id",
+    "READ": "read",
+    "WRITTEN": "written",
+    "LAST": "last_refill",
+  }
+
+  _VERSION_ADDED = stem.version.Requirement.EVENT_TB_EMPTY
+
+  def _parse(self):
+    if self.id and not tor_tools.is_valid_connection_id(self.id):
+      raise stem.ProtocolError("Connection IDs must be one to sixteen alphanumeric characters, got '%s': %s" % (self.id, self))
+    elif not self.read.isdigit():
+      raise stem.ProtocolError("A TB_EMPTY's READ value should be a positive numeric value, received: %s" % self)
+    elif not self.written.isdigit():
+      raise stem.ProtocolError("A TB_EMPTY's WRITTEN value should be a positive numeric value, received: %s" % self)
+    elif not self.last_refill.isdigit():
+      raise stem.ProtocolError("A TB_EMPTY's LAST value should be a positive numeric value, received: %s" % self)
+
+    self.read = int(self.read)
+    self.written = int(self.written)
+    self.last_refill = int(self.last_refill)
+
+    self._log_if_unrecognized('bucket', stem.TokenBucket)
+
+
 def _parse_cell_type_mapping(mapping):
   """
   Parses a mapping of the form...
@@ -1133,6 +1176,7 @@ EVENT_TYPE_TO_CLASS = {
   "STATUS_SERVER": StatusEvent,
   "STREAM": StreamEvent,
   "STREAM_BW": StreamBwEvent,
+  "TB_EMPTY": TokenBucketEmptyEvent,
   "TRANSPORT_LAUNCHED": TransportLaunchedEvent,
   "WARN": LogEvent,
 
diff --git a/stem/version.py b/stem/version.py
index ef1f290..b0563d5 100644
--- a/stem/version.py
+++ b/stem/version.py
@@ -46,6 +46,7 @@ easily parsed and compared, for instance...
   **EVENT_CONN_BW**                     CONN_BW events
   **EVENT_CIRC_BW**                     CIRC_BW events
   **EVENT_CELL_STATS**                  CELL_STATS events
+  **EVENT_TB_EMPTY**                    TB_EMPTY events
   **EXTENDCIRCUIT_PATH_OPTIONAL**       EXTENDCIRCUIT queries can omit the path if the circuit is zero
   **FEATURE_EXTENDED_EVENTS**           'EXTENDED_EVENTS' optional feature
   **FEATURE_VERBOSE_NAMES**             'VERBOSE_NAMES' optional feature
@@ -347,6 +348,7 @@ Requirement = stem.util.enum.Enum(
   ("EVENT_CONN_BW", Version('0.2.5.2-alpha')),
   ("EVENT_CIRC_BW", Version('0.2.5.2-alpha')),
   ("EVENT_CELL_STATS", Version('0.2.5.2-alpha')),
+  ("EVENT_TB_EMPTY", Version('0.2.5.2-alpha')),
   ("EXTENDCIRCUIT_PATH_OPTIONAL", Version("0.2.2.9")),
   ("FEATURE_EXTENDED_EVENTS", Version("0.2.2.1-alpha")),
   ("FEATURE_VERBOSE_NAMES", Version("0.2.2.1-alpha")),
diff --git a/test/unit/response/events.py b/test/unit/response/events.py
index 09fca4f..c3cdf7a 100644
--- a/test/unit/response/events.py
+++ b/test/unit/response/events.py
@@ -357,6 +357,13 @@ CELL_STATS_BAD_1 = "650 CELL_STATS OutboundAdded=create_fast:-1,relay_early:2"
 CELL_STATS_BAD_2 = "650 CELL_STATS OutboundAdded=create_fast:arg,relay_early:-2"
 CELL_STATS_BAD_3 = "650 CELL_STATS OutboundAdded=create_fast!:1,relay_early:-2"
 
+TB_EMPTY_1 = "650 TB_EMPTY ORCONN ID=16 READ=0 WRITTEN=0 LAST=100"
+TB_EMPTY_2 = "650 TB_EMPTY GLOBAL READ=93 WRITTEN=93 LAST=100"
+TB_EMPTY_3 = "650 TB_EMPTY RELAY READ=93 WRITTEN=93 LAST=100"
+
+TB_EMPTY_BAD_1 = "650 TB_EMPTY GLOBAL READ=93 WRITTEN=blarg LAST=100"
+TB_EMPTY_BAD_2 = "650 TB_EMPTY GLOBAL READ=93 WRITTEN=93 LAST=-100"
+
 
 def _get_event(content):
   controller_event = mocking.get_message(content)
@@ -1282,6 +1289,40 @@ class TestEvents(unittest.TestCase):
     self.assertRaises(ProtocolError, _get_event, CELL_STATS_BAD_2)
     self.assertRaises(ProtocolError, _get_event, CELL_STATS_BAD_3)
 
+  def test_token_bucket_empty_event(self):
+    event = _get_event(TB_EMPTY_1)
+
+    self.assertTrue(isinstance(event, stem.response.events.TokenBucketEmptyEvent))
+    self.assertEqual(TB_EMPTY_1.lstrip("650 "), str(event))
+    self.assertEqual(stem.TokenBucket.ORCONN, event.bucket)
+    self.assertEqual("16", event.id)
+    self.assertEqual(0, event.read)
+    self.assertEqual(0, event.written)
+    self.assertEqual(100, event.last_refill)
+
+    event = _get_event(TB_EMPTY_2)
+
+    self.assertTrue(isinstance(event, stem.response.events.TokenBucketEmptyEvent))
+    self.assertEqual(TB_EMPTY_2.lstrip("650 "), str(event))
+    self.assertEqual(stem.TokenBucket.GLOBAL, event.bucket)
+    self.assertEqual(None, event.id)
+    self.assertEqual(93, event.read)
+    self.assertEqual(93, event.written)
+    self.assertEqual(100, event.last_refill)
+
+    event = _get_event(TB_EMPTY_3)
+
+    self.assertTrue(isinstance(event, stem.response.events.TokenBucketEmptyEvent))
+    self.assertEqual(TB_EMPTY_3.lstrip("650 "), str(event))
+    self.assertEqual(stem.TokenBucket.RELAY, event.bucket)
+    self.assertEqual(None, event.id)
+    self.assertEqual(93, event.read)
+    self.assertEqual(93, event.written)
+    self.assertEqual(100, event.last_refill)
+
+    self.assertRaises(ProtocolError, _get_event, TB_EMPTY_BAD_1)
+    self.assertRaises(ProtocolError, _get_event, TB_EMPTY_BAD_2)
+
   def test_unrecognized_enum_logging(self):
     """
     Checks that when event parsing gets a value that isn't recognized by stem's





More information about the tor-commits mailing list