diff --git a/dom/system/b2g/Makefile.in b/dom/system/b2g/Makefile.in index 063145f758c..567c9cde55f 100644 --- a/dom/system/b2g/Makefile.in +++ b/dom/system/b2g/Makefile.in @@ -50,6 +50,7 @@ EXTRA_COMPONENTS = \ $(NULL) EXTRA_JS_MODULES = \ + net_worker.js \ ril_consts.js \ ril_worker.js \ systemlibs.js \ diff --git a/dom/system/b2g/net_worker.js b/dom/system/b2g/net_worker.js new file mode 100644 index 00000000000..61ccfd16d9e --- /dev/null +++ b/dom/system/b2g/net_worker.js @@ -0,0 +1,139 @@ +/* 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 DEBUG = true; + +importScripts("systemlibs.js"); + +/** + * Some reusable data that we pass to C. + */ +let ints = ctypes.int.array(8)(); + +/** + * Convert integer representation of an IP address to the string + * representation. + * + * @param ip + * IP address in number format. + */ +function ipToString(ip) { + return ((ip >> 0) & 0xFF) + "." + + ((ip >> 8) & 0xFF) + "." + + ((ip >> 16) & 0xFF) + "." + + ((ip >> 24) & 0xFF); +} + +/** + * Convert string representation of an IP address to the integer + * representation. + * + * @param string + * String containing the IP address. + */ +function stringToIP(string) { + let ip = 0; + let start, end = -1; + for (let i = 0; i < 4; i++) { + start = end + 1; + end = string.indexOf(".", start); + if (end == -1) { + end = string.length; + } + let num = parseInt(string.slice(start, end), 10); + if (isNaN(num)) { + return null; + } + ip |= num << (i * 8); + } + return ip; +} + +/** + * Get network interface properties from the system property table. + * + * @param ifname + * Name of the network interface. + */ +function getIFProperties(ifname) { + let gateway_str = libcutils.property_get("net." + ifname + ".gw"); + return { + ifname: ifname, + gateway: stringToIP(gateway_str), + gateway_str: gateway_str, + dns1_str: libcutils.property_get("net." + ifname + ".dns1"), + dns2_str: libcutils.property_get("net." + ifname + ".dns2"), + }; +} + +/** + * Routines accessible to the main thread. + */ + +/** + * Dispatch a message from the main thread to a function. + */ +self.onmessage = function onmessage(event) { + let message = event.data; + if (DEBUG) debug("received message: " + JSON.stringify(message)); + let ret = self[message.cmd](message); + postMessage({id: message.id, ret: ret}); +}; + +/** + * Set default route and DNS servers for given network interface. + */ +function setDefaultRouteAndDNS(options) { + if (!options.gateway || !options.dns1_str) { + options = getIFProperties(options.ifname); + } + + libnetutils.ifc_set_default_route(options.ifname, options.gateway); + libcutils.property_set("net.dns1", options.dns1_str); + libcutils.property_set("net.dns2", options.dns2_str); + + // Bump the DNS change property. + let dnschange = libcutils.property_get("net.dnschange", "0"); + libcutils.property_set("net.dnschange", (parseInt(dnschange, 10) + 1).toString()); +} + +/** + * Run DHCP and set default route and DNS servers for a given + * network interface. + */ +function runDHCPAndSetDefaultRouteAndDNS(options) { + let rv = libnetutils.dhcp_do_request(options.ifname, + ints.addressOfElement(0), + ints.addressOfElement(1), + ints.addressOfElement(2), + ints.addressOfElement(3), + ints.addressOfElement(4), + ints.addressOfElement(5), + ints.addressOfElement(6)); + let options = { + ifname: options.ifname, + ipaddr: ints[0], + mask: ints[2], + gateway: ints[1], + dns1: ints[3], + dns2: ints[4], + dhcpServer: ints[5], + dns1_str: ipToString(ints[3]), + dns2_str: ipToString(ints[4]), + dhcpLease: ints[6] + }; + + //TODO this could be race-y... by the time we've finished the DHCP request + // and are now fudging with the routes, another network interface may have + // come online that's preferred... + setDefaultRouteAndDNS(options); +} + +if (!this.debug) { + this.debug = function debug(message) { + dump("Network Worker: " + message + "\n"); + }; +} diff --git a/dom/system/b2g/systemlibs.js b/dom/system/b2g/systemlibs.js index df09d3a3f8c..b4d8f97fa9b 100644 --- a/dom/system/b2g/systemlibs.js +++ b/dom/system/b2g/systemlibs.js @@ -15,7 +15,7 @@ let libcutils = (function() { } catch(ex) { // Return a fallback option in case libcutils.so isn't present (e.g. // when building Firefox with MOZ_B2G_RIL. - dump("Could not load libcutils.so. Using fake propdb."); + dump("Could not load libcutils.so. Using fake propdb.\n"); let fake_propdb = Object.create(null); return { property_get: function fake_property_get(key, defaultValue) { @@ -77,3 +77,95 @@ let libcutils = (function() { }; })(); + + +/** + * Network-related functions from libnetutils. + */ +let libnetutils = (function () { + let library; + try { + library = ctypes.open("libnetutils.so"); + } catch(ex) { + dump("Could not load libnetutils.so!\n"); + // For now we just fake the ctypes library interfacer to return + // no-op functions when library.declare() is called. + library = { + declare: function fake_declare() { + return function fake_libnetutils_function() {}; + } + }; + } + + return { + ifc_enable: library.declare("ifc_enable", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_disable: library.declare("ifc_disable", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_add_host_route: library.declare("ifc_add_host_route", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr, + ctypes.int), + ifc_remove_host_routes: library.declare("ifc_remove_host_routes", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_set_default_route: library.declare("ifc_set_default_route", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr, + ctypes.int), + ifc_get_default_route: library.declare("ifc_get_default_route", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_remove_default_route: library.declare("ifc_remove_default_route", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_reset_connections: library.declare("ifc_reset_connections", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + ifc_configure: library.declare("ifc_configure", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr, + ctypes.int, + ctypes.int, + ctypes.int, + ctypes.int, + ctypes.int), + dhcp_do_request: library.declare("dhcp_do_request", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr), + dhcp_stop: library.declare("dhcp_stop", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + dhcp_release_lease: library.declare("dhcp_release_lease", ctypes.default_abi, + ctypes.int, + ctypes.char.ptr), + dhcp_get_errmsg: library.declare("dhcp_get_errmsg", ctypes.default_abi, + ctypes.char.ptr), + dhcp_do_request_renew: library.declare("dhcp_do_request_renew", + ctypes.default_abi, + ctypes.int, + ctypes.char.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr, + ctypes.int.ptr) + }; +})();