[tor-commits] [stem/master] Add or_addresses to RouterStatusEntryMicroV3

atagar at torproject.org atagar at torproject.org
Mon Jul 16 00:42:31 UTC 2018


commit d5d5e2afe922c2e7c94c27208c5fca2bac4fbd4c
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Jul 15 17:40:42 2018 -0700

    Add or_addresses to RouterStatusEntryMicroV3
    
    Router status entry 'a' lines previously only appeared in the standard
    consensus but now they appear in the microdescriptor consensus as well...
    
      https://trac.torproject.org/projects/tor/ticket/26405
      https://trac.torproject.org/projects/tor/ticket/23826
---
 docs/change_log.rst                         |  1 +
 stem/descriptor/router_status_entry.py      |  7 ++++
 test/unit/descriptor/router_status_entry.py | 53 +++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 09237cba..16f54773 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -67,6 +67,7 @@ The following are only available within Stem's `git repository
   * Added the *orport_v6* attribute to the :class:`~stem.directory.Authority` class
   * Added server descriptor's new is_hidden_service_dir attribute
   * Added the network status vote's new bandwidth_file attribute (:spec:`84591df`)
+  * Added the microdescriptor router status entry's new or_addresses attribute (:trac:`26405`, :spec:`fdc8f3e8`)
   * Don't retry downloading descriptors when we've timed out
   * Don't download from tor26 and Bifroest, which are authorities that frequently timeout
   * `stem.descriptor.remote <api/descriptor/remote.html>`_  now consistently defaults **fall_back_to_authority** to false
diff --git a/stem/descriptor/router_status_entry.py b/stem/descriptor/router_status_entry.py
index 5b99ba0c..b4cd506a 100644
--- a/stem/descriptor/router_status_entry.py
+++ b/stem/descriptor/router_status_entry.py
@@ -662,6 +662,8 @@ class RouterStatusEntryMicroV3(RouterStatusEntry):
   Information about an individual router stored within a microdescriptor
   flavored network status document.
 
+  :var list or_addresses: **\*** relay's OR addresses, this is a tuple listing
+    of the form (address (**str**), port (**int**), is_ipv6 (**bool**))
   :var int bandwidth: bandwidth claimed by the relay (in kb/s)
   :var int measured: bandwidth measured to be available by the relay
   :var bool is_unmeasured: bandwidth measurement isn't based on three or more
@@ -675,11 +677,15 @@ class RouterStatusEntryMicroV3(RouterStatusEntry):
   .. versionchanged:: 1.6.0
      Added the protocols attribute.
 
+  .. versionchanged:: 1.7.0
+     Added the or_addresses attribute.
+
   **\*** attribute is either required when we're parsed with validation or has
   a default value, others are left as **None** if undefined
   """
 
   ATTRIBUTES = dict(RouterStatusEntry.ATTRIBUTES, **{
+    'or_addresses': ([], _parse_a_line),
     'bandwidth': (None, _parse_w_line),
     'measured': (None, _parse_w_line),
     'is_unmeasured': (False, _parse_w_line),
@@ -690,6 +696,7 @@ class RouterStatusEntryMicroV3(RouterStatusEntry):
   })
 
   PARSER_FOR_LINE = dict(RouterStatusEntry.PARSER_FOR_LINE, **{
+    'a': _parse_a_line,
     'w': _parse_w_line,
     'm': _parse_microdescriptor_m_line,
     'pr': _parse_pr_line,
diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py
index a4c14e01..b376f869 100644
--- a/test/unit/descriptor/router_status_entry.py
+++ b/test/unit/descriptor/router_status_entry.py
@@ -26,6 +26,12 @@ from stem.descriptor.router_status_entry import (
   _base64_to_hex,
 )
 
+try:
+  # Added in 2.7
+  from collections import OrderedDict
+except ImportError:
+  from stem.util.ordereddict import OrderedDict
+
 ENTRY_WITHOUT_ED25519 = """\
 r seele AAoQ1DAR6kkoo19hBAX5K0QztNw m0ynPuwzSextzsiXYJYA0Hce+Cs 2015-08-23 00:26:35 73.15.150.172 9001 0
 s Running Stable Valid
