commit 94a86b974e2d7fe4728675ee94d43bded78e4706 Author: Damian Johnson atagar@torproject.org Date: Sat Jan 20 12:05:13 2018 -0800
Add IPv6 address support
I'm a tad uncomfortable since I lack actual tor data to exercise this on, but taking my best stab. --- stem/client/__init__.py | 10 +++++++++- test/unit/client/address.py | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/stem/client/__init__.py b/stem/client/__init__.py index 217e32af..b0da7aae 100644 --- a/stem/client/__init__.py +++ b/stem/client/__init__.py @@ -256,7 +256,15 @@ class Address(Field): self.value = '.'.join([str(Size.CHAR.unpack(value[i])) for i in range(4)]) self.value_bin = value elif self.type == AddrType.IPv6: - self.value, self.value_bin = None, None # TODO: implement + if stem.util.connection.is_valid_ipv6_address(value): + self.value = stem.util.connection.expand_ipv6_address(value).lower() + self.value_bin = ''.join([Size.SHORT.pack(int(v, 16)) for v in self.value.split(':')]) + else: + if len(value) != 16: + raise ValueError('Packed IPv6 addresses should be sixteen bytes, but was: %s' % repr(value)) + + self.value = ':'.join(['%04x' % Size.SHORT.unpack(value[i * 2:(i + 1) * 2]) for i in range(8)]) + self.value_bin = value else: self.value, self.value_bin = None, None # TODO: implement
diff --git a/test/unit/client/address.py b/test/unit/client/address.py index 9e6430ff..689b77a0 100644 --- a/test/unit/client/address.py +++ b/test/unit/client/address.py @@ -3,6 +3,7 @@ Unit tests for stem.client.Address. """
import collections +import re import unittest
from stem.client import AddrType, Address @@ -15,8 +16,11 @@ class TestAddress(unittest.TestCase): test_data = ( ((4, '\x7f\x00\x00\x01'), ExpectedAddress(AddrType.IPv4, 4, '127.0.0.1', '\x7f\x00\x00\x01')), ((4, 'aq\x0f\x02'), ExpectedAddress(AddrType.IPv4, 4, '97.113.15.2', 'aq\x0f\x02')), + ((6, ' \x01\r\xb8\x00\x00\x00\x00\x00\x00\xff\x00\x00B\x83)'), ExpectedAddress(AddrType.IPv6, 6, '2001:0db8:0000:0000:0000:ff00:0042:8329', ' \x01\r\xb8\x00\x00\x00\x00\x00\x00\xff\x00\x00B\x83)')), ((AddrType.IPv4, '127.0.0.1'), ExpectedAddress(AddrType.IPv4, 4, '127.0.0.1', '\x7f\x00\x00\x01')), ((AddrType.IPv4, '97.113.15.2'), ExpectedAddress(AddrType.IPv4, 4, '97.113.15.2', 'aq\x0f\x02')), + ((AddrType.IPv6, '2001:0db8:0000:0000:0000:ff00:0042:8329'), ExpectedAddress(AddrType.IPv6, 6, '2001:0db8:0000:0000:0000:ff00:0042:8329', ' \x01\r\xb8\x00\x00\x00\x00\x00\x00\xff\x00\x00B\x83)')), + ((AddrType.IPv6, '2001:0DB8:AC10:FE01::'), ExpectedAddress(AddrType.IPv6, 6, '2001:0db8:ac10:fe01:0000:0000:0000:0000', ' \x01\r\xb8\xac\x10\xfe\x01\x00\x00\x00\x00\x00\x00\x00\x00')), # collaped and different case )
for (addr_type, addr_value), expected in test_data: @@ -26,6 +30,9 @@ class TestAddress(unittest.TestCase): self.assertEqual(expected.value, addr.value) self.assertEqual(expected.value_bin, addr.value_bin)
+ self.assertRaisesRegexp(ValueError, re.escape("Packed IPv4 addresses should be four bytes, but was: '\x7f\x00'"), Address, 4, '\x7f\x00') + self.assertRaisesRegexp(ValueError, re.escape("Packed IPv6 addresses should be sixteen bytes, but was: '\x7f\x00'"), Address, 6, '\x7f\x00') + def test_pop_ipv4(self): addr, content = Address.pop('\x04\x04\x7f\x00\x00\x01\x01\x04\x04aq\x0f\x02\x00\x00\x00\x00') self.assertEqual('\x01\x04\x04aq\x0f\x02\x00\x00\x00\x00', content)