[tor-commits] [stem/master] Adding controller methods to check NEWNYM availability
atagar at torproject.org
atagar at torproject.org
Mon Jan 27 03:17:05 UTC 2014
commit c510c1b01599781b249f12c06062082309ea5f0e
Author: Damian Johnson <atagar at torproject.org>
Date: Sun Jan 26 19:15:51 2014 -0800
Adding controller methods to check NEWNYM availability
Adding a couple methods to check if tor will respect a NEWNYM signal or not.
This only works if signals are only sent through stem.
---
docs/change_log.rst | 1 +
stem/control.py | 38 +++++++++++++++++++++++++++++++++++++-
test/integ/control/controller.py | 17 +++++++++++++++++
3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index fa8b638..ab52e5f 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -41,6 +41,7 @@ The following are only available within stem's `git repository
* **Controller**
+ * Added :func:`~stem.control.Controller.is_newnym_available` and :func:`~stem.control.Controller.get_newnym_wait` methods to the :class:`~stem.control.Controller`
* Added the id attribute to the :class:`~stem.response.events.ORConnEvent` (:spec:`6f2919a`)
* 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`)
diff --git a/stem/control.py b/stem/control.py
index adfc56f..22a1962 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -64,6 +64,8 @@ providing its own for interacting at a higher level.
|- close_stream - close a stream
|
|- signal - sends a signal to the tor client
+ |- is_newnym_available - true if tor would presently accept a NEWNYM signal
+ |- get_newnym_wait - seconds until tor would accept a NEWNYM signal
|- is_geoip_unavailable - true if we've discovered our geoip db to be unavailable
+- map_address - maps one address to another such that connections to the original are replaced with the other
@@ -679,6 +681,7 @@ class Controller(BaseController):
self._is_caching_enabled = True
self._request_cache = {}
+ self._last_newnym = 0.0
self._cache_lock = threading.RLock()
@@ -688,6 +691,7 @@ class Controller(BaseController):
self._event_listeners_lock = threading.RLock()
# number of sequential 'GETINFO ip-to-country/*' lookups that have failed
+
self._geoip_failure_count = 0
self._enabled_features = []
@@ -2258,12 +2262,44 @@ class Controller(BaseController):
response = self.msg("SIGNAL %s" % signal)
stem.response.convert("SINGLELINE", response)
- if not response.is_ok():
+ if response.is_ok():
+ if signal == stem.Signal.NEWNYM:
+ self._last_newnym = time.time()
+ else:
if response.code == "552":
raise stem.InvalidArguments(response.code, response.message, [signal])
raise stem.ProtocolError("SIGNAL response contained unrecognized status code: %s" % response.code)
+ def is_newnym_available(self):
+ """
+ Indicates if tor would presently accept a NEWNYM signal. This can only
+ account for signals sent via this controller.
+
+ .. versionadded:: 1.2.0
+
+ :returns: **True** if tor would presently accept a NEWNYM signal, **False**
+ otherwise
+ """
+
+ if self.is_alive():
+ return self.get_newnym_wait() == 0.0
+ else:
+ return False
+
+ def get_newnym_wait(self):
+ """
+ Provides the number of seconds until a NEWNYM signal would be respected.
+ This can only account for signals sent via this controller.
+
+ .. versionadded:: 1.2.0
+
+ :returns: **float** for the number of seconds until tor would respect
+ another NEWNYM signal
+ """
+
+ return max(0.0, self._last_newnym + 10 - time.time())
+
def is_geoip_unavailable(self):
"""
Provides **True** if we've concluded hat our geoip database is unavailable,
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 1c0e468..d034853 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -654,6 +654,23 @@ class TestController(unittest.TestCase):
# invalid signals
self.assertRaises(stem.InvalidArguments, controller.signal, "FOOBAR")
+ def test_newnym_availability(self):
+ """
+ Test the is_newnym_available and get_newnym_wait methods.
+ """
+
+ if test.runner.require_control(self):
+ return
+
+ with test.runner.get_runner().get_tor_controller() as controller:
+ self.assertEqual(True, controller.is_newnym_available())
+ self.assertEqual(0.0, controller.get_newnym_wait())
+
+ controller.signal(stem.Signal.NEWNYM)
+
+ self.assertEqual(False, controller.is_newnym_available())
+ self.assertTrue(controller.get_newnym_wait() > 9.0)
+
def test_extendcircuit(self):
if test.runner.require_control(self):
return
More information about the tor-commits
mailing list