@@ -52,6 +58,16 @@ m 18,19,20 sha256=AkZH3gIvz3wunsroqh5izBJizdYuR7kn2oVbsvqgML8
 m 21 sha256=AVp41YVxKEJCaoEf0+77Cdvyw5YgpyDXdob0+LSv/pE
 """
 
+ENTRY_WITH_IPV6 = """\
+r MYLEX AQt3KEVEEfSFzinUx5oUU0FRwsQ 2018-07-15 16:38:10 77.123.42.148 444 800
+a [2001:470:71:9b9:f66d:4ff:fee7:954c]:444
+m GWb+xjav0fsuwPwPNnUvW9Q1Ivk5nz8m1McECM4KY8A
+s Fast Guard HSDir Running Stable V2Dir Valid
+v Tor 0.2.5.16
+pr Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2
+w Bandwidth=4950
+"""
+
 expect_invalid_attr = functools.partial(base_expect_invalid_attr, RouterStatusEntryV3, 'nickname', 'Unnamed')
 expect_invalid_attr_for_text = functools.partial(base_expect_invalid_attr_for_text, RouterStatusEntryV3, 'nickname', 'Unnamed')
 
@@ -222,6 +238,43 @@ class TestRouterStatusEntry(unittest.TestCase):
     self.assertEqual('CAB27A6FFEF7A661C18B0B11120C3E8A77FC585C', entry.digest)
     self.assertEqual([], entry.get_unrecognized_lines())
 
+  def test_with_ipv6(self):
+    """
+    Parse a router status entry with an IPv6 address.
+    """
+
+    expected_protocols = OrderedDict((
+      ('Cons', [1]),
+      ('Desc', [1]),
+      ('DirCache', [1]),
+      ('HSDir', [1]),
+      ('HSIntro', [3]),
+      ('HSRend', [1]),
+      ('Link', [1, 2, 3, 4]),
+      ('LinkAuth', [1]),
+      ('Microdesc', [1]),
+      ('Relay', [1, 2]),
+    ))
+
+    entry = RouterStatusEntryMicroV3(ENTRY_WITH_IPV6, validate = True)
+    self.assertEqual('MYLEX', entry.nickname)
+    self.assertEqual('010B7728454411F485CE29D4C79A14534151C2C4', entry.fingerprint)
+    self.assertEqual(datetime.datetime(2018, 7, 15, 16, 38, 10), entry.published)
+    self.assertEqual('77.123.42.148', entry.address)
+    self.assertEqual(444, entry.or_port)
+    self.assertEqual(800, entry.dir_port)
+    self.assertEqual(set([Flag.FAST, Flag.GUARD, Flag.HSDIR, Flag.RUNNING, Flag.STABLE, Flag.V2DIR, Flag.VALID]), set(entry.flags))
+    self.assertEqual('Tor 0.2.5.16', entry.version_line)
+    self.assertEqual(Version('0.2.5.16'), entry.version)
+    self.assertEqual([('2001:470:71:9b9:f66d:4ff:fee7:954c', 444, True)], entry.or_addresses)
+    self.assertEqual(4950, entry.bandwidth)
+    self.assertEqual(None, entry.measured)
+    self.assertEqual(False, entry.is_unmeasured)
+    self.assertEqual([], entry.unrecognized_bandwidth_entries)
+    self.assertEqual(expected_protocols, entry.protocols)
+    self.assertEqual('1966FEC636AFD1FB2EC0FC0F36752F5BD43522F9399F3F26D4C70408CE0A63C0', entry.digest)
+    self.assertEqual([], entry.get_unrecognized_lines())
+
   def test_missing_fields(self):
     """
     Parses a router status entry that's missing fields.



More information about the tor-commits mailing list