[tor-commits] [stem/master] Connecting to both 9051 and 9151 by default

atagar at torproject.org atagar at torproject.org
Thu May 21 16:27:48 UTC 2015


commit 8e5313a2017599f616fc4bd518a5d1950100b920
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu May 21 09:20:15 2015 -0700

    Connecting to both 9051 and 9151 by default
    
    Tor Browser's control connection is on 9151 by default to avoid conflicting
    with relays (which default to 9051). Changing our methods for making a
    controller to check both by default...
    
      https://trac.torproject.org/projects/tor/ticket/16075
---
 docs/change_log.rst                |    1 +
 stem/connection.py                 |   38 +++++++++++++++++++++++++++++++++---
 stem/control.py                    |   22 +++++++++++++++++----
 stem/interpreter/__init__.py       |    4 +++-
 stem/interpreter/arguments.py      |    2 +-
 stem/response/events.py            |    2 +-
 test/unit/interpreter/arguments.py |    2 +-
 7 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 1486391..f3bbc13 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -44,6 +44,7 @@ The following are only available within Stem's `git repository
 
  * **Controller**
 
+  * :func:`~stem.connection.connect` and :func:`~stem.control.Controller.from_port` now connect to both port 9051 (relay's default) and 9151 (Tor Browser's default) (:trac:`16075`)
   * Added `support for NETWORK_LIVENESS events <api/response.html#stem.response.events.NetworkLivenessEvent>`_ (:spec:`44aac63`)
 
 .. _version_1.4:
diff --git a/stem/connection.py b/stem/connection.py
index fb85225..30d7b41 100644
--- a/stem/connection.py
+++ b/stem/connection.py
@@ -199,7 +199,7 @@ CONNECT_MESSAGES = {
 }
 
 
-def connect(control_port = ('127.0.0.1', 9051), control_socket = '/var/run/tor/control', password = None, password_prompt = False, chroot_path = None, controller = stem.control.Controller):
+def connect(control_port = ('127.0.0.1', 'default'), control_socket = '/var/run/tor/control', password = None, password_prompt = False, chroot_path = None, controller = stem.control.Controller):
   """
   Convenience function for quickly getting a control connection. This is very
   handy for debugging or CLI setup, handling setup and prompting for a password
@@ -214,8 +214,15 @@ def connect(control_port = ('127.0.0.1', 9051), control_socket = '/var/run/tor/c
   details of how this works. Messages and details of this function's behavior
   could change in the future.
 
+  If the **port** is **'default'** then this checks on both 9051 (default for
+  relays) and 9151 (default for the Tor Browser). This default may change in
+  the future.
+
   .. versionadded:: 1.2.0
 
+  .. versionchanged:: 1.5.0
+     Use both port 9051 and 9151 by default.
+
   :param tuple contol_port: address and port tuple, for instance **('127.0.0.1', 9051)**
   :param str path: path where the control socket is located
   :param str password: passphrase to authenticate to the socket
@@ -238,7 +245,7 @@ def connect(control_port = ('127.0.0.1', 9051), control_socket = '/var/run/tor/c
       raise ValueError('The control_port argument for connect() should be an (address, port) tuple.')
     elif not stem.util.connection.is_valid_ipv4_address(control_port[0]):
       raise ValueError("'%s' isn't a vaid IPv4 address" % control_port[0])
-    elif not stem.util.connection.is_valid_port(control_port[1]):
+    elif control_port[1] != 'default' and not stem.util.connection.is_valid_port(control_port[1]):
       raise ValueError("'%s' isn't a valid port" % control_port[1])
 
   control_connection, error_msg = None, ''
@@ -256,7 +263,10 @@ def connect(control_port = ('127.0.0.1', 9051), control_socket = '/var/run/tor/c
     address, port = control_port
 
     try:
-      control_connection = stem.socket.ControlPort(address, port)
+      if port == 'default':
+        control_connection = _connection_for_default_port(address)
+      else:
+        control_connection = stem.socket.ControlPort(address, port)
     except stem.SocketError as exc:
       error_msg = CONNECT_MESSAGES['unable_to_use_port'].format(address = address, port = port, error = exc)
 
@@ -1045,6 +1055,28 @@ def _msg(controller, message):
     return controller.msg(message)
 
 
+def _connection_for_default_port(address):
+  """
+  Attempts to provide a controller connection for either port 9051 (default for
+  relays) or 9151 (default for Tor Browser). If both fail then this raises the
+  exception for port 9051.
+
+  :param str address: address to connect to
+
+  :returns: :class:`~stem.socket.ControlPort` for the controller conneciton
+
+  :raises: :class:`stem.SocketError` if we're unable to establish a connection
+  """
+
+  try:
+    return stem.socket.ControlPort(address, 9051)
+  except stem.SocketError as exc:
+    try:
+      return stem.socket.ControlPort(address, 9151)
+    except stem.SocketError:
+      raise exc
+
+
 def _read_cookie(cookie_path, is_safecookie):
   """
   Provides the contents of a given cookie file.
