summaryrefslogtreecommitdiffstats
path: root/dom/wifi/WifiNetUtil.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/wifi/WifiNetUtil.jsm')
-rw-r--r--dom/wifi/WifiNetUtil.jsm154
1 files changed, 154 insertions, 0 deletions
diff --git a/dom/wifi/WifiNetUtil.jsm b/dom/wifi/WifiNetUtil.jsm
new file mode 100644
index 000000000..2a1866515
--- /dev/null
+++ b/dom/wifi/WifiNetUtil.jsm
@@ -0,0 +1,154 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* 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/systemlibs.js");
+
+XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
+ "@mozilla.org/network/service;1",
+ "nsINetworkService");
+
+this.EXPORTED_SYMBOLS = ["WifiNetUtil"];
+
+const DHCP_PROP = "init.svc.dhcpcd";
+const DHCP = "dhcpcd";
+const DEBUG = false;
+
+this.WifiNetUtil = function(controlMessage) {
+ function debug(msg) {
+ if (DEBUG) {
+ dump('-------------- NetUtil: ' + msg);
+ }
+ }
+
+ var util = {};
+
+ util.runDhcp = function (ifname, gen, callback) {
+ util.stopDhcp(ifname, function() {
+ gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) {
+ util.runIpConfig(ifname, dhcpInfo, function(data) {
+ callback(data, gen);
+ });
+ });
+ });
+ };
+
+ util.stopDhcp = function (ifname, callback) {
+ // This function does exactly what dhcp_stop does. Unforunately, if we call
+ // this function twice before the previous callback is returned. We may block
+ // our self waiting for the callback. It slows down the wifi startup procedure.
+ // Therefore, we have to roll our own version here.
+ let dhcpService = DHCP_PROP + "_" + ifname;
+ let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname;
+ let processName = DHCP + "_" + suffix;
+
+ // The implementation of |dhcp_do_request| would wait until the
+ // |result_prop_name| (e.g. dhcp.wlan0.result) to be non-null
+ // or 30 second timeout. So we manually change the result property
+ // to 'ko' to avoid timeout.
+ //
+ // http://androidxref.com/4.4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#234
+ setProperty('dhcp.' + suffix + '.result', 'ko', function() {
+ stopProcess(dhcpService, processName, callback);
+ });
+ };
+
+ util.startDhcpServer = function (config, callback) {
+ gNetworkService.setDhcpServer(true, config, function (error) {
+ callback(!error);
+ });
+ };
+
+ util.stopDhcpServer = function (callback) {
+ gNetworkService.setDhcpServer(false, null, function (error) {
+ callback(!error);
+ });
+ };
+
+ util.runIpConfig = function (name, data, callback) {
+ if (!data) {
+ debug("IP config failed to run");
+ callback({ info: data });
+ return;
+ }
+
+ setProperty("net." + name + ".dns1", ipToString(data.dns1),
+ function(ok) {
+ if (!ok) {
+ debug("Unable to set net.<ifname>.dns1");
+ return;
+ }
+ setProperty("net." + name + ".dns2", ipToString(data.dns2),
+ function(ok) {
+ if (!ok) {
+ debug("Unable to set net.<ifname>.dns2");
+ return;
+ }
+ setProperty("net." + name + ".gw", ipToString(data.gateway),
+ function(ok) {
+ if (!ok) {
+ debug("Unable to set net.<ifname>.gw");
+ return;
+ }
+ callback({ info: data });
+ });
+ });
+ });
+ };
+
+ //--------------------------------------------------
+ // Helper functions.
+ //--------------------------------------------------
+
+ function stopProcess(service, process, callback) {
+ var count = 0;
+ var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ function tick() {
+ let result = libcutils.property_get(service);
+ if (result === null) {
+ callback();
+ return;
+ }
+ if (result === "stopped" || ++count >= 5) {
+ // Either we succeeded or ran out of time.
+ timer = null;
+ callback();
+ return;
+ }
+
+ // Else it's still running, continue waiting.
+ timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
+ }
+
+ setProperty("ctl.stop", process, tick);
+ }
+
+ // Wrapper around libcutils.property_set that returns true if setting the
+ // value was successful.
+ // Note that the callback is not called asynchronously.
+ function setProperty(key, value, callback) {
+ let ok = true;
+ try {
+ libcutils.property_set(key, value);
+ } catch(e) {
+ ok = false;
+ }
+ callback(ok);
+ }
+
+ function ipToString(n) {
+ return String((n >> 0) & 0xFF) + "." +
+ ((n >> 8) & 0xFF) + "." +
+ ((n >> 16) & 0xFF) + "." +
+ ((n >> 24) & 0xFF);
+ }
+
+ return util;
+};