[tor-commits] [stem/master] Joining get_protocolinfo_* functions

atagar at torproject.org atagar at torproject.org
Tue Dec 13 18:10:36 UTC 2011


commit 4d0d5598eec4936f103293802c217377ada8751f
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Dec 12 18:51:03 2011 -0800

    Joining get_protocolinfo_* functions
    
    Having a joined socket constructor and PROTOCOLINFO query doesn't make sense.
    It allowed the user to make a PROTOCOLINFO query in a single line without a
    leftover socket but that use case is so rare that it's fine for it to take a
    couple more lines. This api is simpler and better for the common case.
---
 stem/connection.py                    |   90 +++++++-------------------------
 test/integ/connection/protocolinfo.py |   23 ++++++---
 2 files changed, 35 insertions(+), 78 deletions(-)

diff --git a/stem/connection.py b/stem/connection.py
index 07dc50e..71b6e5b 100644
--- a/stem/connection.py
+++ b/stem/connection.py
@@ -25,8 +25,7 @@ authenticate_none - Authenticates to an open control socket.
 authenticate_password - Authenticates to a socket supporting password auth.
 authenticate_cookie - Authenticates to a socket supporting cookie auth.
 
-get_protocolinfo_by_port - PROTOCOLINFO query via a control port.
-get_protocolinfo_by_socket - PROTOCOLINFO query via a control socket.
+get_protocolinfo - issues a PROTOCOLINFO query
 ProtocolInfoResponse - Reply from a PROTOCOLINFO query.
   |- Attributes:
   |  |- protocol_version
@@ -292,63 +291,19 @@ def authenticate_cookie(control_socket, cookie_path, suppress_ctl_errors = True)
     if not suppress_ctl_errors: raise exc
     else: raise CookieAuthRejected("Socket failed (%s)" % exc)
 
-def get_protocolinfo_by_port(control_addr = "127.0.0.1", control_port = 9051, get_socket = False):
-  """
-  Issues a PROTOCOLINFO query to a control port, getting information about the
-  tor process running on it.
-  
-  Arguments:
-    control_addr (str) - ip address of the controller
-    control_port (int) - port number of the controller
-    get_socket (bool)  - provides the socket with the response if True,
-                         otherwise the socket is closed when we're done
-  
-  Returns:
-    stem.connection.ProtocolInfoResponse provided by tor, if get_socket is True
-    then this provides a tuple instead with both the response and connected
-    socket (stem.socket.ControlPort)
-  
-  Raises:
-    stem.socket.ProtocolError if the PROTOCOLINFO response is malformed
-    stem.socket.SocketError if problems arise in establishing or using the
-      socket
-  """
-  
-  control_socket = stem.socket.ControlPort(control_addr, control_port, False)
-  
-  try:
-    control_socket.connect()
-    control_socket.send("PROTOCOLINFO 1")
-    protocolinfo_response = control_socket.recv()
-    ProtocolInfoResponse.convert(protocolinfo_response)
-    
-    # attempt to expand relative cookie paths using our port to infer the pid
-    if control_addr == "127.0.0.1":
-      _expand_cookie_path(protocolinfo_response, stem.util.system.get_pid_by_port, control_port)
-    
-    if get_socket:
-      return (protocolinfo_response, control_socket)
-    else:
-      control_socket.close()
-      return protocolinfo_response
-  except stem.socket.ControllerError, exc:
-    control_socket.close()
-    raise exc
-
-def get_protocolinfo_by_socket(socket_path = "/var/run/tor/control", get_socket = False):
+def get_protocolinfo(control_socket):
   """
   Issues a PROTOCOLINFO query to a control socket, getting information about
   the tor process running on it.
   
+  Tor hangs up on sockets after receiving a PROTOCOLINFO query if it isn't next
+  followed by authentication.
+  
   Arguments:
-    socket_path (str) - path where the control socket is located
-    get_socket (bool) - provides the socket with the response if True,
-                        otherwise the socket is closed when we're done
+    control_socket (stem.socket.ControlSocket) - connected tor control socket
   
   Returns:
-    stem.connection.ProtocolInfoResponse provided by tor, if get_socket is True
-    then this provides a tuple instead with both the response and connected
-    socket (stem.socket.ControlSocketFile)
+    stem.connection.ProtocolInfoResponse provided by tor
   
   Raises:
     stem.socket.ProtocolError if the PROTOCOLINFO response is malformed
@@ -356,25 +311,20 @@ def get_protocolinfo_by_socket(socket_path = "/var/run/tor/control", get_socket
       socket
   """
   
-  control_socket = stem.socket.ControlSocketFile(socket_path, False)
+  control_socket.send("PROTOCOLINFO 1")
+  protocolinfo_response = control_socket.recv()
+  ProtocolInfoResponse.convert(protocolinfo_response)
   
