[tor-commits] [tor-launcher/master] Use SETEVENTS to monitor bootstrap status.
brade at torproject.org
brade at torproject.org
Wed Apr 17 17:53:24 UTC 2013
commit 87ee9efd3ff25be118b63e862a1c446e2e513e8e
Author: Kathy Brade <brade at torproject.org>
Date: Wed Apr 17 13:52:59 2013 -0400
Use SETEVENTS to monitor bootstrap status.
---
src/chrome/content/network-settings.js | 7 +-
src/components/tl-process.js | 89 +++++++----------------
src/components/tl-protocol.js | 127 +++++++++++++++++++-------------
3 files changed, 107 insertions(+), 116 deletions(-)
diff --git a/src/chrome/content/network-settings.js b/src/chrome/content/network-settings.js
index 9bdd527..97dcf82 100644
--- a/src/chrome/content/network-settings.js
+++ b/src/chrome/content/network-settings.js
@@ -359,9 +359,10 @@ function applySettings()
gProtocolSvc.TorSendCommand("SAVECONF");
- // Start bootstrap monitor before we open the modal progress dialog.
- gTorProcessService.TorMonitorBootstrap(true);
- openProgressDialog();
+ gIsBootstrapComplete = gTorProcessService.TorIsBootstrapDone;
+ if (!gIsBootstrapComplete)
+ openProgressDialog();
+
if (gIsBootstrapComplete)
close();
}
diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index 0148529..4e73536 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -34,8 +34,6 @@ TorProcessService.prototype =
kInitialControlConnDelayMS: 25,
kMaxControlConnRetryMS: 500,
kControlConnTimeoutMS: 30000, // Wait at most 30 seconds for tor to start.
- kInitialMonitorDelayMS: 1000, // TODO: how can we avoid this delay?
- kMonitorDelayMS: 200,
// nsISupports implementation.
QueryInterface: function(aIID)
@@ -67,6 +65,7 @@ TorProcessService.prototype =
{
const kOpenNetworkSettingsTopic = "TorOpenNetworkSettings";
const kUserQuitTopic = "TorUserRequestedQuit";
+ const kBootstrapStatusTopic = "TorBootstrapStatus";
if (!this.mObsSvc)
{
@@ -79,6 +78,7 @@ TorProcessService.prototype =
this.mObsSvc.addObserver(this, "quit-application-granted", false);
this.mObsSvc.addObserver(this, kOpenNetworkSettingsTopic, false);
this.mObsSvc.addObserver(this, kUserQuitTopic, false);
+ this.mObsSvc.addObserver(this, kBootstrapStatusTopic, false);
if (TorLauncherUtil.shouldStartAndOwnTor)
this._startTor();
@@ -89,7 +89,7 @@ TorProcessService.prototype =
this.mObsSvc.removeObserver(this, "quit-application-granted");
this.mObsSvc.removeObserver(this, kOpenNetworkSettingsTopic);
this.mObsSvc.removeObserver(this, kUserQuitTopic);
- this.TorMonitorBootstrap(false);
+ this.mObsSvc.removeObserver(this, kBootstrapStatusTopic);
if (this.mTorProcess)
{
TorLauncherLogger.log(4, "Shutting down tor process (pid "
@@ -112,7 +112,6 @@ TorProcessService.prototype =
this.mControlConnTimer = null;
}
- this.TorMonitorBootstrap(false);
this.mTorProcess = null;
this.mObsSvc.notifyObservers(null, "TorProcessExited", null);
@@ -135,10 +134,7 @@ TorProcessService.prototype =
this.mIsTorProcessReady = true;
this.mProtocolSvc.TorStartEventMonitor();
- var isInitialBootstrap =
- TorLauncherUtil.getBoolPref(this.kPrefPromptAtStartup);
- if (!isInitialBootstrap)
- this.TorMonitorBootstrap(true);
+ this.mProtocolSvc.TorRetrieveBootstrapStatus();
this.mObsSvc.notifyObservers(null, "TorProcessIsReady", null);
}
@@ -161,16 +157,9 @@ TorProcessService.prototype =
this.mControlConnTimer .TYPE_ONE_SHOT);
}
}
- else if (aSubject == this.mTimer)
- {
- this._checkBootStrapStatus();
- if (this.mTimer)
- {
- this.mTimer.init(this, this.kMonitorDelayMS,
- this.mTimer.TYPE_ONE_SHOT);
- }
- }
}
+ else if (kBootstrapStatusTopic == aTopic)
+ this._processBootstrapStatus(aSubject.wrappedJSObject);
else if (kOpenNetworkSettingsTopic == aTopic)
this._openNetworkSettings(false);
else if (kUserQuitTopic == aTopic)
@@ -209,40 +198,22 @@ TorProcessService.prototype =
lockFactory: function (aDoLock) {},
+
// Public Properties and Methods ///////////////////////////////////////////
get TorIsProcessReady()
{
return (this.mTorProcess) ? this.mIsTorProcessReady : false;
},
- TorMonitorBootstrap: function(aEnable)
+ get TorIsBootstrapDone()
{
- if (!this.mProtocolSvc)
- return;
-
- if (!aEnable)
- {
- if (this.mTimer)
- {
- this.mTimer.cancel();
- this.mTimer = null;
- }
-
- return;
- }
-
- if (this.mTimer)
- return;
-
- this.mTimer = Cc["@mozilla.org/timer;1"]
- .createInstance(Ci.nsITimer);
- this.mTimer.init(this, this.kInitialMonitorDelayMS,
- this.mTimer.TYPE_ONE_SHOT);
+ return this.mIsBootstrapDone;
},
// Private Member Variables ////////////////////////////////////////////////
mIsTorProcessReady: false,
+ mIsBootstrapDone: false,
mIsQuitting: false,
mObsSvc: null,
mProtocolSvc: null,
@@ -251,7 +222,6 @@ TorProcessService.prototype =
mTBBTopDir: null, // nsIFile for top of TBB installation (cached)
mControlConnTimer: null,
mControlConnDelayMS: 0,
- mTimer: null,
mQuitSoon: false, // Quit was requested by the user; do so soon.
@@ -373,39 +343,32 @@ TorProcessService.prototype =
this.mControlConnTimer.TYPE_ONE_SHOT);
},
- _checkBootStrapStatus: function()
+ _processBootstrapStatus: function(aStatusObj)
{
- var statusObj = this.mProtocolSvc.TorGetBootStrapStatus();
- if (!statusObj)
+ if (!aStatusObj)
return;
- statusObj._errorOccurred = (("WARN" == statusObj.TYPE) &&
- ("warn" == statusObj.RECOMMENDATION));
-
- // Notify observers.
- if (this.mObsSvc)
- {
- statusObj.wrappedJSObject = statusObj;
- this.mObsSvc.notifyObservers(statusObj, "TorBootstrapStatus", null);
- }
-
// TODO: keep viewable log of RECOMMENDATION == "ignore" messages.
- if (100 == statusObj.PROGRESS)
+ if (100 == aStatusObj.PROGRESS)
{
- this.TorMonitorBootstrap(false);
+ this.mIsBootstrapDone = true;
TorLauncherUtil.setBoolPref(this.kPrefPromptAtStartup, false);
}
- else if (statusObj._errorOccurred)
+ else
{
- this.TorMonitorBootstrap(false);
- TorLauncherUtil.setBoolPref(this.kPrefPromptAtStartup, true);
- TorLauncherLogger.log(5, "Tor bootstrap error: " + statusObj.WARNING);
+ this.mIsBootstrapDone = false;
- var s = TorLauncherUtil.getFormattedLocalizedString(
- "tor_bootstrap_failed", [statusObj.WARNING], 1);
- TorLauncherUtil.showAlert(null, s);
+ if (aStatusObj._errorOccurred)
+ {
+ TorLauncherUtil.setBoolPref(this.kPrefPromptAtStartup, true);
+ TorLauncherLogger.log(5, "Tor bootstrap error: " + aStatusObj.WARNING);
+
+ var s = TorLauncherUtil.getFormattedLocalizedString(
+ "tor_bootstrap_failed", [aStatusObj.WARNING], 1);
+ TorLauncherUtil.showAlert(null, s);
+ }
}
- }, // _checkBootstrapStatus()
+ }, // _processBootstrapStatus()
// Blocks until network settings dialog is closed.
_openNetworkSettings: function(aIsInitialBootstrap)
diff --git a/src/components/tl-protocol.js b/src/components/tl-protocol.js
index 22df4a6..94ab21d 100644
--- a/src/components/tl-protocol.js
+++ b/src/components/tl-protocol.js
@@ -4,7 +4,8 @@
//
// vim: set sw=2 sts=2 ts=8 et syntax=javascript:
-// Notes: decided to avoid IDL/xpt since it will complicate build process
+// To avoid deadlock due to JavaScript threading limitations, this component
+// should never make a direct call into the process component.
const Cc = Components.classes;
const Ci = Components.interfaces;
@@ -246,25 +247,16 @@ TorProtocolService.prototype =
return this.TorSendCommand("SETCONF", cmdArgs);
}, // TorSetConf()
- // If successful, returns a JS object with these fields:
- // status.TYPE -- "NOTICE" or "WARN"
- // status.PROGRESS -- integer
- // status.TAG -- string
- // status.SUMMARY -- string
- // status.WARNING -- string (optional)
- // status.REASON -- string (optional)
- // status.COUNT -- integer (optional)
- // status.RECOMMENDATION -- string (optional)
- // Returns null upon failure.
- TorGetBootStrapStatus: function()
+ // If successful, sends a "TorBootstrapStatus" notification.
+ TorRetrieveBootstrapStatus: function()
{
var cmd = "GETINFO";
var key = "status/bootstrap-phase";
var reply = this.TorSendCommand(cmd, key);
if (!this.TorCommandSucceeded(reply))
{
- TorLauncherLogger.log(4, "TorGetBootStrapStatus: command failed");
- return null;
+ TorLauncherLogger.log(4, "TorRetrieveBootstrapStatus: command failed");
+ return;
}
// A typical reply looks like:
@@ -272,48 +264,82 @@ TorProtocolService.prototype =
// 250 OK
reply = this._parseReply(cmd, key, reply);
if (reply.lineArray)
- {
- var sawBootstrap = false;
- var statusObj = {};
- statusObj.TYPE = "NOTICE";
+ this._parseBootstrapStatus(reply.lineArray[0]);
+ },
- // The following code assumes that this is a one-line response.
- var paramArray = this._splitReplyLine(reply.lineArray[0]);
- for (var i = 0; i < paramArray.length; ++i)
- {
- var tokenAndVal = paramArray[i];
- var token, val;
- var idx = tokenAndVal.indexOf('=');
- if (idx < 0)
- token = tokenAndVal;
- else
- {
- token = tokenAndVal.substring(0, idx);
- var valObj = {};
- if (!this._strUnescape(tokenAndVal.substring(idx + 1), valObj))
- continue; // skip this token/value pair.
+ // If successful, returns a JS object with these fields:
+ // status.TYPE -- "NOTICE" or "WARN"
+ // status.PROGRESS -- integer
+ // status.TAG -- string
+ // status.SUMMARY -- string
+ // status.WARNING -- string (optional)
+ // status.REASON -- string (optional)
+ // status.COUNT -- integer (optional)
+ // status.RECOMMENDATION -- string (optional)
+ // A "TorBootstrapStatus" notification is also sent.
+ // Returns null upon failure.
+ _parseBootstrapStatus: function(aStatusMsg)
+ {
+ if (!aStatusMsg || (0 == aStatusMsg.length))
+ return null;
- val = valObj.result;
- }
+ var sawBootstrap = false;
+ var sawCircuitEstablished = false;
+ var statusObj = {};
+ statusObj.TYPE = "NOTICE";
- if ("BOOTSTRAP" == token)
- sawBootstrap = true;
- else if (("WARN" == token) || ("NOTICE" == token))
- statusObj.TYPE = token;
- else if (("COUNT" == token) || ("PROGRESS" == token))
- statusObj[token] = parseInt(val, 10);
- else
- statusObj[token] = val;
+ // The following code assumes that this is a one-line response.
+ var paramArray = this._splitReplyLine(aStatusMsg);
+ for (var i = 0; i < paramArray.length; ++i)
+ {
+ var tokenAndVal = paramArray[i];
+ var token, val;
+ var idx = tokenAndVal.indexOf('=');
+ if (idx < 0)
+ token = tokenAndVal;
+ else
+ {
+ token = tokenAndVal.substring(0, idx);
+ var valObj = {};
+ if (!this._strUnescape(tokenAndVal.substring(idx + 1), valObj))
+ continue; // skip this token/value pair.
+
+ val = valObj.result;
}
- if (!sawBootstrap)
- TorLauncherLogger.log(4, "TorGetBootStrapStatus: missing BOOTSTRAP");
+ if ("BOOTSTRAP" == token)
+ sawBootstrap = true;
+ else if ("CIRCUIT_ESTABLISHED" == token)
+ sawCircuitEstablished = true;
+ else if (("WARN" == token) || ("NOTICE" == token))
+ statusObj.TYPE = token;
+ else if (("COUNT" == token) || ("PROGRESS" == token))
+ statusObj[token] = parseInt(val, 10);
else
- this._dumpObj("BootstrapStatus", statusObj); // TODO: remove this.
+ statusObj[token] = val;
}
+ if (!sawBootstrap)
+ {
+ if (sawCircuitEstablished)
+ TorLauncherLogger.log(2, "_parseBootstrapStatus: CIRCUIT_ESTABLISHED");
+ else
+ TorLauncherLogger.log(4, "_parseBootstrapStatus: missing BOOTSTRAP");
+
+ return null;
+ }
+
+ // this._dumpObj("BootstrapStatus", statusObj);
+ statusObj._errorOccurred = (("WARN" == statusObj.TYPE) &&
+ ("warn" == statusObj.RECOMMENDATION));
+
+ // Notify observers.
+ var obsSvc = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ statusObj.wrappedJSObject = statusObj;
+ obsSvc.notifyObservers(statusObj, "TorBootstrapStatus", null);
return statusObj;
- }, // TorGetBootStrapStatus()
+ }, // _parseBootstrapStatus()
// Executes a command on the control port.
// Return a reply object or null if a fatal error occurs.
@@ -422,7 +448,6 @@ TorProtocolService.prototype =
// Private Member Variables ////////////////////////////////////////////////
- mObsSvc: null,
mControlPort: null,
mControlHost: null,
mControlPassword: null, // JS string that contains hex-encoded password.
@@ -1136,6 +1161,7 @@ TorProtocolService.prototype =
if ((idx > 0))
{
let eventType = s.substring(0, idx);
+ let msg = s.substr(idx + 1);
switch (eventType)
{
case "DEBUG":
@@ -1144,13 +1170,14 @@ TorProtocolService.prototype =
case "WARN":
case "ERR":
var now = new Date();
- let logObj = { date: now, type: eventType, msg: s.substr(idx) };
+ let logObj = { date: now, type: eventType, msg: msg };
if (!this.mTorLog)
this.mTorLog = [];
this.mTorLog.push(logObj);
break;
case "STATUS_CLIENT":
- /*FALLTHRU*/
+ this._parseBootstrapStatus(msg);
+ break;
default:
this._dumpObj(eventType + "_event", aReply);
}
More information about the tor-commits
mailing list