[tor-commits] [arm/master] Dropping the tor_tools module

atagar at torproject.org atagar at torproject.org
Tue Jan 28 04:46:04 UTC 2014


commit 91e5b30e4541e1849b5e5b2041c5fc4e6ee08af7
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Jan 27 20:45:41 2014 -0800

    Dropping the tor_tools module
    
    Wow, I didn't expect to reach this point this weekend. The tor_tools module was
    once a wrapper around TorCtl (providing more user friendly methods, thread
    safety, etc). Stem provides all of these so a long term goal with the arm
    rewrite has been to drop this module completely. Now we can!
---
 arm/util/tor_tools.py |  499 -------------------------------------------------
 1 file changed, 499 deletions(-)

diff --git a/arm/util/tor_tools.py b/arm/util/tor_tools.py
deleted file mode 100644
index 1cefa98..0000000
--- a/arm/util/tor_tools.py
+++ /dev/null
@@ -1,499 +0,0 @@
-"""
-Helper for working with an active tor process. This both provides a wrapper for
-accessing stem and notifications of state changes to subscribers.
-"""
-
-import threading
-
-import stem
-import stem.control
-
-from stem.util import log
-
-CONTROLLER = None  # singleton Controller instance
-
-UNDEFINED = "<Undefined_ >"
-
-
-def get_conn():
-  """
-  Singleton constructor for a Controller. Be aware that this starts as being
-  uninitialized, needing a stem Controller before it's fully functional.
-  """
-
-  global CONTROLLER
-
-  if CONTROLLER is None:
-    CONTROLLER = Controller()
-
-  return CONTROLLER
-
-
-class Controller:
-  """
-  Stem wrapper providing convenience functions (mostly from the days of using
-  TorCtl), listener functionality for tor's state, and the capability for
-  controller connections to be restarted if closed.
-  """
-
-  def __init__(self):
-    self.controller = None
-    self.conn_lock = threading.RLock()
-    self._consensus_lookup_cache = {}     # lookup cache with network status entries
-    self._descriptor_lookup_cache = {}    # lookup cache with relay descriptors
-
-  def init(self, controller):
-    """
-    Uses the given stem instance for future operations, notifying listeners
-    about the change.
-
-    Arguments:
-      controller - stem based Controller instance
-    """
-
-    # TODO: We should reuse our controller instance so event listeners will be
-    # re-attached. This is a point of regression until we do... :(
-
-    if controller.is_alive() and controller != self.controller:
-      self.conn_lock.acquire()
-
-      if self.controller:
-        self.close()  # shut down current connection
-
-      self.controller = controller
-      log.info("Stem connected to tor version %s" % self.controller.get_version())
-
-      self.controller.add_event_listener(self.ns_event, stem.control.EventType.NS)
-      self.controller.add_event_listener(self.new_consensus_event, stem.control.EventType.NEWCONSENSUS)
-      self.controller.add_event_listener(self.new_desc_event, stem.control.EventType.NEWDESC)
-
-      # reset caches for ip -> fingerprint lookups
-
-      self._consensus_lookup_cache = {}
-      self._descriptor_lookup_cache = {}
-
-      self.conn_lock.release()
-
-  def close(self):
-    """
-    Closes the current stem instance and notifies listeners.
-    """
-
-    self.conn_lock.acquire()
-
-    if self.controller:
-      self.controller.close()
-
-    self.conn_lock.release()
-
-  def get_controller(self):
-    return self.controller
-
-  def is_alive(self):
-    """
-    Returns True if this has been initialized with a working stem instance,
-    False otherwise.
-    """
-
-    self.conn_lock.acquire()
-
-    result = False
-
-    if self.controller:
-      if self.controller.is_alive():
-        result = True
-      else:
-        self.close()
-
-    self.conn_lock.release()
-    return result
-
-  def get_info(self, param, default = UNDEFINED):
-    """
-    Queries the control port for the given GETINFO option, providing the
-    default if the response is undefined or fails for any reason (error
-    response, control port closed, initiated, etc).
-
-    Arguments:
-      param   - GETINFO option to be queried
-      default - result if the query fails
-    """
-
-    self.conn_lock.acquire()
-
-    try:
-      if not self.is_alive():
-        if default != UNDEFINED:
-          return default
-        else:
-          raise stem.SocketClosed()
-
-      if default != UNDEFINED:
-        return self.controller.get_info(param, default)
-      else:
-        return self.controller.get_info(param)
-    except stem.SocketClosed as exc:
-      self.close()
-      raise exc
-    finally:
-      self.conn_lock.release()
-
-  def get_option(self, param, default = UNDEFINED, multiple = False):
-    """
-    Queries the control port for the given configuration option, providing the
-    default if the response is undefined or fails for any reason. If multiple
-    values exist then this arbitrarily returns the first unless the multiple
-    flag is set.
-
-    Arguments:
-      param     - configuration option to be queried
-      default   - result if the query fails
-      multiple  - provides a list with all returned values if true, otherwise
-                  this just provides the first result
-    """
-
-    self.conn_lock.acquire()
-
-    try:
-      if not self.is_alive():
-        if default != UNDEFINED:
-          return default
-        else:
-          raise stem.SocketClosed()
-
-      if default != UNDEFINED:
-        return self.controller.get_conf(param, default, multiple)
-      else:
-        return self.controller.get_conf(param, multiple = multiple)
-    except stem.SocketClosed as exc:
-      self.close()
-      raise exc
-    finally:
-      self.conn_lock.release()
-
-  def set_option(self, param, value = None):
-    """
-    Issues a SETCONF to set the given option/value pair. An exeptions raised
-    if it fails to be set. If no value is provided then this sets the option to
-    0 or NULL.
-
-    Arguments:
-      param - configuration option to be set
-      value - value to set the parameter to (this can be either a string or a
-              list of strings)
-    """
-
-    self.conn_lock.acquire()
-
-    try:
-      if not self.is_alive():
-        raise stem.SocketClosed()
-
-      self.controller.set_conf(param, value)
-    except stem.SocketClosed as exc:
-      self.close()
-      raise exc
-    finally:
-      self.conn_lock.release()
-
-  def save_conf(self):
-    """
-    Calls tor's SAVECONF method.
-    """
-
-    self.conn_lock.acquire()
-
-    if self.is_alive():
-      self.controller.save_conf()
-
-    self.conn_lock.release()
-
-  def get_circuits(self, default = []):
-    """
-    This provides a list with tuples of the form:
-    (circuit_id, status, purpose, (fingerprint1, fingerprint2...))
-
-    Arguments:
-      default - value provided back if unable to query the circuit-status
-    """
-
-    # TODO: We're losing caching around this. We should check to see the call
-    # volume of this and probably add it to stem.
-
-    results = []
-
-    for entry in self.controller.get_circuits():
-      fingerprints = []
-
-      for fp, nickname in entry.path:
-        if not fp:
-          consensus_entry = self.controller.get_network_status(nickname, None)
-
-          if consensus_entry:
-            fp = consensus_entry.fingerprint
-
-          # It shouldn't be possible for this lookup to fail, but we
-          # need to fill something (callers won't expect our own client
-          # paths to have unknown relays). If this turns out to be wrong
-          # then log a warning.
-
-          if not fp:
-            log.warn("Unable to determine the fingerprint for a relay in our own circuit: %s" % nickname)
-            fp = "0" * 40
-
-        fingerprints.append(fp)
-
-      results.append((int(entry.id), entry.status, entry.purpose, fingerprints))
-
-    if results:
-      return results
-    else:
-      return default
-
-  def get_my_flags(self, default = None):
-    """
-    Provides the flags held by this relay.
-
-    Arguments:
-      default - result if the query fails or this relay isn't a part of the consensus yet
-    """
-
-    my_fingerprint = self.get_info("fingerprint", None)
-
-    if my_fingerprint:
-      my_status_entry = self.controller.get_network_status(my_fingerprint)
-
-      if my_status_entry:
-        return my_status_entry.flags
-
-    return default
-
-  def get_version(self):
-    """
-    Provides the version of our tor instance, this is None if we don't have a
-    connection.
-    """
-
-    self.conn_lock.acquire()
-
-    try:
-      return self.controller.get_version()
-    except stem.SocketClosed:
-      self.close()
-      return None
-    except:
-      return None
-    finally:
-      self.conn_lock.release()
-
-  def get_my_user(self):
-    """
-    Provides the user this process is running under. If unavailable this
-    provides None.
-    """
-
-    return self.controller.get_user(None)
-
-  def get_exit_policy(self):
-    """
-    Provides an ExitPolicy instance for the head of this relay's exit policy
-    chain. If there's no active connection then this provides None.
-    """
-
-    self.conn_lock.acquire()
-
-    result = None
-
-    if self.is_alive():
-      try:
-        result = self.controller.get_exit_policy(None)
-      except:
-        pass
-
-    self.conn_lock.release()
-
-    return result
-
-  def get_consensus_entry(self, relay_fingerprint):
-    """
-    Provides the most recently available consensus information for the given
-    relay. This is none if no such information exists.
-
-    Arguments:
-      relay_fingerprint - fingerprint of the relay
-    """
-
-    self.conn_lock.acquire()
-
-    result = None
-
-    if self.is_alive():
-      if not relay_fingerprint in self._consensus_lookup_cache:
-        ns_entry = self.get_info("ns/id/%s" % relay_fingerprint, None)
-        self._consensus_lookup_cache[relay_fingerprint] = ns_entry
-
-      result = self._consensus_lookup_cache[relay_fingerprint]
-
-    self.conn_lock.release()
-
-    return result
-
-  def get_descriptor_entry(self, relay_fingerprint):
-    """
-    Provides the most recently available descriptor information for the given
-    relay. Unless FetchUselessDescriptors is set this may frequently be
-    unavailable. If no such descriptor is available then this returns None.
-
-    Arguments:
-      relay_fingerprint - fingerprint of the relay
-    """
-
-    self.conn_lock.acquire()
-
-    result = None
-
-    if self.is_alive():
-      if not relay_fingerprint in self._descriptor_lookup_cache:
-        desc_entry = self.get_info("desc/id/%s" % relay_fingerprint, None)
-        self._descriptor_lookup_cache[relay_fingerprint] = desc_entry
-
-      result = self._descriptor_lookup_cache[relay_fingerprint]
-
-    self.conn_lock.release()
-
-    return result
-
-  def get_relay_exit_policy(self, relay_fingerprint):
-    """
-    Provides the ExitPolicy instance associated with the given relay. The tor
-    consensus entries don't indicate if private addresses are rejected or
-    address-specific policies, so this is only used as a fallback if a recent
-    descriptor is unavailable. This returns None if unable to determine the
-    policy.
-
-    Arguments:
-      relay_fingerprint - fingerprint of the relay
-    """
-
-    self.conn_lock.acquire()
-
-    result = None
-
-    if self.is_alive():
-      # attempts to fetch the policy via the descriptor
-      descriptor = self.controller.get_server_descriptor(relay_fingerprint, None)
-
-      if descriptor:
-        result = descriptor.exit_policy
-
-    self.conn_lock.release()
-
-    return result
-
-  def add_event_listener(self, listener, *event_types):
-    """
-    Directs further tor controller events to callback functions of the
-    listener. If a new control connection is initialized then this listener is
-    reattached.
-    """
-
-    self.conn_lock.acquire()
-
-    if self.is_alive():
-      self.controller.add_event_listener(listener, *event_types)
-
-    self.conn_lock.release()
-
-  def remove_event_listener(self, listener):
-    """
-    Stops the given event listener from being notified of further events.
-    """
-
-    self.conn_lock.acquire()
-
-    if self.is_alive():
-      self.controller.remove_event_listener(listener)
-
-    self.conn_lock.release()
-
-  def add_status_listener(self, callback):
-    """
-    Directs further events related to tor's controller status to the callback
-    function.
-
-    Arguments:
-      callback - functor that'll accept the events, expected to be of the form:
-                 myFunction(controller, event_type)
-    """
-
-    self.controller.add_status_listener(callback)
-
-  def reload(self):
-    """
-    This resets tor (sending a RELOAD signal to the control port) causing tor's
-    internal state to be reset and the torrc reloaded.
-    """
-
-    self.conn_lock.acquire()
-
-    try:
-      if self.is_alive():
-        try:
-          self.controller.signal(stem.Signal.RELOAD)
-        except Exception as exc:
-          # new torrc parameters caused an error (tor's likely shut down)
-          raise IOError(str(exc))
-    finally:
-      self.conn_lock.release()
-
-  def shutdown(self, force = False):
-    """
-    Sends a shutdown signal to the attached tor instance. For relays the
-    actual shutdown is delayed for thirty seconds unless the force flag is
-    given. This raises an IOError if a signal is sent but fails.
-
-    Arguments:
-      force - triggers an immediate shutdown for relays if True
-    """
-
-    self.conn_lock.acquire()
-
-    raised_exception = None
-
-    if self.is_alive():
-      try:
-        is_relay = self.get_option("ORPort", None) is not None
-
-        if force:
-          self.controller.signal(stem.Signal.HALT)
-        else:
-          self.controller.signal(stem.Signal.SHUTDOWN)
-
-        # shuts down control connection if we aren't making a delayed shutdown
-
-        if force or not is_relay:
-          self.close()
-      except Exception as exc:
-        raised_exception = IOError(str(exc))
-
-    self.conn_lock.release()
-
-    if raised_exception:
-      raise raised_exception
-
-  def ns_event(self, event):
-    self._consensus_lookup_cache = {}
-
-  def new_consensus_event(self, event):
-    self.conn_lock.acquire()
-
-    # reconstructs consensus based mappings
-
-    self._consensus_lookup_cache = {}
-
-    self.conn_lock.release()
-
-  def new_desc_event(self, event):
-    self.conn_lock.acquire()
-    self._descriptor_lookup_cache = {}
-    self.conn_lock.release()



More information about the tor-commits mailing list