commit 54de59a9ab3eea79c897d386f91ed93066fbb10c Author: Damian Johnson atagar@torproject.org Date: Tue Sep 2 07:57:55 2014 -0700
Default to getting our own descriptor if no relay is specified
Changing get_microdescriptor(), get_server_descriptor(), and get_network_status() to get the descriptor for our own relay if no fingerprint or nickname is provided. --- docs/change_log.rst | 1 + stem/control.py | 39 ++++++++++++++++++++++++++++++++++++--- test/unit/control/controller.py | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index bdd3dfb..57ccd88 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -43,6 +43,7 @@ The following are only available within Stem's `git repository * **Controller**
* Added :func:`~stem.control.BaseController.connection_time` to the :class:`~stem.control.BaseController` + * Changed :func:`~stem.control.Controller.get_microdescriptor`, :func:`~stem.control.Controller.get_server_descriptor`, and :func:`~stem.control.Controller.get_network_status` to get our own descriptor if no fingerprint or nickname is provided.
* **Descriptors**
diff --git a/stem/control.py b/stem/control.py index e5f4769..58dd119 100644 --- a/stem/control.py +++ b/stem/control.py @@ -1311,12 +1311,17 @@ class Controller(BaseController): else: return default
- def get_microdescriptor(self, relay, default = UNDEFINED): + def get_microdescriptor(self, relay = None, default = UNDEFINED): """ Provides the microdescriptor for the relay with the given fingerprint or nickname. If the relay identifier could be either a fingerprint *or* nickname then it's queried as a fingerprint.
+ If no **relay** is provided then this defaults to ourselves. Remember that + this requires that we've retrieved our own descriptor from remote + authorities so this both won't be available for newly started relays and + may be up to around an hour out of date. + :param str relay: fingerprint or nickname of the relay to be queried :param object default: response if the query fails
@@ -1331,6 +1336,12 @@ class Controller(BaseController): """
try: + if relay is None: + try: + relay = self.get_info('fingerprint') + except stem.ControllerError as exc: + raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc) + if stem.util.tor_tools.is_valid_fingerprint(relay): query = 'md/id/%s' % relay elif stem.util.tor_tools.is_valid_nickname(relay): @@ -1395,12 +1406,17 @@ class Controller(BaseController): for entry in default: yield entry
- def get_server_descriptor(self, relay, default = UNDEFINED): + def get_server_descriptor(self, relay = None, default = UNDEFINED): """ Provides the server descriptor for the relay with the given fingerprint or nickname. If the relay identifier could be either a fingerprint *or* nickname then it's queried as a fingerprint.
+ If no **relay** is provided then this defaults to ourselves. Remember that + this requires that we've retrieved our own descriptor from remote + authorities so this both won't be available for newly started relays and + may be up to around an hour out of date. + **As of Tor version 0.2.3.25 relays no longer get server descriptors by default.** It's advised that you use microdescriptors instead, but if you really need server descriptors then you can get them by setting @@ -1420,6 +1436,12 @@ class Controller(BaseController): """
try: + if relay is None: + try: + relay = self.get_info('fingerprint') + except stem.ControllerError as exc: + raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc) + if stem.util.tor_tools.is_valid_fingerprint(relay): query = 'desc/id/%s' % relay elif stem.util.tor_tools.is_valid_nickname(relay): @@ -1487,7 +1509,7 @@ class Controller(BaseController): return self.get_version() < stem.version.Requirement.MICRODESCRIPTOR_IS_DEFAULT or \ self.get_conf('UseMicrodescriptors', None) == '0'
- def get_network_status(self, relay, default = UNDEFINED): + def get_network_status(self, relay = None, default = UNDEFINED): """ Provides the router status entry for the relay with the given fingerprint or nickname. If the relay identifier could be either a fingerprint *or* @@ -1504,6 +1526,11 @@ class Controller(BaseController): ... and :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` otherwise.
+ If no **relay** is provided then this defaults to ourselves. Remember that + this requires that we've retrieved our own descriptor from remote + authorities so this both won't be available for newly started relays and + may be up to around an hour out of date. + :param str relay: fingerprint or nickname of the relay to be queried :param object default: response if the query fails
@@ -1524,6 +1551,12 @@ class Controller(BaseController): # https://trac.torproject.org/7953
try: + if relay is None: + try: + relay = self.get_info('fingerprint') + except stem.ControllerError as exc: + raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc) + if stem.util.tor_tools.is_valid_fingerprint(relay): query = 'ns/id/%s' % relay elif stem.util.tor_tools.is_valid_nickname(relay): diff --git a/test/unit/control/controller.py b/test/unit/control/controller.py index dd61feb..17b64fd 100644 --- a/test/unit/control/controller.py +++ b/test/unit/control/controller.py @@ -12,7 +12,7 @@ import stem.socket import stem.util.system import stem.version
-from stem import InvalidArguments, InvalidRequest, ProtocolError, UnsatisfiableRequest +from stem import ControllerError, InvalidArguments, InvalidRequest, ProtocolError, UnsatisfiableRequest from stem.control import _parse_circ_path, Listener, Controller, EventType from stem.exit_policy import ExitPolicy from test import mocking @@ -23,6 +23,8 @@ try: except ImportError: from mock import Mock, patch
+NS_DESC = 'r %s %s u5lTXJKGsLKufRLnSyVqT7TdGYw 2012-12-30 22:02:49 77.223.43.54 9001 0\ns Fast Named Running Stable Valid\nw Bandwidth=75' +
class TestControl(unittest.TestCase): def setUp(self): @@ -380,6 +382,35 @@ class TestControl(unittest.TestCase): self.assertEqual(432, self.controller.get_pid())
@patch('stem.control.Controller.get_info') + def test_get_network_status_for_ourselves(self, get_info_mock): + """ + Exercises the get_network_status() method for getting our own relay. + """ + + # when there's an issue getting our fingerprint + + get_info_mock.side_effect = ControllerError('nope, too bad') + + try: + self.controller.get_network_status() + self.fail("We should've raised an exception") + except ControllerError as exc: + self.assertEqual('Unable to determine our own fingerprint: nope, too bad', str(exc)) + + self.assertEqual('boom', self.controller.get_network_status(default = 'boom')) + + # successful request + + desc = NS_DESC % ('moria1', '/96bKo4soysolMgKn5Hex2nyFSY') + + get_info_mock.side_effect = lambda param, **kwargs: { + 'fingerprint': '9695DFC35FFEB861329B9F1AB04C46397020CE31', + 'ns/id/9695DFC35FFEB861329B9F1AB04C46397020CE31': desc, + }[param] + + self.assertEqual(stem.descriptor.router_status_entry.RouterStatusEntryV3(desc), self.controller.get_network_status()) + + @patch('stem.control.Controller.get_info') def test_get_network_status(self, get_info_mock): """ Exercises the get_network_status() method. @@ -389,7 +420,7 @@ class TestControl(unittest.TestCase):
nickname = 'Beaver' fingerprint = '/96bKo4soysolMgKn5Hex2nyFSY' - desc = 'r %s %s u5lTXJKGsLKufRLnSyVqT7TdGYw 2012-12-30 22:02:49 77.223.43.54 9001 0\ns Fast Named Running Stable Valid\nw Bandwidth=75' % (nickname, fingerprint) + desc = NS_DESC % (nickname, fingerprint) router = stem.descriptor.router_status_entry.RouterStatusEntryV3(desc)
# always return the same router status entry
tor-commits@lists.torproject.org