[tor-commits] [arm/master] Moving managed tor functions into helper
atagar at torproject.org
atagar at torproject.org
Sun Jul 10 01:05:31 UTC 2011
commit 057637013e32ebf8db9e4b762077add45b4c92d7
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Jul 9 16:53:08 2011 -0700
Moving managed tor functions into helper
Putting the util functions for managing a wizard generated tor instance into a
helper instance accessable from the controller. I'm also fixing a couple
important bugs along the way:
- Race condition between arm and tor starting its control port, so half the
time a managed tor instance reported that it couldn't connect to the control
port. Now waiting for up to five seconds instead.
- If we're already connected to a managed instance then the wizard should
modify that instance rather than starting an new one.
---
src/cli/controller.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++--
src/cli/wizard.py | 17 ++++++-----
2 files changed, 79 insertions(+), 11 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py
index ae1a59b..5ba7f42 100644
--- a/src/cli/controller.py
+++ b/src/cli/controller.py
@@ -21,6 +21,8 @@ import cli.graphing.connStats
import cli.graphing.resourceStats
import cli.connections.connPanel
+from TorCtl import TorCtl
+
from util import connections, conf, enum, log, panel, sysTools, torConfig, torTools
ARM_CONTROLLER = None
@@ -38,6 +40,7 @@ CONFIG = {"startup.events": "N3",
"features.confirmQuit": True,
"features.graph.type": 1,
"features.graph.bw.prepopulate": True,
+ "wizard.default": {},
"log.startTime": log.INFO,
"log.torEventTypeUnrecognized": log.NOTICE,
"log.configEntryUndefined": log.NOTICE,
@@ -167,6 +170,7 @@ class Controller:
self._isPaused = False
self._forceRedraw = False
self._isDone = False
+ self._torManager = TorManager(self)
self.setMsg() # initializes our control message
def getScreen(self):
@@ -380,6 +384,13 @@ class Controller:
if not os.path.exists(dataDir): os.makedirs(dataDir)
return os.path.expanduser(dataDir)
+ def getTorManager(self):
+ """
+ Provides management utils for an arm managed tor instance.
+ """
+
+ return self._torManager
+
def isDone(self):
"""
True if arm should be terminated, false otherwise.
@@ -398,10 +409,8 @@ class Controller:
if CONFIG["features.offerTorShutdownOnQuit"]:
conn = torTools.getConn()
- torrcLoc = conn.getInfo("config-file")
- wizardTorrcLoc = self.getDataDirectory() + "torrc"
- if torrcLoc == wizardTorrcLoc:
+ if self.getTorManager().isManaged(conn):
while True:
msg = "Shut down the Tor instance arm started (y/n)?"
confirmationKey = cli.popups.showMsg(msg, attr = curses.A_BOLD)
@@ -416,6 +425,64 @@ class Controller:
elif confirmationKey in (ord('n'), ord('N')):
break
+class TorManager:
+ """
+ Bundle of utils for starting and manipulating an arm generated tor instance.
+ """
+
+ def __init__(self, controller):
+ self._controller = controller
+
+ def getTorrcPath(self):
+ """
+ Provides the path to a wizard generated torrc.
+ """
+
+ return self._controller.getDataDirectory() + "torrc"
+
+ def isTorrcAvailable(self):
+ """
+ True if a wizard generated torrc exists, false otherwise.
+ """
+
+ return os.path.exists(self.getTorrcPath())
+
+ def isManaged(self, conn):
+ """
+ Returns true if the given tor instance is managed by us, false otherwise.
+
+ Arguments:
+ conn - controller instance to be checked
+ """
+
+ return conn.getInfo("config-file") == self.getTorrcPath()
+
+ def startManagedInstance(self):
+ """
+ Starts a managed instance of tor, raising an IOError if unsuccessful.
+ """
+
+ os.system("tor --quiet -f %s&" % self.getTorrcPath())
+ startTime = time.time()
+
+ # attempts to connect for five seconds (tor might or might not be
+ # immediately available)
+ torctlConn, authType, authValue, raisedExc = None, None, None, None
+ while not torctlConn and time.time() - startTime < 5:
+ try:
+ torctlConn, authType, authValue = TorCtl.preauth_connect(controlPort = int(CONFIG["wizard.default"]["Control"]))
+ except IOError, exc:
+ raisedExc == exc
+ time.sleep(0.5)
+
+ if not torctlConn: raise raisedExc
+
+ if authType == TorCtl.AUTH_TYPE.COOKIE:
+ torctlConn.authenticate(authValue)
+ torTools.getConn().init(torctlConn)
+ else:
+ raise IOError("unexpected authentication type '%s'" % authType)
+
def shutdownDaemons():
"""
Stops and joins on worker threads.
diff --git a/src/cli/wizard.py b/src/cli/wizard.py
index 7e0907e..8a5a138 100644
--- a/src/cli/wizard.py
+++ b/src/cli/wizard.py
@@ -254,6 +254,7 @@ def showWizard():
# remembers the last selection made on the type prompt page
relaySelection = RelayType.RELAY
controller = cli.controller.getController()
+ manager = controller.getTorManager()
while True:
if relayType == None:
@@ -268,7 +269,7 @@ def showWizard():
elif selection == NEXT:
generatedTorrc = getTorrc(relayType, config)
- torrcLocation = controller.getDataDirectory() + "torrc"
+ torrcLocation = manager.getTorrcPath()
controller.requestRedraw(True)
confirmationSelection = showConfirmationDialog(generatedTorrc, torrcLocation)
@@ -285,14 +286,14 @@ def showWizard():
torrcFile.close()
try:
- os.system("tor --quiet -f %s&" % torrcLocation)
- torctlConn, authType, authValue = TorCtl.preauth_connect(controlPort = int(CONFIG["wizard.default"][Options.CONTROL]))
+ conn = torTools.getConn()
- if authType == TorCtl.AUTH_TYPE.COOKIE:
- torctlConn.authenticate(authValue)
- torTools.getConn().init(torctlConn)
- else:
- raise IOError("unexpected authentication type '%s'" % authType)
+ # If we're connected to a managed instance then just need to
+ # issue a sighup to pick up the new settings. Otherwise starts
+ # a new tor instance.
+
+ if manager.isManaged(conn): conn.reset()
+ else: manager.startManagedInstance()
except IOError, exc:
log.log(log.WARN, "Unable to start tor: %s" % exc)
More information about the tor-commits
mailing list