2013-11-15 13:35:33 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2014-01-16 05:57:26 +04:00
|
|
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
|
|
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
2014-08-06 09:51:00 +04:00
|
|
|
Cu.import("resource://gre/modules/Promise.jsm");
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
|
2014-07-10 09:29:47 +04:00
|
|
|
const NETWORKSERVICE_CID = Components.ID("{baec696c-c78d-42db-8b44-603f8fbfafb4}");
|
2013-11-15 13:35:33 +04:00
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
const TOPIC_PREF_CHANGED = "nsPref:changed";
|
|
|
|
const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown";
|
|
|
|
const PREF_NETWORK_DEBUG_ENABLED = "network.debugging.enabled";
|
|
|
|
|
2014-01-29 15:38:50 +04:00
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
|
|
|
|
"@mozilla.org/network/worker;1",
|
|
|
|
"nsINetworkWorker");
|
|
|
|
|
2013-11-15 13:35:33 +04:00
|
|
|
// 1xx - Requested action is proceeding
|
|
|
|
const NETD_COMMAND_PROCEEDING = 100;
|
|
|
|
// 2xx - Requested action has been successfully completed
|
|
|
|
const NETD_COMMAND_OKAY = 200;
|
|
|
|
// 4xx - The command is accepted but the requested action didn't
|
|
|
|
// take place.
|
|
|
|
const NETD_COMMAND_FAIL = 400;
|
|
|
|
// 5xx - The command syntax or parameters error
|
|
|
|
const NETD_COMMAND_ERROR = 500;
|
|
|
|
// 6xx - Unsolicited broadcasts
|
|
|
|
const NETD_COMMAND_UNSOLICITED = 600;
|
|
|
|
|
|
|
|
const WIFI_CTRL_INTERFACE = "wl0.1";
|
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
let debug;
|
|
|
|
function updateDebug() {
|
|
|
|
let debugPref = false; // set default value here.
|
|
|
|
try {
|
|
|
|
debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
|
|
|
|
} catch (e) {}
|
2014-04-09 10:10:04 +04:00
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
if (debugPref) {
|
|
|
|
debug = function(s) {
|
|
|
|
dump("-*- NetworkService: " + s + "\n");
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
debug = function(s) {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
updateDebug();
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
function netdResponseType(code) {
|
|
|
|
return Math.floor(code / 100) * 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isError(code) {
|
|
|
|
let type = netdResponseType(code);
|
|
|
|
return (type !== NETD_COMMAND_PROCEEDING && type !== NETD_COMMAND_OKAY);
|
|
|
|
}
|
|
|
|
|
2015-02-11 11:01:08 +03:00
|
|
|
function Task(id, params, setupFunction) {
|
|
|
|
this.id = id;
|
|
|
|
this.params = params;
|
|
|
|
this.setupFunction = setupFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
function NetworkWorkerRequestQueue(networkService) {
|
|
|
|
this.networkService = networkService;
|
|
|
|
this.tasks = [];
|
|
|
|
}
|
|
|
|
NetworkWorkerRequestQueue.prototype = {
|
|
|
|
runQueue: function() {
|
|
|
|
if (this.tasks.length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let task = this.tasks[0];
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("run task id: " + task.id);
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
if (typeof task.setupFunction === 'function') {
|
|
|
|
// If setupFunction returns false, skip sending to Network Worker but call
|
|
|
|
// handleWorkerMessage() directly with task id, as if the response was
|
|
|
|
// returned from Network Worker.
|
|
|
|
if (!task.setupFunction()) {
|
|
|
|
this.networkService.handleWorkerMessage({id: task.id});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gNetworkWorker.postMessage(task.params);
|
|
|
|
},
|
|
|
|
|
|
|
|
enqueue: function(id, params, setupFunction) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("enqueue id: " + id);
|
2015-02-11 11:01:08 +03:00
|
|
|
this.tasks.push(new Task(id, params, setupFunction));
|
|
|
|
|
|
|
|
if (this.tasks.length === 1) {
|
|
|
|
this.runQueue();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
dequeue: function(id) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("dequeue id: " + id);
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
if (!this.tasks.length || this.tasks[0].id != id) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Id " + id + " is not on top of the queue");
|
2015-02-11 11:01:08 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.tasks.shift();
|
|
|
|
if (this.tasks.length > 0) {
|
|
|
|
// Run queue on the next tick.
|
|
|
|
Services.tm.currentThread.dispatch(() => {
|
|
|
|
this.runQueue();
|
|
|
|
}, Ci.nsIThread.DISPATCH_NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-15 13:35:33 +04:00
|
|
|
/**
|
|
|
|
* This component watches for network interfaces changing state and then
|
|
|
|
* adjusts routes etc. accordingly.
|
|
|
|
*/
|
|
|
|
function NetworkService() {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Starting net_worker.");
|
2013-11-15 13:35:33 +04:00
|
|
|
|
2014-01-29 15:38:50 +04:00
|
|
|
let self = this;
|
|
|
|
|
|
|
|
if (gNetworkWorker) {
|
|
|
|
let networkListener = {
|
|
|
|
onEvent: function(event) {
|
|
|
|
self.handleWorkerMessage(event);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
gNetworkWorker.start(networkListener);
|
|
|
|
}
|
2013-11-15 13:35:33 +04:00
|
|
|
// Callbacks to invoke when a reply arrives from the net_worker.
|
|
|
|
this.controlCallbacks = Object.create(null);
|
2014-01-29 15:38:50 +04:00
|
|
|
|
2015-02-11 11:01:08 +03:00
|
|
|
this.addedRoutes = new Map();
|
|
|
|
this.netWorkerRequestQueue = new NetworkWorkerRequestQueue(this);
|
2014-01-29 15:38:50 +04:00
|
|
|
this.shutdown = false;
|
2015-03-18 12:38:20 +03:00
|
|
|
|
|
|
|
Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
|
|
|
|
Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
|
2013-11-15 13:35:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NetworkService.prototype = {
|
|
|
|
classID: NETWORKSERVICE_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({classID: NETWORKSERVICE_CID,
|
|
|
|
contractID: NETWORKSERVICE_CONTRACTID,
|
|
|
|
classDescription: "Network Service",
|
|
|
|
interfaces: [Ci.nsINetworkService]}),
|
2015-03-18 12:38:20 +03:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService,
|
|
|
|
Ci.nsIObserver]),
|
|
|
|
|
|
|
|
addedRoutes: null,
|
|
|
|
|
|
|
|
shutdown: false,
|
|
|
|
|
|
|
|
// nsIObserver
|
|
|
|
|
|
|
|
observe: function(subject, topic, data) {
|
|
|
|
switch (topic) {
|
|
|
|
case TOPIC_PREF_CHANGED:
|
|
|
|
if (data === PREF_NETWORK_DEBUG_ENABLED) {
|
|
|
|
updateDebug();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TOPIC_XPCOM_SHUTDOWN:
|
|
|
|
debug("NetworkService shutdown");
|
|
|
|
this.shutdown = true;
|
|
|
|
if (gNetworkWorker) {
|
|
|
|
gNetworkWorker.shutdown();
|
|
|
|
gNetworkWorker = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
|
|
|
|
Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
// Helpers
|
|
|
|
|
|
|
|
idgen: 0,
|
2015-02-11 11:01:08 +03:00
|
|
|
controlMessage: function(params, callback, setupFunction) {
|
2014-01-29 15:38:50 +04:00
|
|
|
if (this.shutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-02-11 11:01:08 +03:00
|
|
|
let id = this.idgen++;
|
|
|
|
params.id = id;
|
2013-11-15 13:35:33 +04:00
|
|
|
if (callback) {
|
|
|
|
this.controlCallbacks[id] = callback;
|
|
|
|
}
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
// For now, we use setupFunction to determine if this command needs to be
|
|
|
|
// queued or not.
|
|
|
|
if (setupFunction) {
|
|
|
|
this.netWorkerRequestQueue.enqueue(id, params, setupFunction);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-29 15:38:50 +04:00
|
|
|
if (gNetworkWorker) {
|
|
|
|
gNetworkWorker.postMessage(params);
|
|
|
|
}
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-01-29 15:38:50 +04:00
|
|
|
handleWorkerMessage: function(response) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("NetworkManager received message from worker: " + JSON.stringify(response));
|
2013-11-15 13:35:33 +04:00
|
|
|
let id = response.id;
|
2014-01-29 15:38:50 +04:00
|
|
|
if (response.broadcast === true) {
|
2013-11-15 13:35:33 +04:00
|
|
|
Services.obs.notifyObservers(null, response.topic, response.reason);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let callback = this.controlCallbacks[id];
|
|
|
|
if (callback) {
|
|
|
|
callback.call(this, response);
|
|
|
|
delete this.controlCallbacks[id];
|
|
|
|
}
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
this.netWorkerRequestQueue.dequeue(id);
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
// nsINetworkService
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
getNetworkInterfaceStats: function(networkName, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("getNetworkInterfaceStats for " + networkName);
|
2014-01-08 21:10:21 +04:00
|
|
|
|
2014-01-29 15:38:50 +04:00
|
|
|
let file = new FileUtils.File("/proc/net/dev");
|
2014-01-16 05:57:26 +04:00
|
|
|
if (!file) {
|
2014-08-01 11:08:41 +04:00
|
|
|
callback.networkStatsAvailable(false, 0, 0, Date.now());
|
2014-01-16 05:57:26 +04:00
|
|
|
return;
|
|
|
|
}
|
2014-01-08 21:10:21 +04:00
|
|
|
|
2015-02-05 23:53:14 +03:00
|
|
|
NetUtil.asyncFetch2(file, function(inputStream, status) {
|
2014-08-01 11:08:41 +04:00
|
|
|
let rxBytes = 0,
|
|
|
|
txBytes = 0,
|
|
|
|
now = Date.now();
|
2014-01-16 05:57:26 +04:00
|
|
|
|
|
|
|
if (Components.isSuccessCode(status)) {
|
|
|
|
// Find record for corresponding interface.
|
2014-01-19 13:03:24 +04:00
|
|
|
let statExpr = /(\S+): +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+/;
|
2014-08-01 11:08:41 +04:00
|
|
|
let data =
|
|
|
|
NetUtil.readInputStreamToString(inputStream, inputStream.available())
|
|
|
|
.split("\n");
|
2014-01-16 05:57:26 +04:00
|
|
|
for (let i = 2; i < data.length; i++) {
|
|
|
|
let parseResult = statExpr.exec(data[i]);
|
|
|
|
if (parseResult && parseResult[1] === networkName) {
|
2014-08-01 11:08:41 +04:00
|
|
|
rxBytes = parseInt(parseResult[2], 10);
|
|
|
|
txBytes = parseInt(parseResult[3], 10);
|
2014-01-16 05:57:26 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 11:08:41 +04:00
|
|
|
// netd always return success even interface doesn't exist.
|
|
|
|
callback.networkStatsAvailable(true, rxBytes, txBytes, now);
|
2015-02-05 23:53:14 +03:00
|
|
|
},
|
|
|
|
null, // aLoadingNode
|
|
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
|
|
null, // aTriggeringPrincipal
|
|
|
|
Ci.nsILoadInfo.SEC_NORMAL,
|
|
|
|
Ci.nsIContentPolicy.TYPE_OTHER);
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
setNetworkInterfaceAlarm: function(networkName, threshold, callback) {
|
2013-05-24 13:28:20 +04:00
|
|
|
if (!networkName) {
|
|
|
|
callback.networkUsageAlarmResult(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-10 12:03:29 +04:00
|
|
|
let self = this;
|
|
|
|
this._disableNetworkInterfaceAlarm(networkName, function(result) {
|
|
|
|
if (threshold < 0) {
|
|
|
|
if (!isError(result.resultCode)) {
|
|
|
|
callback.networkUsageAlarmResult(null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
callback.networkUsageAlarmResult(result.reason);
|
|
|
|
return
|
|
|
|
}
|
2013-05-24 13:28:20 +04:00
|
|
|
|
2014-02-10 12:03:29 +04:00
|
|
|
self._setNetworkInterfaceAlarm(networkName, threshold, callback);
|
|
|
|
});
|
2013-05-24 13:28:20 +04:00
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
_setNetworkInterfaceAlarm: function(networkName, threshold, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
|
2013-05-24 13:28:20 +04:00
|
|
|
|
|
|
|
let params = {
|
|
|
|
cmd: "setNetworkInterfaceAlarm",
|
|
|
|
ifname: networkName,
|
|
|
|
threshold: threshold
|
|
|
|
};
|
|
|
|
|
|
|
|
params.report = true;
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
if (!isError(result.resultCode)) {
|
|
|
|
callback.networkUsageAlarmResult(null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._enableNetworkInterfaceAlarm(networkName, threshold, callback);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
_enableNetworkInterfaceAlarm: function(networkName, threshold, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
|
2013-05-24 13:28:20 +04:00
|
|
|
|
|
|
|
let params = {
|
|
|
|
cmd: "enableNetworkInterfaceAlarm",
|
|
|
|
ifname: networkName,
|
|
|
|
threshold: threshold
|
|
|
|
};
|
|
|
|
|
|
|
|
params.report = true;
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
if (!isError(result.resultCode)) {
|
|
|
|
callback.networkUsageAlarmResult(null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
callback.networkUsageAlarmResult(result.reason);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
_disableNetworkInterfaceAlarm: function(networkName, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("disableNetworkInterfaceAlarm for " + networkName);
|
2013-05-24 13:28:20 +04:00
|
|
|
|
|
|
|
let params = {
|
|
|
|
cmd: "disableNetworkInterfaceAlarm",
|
|
|
|
ifname: networkName,
|
|
|
|
};
|
|
|
|
|
|
|
|
params.report = true;
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
2014-02-10 12:03:29 +04:00
|
|
|
callback(result);
|
2013-05-24 13:28:20 +04:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
setWifiOperationMode: function(interfaceName, mode, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("setWifiOperationMode on " + interfaceName + " to " + mode);
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
let params = {
|
|
|
|
cmd: "setWifiOperationMode",
|
|
|
|
ifname: interfaceName,
|
|
|
|
mode: mode
|
|
|
|
};
|
|
|
|
|
|
|
|
params.report = true;
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
if (isError(result.resultCode)) {
|
|
|
|
callback.wifiOperationModeResult("netd command error");
|
|
|
|
} else {
|
|
|
|
callback.wifiOperationModeResult(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
resetRoutingTable: function(network) {
|
2015-01-09 09:45:53 +03:00
|
|
|
let options = {
|
|
|
|
cmd: "removeNetworkRoute",
|
|
|
|
ifname: network.name
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(options);
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-08-18 07:02:56 +04:00
|
|
|
setDNS: function(networkInterface, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Going DNS to " + networkInterface.name);
|
2014-03-29 11:18:18 +04:00
|
|
|
let dnses = networkInterface.getDnses();
|
2013-11-15 13:35:33 +04:00
|
|
|
let options = {
|
|
|
|
cmd: "setDNS",
|
|
|
|
ifname: networkInterface.name,
|
2014-02-20 15:04:51 +04:00
|
|
|
domain: "mozilla." + networkInterface.name + ".doman",
|
2015-04-09 14:09:37 +03:00
|
|
|
dnses: dnses,
|
|
|
|
gateways: networkInterface.getGateways()
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
2014-08-18 07:02:56 +04:00
|
|
|
this.controlMessage(options, function(result) {
|
|
|
|
callback.setDnsResult(result.success ? null : result.reason);
|
|
|
|
});
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-08-18 07:02:56 +04:00
|
|
|
setDefaultRoute: function(network, oldInterface, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Going to change default route to " + network.name);
|
2014-03-29 11:18:18 +04:00
|
|
|
let gateways = network.getGateways();
|
2013-11-15 13:35:33 +04:00
|
|
|
let options = {
|
2014-08-18 07:02:56 +04:00
|
|
|
cmd: "setDefaultRoute",
|
2013-11-15 13:35:33 +04:00
|
|
|
ifname: network.name,
|
|
|
|
oldIfname: (oldInterface && oldInterface !== network) ? oldInterface.name : null,
|
2014-08-18 07:02:56 +04:00
|
|
|
gateways: gateways
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
2014-08-18 07:02:56 +04:00
|
|
|
this.controlMessage(options, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-02-28 16:24:35 +04:00
|
|
|
removeDefaultRoute: function(network) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Remove default route for " + network.name);
|
2014-03-29 11:18:18 +04:00
|
|
|
let gateways = network.getGateways();
|
2013-11-15 13:35:33 +04:00
|
|
|
let options = {
|
|
|
|
cmd: "removeDefaultRoute",
|
2014-02-28 16:24:35 +04:00
|
|
|
ifname: network.name,
|
2014-03-29 11:18:18 +04:00
|
|
|
gateways: gateways
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
2014-03-29 11:18:18 +04:00
|
|
|
this.controlMessage(options);
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2015-02-11 11:01:08 +03:00
|
|
|
_routeToString: function(interfaceName, host, prefixLength, gateway) {
|
|
|
|
return host + "-" + prefixLength + "-" + gateway + "-" + interfaceName;
|
|
|
|
},
|
|
|
|
|
2015-01-09 09:45:53 +03:00
|
|
|
modifyRoute: function(action, interfaceName, host, prefixLength, gateway) {
|
|
|
|
let command;
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case Ci.nsINetworkService.MODIFY_ROUTE_ADD:
|
|
|
|
command = 'addHostRoute';
|
|
|
|
break;
|
|
|
|
case Ci.nsINetworkService.MODIFY_ROUTE_REMOVE:
|
|
|
|
command = 'removeHostRoute';
|
|
|
|
break;
|
|
|
|
default:
|
2015-03-18 12:38:20 +03:00
|
|
|
debug('Unknown action: ' + action);
|
2015-01-09 09:45:53 +03:00
|
|
|
return Promise.reject();
|
|
|
|
}
|
2014-08-06 09:51:00 +04:00
|
|
|
|
2015-02-11 11:01:08 +03:00
|
|
|
let route = this._routeToString(interfaceName, host, prefixLength, gateway);
|
|
|
|
let setupFunc = () => {
|
|
|
|
let count = this.addedRoutes.get(route);
|
2015-03-18 12:38:20 +03:00
|
|
|
debug(command + ": " + route + " -> " + count);
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
// Return false if there is no need to send the command to network worker.
|
|
|
|
if ((action == Ci.nsINetworkService.MODIFY_ROUTE_ADD && count) ||
|
|
|
|
(action == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE &&
|
|
|
|
(!count || count > 1))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
debug(command + " " + host + " on " + interfaceName);
|
2013-11-15 13:35:33 +04:00
|
|
|
let options = {
|
2014-08-06 09:51:00 +04:00
|
|
|
cmd: command,
|
|
|
|
ifname: interfaceName,
|
|
|
|
gateway: gateway,
|
2015-01-09 09:45:53 +03:00
|
|
|
prefixLength: prefixLength,
|
2014-08-06 09:51:00 +04:00
|
|
|
ip: host
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
2015-02-11 11:01:08 +03:00
|
|
|
|
|
|
|
return new Promise((aResolve, aReject) => {
|
|
|
|
this.controlMessage(options, (data) => {
|
|
|
|
let count = this.addedRoutes.get(route);
|
|
|
|
|
|
|
|
// Remove route from addedRoutes on success or failure.
|
|
|
|
if (action == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE) {
|
|
|
|
if (count > 1) {
|
|
|
|
this.addedRoutes.set(route, count - 1);
|
|
|
|
} else {
|
|
|
|
this.addedRoutes.delete(route);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data.error) {
|
|
|
|
aReject(data.reason);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action == Ci.nsINetworkService.MODIFY_ROUTE_ADD) {
|
|
|
|
this.addedRoutes.set(route, count ? count + 1 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
aResolve();
|
|
|
|
}, setupFunc);
|
2014-08-06 09:51:00 +04:00
|
|
|
});
|
2013-11-15 13:35:33 +04:00
|
|
|
},
|
|
|
|
|
2014-02-24 18:19:20 +04:00
|
|
|
addSecondaryRoute: function(ifname, route) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Going to add route to secondary table on " + ifname);
|
2014-02-24 18:19:20 +04:00
|
|
|
let options = {
|
|
|
|
cmd: "addSecondaryRoute",
|
|
|
|
ifname: ifname,
|
|
|
|
ip: route.ip,
|
|
|
|
prefix: route.prefix,
|
|
|
|
gateway: route.gateway
|
|
|
|
};
|
2014-03-29 11:18:18 +04:00
|
|
|
this.controlMessage(options);
|
2014-02-24 18:19:20 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
removeSecondaryRoute: function(ifname, route) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("Going to remove route from secondary table on " + ifname);
|
2014-02-24 18:19:20 +04:00
|
|
|
let options = {
|
|
|
|
cmd: "removeSecondaryRoute",
|
|
|
|
ifname: ifname,
|
|
|
|
ip: route.ip,
|
|
|
|
prefix: route.prefix,
|
|
|
|
gateway: route.gateway
|
|
|
|
};
|
2014-03-29 11:18:18 +04:00
|
|
|
this.controlMessage(options);
|
2014-02-24 18:19:20 +04:00
|
|
|
},
|
|
|
|
|
2013-11-15 13:35:33 +04:00
|
|
|
// Enable/Disable DHCP server.
|
2014-01-13 06:44:40 +04:00
|
|
|
setDhcpServer: function(enabled, config, callback) {
|
2013-11-15 13:35:33 +04:00
|
|
|
if (null === config) {
|
|
|
|
config = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
config.cmd = "setDhcpServer";
|
|
|
|
config.enabled = enabled;
|
|
|
|
|
|
|
|
this.controlMessage(config, function setDhcpServerResult(response) {
|
|
|
|
if (!response.success) {
|
|
|
|
callback.dhcpServerResult('Set DHCP server error');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
callback.dhcpServerResult(null);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// Enable/disable WiFi tethering by sending commands to netd.
|
2014-01-13 06:44:40 +04:00
|
|
|
setWifiTethering: function(enable, config, callback) {
|
2013-11-15 13:35:33 +04:00
|
|
|
// config should've already contained:
|
|
|
|
// .ifname
|
|
|
|
// .internalIfname
|
|
|
|
// .externalIfname
|
|
|
|
config.wifictrlinterfacename = WIFI_CTRL_INTERFACE;
|
|
|
|
config.cmd = "setWifiTethering";
|
|
|
|
|
|
|
|
// The callback function in controlMessage may not be fired immediately.
|
|
|
|
this.controlMessage(config, function setWifiTetheringResult(data) {
|
|
|
|
let code = data.resultCode;
|
|
|
|
let reason = data.resultReason;
|
|
|
|
let enable = data.enable;
|
|
|
|
let enableString = enable ? "Enable" : "Disable";
|
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
if (isError(code)) {
|
|
|
|
callback.wifiTetheringEnabledChange("netd command error");
|
|
|
|
} else {
|
|
|
|
callback.wifiTetheringEnabledChange(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// Enable/disable USB tethering by sending commands to netd.
|
2014-01-13 06:44:40 +04:00
|
|
|
setUSBTethering: function(enable, config, callback) {
|
2013-11-15 13:35:33 +04:00
|
|
|
config.cmd = "setUSBTethering";
|
|
|
|
// The callback function in controlMessage may not be fired immediately.
|
|
|
|
this.controlMessage(config, function setUsbTetheringResult(data) {
|
|
|
|
let code = data.resultCode;
|
|
|
|
let reason = data.resultReason;
|
|
|
|
let enable = data.enable;
|
|
|
|
let enableString = enable ? "Enable" : "Disable";
|
|
|
|
|
2015-03-18 12:38:20 +03:00
|
|
|
debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
if (isError(code)) {
|
|
|
|
callback.usbTetheringEnabledChange("netd command error");
|
|
|
|
} else {
|
|
|
|
callback.usbTetheringEnabledChange(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// Switch usb function by modifying property of persist.sys.usb.config.
|
2014-01-13 06:44:40 +04:00
|
|
|
enableUsbRndis: function(enable, callback) {
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("enableUsbRndis: " + enable);
|
2013-11-15 13:35:33 +04:00
|
|
|
|
|
|
|
let params = {
|
|
|
|
cmd: "enableUsbRndis",
|
|
|
|
enable: enable
|
|
|
|
};
|
|
|
|
// Ask net work to report the result when this value is set to true.
|
|
|
|
if (callback) {
|
|
|
|
params.report = true;
|
|
|
|
} else {
|
|
|
|
params.report = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The callback function in controlMessage may not be fired immediately.
|
|
|
|
//this._usbTetheringAction = TETHERING_STATE_ONGOING;
|
2014-01-13 06:44:33 +04:00
|
|
|
this.controlMessage(params, function(data) {
|
2013-11-15 13:35:33 +04:00
|
|
|
callback.enableUsbRndisResult(data.result, data.enable);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-01-13 06:44:40 +04:00
|
|
|
updateUpStream: function(previous, current, callback) {
|
2013-11-15 13:35:33 +04:00
|
|
|
let params = {
|
|
|
|
cmd: "updateUpStream",
|
2014-02-27 11:40:00 +04:00
|
|
|
preInternalIfname: previous.internalIfname,
|
|
|
|
preExternalIfname: previous.externalIfname,
|
|
|
|
curInternalIfname: current.internalIfname,
|
|
|
|
curExternalIfname: current.externalIfname
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
|
|
|
|
2014-01-13 06:44:33 +04:00
|
|
|
this.controlMessage(params, function(data) {
|
2013-11-15 13:35:33 +04:00
|
|
|
let code = data.resultCode;
|
|
|
|
let reason = data.resultReason;
|
2015-03-18 12:38:20 +03:00
|
|
|
debug("updateUpStream result: Code " + code + " reason " + reason);
|
2014-02-27 11:40:00 +04:00
|
|
|
callback.updateUpStreamResult(!isError(code), data.curExternalIfname);
|
2013-11-15 13:35:33 +04:00
|
|
|
});
|
|
|
|
},
|
2014-01-29 15:38:50 +04:00
|
|
|
|
2014-08-18 07:02:56 +04:00
|
|
|
configureInterface: function(config, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "configureInterface",
|
|
|
|
ifname: config.ifname,
|
|
|
|
ipaddr: config.ipaddr,
|
|
|
|
mask: config.mask,
|
|
|
|
gateway_long: config.gateway,
|
|
|
|
dns1_long: config.dns1,
|
|
|
|
dns2_long: config.dns2,
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
dhcpRequest: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "dhcpRequest",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.dhcpRequestResult(!result.error, result.error ? null : result);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
enableInterface: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "enableInterface",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
disableInterface: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "disableInterface",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
resetConnections: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "resetConnections",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2015-01-09 09:45:53 +03:00
|
|
|
createNetwork: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "createNetwork",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
destroyNetwork: function(interfaceName, callback) {
|
|
|
|
let params = {
|
|
|
|
cmd: "destroyNetwork",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlMessage(params, function(result) {
|
|
|
|
callback.nativeCommandResult(!result.error);
|
|
|
|
});
|
|
|
|
},
|
2015-04-09 14:09:37 +03:00
|
|
|
|
|
|
|
getNetId: function(interfaceName) {
|
|
|
|
let params = {
|
|
|
|
cmd: "getNetId",
|
|
|
|
ifname: interfaceName
|
|
|
|
};
|
|
|
|
|
|
|
|
return new Promise((aResolve, aReject) => {
|
|
|
|
this.controlMessage(params, result => {
|
|
|
|
if (result.error) {
|
|
|
|
aReject(result.reason);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
aResolve(result.netId);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
2013-11-15 13:35:33 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);
|