Bumping manifests a=b2g-bump
[gecko.git] / dom / wifi / WifiNetUtil.jsm
blob32907dedf1fe2a357d341a4e983eb95912dce33d
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 "use strict";
9 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
11 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
12 Cu.import("resource://gre/modules/systemlibs.js");
14 XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
15                                    "@mozilla.org/network/service;1",
16                                    "nsINetworkService");
18 this.EXPORTED_SYMBOLS = ["WifiNetUtil"];
20 const DHCP_PROP = "init.svc.dhcpcd";
21 const DHCP      = "dhcpcd";
22 const DEBUG     = false;
24 this.WifiNetUtil = function(controlMessage) {
25   function debug(msg) {
26     if (DEBUG) {
27       dump('-------------- NetUtil: ' + msg);
28     }
29   }
31   var util = {};
33   util.configureInterface = function(cfg, callback) {
34     let message = { cmd:     "ifc_configure",
35                     ifname:  cfg.ifname,
36                     ipaddr:  cfg.ipaddr,
37                     mask:    cfg.mask,
38                     gateway: cfg.gateway,
39                     dns1:    cfg.dns1,
40                     dns2:    cfg.dns2 };
42     controlMessage(message, function(data) {
43       callback(!data.status);
44     });
45   };
47   util.runDhcp = function (ifname, callback) {
48     util.stopDhcp(ifname, function() {
49       controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
50         var dhcpInfo = data.status ? null : data;
51         util.runIpConfig(ifname, dhcpInfo, callback);
52       });
53     });
54   };
56   util.stopDhcp = function (ifname, callback) {
57     // This function does exactly what dhcp_stop does. Unforunately, if we call
58     // this function twice before the previous callback is returned. We may block
59     // our self waiting for the callback. It slows down the wifi startup procedure.
60     // Therefore, we have to roll our own version here.
61     let dhcpService = DHCP_PROP + "_" + ifname;
62     let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname;
63     let processName = DHCP + "_" + suffix;
65     // The implementation of |dhcp_do_request| would wait until the
66     // |result_prop_name| (e.g. dhcp.wlan0.result) to be non-null
67     // or 30 second timeout. So we manually change the result property
68     // to 'ko' to avoid timeout.
69     //
70     // http://androidxref.com/4.4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#234
71     setProperty('dhcp.' + suffix + '.result', 'ko', function() {
72       stopProcess(dhcpService, processName, callback);
73     });
74   };
76   util.enableInterface = function (ifname, callback) {
77     controlMessage({ cmd: "ifc_enable", ifname: ifname }, function (data) {
78       callback(!data.status);
79     });
80   };
82   util.disableInterface = function (ifname, callback) {
83     controlMessage({ cmd: "ifc_disable", ifname: ifname }, function (data) {
84       callback(!data.status);
85     });
86   };
88   util.startDhcpServer = function (config, callback) {
89     gNetworkService.setDhcpServer(true, config, function (error) {
90       callback(!error);
91     });
92   };
94   util.stopDhcpServer = function (callback) {
95     gNetworkService.setDhcpServer(false, null, function (error) {
96       callback(!error);
97     });
98   };
100   util.addHostRoute = function (ifname, route, callback) {
101     controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) {
102       callback(!data.status);
103     });
104   };
106   util.removeHostRoutes = function (ifname, callback) {
107     controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) {
108       callback(!data.status);
109     });
110   };
112   util.setDefaultRoute = function (ifname, route, callback) {
113     controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) {
114       callback(!data.status);
115     });
116   };
118   util.getDefaultRoute = function (ifname, callback) {
119     controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) {
120       callback(!data.route);
121     });
122   };
124   util.removeDefaultRoute = function (ifname, callback) {
125     controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) {
126       callback(!data.status);
127     });
128   };
130   util.resetConnections = function (ifname, callback) {
131     controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) {
132       callback(!data.status);
133     });
134   };
136   util.releaseDhcpLease = function (ifname, callback) {
137     controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) {
138       callback(!data.status);
139     });
140   };
142   util.getDhcpError = function (callback) {
143     controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) {
144       callback(data.error);
145     });
146   };
148   util.runDhcpRenew = function (ifname, callback) {
149     controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
150       callback(data.status ? null : data);
151     });
152   };
154   util.runIpConfig = function (name, data, callback) {
155     if (!data) {
156       debug("IP config failed to run");
157       callback({ info: data });
158       return;
159     }
161     setProperty("net." + name + ".dns1", ipToString(data.dns1),
162                 function(ok) {
163       if (!ok) {
164         debug("Unable to set net.<ifname>.dns1");
165         return;
166       }
167       setProperty("net." + name + ".dns2", ipToString(data.dns2),
168                   function(ok) {
169         if (!ok) {
170           debug("Unable to set net.<ifname>.dns2");
171           return;
172         }
173         setProperty("net." + name + ".gw", ipToString(data.gateway),
174                     function(ok) {
175           if (!ok) {
176             debug("Unable to set net.<ifname>.gw");
177             return;
178           }
179           callback({ info: data });
180         });
181       });
182     });
183   };
185   //--------------------------------------------------
186   // Helper functions.
187   //--------------------------------------------------
189   function stopProcess(service, process, callback) {
190     var count = 0;
191     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
192     function tick() {
193       let result = libcutils.property_get(service);
194       if (result === null) {
195         callback();
196         return;
197       }
198       if (result === "stopped" || ++count >= 5) {
199         // Either we succeeded or ran out of time.
200         timer = null;
201         callback();
202         return;
203       }
205       // Else it's still running, continue waiting.
206       timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
207     }
209     setProperty("ctl.stop", process, tick);
210   }
212   // Wrapper around libcutils.property_set that returns true if setting the
213   // value was successful.
214   // Note that the callback is not called asynchronously.
215   function setProperty(key, value, callback) {
216     let ok = true;
217     try {
218       libcutils.property_set(key, value);
219     } catch(e) {
220       ok = false;
221     }
222     callback(ok);
223   }
225   function ipToString(n) {
226     return String((n >>  0) & 0xFF) + "." +
227                  ((n >>  8) & 0xFF) + "." +
228                  ((n >> 16) & 0xFF) + "." +
229                  ((n >> 24) & 0xFF);
230   }
232   return util;