Commit f4980a6c authored by Kathleen Brade's avatar Kathleen Brade Committed by Georg Koppen
Browse files

Bug 20111: use Unix domain sockets for SOCKS port by default

Retrieve SOCKS port configuration from Tor Launcher if available.
Support the TOR_SOCKS_IPC_PATH environment variable.

Consistently use IPC to refer to Unix domain sockets.

Enhance torbutton_local_tor_check() to correctly handle spaces and
escaped characters within the 'GETINFO net/listeners/socks' response.

Within startup-observer.js, use Services.jsm, Cc and similar
constants, and remove unused code.
parent 70e5f3b2
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// with docco.js to produce pretty documentation. // with docco.js to produce pretty documentation.
// //
// This script is to be embedded in torbutton.xul. It defines a single global // This script is to be embedded in torbutton.xul. It defines a single global
// function, createTorCircuitDisplay(socketFile, host, port, password), which // function, createTorCircuitDisplay(ipcFile, host, port, password), which
// activates the automatic Tor circuit display for the current tab and any // activates the automatic Tor circuit display for the current tab and any
// future tabs. // future tabs.
// //
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
/* global document, gBrowser, Components */ /* global document, gBrowser, Components */
// ### Main function // ### Main function
// __createTorCircuitDisplay(socketFile, host, port, password, enablePrefName)__. // __createTorCircuitDisplay(ipcFile, host, port, password, enablePrefName)__.
// The single function that prepares tor circuit display. Connects to a tor // The single function that prepares tor circuit display. Connects to a tor
// control port with the given socketFile or host plus port, and password, and // control port with the given ipcFile or host plus port, and password, and
// binds to a named bool pref whose value determines whether the circuit display // binds to a named bool pref whose value determines whether the circuit display
// is enabled or disabled. // is enabled or disabled.
let createTorCircuitDisplay = (function () { let createTorCircuitDisplay = (function () {
...@@ -312,11 +312,11 @@ let syncDisplayWithSelectedTab = (function() { ...@@ -312,11 +312,11 @@ let syncDisplayWithSelectedTab = (function() {
// ## Main function // ## Main function
// __setupDisplay(socketFile, host, port, password, enablePrefName)__. // __setupDisplay(ipcFile, host, port, password, enablePrefName)__.
// Once called, the Tor circuit display will be started whenever // Once called, the Tor circuit display will be started whenever
// the "enablePref" is set to true, and stopped when it is set to false. // the "enablePref" is set to true, and stopped when it is set to false.
// A reference to this function (called createTorCircuitDisplay) is exported as a global. // A reference to this function (called createTorCircuitDisplay) is exported as a global.
let setupDisplay = function (socketFile, host, port, password, enablePrefName) { let setupDisplay = function (ipcFile, host, port, password, enablePrefName) {
let myController = null, let myController = null,
stopCollectingIsolationData = null, stopCollectingIsolationData = null,
stop = function() { stop = function() {
...@@ -330,7 +330,7 @@ let setupDisplay = function (socketFile, host, port, password, enablePrefName) { ...@@ -330,7 +330,7 @@ let setupDisplay = function (socketFile, host, port, password, enablePrefName) {
}, },
start = function () { start = function () {
if (!myController) { if (!myController) {
myController = controller(socketFile, host, port || 9151, password, myController = controller(ipcFile, host, port || 9151, password,
function (err) { function (err) {
// An error has occurred. // An error has occurred.
logger.eclog(5, err); logger.eclog(5, err);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
let { LoadContextInfo } = Cu.import('resource://gre/modules/LoadContextInfo.jsm'); let { LoadContextInfo } = Cu.import('resource://gre/modules/LoadContextInfo.jsm');
let { Services } = Cu.import("resource://gre/modules/Services.jsm"); let { Services } = Cu.import("resource://gre/modules/Services.jsm");
let { showDialog } = Cu.import("resource://torbutton/modules/utils.js"); let { showDialog } = Cu.import("resource://torbutton/modules/utils.js");
let { unescapeTorString } = Cu.import("resource://torbutton/modules/utils.js");
const k_tb_last_browser_version_pref = "extensions.torbutton.lastBrowserVersion"; const k_tb_last_browser_version_pref = "extensions.torbutton.lastBrowserVersion";
const k_tb_browser_update_needed_pref = "extensions.torbutton.updateNeeded"; const k_tb_browser_update_needed_pref = "extensions.torbutton.updateNeeded";
...@@ -33,9 +34,9 @@ var m_tb_window_width = window.outerWidth; ...@@ -33,9 +34,9 @@ var m_tb_window_width = window.outerWidth;
var m_tb_tbb = false; var m_tb_tbb = false;
var m_tb_control_socket_file = null; // Set if using a UNIX domain socket. var m_tb_control_ipc_file = null; // Set if using IPC (UNIX domain socket).
var m_tb_control_port = null; // Set if not using a socket. var m_tb_control_port = null; // Set if using TCP.
var m_tb_control_host = null; // Set if not using a socket. var m_tb_control_host = null; // Set if using TCP.
var m_tb_control_pass = null; var m_tb_control_pass = null;
var m_tb_control_desc = null; // For logging. var m_tb_control_desc = null; // For logging.
...@@ -327,15 +328,15 @@ function torbutton_init() { ...@@ -327,15 +328,15 @@ function torbutton_init() {
m_tb_control_pass = tlps.TorGetPassword(false); m_tb_control_pass = tlps.TorGetPassword(false);
} catch(e) {} } catch(e) {}
// Try to get control port socket (an nsIFile) from Tor Launcher, since // Try to get the control port IPC file (an nsIFile) from Tor Launcher,
// Tor Launcher knows how to handle its own preferences and how to // since Tor Launcher knows how to handle its own preferences and how to
// resolve relative paths. // resolve relative paths.
try { try {
m_tb_control_socket_file = tlps.TorGetControlSocketFile(); m_tb_control_ipc_file = tlps.TorGetControlIPCFile();
} catch(e) {} } catch(e) {}
if (m_tb_control_socket_file) { if (m_tb_control_ipc_file) {
m_tb_control_desc = m_tb_control_socket_file.path; m_tb_control_desc = m_tb_control_ipc_file.path;
} else { } else {
if (environ.exists("TOR_CONTROL_PORT")) { if (environ.exists("TOR_CONTROL_PORT")) {
m_tb_control_port = environ.get("TOR_CONTROL_PORT"); m_tb_control_port = environ.get("TOR_CONTROL_PORT");
...@@ -438,7 +439,7 @@ function torbutton_init() { ...@@ -438,7 +439,7 @@ function torbutton_init() {
torbutton_notify_if_update_needed(); torbutton_notify_if_update_needed();
torbutton_update_sync_ui(); torbutton_update_sync_ui();
createTorCircuitDisplay(m_tb_control_socket_file, m_tb_control_host, createTorCircuitDisplay(m_tb_control_ipc_file, m_tb_control_host,
m_tb_control_port, m_tb_control_pass, m_tb_control_port, m_tb_control_pass,
"extensions.torbutton.display_circuit"); "extensions.torbutton.display_circuit");
...@@ -1009,8 +1010,8 @@ function torbutton_send_ctrl_cmd(command) { ...@@ -1009,8 +1010,8 @@ function torbutton_send_ctrl_cmd(command) {
let sts = Cc["@mozilla.org/network/socket-transport-service;1"] let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService); .getService(Ci.nsISocketTransportService);
let socket; let socket;
if (m_tb_control_socket_file) { if (m_tb_control_ipc_file) {
socket = sts.createUnixDomainTransport(m_tb_control_socket_file); socket = sts.createUnixDomainTransport(m_tb_control_ipc_file);
} else { } else {
socket = sts.createTransport(null, 0, m_tb_control_host, socket = sts.createTransport(null, 0, m_tb_control_host,
m_tb_control_port, null); m_tb_control_port, null);
...@@ -1350,7 +1351,7 @@ function torbutton_do_new_identity() { ...@@ -1350,7 +1351,7 @@ function torbutton_do_new_identity() {
torbutton_log(3, "New Identity: Sending NEWNYM"); torbutton_log(3, "New Identity: Sending NEWNYM");
// We only support TBB for newnym. // We only support TBB for newnym.
if (!m_tb_control_pass || (!m_tb_control_socket_file && !m_tb_control_port)) { if (!m_tb_control_pass || (!m_tb_control_ipc_file && !m_tb_control_port)) {
var warning = torbutton_get_property_string("torbutton.popup.no_newnym"); var warning = torbutton_get_property_string("torbutton.popup.no_newnym");
torbutton_log(5, "Torbutton cannot safely newnym. It does not have access to the Tor Control Port."); torbutton_log(5, "Torbutton cannot safely newnym. It does not have access to the Tor Control Port.");
window.alert(warning); window.alert(warning);
...@@ -1508,7 +1509,7 @@ function torbutton_do_tor_check() ...@@ -1508,7 +1509,7 @@ function torbutton_do_tor_check()
const kEnvUseTransparentProxy = "TOR_TRANSPROXY"; const kEnvUseTransparentProxy = "TOR_TRANSPROXY";
var env = Cc["@mozilla.org/process/environment;1"] var env = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment); .getService(Ci.nsIEnvironment);
if ((m_tb_control_socket_file || m_tb_control_port) && if ((m_tb_control_ipc_file || m_tb_control_port) &&
!env.exists(kEnvUseTransparentProxy) && !env.exists(kEnvUseTransparentProxy) &&
!env.exists(kEnvSkipControlPortTest) && !env.exists(kEnvSkipControlPortTest) &&
m_tb_prefs.getBoolPref("extensions.torbutton.local_tor_check")) { m_tb_prefs.getBoolPref("extensions.torbutton.local_tor_check")) {
...@@ -1559,19 +1560,20 @@ function torbutton_local_tor_check() ...@@ -1559,19 +1560,20 @@ function torbutton_local_tor_check()
} }
// Sample response: net/listeners/socks="127.0.0.1:9149" "127.0.0.1:9150" // Sample response: net/listeners/socks="127.0.0.1:9149" "127.0.0.1:9150"
// First, check for command argument prefix. // First, check for and remove the command argument prefix.
if (0 != resp.indexOf(kCmdArg + '=')) { if (0 != resp.indexOf(kCmdArg + '=')) {
logUnexpectedResponse(); logUnexpectedResponse();
return false; return false;
} }
resp = resp.substr(kCmdArg.length + 1);
// Retrieve configured proxy settings and check each listener against them. // Retrieve configured proxy settings and check each listener against them.
// When a Unix domain socket is configured, a file URL should be present in // When the SOCKS prefs are set to use IPC (e.g., a Unix domain socket), a
// network.proxy.socks. // file URL should be present in network.proxy.socks.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1211567 // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1211567
let socksAddr = m_tb_prefs.getCharPref("network.proxy.socks"); let socksAddr = m_tb_prefs.getCharPref("network.proxy.socks");
let socksPort = m_tb_prefs.getIntPref("network.proxy.socks_port"); let socksPort = m_tb_prefs.getIntPref("network.proxy.socks_port");
let socketPath; let socksIPCPath;
if (socksAddr && socksAddr.startsWith("file:")) { if (socksAddr && socksAddr.startsWith("file:")) {
// Convert the file URL to a file path. // Convert the file URL to a file path.
try { try {
...@@ -1579,19 +1581,29 @@ function torbutton_local_tor_check() ...@@ -1579,19 +1581,29 @@ function torbutton_local_tor_check()
.getService(Ci.nsIIOService); .getService(Ci.nsIIOService);
let fph = ioService.getProtocolHandler("file") let fph = ioService.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler); .QueryInterface(Ci.nsIFileProtocolHandler);
socketPath = fph.getFileFromURLSpec(socksAddr).path; socksIPCPath = fph.getFileFromURLSpec(socksAddr).path;
} catch (e) { } catch (e) {
torbutton_log(5, "Local Tor check: Unix domain socket error: " + e); torbutton_log(5, "Local Tor check: IPC file error: " + e);
return false; return false;
} }
} else { } else {
socksAddr = removeBrackets(socksAddr); socksAddr = removeBrackets(socksAddr);
} }
let addrArray = resp.substr(kCmdArg.length + 1).split(' '); // Split into quoted strings. This code is adapted from utils.splitAtSpaces()
// within tor-control-port.js; someday this code should use the entire
// tor-control-port.js framework.
let addrArray = [];
resp.replace(/((\S*?"(.*?)")+\S*|\S+)/g, function (a, captured) {
addrArray.push(captured);
});
let foundSocksListener = false; let foundSocksListener = false;
for (let i = 0; !foundSocksListener && (i < addrArray.length); ++i) { for (let i = 0; !foundSocksListener && (i < addrArray.length); ++i) {
let addr = addrArray[i]; let addr;
try { addr = unescapeTorString(addrArray[i]); } catch (e) {}
if (!addr)
continue;
// Remove double quotes if present. // Remove double quotes if present.
let len = addr.length; let len = addr.length;
...@@ -1599,14 +1611,14 @@ function torbutton_local_tor_check() ...@@ -1599,14 +1611,14 @@ function torbutton_local_tor_check()
addr = addr.substring(1, len - 1); addr = addr.substring(1, len - 1);
if (addr.startsWith("unix:")) { if (addr.startsWith("unix:")) {
if (!socketPath) if (!socksIPCPath)
continue; continue;
// Check against the configured UNIX domain socket proxy. // Check against the configured UNIX domain socket proxy.
let path = addr.substring(5); let path = addr.substring(5);
torbutton_log(2, "Tor socks listener (socket): " + path); torbutton_log(2, "Tor socks listener (Unix domain socket): " + path);
foundSocksListener = (socketPath === path); foundSocksListener = (socksIPCPath === path);
} else if (!socketPath) { } else if (!socksIPCPath) {
// Check against the configured TCP proxy. We expect addr:port where addr // Check against the configured TCP proxy. We expect addr:port where addr
// may be an IPv6 address; that is, it may contain colon characters. // may be an IPv6 address; that is, it may contain colon characters.
// Also, we remove enclosing square brackets before comparing addresses // Also, we remove enclosing square brackets before comparing addresses
...@@ -2088,7 +2100,7 @@ function torbutton_check_protections() ...@@ -2088,7 +2100,7 @@ function torbutton_check_protections()
// See https://trac.torproject.org/projects/tor/ticket/10353 for more info. // See https://trac.torproject.org/projects/tor/ticket/10353 for more info.
document.getElementById("torbutton-cookie-protector").hidden = m_tb_prefs.getBoolPref("browser.privatebrowsing.autostart"); document.getElementById("torbutton-cookie-protector").hidden = m_tb_prefs.getBoolPref("browser.privatebrowsing.autostart");
if (!m_tb_control_pass || (!m_tb_control_socket_file && !m_tb_control_port)) { if (!m_tb_control_pass || (!m_tb_control_ipc_file && !m_tb_control_port)) {
document.getElementById("torbutton-new-identity").disabled = true; document.getElementById("torbutton-new-identity").disabled = true;
} }
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cr = Components.results; const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
// Module specific constants // Module specific constants
const kMODULE_NAME = "Startup"; const kMODULE_NAME = "Startup";
...@@ -22,10 +29,9 @@ const kMODULE_CONTRACTID = "@torproject.org/startup-observer;1"; ...@@ -22,10 +29,9 @@ const kMODULE_CONTRACTID = "@torproject.org/startup-observer;1";
const kMODULE_CID = Components.ID("06322def-6fde-4c06-aef6-47ae8e799629"); const kMODULE_CID = Components.ID("06322def-6fde-4c06-aef6-47ae8e799629");
function StartupObserver() { function StartupObserver() {
this.logger = Components.classes["@torproject.org/torbutton-logger;1"] this.logger = Cc["@torproject.org/torbutton-logger;1"]
.getService(Components.interfaces.nsISupports).wrappedJSObject; .getService(Ci.nsISupports).wrappedJSObject;
this._prefs = Components.classes["@mozilla.org/preferences-service;1"] this._prefs = Services.prefs;
.getService(Components.interfaces.nsIPrefBranch);
this.logger.log(3, "Startup Observer created"); this.logger.log(3, "Startup Observer created");
var env = Cc["@mozilla.org/process/environment;1"] var env = Cc["@mozilla.org/process/environment;1"]
...@@ -61,41 +67,74 @@ StartupObserver.prototype = { ...@@ -61,41 +67,74 @@ StartupObserver.prototype = {
// some weird proxy caching code that showed up in FF15. // some weird proxy caching code that showed up in FF15.
// Otherwise, homepage domain loads fail forever. // Otherwise, homepage domain loads fail forever.
setProxySettings: function() { setProxySettings: function() {
if (!this.is_tbb)
return;
// Bug 1506: Still want to get these env vars // Bug 1506: Still want to get these env vars
var environ = Components.classes["@mozilla.org/process/environment;1"] let environ = Cc["@mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment); .getService(Ci.nsIEnvironment);
if (environ.exists("TOR_TRANSPROXY")) {
if (environ.exists("TOR_SOCKS_PORT")) { this.logger.log(3, "Resetting Tor settings to transproxy");
if (this.is_tbb) { this._prefs.setBoolPref("network.proxy.socks_remote_dns", false);
this._prefs.setIntPref('network.proxy.socks_port', this._prefs.setIntPref("network.proxy.type", 0);
parseInt(environ.get("TOR_SOCKS_PORT"))); this._prefs.setIntPref("network.proxy.socks_port", 0);
this._prefs.setBoolPref('network.proxy.socks_remote_dns', true); this._prefs.setCharPref("network.proxy.socks", "");
this._prefs.setIntPref('network.proxy.type', 1); } else {
// Try to retrieve SOCKS proxy settings from Tor Launcher.
let socksPortInfo;
try {
let tlps = Cc["@torproject.org/torlauncher-protocol-service;1"]
.getService(Ci.nsISupports).wrappedJSObject;
socksPortInfo = tlps.TorGetSOCKSPortInfo();
} catch(e) {}
// If Tor Launcher is not available, check environment variables.
if (!socksPortInfo) {
socksPortInfo = { ipcFile: undefined, host: undefined, port: 0 };
let isWindows = Services.appinfo.OS === "WINNT";
if (!isWindows && environ.exists("TOR_SOCKS_IPC_PATH")) {
socksPortInfo.ipcFile = new FileUtils.File(
environ.get("TOR_SOCKS_IPC_PATH"));
}
else
{
if (environ.exists("TOR_SOCKS_HOST"))
socksPortInfo.host = environ.get("TOR_SOCKS_HOST");
if (environ.exists("TOR_SOCKS_PORT"))
socksPortInfo.port = parseInt(environ.get("TOR_SOCKS_PORT"));
}
} }
this.logger.log(3, "Reset socks port to "+environ.get("TOR_SOCKS_PORT"));
}
if (environ.exists("TOR_SOCKS_HOST")) { // Adjust network.proxy prefs.
if (this.is_tbb) { if (socksPortInfo.ipcFile) {
this._prefs.setCharPref('network.proxy.socks', environ.get("TOR_SOCKS_HOST")); let fph = Services.io.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
let fileURI = fph.newFileURI(socksPortInfo.ipcFile);
this.logger.log(3, "Reset socks to "+fileURI.spec);
this._prefs.setCharPref("network.proxy.socks", fileURI.spec);
this._prefs.setIntPref("network.proxy.socks_port", 0);
} else {
if (socksPortInfo.host) {
this._prefs.setCharPref("network.proxy.socks", socksPortInfo.host);
this.logger.log(3, "Reset socks host to "+socksPortInfo.host);
}
if (socksPortInfo.port) {
this._prefs.setIntPref("network.proxy.socks_port",
socksPortInfo.port);
this.logger.log(3, "Reset socks port to "+socksPortInfo.port);
}
} }
}
if (environ.exists("TOR_TRANSPROXY")) { if (socksPortInfo.ipcFile || socksPortInfo.host || socksPortInfo.port) {
this.logger.log(3, "Resetting Tor settings to transproxy"); this._prefs.setBoolPref("network.proxy.socks_remote_dns", true);
if (this.is_tbb) { this._prefs.setIntPref("network.proxy.type", 1);
this._prefs.setBoolPref('network.proxy.socks_remote_dns', false);
this._prefs.setIntPref('network.proxy.type', 0);
this._prefs.setIntPref('network.proxy.socks_port', 0);
this._prefs.setCharPref('network.proxy.socks', "");
} }
} }
// Force prefs to be synced to disk // Force prefs to be synced to disk
var prefService = Components.classes["@mozilla.org/preferences-service;1"] this._prefs.savePrefFile(null);
.getService(Components.interfaces.nsIPrefService);
prefService.savePrefFile(null);
this.logger.log(3, "Synced network settings to environment."); this.logger.log(3, "Synced network settings to environment.");
}, },
...@@ -109,16 +148,14 @@ StartupObserver.prototype = { ...@@ -109,16 +148,14 @@ StartupObserver.prototype = {
} }
// In all cases, force prefs to be synced to disk // In all cases, force prefs to be synced to disk
var prefService = Components.classes["@mozilla.org/preferences-service;1"] this._prefs.savePrefFile(null);
.getService(Components.interfaces.nsIPrefService);
prefService.savePrefFile(null);
}, },
QueryInterface: function(iid) { QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsISupports)) { if (iid.equals(Ci.nsISupports)) {
return this; return this;
} }
if(iid.equals(Components.interfaces.nsIClassInfo)) { if(iid.equals(Ci.nsIClassInfo)) {
return this; return this;
} }
return this; return this;
...@@ -141,12 +178,4 @@ StartupObserver.prototype = { ...@@ -141,12 +178,4 @@ StartupObserver.prototype = {
}; };
/** var NSGetFactory = XPCOMUtils.generateNSGetFactory([StartupObserver]);
* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
*/
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
if (XPCOMUtils.generateNSGetFactory)
var NSGetFactory = XPCOMUtils.generateNSGetFactory([StartupObserver]);
else
var NSGetModule = XPCOMUtils.generateNSGetModule([StartupObserver]);
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// let { controller } = Components.utils.import("path/to/tor-control-port.js"); // let { controller } = Components.utils.import("path/to/tor-control-port.js");
// //
// See the last function defined in this file: // See the last function defined in this file:
// controller(socketFile, host, port, password, onError) // controller(ipcFile, host, port, password, onError)
// for usage of the controller function. // for usage of the controller function.
/* jshint esnext: true */ /* jshint esnext: true */
...@@ -42,18 +42,18 @@ log("Loading tor-control-port.js\n"); ...@@ -42,18 +42,18 @@ log("Loading tor-control-port.js\n");
// I/O utilities namespace // I/O utilities namespace
let io = {}; let io = {};
// __io.asyncSocketStreams(socketFile, host, port)__. // __io.asyncSocketStreams(ipcFile, host, port)__.
// Creates a pair of asynchronous input and output streams for a socket at the // Creates a pair of asynchronous input and output streams for a socket at the
// given socketFile or host and port. // given ipcFile or host and port.
io.asyncSocketStreams = function (socketFile, host, port) { io.asyncSocketStreams = function (ipcFile, host, port) {
let sts = Cc["@mozilla.org/network/socket-transport-service;1"] let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Components.interfaces.nsISocketTransportService), .getService(Components.interfaces.nsISocketTransportService),
UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED; UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED;
// Create an instance of a socket transport. // Create an instance of a socket transport.
let socketTransport; let socketTransport;
if (socketFile) { if (ipcFile) {
socketTransport = sts.createUnixDomainTransport(socketFile); socketTransport = sts.createUnixDomainTransport(ipcFile);
} else { } else {
socketTransport = sts.createTransport(null, 0, host, port, null); socketTransport = sts.createTransport(null, 0, host, port, null);
} }
...@@ -99,16 +99,15 @@ io.pumpInputStream = function (inputStream, onInputData, onError) { ...@@ -99,16 +99,15 @@ io.pumpInputStream = function (inputStream, onInputData, onError) {
} }, null); } }, null);
}; };
// __io.asyncSocket(socketFile, host, port, onInputData, onError)__. // __io.asyncSocket(ipcFile, host, port, onInputData, onError)__.
// Creates an asynchronous, text-oriented UNIX domain socket (if socketFile // Creates an asynchronous, text-oriented IPC socket (if ipcFile is defined)
// is defined) or TCP socket at host:port. // or a TCP socket at host:port.
// The onInputData callback should accept a single argument, which will be called // The onInputData callback should accept a single argument, which will be called
// repeatedly, whenever incoming text arrives. Returns a socket object with two methods: // repeatedly, whenever incoming text arrives. Returns a socket object with two methods:
// socket.write(text) and socket.close(). onError will be passed the error object // socket.write(text) and socket.close(). onError will be passed the error object
// whenever a write fails. // whenever a write fails.
io.asyncSocket = function (socketFile, host, port, onInputData, onError) { io.asyncSocket = function (ipcFile, host, port, onInputData, onError) {
let [inputStream, outputStream] = io.asyncSocketStreams(socketFile, host, let [inputStream, outputStream] = io.asyncSocketStreams(ipcFile, host, port),
port),
pendingWrites = []; pendingWrites = [];
// Run an input stream pump to send incoming data to the onInputData callback. // Run an input stream pump to send incoming data to the onInputData callback.
io.pumpInputStream(inputStream, onInputData, onError); io.pumpInputStream(inputStream, onInputData, onError);
...@@ -253,8 +252,8 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) { ...@@ -253,8 +252,8 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) {
}); });
}; };
// __io.controlSocket(socketFile, host, port, password, onError)__. // __io.controlSocket(ipcFile, host, port, password, onError)__.
// Instantiates and returns a socket to a tor ControlPort at socketFile or // Instantiates and returns a socket to a tor ControlPort at ipcFile or
// host:port, authenticating with the given password. onError is called with an // host:port, authenticating with the given password. onError is called with an
// error object as its single argument whenever an error occurs. Example: // error object as its single argument whenever an error occurs. Example:
// //
...@@ -269,11 +268,11 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) { ...@@ -269,11 +268,11 @@ io.matchRepliesToCommands = function (asyncSend, dispatcher) {
// socket.removeNotificationCallback(callback); // socket.removeNotificationCallback(callback);
// // Close the socket permanently // // Close the socket permanently
// socket.close(); // socket.close();
io.controlSocket = function (socketFile, host, port, password, onError) { io.controlSocket = function (ipcFile, host, port, password, onError) {
// Produce a callback dispatcher for Tor messages. // Produce a callback dispatcher for Tor messages.
let mainDispatcher = io.callbackDispatcher(), let mainDispatcher = io.callbackDispatcher(),
// Open the socket and convert format to Tor messages. // Open the socket and convert format to Tor messages.
socket = io.asyncSocket(socketFile, host, port, socket = io.asyncSocket(ipcFile, host, port,
io.onDataFromOnLine( io.onDataFromOnLine(
io.onLineFromOnMessage(mainDispatcher.pushMessage)), io.onLineFromOnMessage(mainDispatcher.pushMessage)),
onError),