[tor-commits] [stem/master] Implement wrapper method for Controller to handle SIGNAL requests

atagar at torproject.org atagar at torproject.org
Sun Aug 26 20:36:53 UTC 2012


commit aeb39b813961d02509a9c3e4e3db585b4190cac1
Author: Ravi Chandra Padmala <neenaoffline at gmail.com>
Date:   Thu Aug 23 21:52:01 2012 -0700

    Implement wrapper method for Controller to handle SIGNAL requests
---
 stem/control.py                  |   31 +++++++++++++++++++++++++++++++
 test/integ/control/controller.py |   16 ++++++++++++++++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index 7edd7bf..adf1d8a 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -26,6 +26,7 @@ interacting at a higher level.
     |- save_conf - saves configuration information to the torrc
     |- is_feature_enabled - checks if a given controller feature is enabled
     |- enable_feature - enables a controller feature that has been disabled by default
+    |- signal - sends a signal to the tor client
     |- get_version - convenience method to get tor version
     |- authenticate - convenience method to authenticate the controller
     +- protocolinfo - convenience method to get the protocol info
@@ -1026,6 +1027,35 @@ class Controller(BaseController):
       raise stem.socket.ProtocolError("USEFEATURE provided an invalid response code: %s" % response.code)
     
     self.enabled_features += [entry.upper() for entry in features]
+  
+  def signal(self, signal):
+    """
+    Sends a signal to the Tor client.
+    
+    :param str signal: type of signal to be sent. Must be one of the following...
+      * HUP - Reload configuration
+      * INT - If server is an OP, exit immediately.  If it's an OR, close listeners and exit after ShutdownWaitLength seconds
+      * USR1 - Dump log information about open connections and circuits
+      * USR2 - Switch all open logs to loglevel debug
+      * TERM - Clean up and exit immediately
+      * RELOAD - equivalent to HUP
+      * SHUTDOWN - equivalent to INT
+      * DUMP - . equivalent to USR1
+      * DEBUG - . equivalent to USR2
+      * HALT - . equivalent to TERM
+      * NEWNYM - Switch to clean circuits, so new application requests don't share any circuits with old ones and clear the client-side dns cache
+      * CLEARDNSCACHE - Forget the client-side cached IPs for all hostnames
+    
+    :raises: :class:`stem.socket.InvalidArguments` if signal provided wasn't recognized.
+    """
+    
+    response = self.msg("SIGNAL %s" % signal)
+    stem.response.convert("SINGLELINE", response)
+    
+    if not response.is_ok():
+      if response.code == "552":
+        raise stem.socket.InvalidArguments(response.code, response.message, [signal])
+      raise stem.socket.ProtocolError("SIGNAL response contained unrecognized status code")
 
 def _case_insensitive_lookup(entries, key, default = UNDEFINED):
   """
@@ -1053,3 +1083,4 @@ def _case_insensitive_lookup(entries, key, default = UNDEFINED):
   if default != UNDEFINED: return default
   else: raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries))
 
+
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 2723e27..450d219 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -348,4 +348,20 @@ class TestController(unittest.TestCase):
       except stem.socket.InvalidArguments, exc:
         self.assertEqual(["NOT"], exc.arguments)
       else: self.fail()
+  
+  def test_signal(self):
+    """
+    Test controller.signal with valid and invalid signals.
+    """
+    runner = test.runner.get_runner()
+    
+    with runner.get_tor_controller() as controller:
+      # valid signal
+      controller.signal("CLEARDNSCACHE")
+      
+      # invalid signals
+      self.assertRaises(stem.socket.InvalidArguments, controller.signal, "FOOBAR")
+      
+      controller.signal("INT")
+      self.assertRaises(stem.socket.SocketClosed, controller.msg, "GETINFO version")
 





More information about the tor-commits mailing list