[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Parsing network-status-version attribute
commit 5e12da0a50ee60577f3a571eea0ef3350e146d10
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sat Sep 8 12:15:34 2012 -0700
Parsing network-status-version attribute
I don't like our assumption that this is a v3 network status document, but I'll
need to think more about how to handle other versions later. For now keeping
the validation assertion that parsed documents are v3.
---
stem/descriptor/networkstatus.py | 56 +++++++++++++++---------
test/integ/descriptor/networkstatus.py | 4 +-
test/unit/descriptor/networkstatus/document.py | 16 ++++++-
3 files changed, 50 insertions(+), 26 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 2140b4d..d554d42 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -198,7 +198,7 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
:var tuple routers: RouterStatusEntry contained in the document
- :var str network_status_version: **\*** document version
+ :var str version: **\*** document version
:var str vote_status: **\*** status of the vote (is either "vote" or "consensus")
:var int consensus_method: **~** consensus method used to generate a consensus
:var list consensus_methods: **^** A list of supported consensus generation methods (integers)
@@ -236,7 +236,7 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
self.directory_authorities = []
self.directory_signatures = []
- self.network_status_version = None
+ self.version = None
self.vote_status = None
self.consensus_methods = []
self.published = None
@@ -255,8 +255,8 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
document_file = StringIO(raw_content)
header, footer, routers_end = _get_document_content(document_file, validate)
- self._parse_old(header + footer, validate)
self._parse(header, footer, validate)
+ self._parse_old(header + footer, validate)
if document_file.tell() < routers_end:
self.routers = tuple(_get_routers(document_file, validate, self, routers_end, self._get_router_type()))
@@ -266,9 +266,6 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
def _get_router_type(self):
return RouterStatusEntry
- def _validate_network_status_version(self):
- return self.network_status_version == "3"
-
def get_unrecognized_lines(self):
"""
Returns any unrecognized trailing lines.
@@ -292,23 +289,27 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
header_entries = stem.descriptor._get_descriptor_components(header, validate)[0]
footer_entries = stem.descriptor._get_descriptor_components(footer, validate)[0]
- if validate:
- if not 'vote-status' in header_entries:
- raise ValueError("Network status documents must have a 'vote-status' line to say if they're a vote or consensus")
-
+ all_entries = dict()
+ all_entries.update(header_entries)
+ all_entries.update(footer_entries)
+
+ if 'vote-status' in header_entries:
is_consensus = header_entries['vote-status'][0][0] == "consensus"
is_vote = not is_consensus
+ else:
+ if validate:
+ raise ValueError("Network status documents must have a 'vote-status' line to say if they're a vote or consensus")
+
+ is_consensus, is_vote = True, False
+
+ if validate:
self._check_for_missing_and_disallowed_fields(is_consensus, header_entries, footer_entries)
self._check_for_misordered_fields(is_consensus, header_entries, footer_entries)
known_fields = [attr[0] for attr in HEADER_STATUS_DOCUMENT_FIELDS + FOOTER_STATUS_DOCUMENT_FIELDS]
content = header + '\n' + footer
- entries = dict()
- entries.update(header_entries)
- entries.update(footer_entries)
-
- for keyword, values in entries.items():
+ for keyword, values in all_entries.items():
value, block_contents = values[0]
line = "%s %s" % (keyword, value)
@@ -318,15 +319,28 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
if validate and len(values) > 1 and keyword in known_fields:
if not (keyword == 'directory-signature' and is_consensus):
raise ValueError("Network status documents can only have a single '%s' line, got %i:\n%s" % (keyword, len(values), content))
+
+ if keyword == 'network-status-version':
+ # "network-status-version" version
+
+ self.version = value
+
+ # TODO: Obviously not right when we extend this to parse v2 documents,
+ # but we'll cross that bridge when we come to it.
+
+ if validate and self.version != "3":
+ raise ValueError("Expected a version 3 network status documents, got version '%s' instead" % self.version)
def _parse_old(self, raw_content, validate):
# preamble
content = StringIO(raw_content)
read_keyword_line = lambda keyword, optional = False: setattr(self, keyword.replace("-", "_"), _read_keyword_line(keyword, content, validate, optional))
- map(read_keyword_line, ["network-status-version", "vote-status"])
- if validate and not self._validate_network_status_version():
- raise ValueError("Invalid network-status-version: %s" % self.network_status_version)
+ # ignore things the parse() method handles
+ _read_keyword_line("network-status-version", content, False, True)
+
+
+ map(read_keyword_line, ["vote-status"])
vote = False
if self.vote_status == "vote": vote = True
@@ -479,7 +493,7 @@ class NetworkStatusDocument(stem.descriptor.Descriptor):
if actual != expected:
actual_label = ', '.join(actual)
expected_label = ', '.join(expected)
- raise ValueError("The fields in the document's %s are misordered. It should be '%s' but was '%s'" % (lable, actual_label, expected_label))
+ raise ValueError("The fields in the document's %s are misordered. It should be '%s' but was '%s'" % (label, actual_label, expected_label))
class DirectoryAuthority(stem.descriptor.Descriptor):
"""
@@ -855,7 +869,7 @@ class MicrodescriptorConsensus(NetworkStatusDocument):
"""
A v3 microdescriptor consensus.
- :var str network_status_version: **\*** a document format version. For v3 microdescriptor consensuses this is "3 microdesc"
+ :var str version: **\*** a document format version. For v3 microdescriptor consensuses this is "3 microdesc"
:var str vote_status: **\*** status of the vote (is "consensus")
:var int consensus_method: **~** consensus method used to generate a consensus
:var datetime valid_after: **\*** time when the consensus becomes valid
@@ -879,7 +893,7 @@ class MicrodescriptorConsensus(NetworkStatusDocument):
return RouterMicrodescriptor
def _validate_network_status_version(self):
- return self.network_status_version == "3 microdesc"
+ return self.version == "3 microdesc"
class RouterMicrodescriptor(RouterStatusEntry):
"""
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 4ca8e5c..1777828 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -85,7 +85,7 @@ class TestNetworkStatus(unittest.TestCase):
router1 = desc.routers[0]
descriptor_file.close()
- self.assertEquals("3", desc.network_status_version)
+ self.assertEquals("3", desc.version)
self.assertEquals("consensus", desc.vote_status)
self.assertEquals([], desc.consensus_methods)
self.assertEquals(None, desc.published)
@@ -177,7 +177,7 @@ I/TJmV928na7RLZe2mGHCAW3VQOvV+QkCfj05VZ8CsY=
router1 = desc.routers[0]
descriptor_file.close()
- self.assertEquals("3", desc.network_status_version)
+ self.assertEquals("3", desc.version)
self.assertEquals("vote", desc.vote_status)
self.assertEquals(range(1, 13), desc.consensus_methods)
self.assertEquals(_strptime("2012-07-11 23:50:01"), desc.published)
diff --git a/test/unit/descriptor/networkstatus/document.py b/test/unit/descriptor/networkstatus/document.py
index ef77391..a099fa9 100644
--- a/test/unit/descriptor/networkstatus/document.py
+++ b/test/unit/descriptor/networkstatus/document.py
@@ -100,7 +100,7 @@ class TestNetworkStatusDocument(unittest.TestCase):
sig = DirectorySignature("directory-signature " + NETWORK_STATUS_DOCUMENT_ATTR["directory-signature"])
self.assertEqual((), document.routers)
- self.assertEqual("3", document.network_status_version)
+ self.assertEqual("3", document.version)
self.assertEqual("consensus", document.vote_status)
self.assertEqual(9, document.consensus_method)
self.assertEqual([], document.consensus_methods)
@@ -133,7 +133,7 @@ class TestNetworkStatusDocument(unittest.TestCase):
sig = DirectorySignature("directory-signature " + NETWORK_STATUS_DOCUMENT_ATTR["directory-signature"])
self.assertEqual((), document.routers)
- self.assertEqual("3", document.network_status_version)
+ self.assertEqual("3", document.version)
self.assertEqual("vote", document.vote_status)
self.assertEqual(None, document.consensus_method)
self.assertEqual([9], document.consensus_methods)
@@ -213,5 +213,15 @@ class TestNetworkStatusDocument(unittest.TestCase):
content = "\n".join(test_lines)
self.assertRaises(ValueError, NetworkStatusDocument, content)
NetworkStatusDocument(content, False) # constructs without validation
-
+
+ def test_invalid_version(self):
+ """
+ Try parsing a different document version with the v3 parser.
+ """
+
+ content = get_network_status_document({"network-status-version": "4"})
+ self.assertRaises(ValueError, NetworkStatusDocument, content)
+
+ document = NetworkStatusDocument(content, False)
+ self.assertEquals("4", document.version)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits