commit 0bc8b8c8d76f301de50b71141836fc654348cbe5 Author: Damian Johnson atagar@torproject.org Date: Wed Jul 13 10:01:30 2016 -0700
Recognize listeners with IPv6 addresses
Oops, Stem only recognized IPv4 listener addresses. As a result nyx showed 'Relaying Disabled' even if you had an IPv6 ORPort. Caught by dgoulet. --- docs/change_log.rst | 1 + stem/control.py | 12 +++++++++++- stem/util/__init__.py | 2 +- test/unit/control/controller.py | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 1713360..12764e8 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -56,6 +56,7 @@ The following are only available within Stem's `git repository * Added :func:`~stem.control.Controller.is_user_traffic_allowed` to the :class:`~stem.control.Controller` * Added the replica attribute to the :class:`~stem.response.events.HSDescEvent` (:spec:`4989e73`) * Added the NoEdConsensus :data:`~stem.Flag` (:spec:`dc99160`) + * Recognize listeners with IPv6 addresses in :func:`~stem.control.Controller.get_listeners` * :func:`~stem.process.launch_tor` could leave a lingering process during an unexpected exception (:trac:`17946`) * IPv6 addresses could trigger errors in :func:`~stem.control.Controller.get_listeners`, :class:`~stem.response.events.ORConnEvent`, and quite a few other things (:trac:`16174`) * Don't obscure stacktraces, most notably :class:`~stem.control.Controller` getter methods with default values diff --git a/stem/control.py b/stem/control.py index 9101cc1..9b98758 100644 --- a/stem/control.py +++ b/stem/control.py @@ -1314,6 +1314,9 @@ class Controller(BaseController):
.. versionadded:: 1.2.0
+ .. versionchanged:: 1.5.0 + Recognize listeners with IPv6 addresses. + :param stem.control.Listener listener_type: connection type being handled by the listeners we return :param object default: response if the query fails @@ -1347,6 +1350,9 @@ class Controller(BaseController): if addr == 'unix': continue
+ if addr.startswith('[') and addr.endswith(']'): + addr = addr[1:-1] # unbracket ipv6 address + proxy_addrs.append((addr, port)) except stem.InvalidArguments: # Tor version is old (pre-tor-0.2.2.26-beta), use get_conf() instead. @@ -1378,6 +1384,10 @@ class Controller(BaseController): for listener in self.get_conf(listener_option, multiple = True): if ':' in listener: addr, port = listener.rsplit(':', 1) + + if addr.startswith('[') and addr.endswith(']'): + addr = addr[1:-1] # unbracket ipv6 address + proxy_addrs.append((addr, port)) else: proxy_addrs.append((listener, port_value)) @@ -1385,7 +1395,7 @@ class Controller(BaseController): # validate that address/ports are valid, and convert ports to ints
for addr, port in proxy_addrs: - if not stem.util.connection.is_valid_ipv4_address(addr): + if not stem.util.connection.is_valid_ipv4_address(addr) and not stem.util.connection.is_valid_ipv6_address(addr): raise stem.ProtocolError('Invalid address for a %s listener: %s' % (listener_type, addr)) elif not stem.util.connection.is_valid_port(port): raise stem.ProtocolError('Invalid port for a %s listener: %s' % (listener_type, port)) diff --git a/stem/util/__init__.py b/stem/util/__init__.py index fd5bfad..de3c0ea 100644 --- a/stem/util/__init__.py +++ b/stem/util/__init__.py @@ -58,7 +58,7 @@ def _hash_attr(obj, *attributes, **kwargs): :param class parent: parent object to include in the hash value """
- my_hash = 0 if kwargs.get('parent') == None else kwargs.get('parent').__hash__(obj) + my_hash = 0 if kwargs.get('parent') is None else kwargs.get('parent').__hash__(obj)
for attr in attributes: my_hash *= 1024 diff --git a/test/unit/control/controller.py b/test/unit/control/controller.py index b9870ae..fedb86a 100644 --- a/test/unit/control/controller.py +++ b/test/unit/control/controller.py @@ -180,6 +180,15 @@ class TestControl(unittest.TestCase):
self.assertEqual([1112, 1114], self.controller.get_ports(Listener.CONTROL))
+ # IPv6 address + + get_info_mock.return_value = '"0.0.0.0:9001" "[fe80:0000:0000:0000:0202:b3ff:fe1e:8329]:9001"' + + self.assertEqual( + [('0.0.0.0', 9001), ('fe80:0000:0000:0000:0202:b3ff:fe1e:8329', 9001)], + self.controller.get_listeners(Listener.CONTROL) + ) + # unix socket file
get_info_mock.return_value = '"unix:/tmp/tor/socket"'