commit 4d0d5598eec4936f103293802c217377ada8751f Author: Damian Johnson atagar@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): """
tor-commits@lists.torproject.org