diff --git a/stem/control.py b/stem/control.py
index a903e4d..efc0d18 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -897,10 +897,17 @@ class Controller(BaseController):
   """
 
   @staticmethod
-  def from_port(address = '127.0.0.1', port = 9051):
+  def from_port(address = '127.0.0.1', port = 'default'):
     """
     Constructs a :class:`~stem.socket.ControlPort` based Controller.
 
+    If the **port** is **'default'** then this checks on both 9051 (default
+    for relays) and 9151 (default for the Tor Browser). This default may change
+    in the future.
+
+    .. versionchanged:: 1.5.0
+       Use both port 9051 and 9151 by default.
+
     :param str address: ip address of the controller
     :param int port: port number of the controller
 
@@ -914,7 +921,11 @@ class Controller(BaseController):
     elif not stem.util.connection.is_valid_port(port):
       raise ValueError('Invalid port: %s' % port)
 
-    control_port = stem.socket.ControlPort(address, port)
+    if port == 'default':
+      control_port = stem.connection._connection_for_default_port(address)
+    else:
+      control_port = stem.socket.ControlPort(address, port)
+
     return Controller(control_port)
 
   @staticmethod
@@ -989,7 +1000,6 @@ class Controller(BaseController):
     pass-through to :func:`stem.connection.authenticate`.
     """
 
-    import stem.connection
     stem.connection.authenticate(self, *args, **kwargs)
 
   @with_default()
@@ -1391,7 +1401,6 @@ class Controller(BaseController):
       An exception is only raised if we weren't provided a default response.
     """
 
-    import stem.connection
     return stem.connection.get_protocolinfo(self)
 
   @with_default()
@@ -3631,3 +3640,8 @@ def _case_insensitive_lookup(entries, key, default = UNDEFINED):
           return entry
 
   raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries))
+
+
+# importing at the end to avoid circular dependency
+
+import stem.connection
diff --git a/stem/interpreter/__init__.py b/stem/interpreter/__init__.py
index cf69d63..980e3ba 100644
--- a/stem/interpreter/__init__.py
+++ b/stem/interpreter/__init__.py
@@ -78,10 +78,12 @@ def main():
       else:
         print(format(msg('msg.starting_tor'), *HEADER_OUTPUT))
 
+        control_port = '9051' if args.control_port == 'default' else str(args.control_port)
+
         stem.process.launch_tor_with_config(
           config = {
             'SocksPort': '0',
-            'ControlPort': str(args.control_port),
+            'ControlPort': control_port,
             'CookieAuthentication': '1',
             'ExitPolicy': 'reject *:*',
           },
diff --git a/stem/interpreter/arguments.py b/stem/interpreter/arguments.py
index eadd043..eeae504 100644
--- a/stem/interpreter/arguments.py
+++ b/stem/interpreter/arguments.py
@@ -13,7 +13,7 @@ import stem.util.connection
 
 DEFAULT_ARGS = {
   'control_address': '127.0.0.1',
-  'control_port': 9051,
+  'control_port': 'default',
   'user_provided_port': False,
   'control_socket': '/var/run/tor/control',
   'user_provided_socket': False,
diff --git a/stem/response/events.py b/stem/response/events.py
index 2ae01be..464dd61 100644
--- a/stem/response/events.py
+++ b/stem/response/events.py
@@ -163,7 +163,7 @@ class AddrMapEvent(Event):
      Added the cached attribute.
 
   :var str hostname: address being resolved
-  :var str destination: destionation of the resolution, this is usually an ip,
+  :var str destination: destination of the resolution, this is usually an ip,
     but could be a hostname if TrackHostExits is enabled or **NONE** if the
     resolution failed
   :var datetime expiry: expiration time of the resolution in local time
diff --git a/test/unit/interpreter/arguments.py b/test/unit/interpreter/arguments.py
index 60fda3d..6a765b1 100644
--- a/test/unit/interpreter/arguments.py
+++ b/test/unit/interpreter/arguments.py
@@ -54,4 +54,4 @@ class TestArgumentParsing(unittest.TestCase):
   def test_get_help(self):
     help_text = get_help()
     self.assertTrue('Interactive interpreter for Tor.' in help_text)
-    self.assertTrue('change control interface from 127.0.0.1:9051' in help_text)
+    self.assertTrue('change control interface from 127.0.0.1:default' in help_text)



More information about the tor-commits mailing list