[stem/master] Missing version 3 attributes

commit 7dc7d82bd7b7f70f3dfae21dd607502b4eff6477 Author: Damian Johnson <atagar@torproject.org> Date: Sat Mar 24 19:38:27 2012 -0700 Missing version 3 attributes Adding the server descriptor attributes that are new as of version 3. The only attributes that I'm still excluding are eventdns (because it's dead) and read/write-history (since they're extra-info now). --- stem/descriptor/server_descriptor.py | 56 +++++++++++++++++++++++++-- test/integ/descriptor/server_descriptor.py | 6 +++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index c301840..ceee835 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -33,26 +33,31 @@ PGP_BLOCK_START = re.compile("^-----BEGIN ([%s%s]+)-----$" % (KEYWORD_CHAR, WHIT PGP_BLOCK_END = "-----END %s-----" # entries must have exactly one of the following -# TODO: spec doesn't list 'router-signature', but that's a spec bug I should fix REQUIRED_FIELDS = ( + "router", + "bandwidth", "published", "onion-key", "signing-key", - "bandwidth", "router-signature", ) # optional entries that can appear at most once SINGLE_FIELDS = ( - "contact", - "uptime", + "platform", "fingerprint", "hibernating", + "uptime", + "contact", "read-history", "write-history", "eventdns", - "platform", "family", + "caches-extra-info", + "extra-info-digest", + "hidden-service-dir", + "protocols", + "allow-single-hop-exits", ) def parse_file_v3(descriptor_file, validate = True): @@ -203,7 +208,13 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): uptime (int) - relay's uptime when published in seconds published (datetime.datetime) - time in GMT when the descriptor was generated (*) contact (str) - relay's contact information + link_protocols (list) - link protocols supported by the relay + circuit_protocols (list) - circuit protocols supported by the relay hibernating (bool) - flag to indicate if the relay was hibernating when published (*) + allow_single_hop_exits (bool) - flag to indicate if single hop exiting is allowed from it (*) + extra_info_cache (bool) - flag to indicate if it's a mirror for extra-info documents (*) + extra_info_digest (str) - hex encoded digest of our extra-info document + hidden_service_dir (list) - hidden service descriptor versions that it stores exit_policy (stem.exit_policy.ExitPolicy) - relay's stated exit policy family (list) - nicknames or fingerprints of relays it has a declared family with (*) average_bandwidth (int) - rate of traffic relay is willing to relay in bytes/s (*) @@ -253,7 +264,13 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): self.uptime = None self.published = None self.contact = None + self.link_protocols = None + self.circuit_protocols = None self.hibernating = False + self.allow_single_hop_exits = False + self.extra_info_cache = False + self.extra_info_digest = None + self.hidden_service_dir = None self.family = [] self.average_bandwidth = None self.burst_bandwidth = None @@ -337,6 +354,9 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): for keyword in SINGLE_FIELDS + REQUIRED_FIELDS: if keyword in entries and len(entries[keyword]) > 1: raise ValueError("The '%s' entry can only appear once in a descriptor" % keyword) + + if not self.exit_policy: + raise ValueError("Descriptor must have at least one 'accept' or 'reject' entry") # parse all the entries into our attributes for keyword, values in entries.items(): @@ -444,6 +464,23 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): raise ValueError("Hibernating line had an invalid value, must be zero or one: %s" % value) self.hibernating = value == "1" + elif keyword == "allow-single-hop-exits": + self.allow_single_hop_exits = True + elif keyword == "caches-extra-info": + self.extra_info_cache = True + elif keyword == "extra-info-digest": + # this is fourty hex digits which just so happens to be the same a + # fingerprint + + if validate and not stem.util.tor_tools.is_valid_fingerprint(value): + raise ValueError("Hidden service digests should consist of fourty hex digits: %s" % value) + + self.extra_info_digest = value + elif keyword == "hidden-service-dir": + if value: + self.hidden_service_dir = value.split(" ") + else: + self.hidden_service_dir = ["2"] elif keyword == "uptime": if not value.isdigit(): if not validate: continue @@ -470,6 +507,15 @@ class ServerDescriptorV3(stem.descriptor.Descriptor): self.signature = block_contents elif keyword == "contact": self.contact = value + elif keyword == "protocols": + protocols_match = re.match("^Link (.*) Circuit (.*)$", value) + + if protocols_match: + link_versions, circuit_versions = protocols_match.groups() + self.link_protocols = link_versions.split(" ") + self.circuit_protocols = circuit_versions.split(" ") + elif validate: + raise ValueError("Protocols line did not match the expected pattern: %s" % line) elif keyword == "family": self.family = value.split(" ") else: diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py index 5a070a2..a956606 100644 --- a/test/integ/descriptor/server_descriptor.py +++ b/test/integ/descriptor/server_descriptor.py @@ -68,7 +68,13 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4= self.assertEquals(588217, desc.uptime) self.assertEquals(expected_published, desc.published) self.assertEquals("www.atagar.com/contact", desc.contact) + self.assertEquals(["1", "2"], desc.link_protocols) + self.assertEquals(["1"], desc.circuit_protocols) self.assertEquals(False, desc.hibernating) + self.assertEquals(False, desc.allow_single_hop_exits) + self.assertEquals(False, desc.extra_info_cache) + self.assertEquals("D225B728768D7EA4B5587C13A7A9D22EBBEE6E66", desc.extra_info_digest) + self.assertEquals(["2"], desc.hidden_service_dir) self.assertEquals(expected_family, desc.family) self.assertEquals(153600, desc.average_bandwidth) self.assertEquals(256000, desc.burst_bandwidth)
participants (1)
-
atagar@torproject.org