commit 32092205f1be4ccc01ac2cd4bd78a63fd732ae45 Author: Damian Johnson atagar@torproject.org Date: Wed Jan 16 07:38:29 2013 -0800
Adding a BaseController is_authenticated() method
I've been running into some situations where I need to know if the controller is not only connected, but authenticated (since that determines if it's... well, usable).
A use case where this could get confused is...
* User gets a ControlSocket instance. * Manually authenticates via the send() and recv() methods. * Makes a new Controller object from this control socket.
Unfortunately this is *exactly* what our test runner did, so tweaking it so that it hits our post_authentication method (I'm surprised that it hadn't bitten us before). --- stem/control.py | 23 +++++++++++++++++++++-- test/runner.py | 9 +++++++-- 2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/stem/control.py b/stem/control.py index 5649b59..35d9701 100644 --- a/stem/control.py +++ b/stem/control.py @@ -62,6 +62,7 @@ providing its own for interacting at a higher level. BaseController - Base controller class asynchronous message handling |- msg - communicates with the tor process |- is_alive - reports if our connection to tor is open or closed + |- is_authenticated - checks if we're authenticated to tor |- connect - connects or reconnects to tor |- close - shuts down our connection to the tor process |- get_socket - provides the socket used for control communication @@ -253,6 +254,7 @@ class BaseController(object): self._socket._close = self._close
self._last_heartbeat = 0.0 # timestamp for when we last heard from tor + self._is_authenticated = False
if self._socket.is_alive(): self._launch_threads() @@ -346,6 +348,19 @@ class BaseController(object):
return self._socket.is_alive()
+ def is_authenticated(self): + """ + Checks if our socket is both connected and authenticated. + + :returns: **bool** that's **True** if our socket is authenticated to tor + and **False** otherwise + """ + + if self.is_alive(): + return self._is_authenticated + + return False + def connect(self): """ Reconnects our control socket. This is a pass-through for our socket's @@ -456,6 +471,7 @@ class BaseController(object): self._launch_threads() self._notify_status_listeners(State.INIT) self._socket_connect() + self._is_authenticated = False
def _close(self): # Our is_alive() state is now false. Our reader thread should already be @@ -463,6 +479,7 @@ class BaseController(object): # too so it can end.
self._event_notice.set() + self._is_authenticated = False
# joins on our threads if it's safe to do so
@@ -476,7 +493,7 @@ class BaseController(object): def _post_authentication(self): # actions to be taken after we have a newly authenticated connection
- pass + self._is_authenticated = True
def _notify_status_listeners(self, state): """ @@ -1928,6 +1945,8 @@ class Controller(BaseController): return response.entries
def _post_authentication(self): + super(Controller, self)._post_authentication() + # try to re-attach event listeners to the new instance
try: @@ -1950,7 +1969,7 @@ class Controller(BaseController): try: self.reset_conf("__OwningControllerProcess") except stem.ControllerError, exc: - log.warn("We were unable to reset tor's __OwningControllerProcess configuration. It will continue to periodically check if our pid exists. (%s)" % response) + log.warn("We were unable to reset tor's __OwningControllerProcess configuration. It will continue to periodically check if our pid exists. (%s)" % exc) else: log.warn("We were unable assert ownership of tor through TAKEOWNERSHIP, despite being configured to be the owning process through __OwningControllerProcess. (%s)" % response)
diff --git a/test/runner.py b/test/runner.py index 8009e37..799e0d5 100644 --- a/test/runner.py +++ b/test/runner.py @@ -546,8 +546,13 @@ class Runner(object): :raises: :class: `test.runner.TorInaccessable` if tor can't be connected to """
- control_socket = self.get_tor_socket(authenticate) - return stem.control.Controller(control_socket) + control_socket = self.get_tor_socket(False) + controller = stem.control.Controller(control_socket) + + if authenticate: + controller.authenticate(password = CONTROL_PASSWORD, chroot_path = self.get_chroot()) + + return controller
def get_tor_version(self): """