gecko/dom/wifi/WifiNetUtil.jsm

155 lines
4.6 KiB
JavaScript

/* -*- 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;
};