[tor-commits] [stem/master] Add orport_v6 to the Authority class

atagar at torproject.org atagar at torproject.org
Tue May 8 20:20:09 UTC 2018


commit e554de7373e017c788ba411dd850d2e7c518390a
Author: Damian Johnson <atagar at torproject.org>
Date:   Tue May 8 12:01:34 2018 -0700

    Add orport_v6 to the Authority class
    
    Moving the orport_v6 attribute from Fallback up to the parent Directory class,
    effectively adding it to directory authorities. This was added to tor's backed
    in information.
---
 docs/change_log.rst              |  1 +
 stem/directory.py                | 51 +++++++++++++++++++++-------------------
 test/unit/directory/authority.py |  2 ++
 3 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 67359a95..3836b8ad 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -60,6 +60,7 @@ The following are only available within Stem's `git repository
   * Moved the Directory classes into their own `stem.directory <api/directory.html>`_ module
   * Added :func:`~stem.descriptor.remote.Directory.from_cache` and :func:`~stem.descriptor.remote.Directory.from_remote` to the :class:`~stem.descriptor.remote.DirectoryAuthority` subclass
   * `Fallback directory v2 support <https://lists.torproject.org/pipermail/tor-dev/2017-December/012721.html>`_, which adds *nickname* and *extrainfo*
+  * Added the *orport_v6* attribute to the :class:`~stem.directory.Authority` class
   * Added server descriptor's new is_hidden_service_dir attribute
   * Don't retry downloading descriptors when we've timed out
   * Don't download from tor26 and Bifroest, which are authorities that frequently timeout
diff --git a/stem/directory.py b/stem/directory.py
index acd24a80..b638a354 100644
--- a/stem/directory.py
+++ b/stem/directory.py
@@ -91,17 +91,16 @@ class Directory(object):
   names, whereas fallbacks vary more and don't necessarily have a nickname to
   key off of.
 
-  .. versionchanged:: 1.3.0
-     Moved nickname from subclasses to this base class.
-
   :var str address: IPv4 address of the directory
   :var int or_port: port on which the relay services relay traffic
   :var int dir_port: port on which directory information is available
   :var str fingerprint: relay fingerprint
   :var str nickname: relay nickname
+  :var str orport_v6: **(address, port)** tuple for the directory's IPv6
+    ORPort, or **None** if it doesn't have one
   """
 
-  def __init__(self, address, or_port, dir_port, fingerprint, nickname):
+  def __init__(self, address, or_port, dir_port, fingerprint, nickname, orport_v6):
     identifier = '%s (%s)' % (fingerprint, nickname) if nickname else fingerprint
 
     if not connection.is_valid_ipv4_address(address):
@@ -115,11 +114,20 @@ class Directory(object):
     elif nickname and not tor_tools.is_valid_nickname(nickname):
       raise ValueError('%s has an invalid nickname: %s' % (fingerprint, nickname))
 
+    if orport_v6:
+      if not isinstance(orport_v6, tuple) or len(orport_v6) != 2:
+        raise ValueError('%s orport_v6 should be a two value tuple: %s' % (identifier, str(orport_v6)))
+      elif not connection.is_valid_ipv6_address(orport_v6[0]):
+        raise ValueError('%s has an invalid IPv6 address: %s' % (identifier, orport_v6[0]))
+      elif not connection.is_valid_port(orport_v6[1]):
+        raise ValueError('%s has an invalid IPv6 port: %s' % (identifier, orport_v6[1]))
+
     self.address = address
     self.or_port = int(or_port)
     self.dir_port = int(dir_port)
     self.fingerprint = fingerprint
     self.nickname = nickname
+    self.orport_v6 = (orport_v6[0], int(orport_v6[1])) if orport_v6 else None
 
   @staticmethod
   def from_cache():
@@ -169,7 +177,7 @@ class Directory(object):
     raise NotImplementedError('Unsupported Operation: this should be implemented by the Directory subclass')
 
   def __hash__(self):
-    return _hash_attr(self, 'address', 'or_port', 'dir_port', 'fingerprint', 'nickname')
+    return _hash_attr(self, 'address', 'or_port', 'dir_port', 'fingerprint', 'nickname', 'orport_v6')
 
   def __eq__(self, other):
     return hash(self) == hash(other) if isinstance(other, Directory) else False
@@ -187,6 +195,9 @@ class Authority(Directory):
   .. versionchanged:: 1.3.0
      Added the is_bandwidth_authority attribute.
 
+  .. versionchanged:: 1.7.0
+     Added the orport_v6 attribute.
+
   .. deprecated:: 1.7.0
      The is_bandwidth_authority attribute is deprecated and will be removed in
      the future.
@@ -194,8 +205,8 @@ class Authority(Directory):
   :var str v3ident: identity key fingerprint used to sign votes and consensus
   """
 
-  def __init__(self, address = None, or_port = None, dir_port = None, fingerprint = None, nickname = None, v3ident = None, is_bandwidth_authority = False):
-    super(Authority, self).__init__(address, or_port, dir_port, fingerprint, nickname)
+  def __init__(self, address = None, or_port = None, dir_port = None, fingerprint = None, nickname = None, orport_v6 = None, v3ident = None, is_bandwidth_authority = False):
+    super(Authority, self).__init__(address, or_port, dir_port, fingerprint, nickname, orport_v6)
     identifier = '%s (%s)' % (fingerprint, nickname) if nickname else fingerprint
 
     if v3ident and not tor_tools.is_valid_fingerprint(v3ident):
@@ -271,7 +282,7 @@ class Authority(Directory):
 
     nickname, or_port = matches.get(AUTHORITY_NAME)
     v3ident = matches.get(AUTHORITY_V3IDENT)
