Bug 734299 - Part 2: Worker code for network configuration. r=qDot
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Mon, 12 Mar 2012 16:45:57 -0700
changeset 88811 789068a4ba16cbc641652b7d504ec0ff797388e9
parent 88810 94c48b2660cb061f2b24fcd72461e44191f0df7e
child 88812 dfcb11712ec227cc6ec259acc8646b98f81f8d00
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersqDot
bugs734299
milestone13.0a1
Bug 734299 - Part 2: Worker code for network configuration. r=qDot
dom/system/b2g/Makefile.in
dom/system/b2g/net_worker.js
dom/system/b2g/systemlibs.js
--- a/dom/system/b2g/Makefile.in
+++ b/dom/system/b2g/Makefile.in
@@ -45,16 +45,17 @@ LOCAL_INCLUDES = \
   $(NULL)
 
 EXTRA_COMPONENTS = \
   RadioInterfaceLayer.manifest \
   RadioInterfaceLayer.js \
   $(NULL)
 
 EXTRA_JS_MODULES = \
+  net_worker.js \
   ril_consts.js \
   ril_worker.js \
   systemlibs.js \
   $(NULL)
 
 ifdef ENABLE_TESTS
 XPCSHELL_TESTS = tests
 endif
new file mode 100644
--- /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");
+  };
+}
--- a/dom/system/b2g/systemlibs.js
+++ b/dom/system/b2g/systemlibs.js
@@ -10,17 +10,17 @@ const SYSTEM_PROPERTY_VALUE_MAX = 92;
  */
 let libcutils = (function() {
   let lib;
   try {
     lib = ctypes.open("libcutils.so");
   } 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) {
         if (key in fake_propdb) {
           return fake_propdb[key];
         }
         return defaultValue === undefined ? null : defaultValue;
       },
@@ -72,8 +72,100 @@ let libcutils = (function() {
       if (rv) {
         throw Error('libcutils.property_set("' + key + '", "' + value +
                     '") failed with error ' + rv);
       }
     }
 
   };
 })();
+
+
+/**
+ * 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)
+  };
+})();