commit 0687e99789827aa43dd8523006eb49aed837c2ef
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Dec 2 20:20:33 2012 -0800
Support for BUILDTIMEOUT_SET events
Impementation and testing for BUILDTIMEOUT_SET events. Snagged test data by
listening for the events while bootstrapping...
650 BUILDTIMEOUT_SET COMPUTED TOTAL_TIMES=124 TIMEOUT_MS=9019 XM=1375 ALPHA=0.855662 CUTOFF_QUANTILE=0.800000 TIMEOUT_RATE=0.137097 CLOSE_MS=21850 CLOSE_RATE=0.072581
650 BUILDTIMEOUT_SET COMPUTED TOTAL_TIMES=125 TIMEOUT_MS=8915 XM=1375 ALPHA=0.860984 CUTOFF_QUANTILE=0.800000 TIMEOUT_RATE=0.136000 CLOSE_MS=21850 CLOSE_RATE=0.072000
650 BUILDTIMEOUT_SET COMPUTED TOTAL_TIMES=126 TIMEOUT_MS=8923 XM=1375 ALPHA=0.860563 CUTOFF_QUANTILE=0.800000 TIMEOUT_RATE=0.134921 CLOSE_MS=21850 CLOSE_RATE=0.071429
650 BUILDTIMEOUT_SET COMPUTED TOTAL_TIMES=127 TIMEOUT_MS=8814 XM=1375 ALPHA=0.866231 CUTOFF_QUANTILE=0.800000 TIMEOUT_RATE=0.133858 CLOSE_MS=21850 CLOSE_RATE=0.070866
---
stem/__init__.py | 24 ++++++++++++++++
stem/control.py | 1 +
stem/response/events.py | 63 ++++++++++++++++++++++++++++++++++++++++--
test/unit/response/events.py | 27 ++++++++++++++++++
4 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/stem/__init__.py b/stem/__init__.py
index 815e82c..ea3a5eb 100644
--- a/stem/__init__.py
+++ b/stem/__init__.py
@@ -291,6 +291,21 @@ Library for working with the tor process.
**GOOD** unknown
**DROPPED** unknown
============= ===========
+
+.. data:: TimeoutSetType (enum)
+
+ Way in which the timeout value of a circuit is changing. Tor may provide
+ types not in this enum.
+
+ =============== ===========
+ TimeoutSetType Description
+ =============== ===========
+ **COMPUTED** tor has computed a new timeout based on prior circuits
+ **RESET** timeout reverted to its default
+ **SUSPENDED** timeout reverted to its default until network connectivity has recovered
+ **DISCARD** throwing out timeout value from when the network was down
+ **RESUME** resumed calculations to determine the proper timeout
+ =============== ===========
"""
__version__ = '0.0.1'
@@ -334,6 +349,7 @@ __all__ = [
"StatusType",
"GuardType",
"GuardStatus",
+ "TimeoutSetType",
]
import stem.util.enum
@@ -542,3 +558,11 @@ GuardStatus = stem.util.enum.UppercaseEnum(
"DROPPED",
)
+TimeoutSetType = stem.util.enum.UppercaseEnum(
+ "COMPUTED",
+ "RESET",
+ "SUSPENDED",
+ "DISCARD",
+ "RESUME",
+)
+
diff --git a/stem/control.py b/stem/control.py
index ec727ce..a8f7913 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -80,6 +80,7 @@ providing its own for interacting at a higher level.
===================== ===========
**ADDRMAP** :class:`stem.response.events.AddrMapEvent`
**AUTHDIR_NEWDESCS** :class:`stem.response.events.AuthDirNewDescEvent`
+ **BUILDTIMEOUT_SET** :class:`stem.response.events.BuildTimeoutSetEvent`
**BW** :class:`stem.response.events.BandwidthEvent`
**CIRC** :class:`stem.response.events.CircuitEvent`
**CLIENTS_SEEN** :class:`stem.response.events.ClientsSeenEvent`
diff --git a/stem/response/events.py b/stem/response/events.py
index 522f9cc..8e437d9 100644
--- a/stem/response/events.py
+++ b/stem/response/events.py
@@ -232,6 +232,62 @@ class BandwidthEvent(Event):
self.read = long(self.read)
self.written = long(self.written)
+class BuildTimeoutSetEvent(Event):
+ """
+ Event indicating that the timeout value for a circuit has changed. This was
+ first added in tor version 0.2.2.7.
+
+ :var stem.TimeoutSetType set_type: way in which the timeout is changing
+ :var int total_times: circuit build times tor used to determine the timeout
+ :var int timeout: circuit timeout value in milliseconds
+ :var int xm: Pareto parameter Xm in milliseconds
+ :var float alpha: Paredo paremter alpha
+ :var float quantile: CDF quantile cutoff point
+ :var float timeout_rate: ratio of circuits that have time out
+ :var int close_timeout: duration to keep measurement circuits in milliseconds
+ :var float close_rate: ratio of measurement circuits that are closed
+ """
+
+ _POSITIONAL_ARGS = ("set_type",)
+ _KEYWORD_ARGS = {
+ "TOTAL_TIMES": "total_times",
+ "TIMEOUT_MS": "timeout",
+ "XM": "xm",
+ "ALPHA": "alpha",
+ "CUTOFF_QUANTILE": "quantile",
+ "TIMEOUT_RATE": "timeout_rate",
+ "CLOSE_MS": "close_timeout",
+ "CLOSE_RATE": "close_rate",
+ }
+
+ def _parse(self):
+ # convert our integer and float parameters
+
+ for param in ('total_times', 'timeout', 'xm', 'close_timeout'):
+ param_value = getattr(self, param)
+
+ if param_value != None:
+ try:
+ setattr(self, param, int(param_value))
+ except ValueError:
+ raise stem.ProtocolError("The %s of a BUILDTIMEOUT_SET should be an integer: %s" % (param, self))
+
+ for param in ('alpha', 'quantile', 'timeout_rate', 'close_rate'):
+ param_value = getattr(self, param)
+
+ if param_value != None:
+ try:
+ setattr(self, param, float(param_value))
+ except ValueError:
+ raise stem.ProtocolError("The %s of a BUILDTIMEOUT_SET should be a float: %s" % (param, self))
+
+ # log if we have an unrecognized timeout set type
+ unrecognized_msg = UNRECOGNIZED_ATTR_MSG % ("BUILDTIMEOUT_SET", self)
+
+ if self.set_type and (not self.set_type in stem.TimeoutSetType):
+ log_id = "event.buildtimeout_set.unknown_timeout_set_type.%s" % self.set_type
+ log.log_once(log_id, log.INFO, unrecognized_msg % ('timeout set type', self.set_type))
+
class CircuitEvent(Event):
"""
Event that indicates that a circuit has changed.
@@ -424,7 +480,7 @@ class NetworkStatusEvent(Event):
Event for when our copy of the consensus has changed. This was introduced in
tor version 0.1.2.3.
- :param list desc: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for the changed descriptors
+ :var list desc: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for the changed descriptors
"""
_SKIP_PARSING = True
@@ -447,7 +503,7 @@ class NewConsensusEvent(Event):
This was introduced in tor version 0.2.1.13.
- :param list desc: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for the changed descriptors
+ :var list desc: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for the changed descriptors
"""
_SKIP_PARSING = True
@@ -469,7 +525,7 @@ class NewDescEvent(Event):
VERBOSE_NAMES feature isn't enabled. The option was first introduced in tor
version 0.1.2.2, and on by default after 0.2.2.1.
- :param tuple relays: **(fingerprint, nickname)** tuples for the relays with
+ :var tuple relays: **(fingerprint, nickname)** tuples for the relays with
new descriptors
"""
@@ -659,6 +715,7 @@ class StreamEvent(Event):
EVENT_TYPE_TO_CLASS = {
"ADDRMAP": AddrMapEvent,
"AUTHDIR_NEWDESCS": AuthDirNewDescEvent,
+ "BUILDTIMEOUT_SET": BuildTimeoutSetEvent,
"BW": BandwidthEvent,
"CIRC": CircuitEvent,
"CLIENTS_SEEN": ClientsSeenEvent,
diff --git a/test/unit/response/events.py b/test/unit/response/events.py
index 6f18676..b74f4ad 100644
--- a/test/unit/response/events.py
+++ b/test/unit/response/events.py
@@ -12,6 +12,18 @@ import test.mocking as mocking
from stem import * # enums and exceptions
+# BUILDTIMEOUT_SET event from tor 0.2.3.16.
+
+BUILD_TIMEOUT_EVENT = "650 BUILDTIMEOUT_SET COMPUTED \
+TOTAL_TIMES=124 \
+TIMEOUT_MS=9019 \
+XM=1375 \
+ALPHA=0.855662 \
+CUTOFF_QUANTILE=0.800000 \
+TIMEOUT_RATE=0.137097 \
+CLOSE_MS=21850 \
+CLOSE_RATE=0.072581"
+
# CIRC events from tor v0.2.3.16
CIRC_LAUNCHED = "650 CIRC 7 LAUNCHED \
@@ -244,6 +256,21 @@ class TestEvents(unittest.TestCase):
self.assertEqual([], event.positional_args)
self.assertEqual({}, event.keyword_args)
+ def test_build_timeout_set_event(self):
+ event = _get_event(BUILD_TIMEOUT_EVENT)
+
+ self.assertTrue(isinstance(event, stem.response.events.BuildTimeoutSetEvent))
+ self.assertEqual(BUILD_TIMEOUT_EVENT.lstrip("650 "), str(event))
+ self.assertEqual(TimeoutSetType.COMPUTED, event.set_type)
+ self.assertEqual(124, event.total_times)
+ self.assertEqual(9019, event.timeout)
+ self.assertEqual(1375, event.xm)
+ self.assertEqual(0.855662, event.alpha)
+ self.assertEqual(0.8, event.quantile)
+ self.assertEqual(0.137097, event.timeout_rate)
+ self.assertEqual(21850, event.close_timeout)
+ self.assertEqual(0.072581, event.close_rate)
+
def test_bw_event(self):
event = _get_event("650 BW 15 25")