[tor-commits] [stem/master] Implement Controller.extend_circuit
atagar at torproject.org
atagar at torproject.org
Sun Aug 26 20:36:53 UTC 2012
commit fea0a43ded650b78d9453c1bc2ce15fdb99e394f
Author: Ravi Chandra Padmala <neenaoffline at gmail.com>
Date: Thu Aug 23 22:07:01 2012 -0700
Implement Controller.extend_circuit
---
stem/control.py | 57 ++++++++++++++++++++++++++++++++++++++
test/integ/control/controller.py | 17 ++++++++++-
2 files changed, 73 insertions(+), 1 deletions(-)
diff --git a/stem/control.py b/stem/control.py
index 247969e..2f0c773 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -27,6 +27,8 @@ interacting at a higher level.
|- 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
+ |- new_circuit - create new circuits
+ |- extend_circuit - create new circuits and extend existing ones
|- get_version - convenience method to get tor version
|- authenticate - convenience method to authenticate the controller
+- protocolinfo - convenience method to get the protocol info
@@ -1052,6 +1054,61 @@ class Controller(BaseController):
raise stem.socket.InvalidArguments(response.code, response.message, [signal])
raise stem.socket.ProtocolError("SIGNAL response contained unrecognized status code: %s" % response.code)
+
+ def new_circuit(self, relays = None, purpose = None):
+ """
+ Requests Tor to build a new circuit.
+
+ If the path isn't provided, one is automatically selected. If the purpose
+ isn't provided, "general" circuits are built.
+
+ :param list,str relays: list of relay nicknames/longnames or a single nickname/longname
+ :param str purpose: "general" or "controller"
+
+ :returns: Circuit id of the newly created circuit
+ """
+
+ return self.extend_circuit(0, relays, purpose)
+
+ def extend_circuit(self, circuit=0, relays = None, purpose = None):
+ """
+ Requests Tor to build a new circuit or extend an existing circuit.
+
+ When called without any arguments, a new general purpose circuit is created.
+ If circuit is zero, a new circuit is created. If circuit is non-zero, Tor
+ extends the existing circuit with that id . If the path isn't provided, one
+ is automatically selected. If the purpose isn't provided, "general" circuits
+ are built.
+
+ :param int circuit: id of the circuit which needs extending
+ :param list,str relays: list of relay nicknames/longnames or a single nickname/longname
+ :param str purpose: "general" or "controller"
+
+ :returns: Circuit id of the created/extended circuit
+
+ :raises: :class:`stem.socket.InvalidRequest` if one of the parameters were invalid
+ """
+
+ args = [str(circuit)]
+ if type(relays) == str: relays = [relays]
+ if relays: args.append(",".join(relays))
+ if purpose: args.append("purpose=%s" % purpose)
+
+ response = self.msg("EXTENDCIRCUIT %s" % " ".join(args))
+ stem.response.convert("SINGLELINE", response)
+
+ if response.is_ok():
+ try:
+ extended, new_circuit = response.message.split(" ")
+ assert extended == "EXTENDED"
+ except:
+ raise stem.socket.ProtocolError("EXTENDCIRCUIT response invalid:\n%s", str(response))
+ elif response.code == '552':
+ raise stem.socket.InvalidRequest(response.code, response.message)
+ else:
+ raise stem.socket.ProtocolError("EXTENDCIRCUIT returned unexpected response code: %s" % response.code)
+
+ return int(new_circuit)
def _case_insensitive_lookup(entries, key, default = UNDEFINED):
"""
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 450d219..9a64d36 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -299,7 +299,6 @@ class TestController(unittest.TestCase):
controller.load_conf(oldconf)
def test_saveconf(self):
-
if test.runner.require_control(self): return
runner = test.runner.get_runner()
@@ -364,4 +363,20 @@ class TestController(unittest.TestCase):
controller.signal("INT")
self.assertRaises(stem.socket.SocketClosed, controller.msg, "GETINFO version")
+
+ def test_extendcircuit(self):
+ if test.runner.require_control(self): return
+
+ runner = test.runner.get_runner()
+
+ with runner.get_tor_controller() as controller:
+ circ_id = controller.extend_circuit(0)
+ # check if our circuit was created
+ self.assertTrue(filter(lambda x: int(x.split()[0]) == circ_id, controller.get_info('circuit-status').splitlines()))
+ circ_id = controller.new_circuit()
+ self.assertTrue(filter(lambda x: int(x.split()[0]) == circ_id, controller.get_info('circuit-status').splitlines()))
+
+ self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, "foo")
+ self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#")
+ self.assertRaises(stem.socket.InvalidRequest, controller.extend_circuit, 0, "thisroutershouldntexistbecausestemexists!@##$%#", "foo")
More information about the tor-commits
mailing list