commit 938c397648003b15a44412bb0c97b5ad114ad9fa Author: Damian Johnson atagar@torproject.org Date: Thu Oct 31 11:39:35 2019 -0700
Simplify LinkSpecifier construction
Constructing from packed values made construction of a LinkSpecifier a pita. Taking an address/port argument instead. --- stem/client/datatype.py | 56 ++++++++++++++++++++++++++------------ test/unit/client/link_specifier.py | 10 ++++++- 2 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/stem/client/datatype.py b/stem/client/datatype.py index a0e59cb0..ac417b83 100644 --- a/stem/client/datatype.py +++ b/stem/client/datatype.py @@ -566,6 +566,8 @@ class LinkSpecifier(Field): `EXTEND cell specification https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt#n975`_.
+ .. versionadded:: 1.8.0 + :var int type: numeric identifier of our type :var bytes value: encoded link specification destination """ @@ -589,9 +591,9 @@ class LinkSpecifier(Field): value, packed = split(packed, value_size)
if link_type == 0: - return LinkByIPv4(value), packed + return LinkByIPv4.unpack(value), packed elif link_type == 1: - return LinkByIPv6(value), packed + return LinkByIPv6.unpack(value), packed elif link_type == 2: return LinkByFingerprint(value), packed elif link_type == 3: @@ -611,46 +613,58 @@ class LinkByIPv4(LinkSpecifier): """ TLS connection to an IPv4 address.
+ .. versionadded:: 1.8.0 + :var str address: relay IPv4 address :var int port: relay ORPort """
- def __init__(self, value): - super(LinkByIPv4, self).__init__(0, value) + def __init__(self, address, port): + super(LinkByIPv4, self).__init__(0, _pack_ipv4_address(address) + Size.SHORT.pack(port))
+ self.address = address + self.port = port + + @staticmethod + def unpack(value): if len(value) != 6: raise ValueError('IPv4 link specifiers should be six bytes, but was %i instead: %s' % (len(value), binascii.hexlify(value)))
- address_bin, value = split(value, 4) - self.address = _unpack_ipv4_address(address_bin) - - self.port, _ = Size.SHORT.pop(value) + addr, port = split(value, 4) + return LinkByIPv4(_unpack_ipv4_address(addr), Size.SHORT.unpack(port))
class LinkByIPv6(LinkSpecifier): """ TLS connection to an IPv6 address.
+ .. versionadded:: 1.8.0 + :var str address: relay IPv6 address :var int port: relay ORPort """
- def __init__(self, value): - super(LinkByIPv6, self).__init__(1, value) + def __init__(self, address, port): + super(LinkByIPv6, self).__init__(1, _pack_ipv6_address(address) + Size.SHORT.pack(port))
+ self.address = address + self.port = port + + @staticmethod + def unpack(value): if len(value) != 18: raise ValueError('IPv6 link specifiers should be eighteen bytes, but was %i instead: %s' % (len(value), binascii.hexlify(value)))
- address_bin, value = split(value, 16) - self.address = _unpack_ipv6_address(address_bin) - - self.port, _ = Size.SHORT.pop(value) + addr, port = split(value, 16) + return LinkByIPv6(_unpack_ipv6_address(addr), Size.SHORT.unpack(port))
class LinkByFingerprint(LinkSpecifier): """ Connection to a SHA1 identity fingerprint.
+ .. versionadded:: 1.8.0 + :var str fingerprint: relay sha1 fingerprint """
@@ -667,6 +681,8 @@ class LinkByEd25519(LinkSpecifier): """ Connection to a Ed25519 identity fingerprint.
+ .. versionadded:: 1.8.0 + :var str fingerprint: relay ed25519 fingerprint """
@@ -713,15 +729,19 @@ class KDF(collections.namedtuple('KDF', ['key_hash', 'forward_digest', 'backward return KDF(key_hash, forward_digest, backward_digest, forward_key, backward_key)
-def _unpack_ipv4_address(value): - # convert bytes to a standard IPv4 address +def _pack_ipv4_address(address): + return b''.join([Size.CHAR.pack(int(v)) for v in address.split('.')]) +
+def _unpack_ipv4_address(value): return '.'.join([str(Size.CHAR.unpack(value[i:i + 1])) for i in range(4)])
-def _unpack_ipv6_address(value): - # convert bytes to a standard IPv6 address +def _pack_ipv6_address(address): + return b''.join([Size.SHORT.pack(int(v, 16)) for v in address.split(':')])
+ +def _unpack_ipv6_address(value): return ':'.join(['%04x' % Size.SHORT.unpack(value[i * 2:(i + 1) * 2]) for i in range(8)])
diff --git a/test/unit/client/link_specifier.py b/test/unit/client/link_specifier.py index b42ea57c..181627de 100644 --- a/test/unit/client/link_specifier.py +++ b/test/unit/client/link_specifier.py @@ -15,7 +15,7 @@ from stem.client.datatype import (
class TestLinkSpecifier(unittest.TestCase): def test_link_by_ipv4_address(self): - destination, _ = LinkSpecifier.pop(b'\x00\x06\x01\x02\x03\x04#)') + destination = LinkSpecifier.unpack(b'\x00\x06\x01\x02\x03\x04#)')
self.assertEqual(LinkByIPv4, type(destination)) self.assertEqual(0, destination.type) @@ -23,6 +23,10 @@ class TestLinkSpecifier(unittest.TestCase): self.assertEqual('1.2.3.4', destination.address) self.assertEqual(9001, destination.port)
+ destination = LinkByIPv4('1.2.3.4', 9001) + self.assertEqual(b'\x00\x06\x01\x02\x03\x04#)', destination.pack()) + self.assertEqual(b'\x01\x02\x03\x04#)', destination.value) + def test_link_by_ipv6_address(self): destination, _ = LinkSpecifier.pop(b'\x01\x12&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01#)')
@@ -32,6 +36,10 @@ class TestLinkSpecifier(unittest.TestCase): self.assertEqual('2600:0000:0000:0000:0000:0000:0000:0001', destination.address) self.assertEqual(9001, destination.port)
+ destination = LinkByIPv6('2600:0000:0000:0000:0000:0000:0000:0001', 9001) + self.assertEqual(b'\x01\x12&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01#)', destination.pack()) + self.assertEqual(b'&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01#)', destination.value) + def test_link_by_fingerprint(self): destination, _ = LinkSpecifier.pop(b'\x02\x14CCCCCCCCCCCCCCCCCCCC')