-    # orport_v6 = matches.get(AUTHORITY_IPV6)  # TODO: add this to stem's data?
+    orport_v6 = matches.get(AUTHORITY_IPV6)
     address, dir_port, fingerprint = matches.get(AUTHORITY_ADDR)
 
     return Authority(
@@ -280,6 +291,7 @@ class Authority(Directory):
       dir_port = dir_port,
       fingerprint = fingerprint.replace(' ', ''),
       nickname = nickname,
+      orport_v6 = orport_v6,
       v3ident = v3ident,
     )
 
@@ -339,31 +351,18 @@ class Fallback(Directory):
   .. versionadded:: 1.5.0
 
   .. versionchanged:: 1.7.0
-     Added the nickname, has_extrainfo, and header attributes which are part of
+     Added the has_extrainfo, and header attributes which are part of
      the `second version of the fallback directories
      <https://lists.torproject.org/pipermail/tor-dev/2017-December/012721.html>`_.
 
   :var bool has_extrainfo: **True** if the relay should be able to provide
     extrainfo descriptors, **False** otherwise.
-  :var str orport_v6: **(address, port)** tuple for the directory's IPv6
-    ORPort, or **None** if it doesn't have one
   :var dict header: metadata about the fallback directory file this originated from
   """
 
   def __init__(self, address = None, or_port = None, dir_port = None, fingerprint = None, nickname = None, has_extrainfo = False, orport_v6 = None, header = None):
-    super(Fallback, self).__init__(address, or_port, dir_port, fingerprint, nickname)
-    identifier = '%s (%s)' % (fingerprint, nickname) if nickname else fingerprint
-
-    if orport_v6:
-      if not isinstance(orport_v6, tuple) or len(orport_v6) != 2:
-        raise ValueError('%s orport_v6 should be a two value tuple: %s' % (identifier, str(orport_v6)))
-      elif not connection.is_valid_ipv6_address(orport_v6[0]):
-        raise ValueError('%s has an invalid IPv6 address: %s' % (identifier, orport_v6[0]))
-      elif not connection.is_valid_port(orport_v6[1]):
-        raise ValueError('%s has an invalid IPv6 port: %s' % (identifier, orport_v6[1]))
-
+    super(Fallback, self).__init__(address, or_port, dir_port, fingerprint, nickname, orport_v6)
     self.has_extrainfo = has_extrainfo
-    self.orport_v6 = (orport_v6[0], int(orport_v6[1])) if orport_v6 else None
     self.header = header if header else OrderedDict()
 
   @staticmethod
@@ -556,7 +555,7 @@ class Fallback(Directory):
     conf.save(path)
 
   def __hash__(self):
-    return _hash_attr(self, 'has_extrainfo', 'orport_v6', 'header', parent = Directory)
+    return _hash_attr(self, 'has_extrainfo', 'header', parent = Directory)
 
   def __eq__(self, other):
     return hash(self) == hash(other) if isinstance(other, Fallback) else False
@@ -626,6 +625,7 @@ DIRECTORY_AUTHORITIES = {
     or_port = 443,
     dir_port = 80,
     fingerprint = '847B1F850344D7876491A54892F904934E4EB85D',
+    orport_v6 = ('2001:858:2:2:aabb:0:563b:1526', 443),
     v3ident = '14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4',
   ),
   'dizum': Authority(
@@ -642,6 +642,7 @@ DIRECTORY_AUTHORITIES = {
     or_port = 443,
     dir_port = 80,
     fingerprint = 'F2044413DAC2E02E3D6BCF4735A19BCA1DE97281',
+    orport_v6 = ('2001:638:a000:4140::ffff:189', 443),
     v3ident = 'ED03BB616EB2F60BEC80151114BB25CEF515B226',
   ),
   'dannenberg': Authority(
@@ -658,6 +659,7 @@ DIRECTORY_AUTHORITIES = {
     or_port = 80,
     dir_port = 443,
     fingerprint = 'BD6A829255CB08E66FBE7D3748363586E46B3810',
+    orport_v6 = ('2001:67c:289c::9', 80),
     v3ident = '49015F787433103580E3B66A1707A00E60F2D15B',
   ),
   'Faravahar': Authority(
@@ -682,6 +684,7 @@ DIRECTORY_AUTHORITIES = {
     or_port = 443,
     dir_port = 80,
     fingerprint = '24E2F139121D4394C54B5BCC368B3B411857C413',
+    orport_v6 = ('2620:13:4000:6000::1000:118', 443),
     v3ident = '27102BC123E7AF1D4741AE047E160C91ADC76B21',
   ),
   'Bifroest': Authority(
diff --git a/test/unit/directory/authority.py b/test/unit/directory/authority.py
index 8fd70880..56bd6ec8 100644
--- a/test/unit/directory/authority.py
+++ b/test/unit/directory/authority.py
@@ -35,6 +35,7 @@ class TestAuthority(unittest.TestCase):
       'dir_port': 9030,
       'fingerprint': '0756B7CD4DFC8182BE23143FAC0642F515182CEB',
       'nickname': 'rueckgrat',
+      'orport_v6': ('2a01:4f8:162:51e2::2', 9001),
       'v3ident': '23D15D965BC35114467363C165C4F724B64B4F66',
     }
 
@@ -68,6 +69,7 @@ class TestAuthority(unittest.TestCase):
         or_port = 443,
         dir_port = 80,
         fingerprint = '847B1F850344D7876491A54892F904934E4EB85D',
+        orport_v6 = ('2001:858:2:2:aabb:0:563b:1526', 443),
         v3ident = '14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4',
       ),
     }





More information about the tor-commits mailing list