commit c6a9cde0f4eb5c627f5ba41f9d263be0c5854ae8 Author: Damian Johnson atagar@torproject.org Date: Sun Feb 3 22:14:20 2013 -0800
Allowing for IPv4 'a' lines in router status entries
Karsten reports on ticket #8036 that IPv4 addresses are indeed allowed on a router status entry's 'a' line. This is a little unfortunate since it means a less friendly attribute but not a big whoop. --- stem/descriptor/router_status_entry.py | 34 +++++++++++++++----------- stem/descriptor/server_descriptor.py | 5 +-- test/unit/descriptor/router_status_entry.py | 19 ++++++++------- 3 files changed, 32 insertions(+), 26 deletions(-)
diff --git a/stem/descriptor/router_status_entry.py b/stem/descriptor/router_status_entry.py index 2cd6632..d22dfa3 100644 --- a/stem/descriptor/router_status_entry.py +++ b/stem/descriptor/router_status_entry.py @@ -298,8 +298,8 @@ class RouterStatusEntryV3(RouterStatusEntry): Information about an individual router stored within a version 3 network status document.
- :var dict addresses_v6: ***** relay's IPv6 OR addresses, this is a mapping - of IPv6 addresses to a tuple with the ports it accepts + :var list addresses_v6: ***** relay's OR addresses, this is a tuple listing + of the form (address (**str**), port (**int**), is_ipv6 (**bool**)) :var str digest: ***** router's digest
:var int bandwidth: bandwidth claimed by the relay (in kb/s) @@ -318,7 +318,7 @@ class RouterStatusEntryV3(RouterStatusEntry): """
def __init__(self, content, validate = True, document = None): - self.addresses_v6 = {} + self.addresses_v6 = [] self.digest = None
self.bandwidth = None @@ -521,21 +521,27 @@ def _parse_a_line(desc, value, validate):
raise ValueError("%s 'a' line must be of the form '[address]:[ports]': a %s" % (desc._name(), value))
- address, port_label = value.rsplit(':', 1) + address, ports = value.rsplit(':', 1) + is_ipv6 = address.startswith("[") and address.endswith("]")
- if validate and not stem.util.connection.is_valid_ipv6_address(address, allow_brackets = True): - raise ValueError("%s 'a' line must start with an IPv6 address: a %s" % (desc._name(), value)) + if is_ipv6: + address = address[1:-1] # remove brackets
- address = address.lstrip('[').rstrip(']') - ports = [] + if not ((not is_ipv6 and stem.util.connection.is_valid_ip_address(address)) or + (is_ipv6 and stem.util.connection.is_valid_ipv6_address(address))): + if not validate: + return + else: + raise ValueError("%s 'a' line must start with an IPv6 address: a %s" % (desc._name(), value))
- for port in port_label.split(','): - if stem.util.connection.is_valid_port(port): - ports.append(int(port)) - elif validate: - raise ValueError("%s 'a' line had an invalid port (%s): a %s" % (desc._name(), port, value)) + for port in ports.split(','): + if not stem.util.connection.is_valid_port(port): + if not validate: + continue + else: + raise ValueError("%s 'a' line had an invalid port (%s): a %s" % (desc._name(), port, value))
- desc.addresses_v6[address] = tuple(ports) + desc.addresses_v6.append((address, int(port), is_ipv6))
def _parse_s_line(desc, value, validate): diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index 95a4ef0..be63ddf 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -514,8 +514,7 @@ class ServerDescriptor(stem.descriptor.Descriptor): else: raise ValueError("or-address line missing a colon: %s" % line)
- div = entry.rfind(":") - address, ports = entry[:div], entry[div + 1:] + address, ports = entry.rsplit(':', 1) is_ipv6 = address.startswith("[") and address.endswith("]")
if is_ipv6: @@ -531,7 +530,7 @@ class ServerDescriptor(stem.descriptor.Descriptor): for port in ports.split(","): if not stem.util.connection.is_valid_port(port): if not validate: - break + continue else: raise ValueError("or-address line has malformed ports: %s" % line)
diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py index b9d3649..b994f23 100644 --- a/test/unit/descriptor/router_status_entry.py +++ b/test/unit/descriptor/router_status_entry.py @@ -312,10 +312,11 @@ class TestRouterStatusEntry(unittest.TestCase): """
test_values = { - "[2607:fcd0:daaa:101::602c:bd62]:443": { - '2607:fcd0:daaa:101::602c:bd62': (443,)}, - "[2607:fcd0:daaa:101::602c:bd62]:80,443": { - '2607:fcd0:daaa:101::602c:bd62': (80, 443)}, + "[2607:fcd0:daaa:101::602c:bd62]:443": [ + ('2607:fcd0:daaa:101::602c:bd62', 443, True)], + "[2607:fcd0:daaa:101::602c:bd62]:80,443": [ + ('2607:fcd0:daaa:101::602c:bd62', 80, True), + ('2607:fcd0:daaa:101::602c:bd62', 443, True)] }
for a_line, expected in test_values.items(): @@ -328,10 +329,11 @@ class TestRouterStatusEntry(unittest.TestCase): content += "\na [2607:fcd0:daaa:101::602c:bd62]:80,443" content += "\na [1148:fcd0:daaa:101::602c:bd62]:80"
- expected = { - '2607:fcd0:daaa:101::602c:bd62': (80, 443), - '1148:fcd0:daaa:101::602c:bd62': (80,), - } + expected = [ + ('2607:fcd0:daaa:101::602c:bd62', 80, True), + ('2607:fcd0:daaa:101::602c:bd62', 443, True), + ('1148:fcd0:daaa:101::602c:bd62', 80, True), + ]
entry = RouterStatusEntryV3(content) self.assertEquals(expected, entry.addresses_v6) @@ -340,7 +342,6 @@ class TestRouterStatusEntry(unittest.TestCase):
test_values = ( "", - "127.0.0.1:80", "[1148:fcd0:daaa:101::602c:bd62]:80000", )
tor-commits@lists.torproject.org