[tor-commits] [stem/master] RouterDescriptor objects store a list of flags

atagar at torproject.org atagar at torproject.org
Sat Oct 13 18:35:44 UTC 2012


commit dcf2092607c8be29d065def1cb104290709bef87
Author: Ravi Chandra Padmala <neenaoffline at gmail.com>
Date:   Thu Aug 9 17:21:09 2012 +0530

    RouterDescriptor objects store a list of flags
---
 stem/descriptor/networkstatus.py       |   83 ++++++++++----------------------
 test/integ/descriptor/networkstatus.py |    7 +--
 2 files changed, 29 insertions(+), 61 deletions(-)

diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index b1dc4dd..214a33c 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -49,6 +49,7 @@ except:
 import stem.descriptor
 import stem.version
 import stem.exit_policy
+import stem.util.enum
 
 from stem.descriptor import _read_until_keywords, _skip_until_keywords, _peek_keyword, _strptime
 from stem.descriptor import _read_keyword_line, _read_keyword_line_str, _get_pseudo_pgp_block, _peek_line
@@ -58,6 +59,8 @@ _bandwidth_weights_regex = re.compile(" ".join(["W%s=\d+" % weight for weight in
 
 _router_desc_end_kws = ["r", "bandwidth-weights", "directory-footer", "directory-signature"]
 
+Flag = stem.util.enum.Enum(*[(flag.upper(), flag) for flag in ["Authority", "BadExit", "Exit", "Fast", "Guard", "HSDir", "Named", "Running", "Stable", "Unnamed", "V2Dir", "Valid"]])
+
 def parse_file(document_file, validate = True):
   """
   Iterates over the router descriptors in a network status document.
@@ -82,13 +85,13 @@ def parse_file(document_file, validate = True):
   document_data = document_data + document_file.read()
   document = NetworkStatusDocument(document_data, validate)
   document_file.seek(r_offset)
-  document.router_descriptors = _router_desc_generator(document_file, document.vote_status == "vote", validate)
+  document.router_descriptors = _router_desc_generator(document_file, document.vote_status == "vote", validate, document.known_flags)
   return document.router_descriptors
 
-def _router_desc_generator(document_file, vote, validate):
+def _router_desc_generator(document_file, vote, validate, known_flags):
   while _peek_keyword(document_file) == "r":
     desc_content = "".join(_read_until_keywords(_router_desc_end_kws, document_file, False, True))
-    yield RouterDescriptor(desc_content, vote, validate)
+    yield RouterDescriptor(desc_content, vote, validate, known_flags)
 
 class NetworkStatusDocument(stem.descriptor.Descriptor):
   """
@@ -156,8 +159,8 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
     
     self._parse(raw_content)
   
-  def _generate_router(self, raw_content, vote, validate):
-    return RouterDescriptor(raw_content, vote, validate)
+  def _generate_router(self, raw_content, vote, validate, known_flags):
+    return RouterDescriptor(raw_content, vote, validate, known_flags)
   
   def _validate_network_status_version(self):
     return self.network_status_version == "3"
@@ -220,7 +223,7 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
     # router descriptors
     if _peek_keyword(content) == "r":
       router_descriptors_data = "".join(_read_until_keywords(["bandwidth-weights", "directory-footer", "directory-signature"], content, False, True))
-      self.router_descriptors = _router_desc_generator(StringIO(router_descriptors_data), vote, validate)
+      self.router_descriptors = _router_desc_generator(StringIO(router_descriptors_data), vote, validate, self.known_flags)
     
     # footer section
     if self.consensus_method > 9 or vote and filter(lambda x: x >= 9, self.consensus_methods):
@@ -366,20 +369,8 @@ class RouterDescriptor(stem.descriptor.Descriptor):
   :var int orport: **\*** router's ORPort
   :var int dirport: **\*** router's DirPort
   
-  :var bool is_valid: **\*** router is valid
-  :var bool is_guard: **\*** router is suitable for use as an entry guard
-  :var bool is_named: **\*** router is named
-  :var bool is_unnamed: **\*** router is unnamed
-  :var bool is_running: **\*** router is running and currently usable
-  :var bool is_stable: **\*** router is stable, i.e., it's suitable for for long-lived circuits
-  :var bool is_exit: **\*** router is an exit router
-  :var bool is_fast: **\*** router is Fast, i.e., it's usable for high-bandwidth circuits
-  :var bool is_authority: **\*** router is a directory authority
-  :var bool supports_v2dir: **\*** router supports v2dir
-  :var bool supports_v3dir: **\*** router supports v3dir
-  :var bool is_hsdir: **\*** router is a hidden status
-  :var bool is_badexit: **\*** router is marked a bad exit
-  :var bool is_baddirectory: **\*** router is a bad directory
+  :var list flags: **\*** list of status flags
+  :var list unknown_flags: **\*** list of unidentified status flags
   
   :var :class:`stem.version.Version`,str version: Version of the Tor protocol this router is running
   
@@ -394,13 +385,17 @@ class RouterDescriptor(stem.descriptor.Descriptor):
   | exit_policy appears only in votes
   """
   
-  def __init__(self, raw_contents, vote = True, validate = True):
+  def __init__(self, raw_contents, vote = True, validate = True, known_flags = Flag):
     """
     Parse a router descriptor in a v3 network status document and provide a new
     RouterDescriptor object.
     
     :param str raw_content: router descriptor content to be parsed
+    :param bool vote: True if the descriptor is from a vote document
     :param bool validate: whether the router descriptor should be validated
+    :param bool known_flags: list of known router status flags
+
+    :raises: ValueError if the descriptor data is invalid
     """
     
     super(RouterDescriptor, self).__init__(raw_contents)
@@ -413,20 +408,8 @@ class RouterDescriptor(stem.descriptor.Descriptor):
     self.orport = None
     self.dirport = None
     
-    self.is_valid = False
-    self.is_guard = False
-    self.is_named = False
-    self.is_unnamed = False
-    self.is_running = False
-    self.is_stable = False
-    self.is_exit = False
-    self.is_fast = False
-    self.is_authority = False
-    self.supports_v2dir = False
-    self.supports_v3dir = False
-    self.is_hsdir = False
-    self.is_badexit = False
-    self.is_baddirectory = False
+    self.flags = []
+    self.unknown_flags = []
     
     self.version = None
     
@@ -437,12 +420,14 @@ class RouterDescriptor(stem.descriptor.Descriptor):
     
     self.microdescriptor_hashes = []
     
-    self._parse(raw_contents, vote, validate)
+    self._parse(raw_contents, vote, validate, known_flags)
   
-  def _parse(self, raw_content, vote, validate):
+  def _parse(self, raw_content, vote, validate, known_flags):
     """
     :param dict raw_content: iptor contents to be applied
+    :param bool vote: True if the descriptor is from a vote document
     :param bool validate: checks the validity of descriptor content if True
+    :param bool known_flags: list of known router status flags
     
     :raises: ValueError if an error occures in validation
     """
@@ -471,27 +456,11 @@ class RouterDescriptor(stem.descriptor.Descriptor):
         seen_keywords.add("s")
         # s Named Running Stable Valid
         #A series of space-separated status flags, in *lexical order*
-        flags = line.split(" ")
-        flag_map = {
-          "Valid": "is_valid",
-          "Guard": "is_guard",
-          "Named": "is_named",
-          "Unnamed": "is_unnamed",
-          "Running": "is_running",
-          "Stable": "is_stable",
-          "Exit": "is_exit",
-          "Fast": "is_fast",
-          "Authority": "is_authority",
-          "V2Dir": "supports_v2dir",
-          "V3Dir": "supports_v3dir",
-          "HSDir": "is_hsdir",
-          "BadExit": "is_badexit",
-          "BadDirectory": "is_baddirectory",
-        }
-        map(lambda flag: setattr(self, flag_map[flag], True), flags)
+        self.flags = line.split(" ")
         
-        if self.is_unnamed: self.is_named = False
-        elif self.is_named: self.is_unnamed = False
+        self.unknown_flags = filter(lambda f: not f in known_flags, self.flags)
+        if validate and self.unknown_flags:
+          raise ValueError("Router contained unknown flags: %s", " ".join(self.unknown_flags))
       
       elif peek_check_kw("v"):
         if "v" in seen_keywords: raise ValueError("Invalid router descriptor: 'v' line appears twice")
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index f5d8942..07414c3 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -98,8 +98,7 @@ class TestNetworkStatusDocument(unittest.TestCase):
       "0.2.3.18-rc", "0.2.3.19-rc"]]
     self.assertEquals(expected_client_versions, desc.client_versions)
     self.assertEquals(expected_server_versions, desc.server_versions)
-    known_flags = ["Authority", "BadExit", "Exit", "Fast", "Guard", "HSDir", "Named", "Running", "Stable", "Unnamed", "V2Dir", "Valid"]
-    self.assertEquals(known_flags, desc.known_flags)
+    self.assertEquals(set(desc.known_flags), set(["Authority", "BadExit", "Exit", "Fast", "Guard", "HSDir", "Named", "Running", "Stable", "Unnamed", "V2Dir", "Valid"]))
     expected_params = {"CircuitPriorityHalflifeMsec": 30000, "bwauthpid": 1}
     self.assertEquals(expected_params, desc.params)
     router1 = next(desc.router_descriptors)
@@ -110,6 +109,7 @@ class TestNetworkStatusDocument(unittest.TestCase):
     self.assertEquals("178.218.213.229", router1.ip)
     self.assertEquals(80, router1.orport)
     self.assertEquals(None, router1.dirport)
+    self.assertEquals(set(["Exit", "Fast", "Named", "Running", "Valid"]), set(router1.flags))
     
     self.assertEquals(8, len(desc.directory_authorities))
     self.assertEquals("tor26", desc.directory_authorities[0].nickname)
@@ -182,8 +182,7 @@ I/TJmV928na7RLZe2mGHCAW3VQOvV+QkCfj05VZ8CsY=
     self.assertEquals(300, desc.dist_delay)
     self.assertEquals([], desc.client_versions)
     self.assertEquals([], desc.server_versions)
-    known_flags = ["Authority", "BadExit", "Exit", "Fast", "Guard", "HSDir", "Running", "Stable", "V2Dir", "Valid"]
-    self.assertEquals(known_flags, desc.known_flags)
+    self.assertEquals(set(desc.known_flags), set(["Authority", "BadExit", "Exit", "Fast", "Guard", "HSDir", "Running", "Stable", "V2Dir", "Valid"]))
     expected_params = {"CircuitPriorityHalflifeMsec": 30000, "bwauthpid": 1}
     self.assertEquals(expected_params, desc.params)
     router1 = next(desc.router_descriptors)





More information about the tor-commits mailing list