[tor-commits] [arm/release] Batch SETCONF and SET/RESETCONF in the interpretor
atagar at torproject.org
atagar at torproject.org
Sun Sep 25 21:38:29 UTC 2011
commit 3b803423be0f7a3edb09999c1b7c99b615facc1d
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Sep 17 16:14:39 2011 -0700
Batch SETCONF and SET/RESETCONF in the interpretor
Supporting a batch SETCONF or RESETCONF in torTools, and better handling those
inputs in the interpretor.
---
src/util/torInterpretor.py | 43 ++++++++++++++++++++++++-------
src/util/torTools.py | 60 +++++++++++++++++++++++++++++++------------
2 files changed, 76 insertions(+), 27 deletions(-)
diff --git a/src/util/torInterpretor.py b/src/util/torInterpretor.py
index 71080c9..1cc66bd 100644
--- a/src/util/torInterpretor.py
+++ b/src/util/torInterpretor.py
@@ -75,7 +75,7 @@ Tor commands include:
RESOLVE - issues an asynchronous dns or rdns request over tor
TAKEOWNERSHIP - instructs tor to quit when this control connection is closed
PROTOCOLINFO - queries version and controller authentication information
- QUIT - disconnect control connection
+ QUIT - disconnect the control connection
For more information use '/help [OPTION]'."""
@@ -647,16 +647,39 @@ class ControlInterpretor:
except Exception, exc:
outputEntry.append((str(exc), ERROR_FORMAT))
elif cmd == "SETCONF":
- if "=" in arg:
- param, value = arg.split("=", 1)
+ # arguments can either be '<param>' or '<param>="<value>"' entries
+ paramList = []
+
+ while arg:
+ # TODO: I'm a little dubious of this for LineList values (like the
+ # ExitPolicy) since they're parsed as a single value. However, tor
+ # seems to be happy to get a single comma separated string (though it
+ # echos back faithfully rather than being parsed) so leaving this
+ # alone for now.
- try:
- conn.setOption(param.strip(), value.strip())
- except Exception, exc:
- outputEntry.append((str(exc), ERROR_FORMAT))
- else:
- # TODO: resets the attribute
- outputEntry.append(("Not yet implemented...", ERROR_FORMAT)) # TODO: implement
+ m = re.match(r'^(\S+)=\"([^"]+)\"', arg)
+
+ if m:
+ # we're dealing with a '<param>="<value>"' entry
+ param, value = m.groups()
+
+ paramList.append((param, value))
+ arg = arg[len(param) + len(value) + 3:].strip()
+ else:
+ # starts with just a param
+ param = arg.split()[0]
+ paramList.append((param, None))
+ arg = arg[len(param):].strip()
+
+ try:
+ conn.setOptions(paramList)
+ except Exception, exc:
+ outputEntry.append((str(exc), ERROR_FORMAT))
+ elif cmd == "RESETCONF":
+ try:
+ conn.setOptions([(param, None) for param in arg.split()])
+ except Exception, exc:
+ outputEntry.append((str(exc), ERROR_FORMAT))
else:
try:
response = conn.getTorCtl().sendAndRecv("%s\r\n" % input)
diff --git a/src/util/torTools.py b/src/util/torTools.py
index b9d9ac8..fcd8247 100644
--- a/src/util/torTools.py
+++ b/src/util/torTools.py
@@ -725,10 +725,11 @@ class Controller(TorCtl.PostEventListener):
elif result == []: return default
else: return result
- def setOption(self, param, value):
+ def setOption(self, param, value = None):
"""
Issues a SETCONF to set the given option/value pair. An exeptions raised
- if it fails to be set.
+ if it fails to be set. If no value is provided then this resets the
+ configuration option.
Arguments:
param - configuration option to be set
@@ -736,27 +737,53 @@ class Controller(TorCtl.PostEventListener):
list of strings)
"""
- isMultiple = isinstance(value, list) or isinstance(value, tuple)
+ self.setOptions(((param, value),))
+
+ def setOptions(self, paramList):
+ """
+ Issues a SETCONF to replace a set of configuration options. This takes a
+ list of parameter/new value tuple pairs. Values can be...
+ - a string to set a single value
+ - a list of strings to set a series of values (for instance the ExitPolicy)
+ - None to reset the parameter
+
+ Arguments:
+ paramList - list of parameter/value tuple pairs
+ """
+
self.connLock.acquire()
+ # constructs the SETCONF string
+ setConfComp = []
+
+ for param, value in paramList:
+ if isinstance(value, list) or isinstance(value, tuple):
+ setConfComp += ["%s=\"%s\"" % (param, val.strip()) for val in value]
+ elif value:
+ setConfComp.append("%s=\"%s\"" % (param, value.strip()))
+ else:
+ setConfComp.append(param)
+
+ setConfStr = " ".join(setConfComp)
+
startTime, raisedExc = time.time(), None
if self.isAlive():
try:
- if isMultiple: self.conn.set_options([(param, val) for val in value])
- else: self.conn.set_option(param, value)
+ self.conn.sendAndRecv("SETCONF %s\r\n" % setConfStr)
# flushing cached values (needed until we can detect SETCONF calls)
- for fetchType in ("str", "list", "map"):
- entry = (param.lower(), fetchType)
+ for param, _ in paramList:
+ for fetchType in ("str", "list", "map"):
+ entry = (param.lower(), fetchType)
+
+ if entry in self._cachedConf:
+ del self._cachedConf[entry]
- if entry in self._cachedConf:
- del self._cachedConf[entry]
-
- # special caches for the exit policy
- if param.lower() == "exitpolicy":
- self._exitPolicyChecker = self.getExitPolicy()
- self._isExitingAllowed = self._exitPolicyChecker.isExitingAllowed()
- self._exitPolicyLookupCache = {}
+ # special caches for the exit policy
+ if param.lower() == "exitpolicy":
+ self._exitPolicyChecker = self.getExitPolicy()
+ self._isExitingAllowed = self._exitPolicyChecker.isExitingAllowed()
+ self._exitPolicyLookupCache = {}
except (socket.error, TorCtl.ErrorReply, TorCtl.TorCtlClosed), exc:
if type(exc) == TorCtl.TorCtlClosed: self.close()
elif type(exc) == TorCtl.ErrorReply:
@@ -777,9 +804,8 @@ class Controller(TorCtl.PostEventListener):
self.connLock.release()
- setCall = "%s %s" % (param, ", ".join(value) if isMultiple else value)
excLabel = "failed: \"%s\", " % raisedExc if raisedExc else ""
- msg = "SETCONF %s (%sruntime: %0.4f)" % (setCall.strip(), excLabel, time.time() - startTime)
+ msg = "SETCONF %s (%sruntime: %0.4f)" % (setConfStr, excLabel, time.time() - startTime)
log.log(CONFIG["log.torSetConf"], msg)
if raisedExc: raise raisedExc
More information about the tor-commits
mailing list