-  try:
-    control_socket.connect()
-    control_socket.send("PROTOCOLINFO 1")
-    protocolinfo_response = control_socket.recv()
-    ProtocolInfoResponse.convert(protocolinfo_response)
-    
-    # attempt to expand relative cookie paths using our port to infer the pid
-    _expand_cookie_path(protocolinfo_response, stem.util.system.get_pid_by_open_file, socket_path)
-    
-    if get_socket:
-      return (protocolinfo_response, control_socket)
-    else:
-      control_socket.close()
-      return protocolinfo_response
-  except stem.socket.ControllerError, exc:
-    control_socket.close()
-    raise exc
+  # attempt ot expand relative cookie paths via the control port or socket file
+  if isinstance(control_socket, stem.socket.ControlPort):
+    if control_socket.get_address() == "127.0.0.1":
+      pid_method = stem.util.system.get_pid_by_port
+      _expand_cookie_path(protocolinfo_response, pid_method, control_socket.get_port())
+  elif isinstance(control_socket, stem.socket.ControlSocketFile):
+    pid_method = stem.util.system.get_pid_by_open_file
+    _expand_cookie_path(protocolinfo_response, pid_method, control_socket.get_socket_path())
+  
+  return protocolinfo_response
 
 def _expand_cookie_path(protocolinfo_response, pid_resolver, pid_resolution_arg):
   """
diff --git a/test/integ/connection/protocolinfo.py b/test/integ/connection/protocolinfo.py
index 02d097d..dfc1c01 100644
--- a/test/integ/connection/protocolinfo.py
+++ b/test/integ/connection/protocolinfo.py
@@ -49,7 +49,8 @@ class TestProtocolInfo(unittest.TestCase):
   
   def test_get_protocolinfo_by_port(self):
     """
-    Exercises the stem.connection.get_protocolinfo_by_port function.
+    Exercises the stem.connection.get_protocolinfo function with a control
+    port.
     """
     
     # If we have both the 'RELATIVE' target and a cookie then test_parsing
@@ -74,15 +75,21 @@ class TestProtocolInfo(unittest.TestCase):
     connection_type = test.runner.get_runner().get_connection_type()
     
     if test.runner.OPT_PORT in test.runner.CONNECTION_OPTS[connection_type]:
-      protocolinfo_response = stem.connection.get_protocolinfo_by_port(control_port = test.runner.CONTROL_PORT)
+      control_socket = stem.socket.ControlPort(control_port = test.runner.CONTROL_PORT)
+      protocolinfo_response = stem.connection.get_protocolinfo(control_socket)
       self.assert_protocolinfo_attr(protocolinfo_response, connection_type)
+      
+      # we should have a usable socket at this point
+      self.assertTrue(control_socket.is_alive())
+      control_socket.close()
     else:
       # we don't have a control port
-      self.assertRaises(stem.socket.SocketError, stem.connection.get_protocolinfo_by_port, "127.0.0.1", test.runner.CONTROL_PORT)
+      self.assertRaises(stem.socket.SocketError, stem.socket.ControlPort, "127.0.0.1", test.runner.CONTROL_PORT)
   
   def test_get_protocolinfo_by_socket(self):
     """
-    Exercises the stem.connection.get_protocolinfo_by_socket function.
+    Exercises the stem.connection.get_protocolinfo function with a control
+    socket.
     """
     
     cwd_by_socket_lookup_prefixes = (
@@ -100,16 +107,16 @@ class TestProtocolInfo(unittest.TestCase):
     connection_type = test.runner.get_runner().get_connection_type()
     
     if test.runner.OPT_SOCKET in test.runner.CONNECTION_OPTS[connection_type]:
-      protocolinfo_response, control_socket = stem.connection.get_protocolinfo_by_socket(socket_path = test.runner.CONTROL_SOCKET_PATH, get_socket = True)
+      control_socket = stem.socket.ControlSocketFile(test.runner.CONTROL_SOCKET_PATH)
+      protocolinfo_response = stem.connection.get_protocolinfo(control_socket)
       self.assert_protocolinfo_attr(protocolinfo_response, connection_type)
       
-      # also exercising the get_socket argument - we should have a usable
-      # socket at this point
+      # we should have a usable socket at this point
       self.assertTrue(control_socket.is_alive())
       control_socket.close()
     else:
       # we don't have a control socket
-      self.assertRaises(stem.socket.SocketError, stem.connection.get_protocolinfo_by_socket, test.runner.CONTROL_SOCKET_PATH)
+      self.assertRaises(stem.socket.SocketError, stem.socket.ControlSocketFile, test.runner.CONTROL_SOCKET_PATH)
   
   def assert_protocolinfo_attr(self, protocolinfo_response, connection_type):
     """





More information about the tor-commits mailing list