2 * Copyright (c) 2013, Intel Corporation.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 /* Dummy backend for faking websocket daemon */
11 var dummyBackend = false;
13 var ERROR_SETTINGSD_DISCONNECTED = 'Settings daemon is not connected';
15 var WS_REQUEST_TYPE = {
16 CONNMAN_MANAGER: "connman::manager",
17 CONNMAN_TECHNOLOGY: "connman::technology",
18 CONNMAN_SERVICE: "connman::service",
19 BLUETOOTH: "bluetooth",
28 BLUETOOTH: "bluetooth",
35 /* web socket module to connect to the settings daemon */
36 var wsAPI = (function() {
37 /* number of connection retries to attempt if the socket closes */
39 this.connected = false;
40 this.event_callbacks = $.Callbacks();
42 /* default values for WebSocket */
43 this.socketUrl = 'ws://localhost:16000/';
44 this.socketProtocol = 'http-only';
46 this.timeouttime = 15000;
48 this.methodCalls = [];
49 for (var i = 0; i < 100; i++) {
50 this.methodCalls[i] = null;
53 this.MethodCall = function(id, name, success_cb, error_cb) {
55 this.successCB = success_cb;
56 this.errorCB = error_cb;
57 this.transactionid = id;
60 this.start = function() {
61 me.timeout = setTimeout(function() {
62 if (me.errorCB !== undefined) {
63 me.errorCB('\"' + me.name + '\" method timed out after ' + self.timeouttime + ' ms');
68 this.finish = function() {
69 if (me.timeout !== undefined) {
70 clearTimeout(me.timeout);
76 this.EventObject = function(type, id, name, value) {
84 function connect(url, protocol, sucess_cb, error_cb) {
85 self.socketUrl = typeof url !== 'undefined' ? url : self.socketUrl;
86 self.socketProtocol = typeof protocol !== 'undefined' ? protocol : self.socketProtocol;
87 self.successCB = sucess_cb;
88 self.errorCB = error_cb;
90 if ('WebSocket' in window) {
91 if (self.socketProtocol.length > 0) {
92 self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
94 self.socket = new WebSocket(self);
96 console.log('Connecting to websocket: ' + self.socketUrl);
98 self.socket.onopen = function() {
99 self.connected = true;
100 console.log('websocket opened');
104 self.socket.onclose = function(code, reason, remote) {
105 self.connected = false;
106 console.log('websocket closed - ' + reason);
109 /* fake the connection for dummy backend */
110 self.connected = true;
115 self.errorCB(reason);
118 self.socket.onerror = function(e) {
120 /* ignore websocket error */
125 self.errorCB('websocket error: ' + e.data);
127 self.errorCB('websocket error: unknown');
131 self.socket.onmessage = function(e) {
135 console.log('Websockets not supported');
139 function reconnect() {
140 if (this.connected) return;
142 setTimeout(function() {
143 connect(self.socketUrl, self.socketProtocol, self.successCB, self.errorCB);
147 function send(msg, success_cb, error_cb) {
148 if (!this.connected) {
149 if (error_cb !== undefined) {
150 error_cb(ERROR_SETTINGSD_DISCONNECTED);
154 var i = this.methodIdx;
155 this.methodIdx = (this.methodIdx + 1) % 100;
156 this.methodCalls[i] = new this.MethodCall(msg.transactionid, msg.name, success_cb, error_cb);
157 this.methodCalls[i].start();
159 var jsonMsg = JSON.stringify(msg);
160 console.log('Sending json msg: ' + jsonMsg);
162 /* fake with dummy data */
163 dummyBackendSend(msg);
165 this.socket.send(jsonMsg);
169 function fireEvent(type, id, name, value) {
170 var event = new this.EventObject(type, id, name, value);
171 console.log('Firing ' + type + ' event id=' + id + ', name=' + name + ', value=' + value);
172 event_callbacks.fire(event);
175 function receive(msg) {
179 console.log("Received json msg: " + msg);
180 response = JSON.parse(msg);
182 console.error('Garbage message: ' + msg);
186 if ((response === undefined) || (response.type === undefined)) {
187 console.error('Badly formed message: ' + msg);
188 } else if (response.type === 'event' && response.value !== undefined) {
189 if (response.value.interface_name === 'net.connman.Manager' || response.value.interface_name === 'net.connman.Service' || response.value.interface_name === 'net.connman.Technology') {
190 if (response.value.signal_name === undefined || response.value.parameters === undefined) {
191 console.error('Badly formed event: ' + msg);
194 if (response.value.signal_name === 'ServiceChanged' && response.value.parameters.length !== 2) {
195 console.error('Badly formed event parameters: ' + msg);
199 if (response.value.object_path === '/' || response.value.object_path.indexOf('/net/connman/technology/') >= 0) {
200 fireEvent(WS_EVENT_TYPE.CONNMAN, response.value.object_path, response.value.signal_name, response.value.parameters);
202 console.error('Unrecognized event object_path, skipping');
205 console.error('Unrecognized event, skipping');
207 } else if (response.transactionid === undefined) {
208 console.error('Badly formed response: ' + msg);
210 var calls = this.methodCalls;
211 for (var i = 0; i < calls.length; i++) {
213 if (call && (!call.done) && (call.transactionid === response.transactionid)) {
215 if (response.result !== 'succeeded' && response.reason !== undefined && call.errorCB !== undefined) {
216 call.errorCB(response.reason);
217 } else if (call.successCB !== undefined) {
218 if (response.value !== undefined) {
219 call.successCB(response.value);
230 function generateTransactionId() {
232 for (i = 0; i < 8; i++) {
233 var num = Math.floor((Math.random() + 1) * 65536);
234 val[i] = num.toString(16).substring(1);
236 var uuid = val[0] + val[1] + '-' + val[2] + '-' + val[3] + '-' + val[4] + '-' + val[5] + val[6] + val[7];
240 function sendRequest(request_type, request_name, request_args, success_cb, error_cb) {
242 'type': request_type,
243 'transactionid': generateTransactionId(),
244 'name': request_name,
245 'value': request_args
248 send(msg, success_cb, error_cb);
251 function subscribeEvents(callback) {
252 event_callbacks.add(callback);
255 function unsubscribeEvents(callback) {
256 event_callbacks.remove(callback);
259 /* this is dummy data for testing purposes */
260 function dummyBackendSend(msg) {
262 console.log('Sending to dummy server');
264 var calls = this.methodCalls;
267 for (var i = 0; i < calls.length; i++) {
269 if (call && (!call.done) && (call.transactionid === msg.transactionid)) {
271 if (msg.error !== undefined) {
273 call.errorCB(msg.error);
276 if (msg.value !== undefined && call.successCB !== undefined) {
278 case WS_REQUEST_TYPE.CONNMAN_MANAGER:
279 case WS_REQUEST_TYPE.CONNMAN_TECHNOLOGY:
280 if (msg.name === 'get_technologies') {
283 ["/net/connman/technology/ethernet",
291 ["/net/connman/technology/wifi",
298 "TetheringIdentifier": "tetherme",
299 "TetheringPassphrase": "0123456789"
301 ["/net/connman/technology/bluetooth",
312 replyMsg = JSON.stringify(results);
313 call.successCB(results);
315 } else if (msg.name === 'enable' && msg.value[1] === true) {
317 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Powered", true]);
319 } else if (msg.name === 'enable' && msg.value[1] === false) {
321 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Powered", false]);
323 } else if (msg.name === 'tethering') {
326 } else if (msg.name === 'get_services' || msg.name === 'scan') {
329 ["/net/connman/service/ethernet_0010f32f5a70_cable",
335 "Domains": ["ftrdhcpuser.net"],
336 "Domains.Configuration": [],
338 "Address": "10:20:F3:2F:5E:23",
345 "Address": "192.168.1.20",
346 "Gateway": "192.168.1.1",
348 "Netmask": "255.255.255.0"
350 "IPv4.Configuration": {
354 "IPv6.Configuration": {
356 "Privacy": "disabled"
360 "Nameservers": ["192.168.1.1", "184.11.12.13"],
361 "Nameservers.Configuration": [],
366 "Proxy.Configuration": {},
367 "Timeservers": ["192.168.1.1", "pool.ntp.org"],
368 "Timeservers.Configuration": []
370 ["/net/connman/service/wifi_c8f733acdf96_3558364737_managed_psk",
378 "AutoConnect": false,
379 "Name": "Access Point 1",
380 "BSSID": "11:5d:49:88:3d:20",
383 "EncryptionMode": "none",
386 "Interface": "wlp1s0",
387 "Address": "B2:D3:55:66:44:22",
391 "Address": "192.168.1.20",
392 "Gateway": "192.168.1.1",
394 "Netmask": "255.255.255.0"
396 "IPv4.Configuration": {
400 "IPv6.Configuration": {
402 "Privacy": "disabled"
405 "Nameservers.Configuration": [],
407 "Timeservers.Configuration": [],
409 "Domains.Configuration": [],
411 "Proxy.Configuration": {},
414 ["/net/connman/service/wifi_c8f733acdf96_446f75636865626167_managed_psk",
422 "AutoConnect": false,
423 "Name": "Access Point 2",
424 "BSSID": "21:ef:30:b9:ad:86",
427 "EncryptionMode": "aes",
430 "Interface": "wlp1s0",
431 "Address": "E8:F2:33:AC:DF:96",
435 "IPv4.Configuration": {
439 "IPv6.Configuration": {
441 "Privacy": "disabled"
444 "Nameservers.Configuration": [],
446 "Timeservers.Configuration": [],
448 "Domains.Configuration": [],
450 "Proxy.Configuration": {},
453 ["/net/connman/service/wifi_c8f733acdf96_536563757265446f75636865626167_managed_psk",
461 "AutoConnect": false,
462 "Name": "Access Point 3",
463 "BSSID": "25:ad:44:b7:e3:66",
466 "EncryptionMode": "aes",
469 "Interface": "wlp1s0",
470 "Address": "A9:28:44:AD:FF:26",
474 "IPv4.Configuration": {
478 "IPv6.Configuration": {
480 "Privacy": "disabled"
483 "Nameservers.Configuration": [],
485 "Timeservers.Configuration": [],
487 "Domains.Configuration": [],
489 "Proxy.Configuration": {},
495 replyMsg = JSON.stringify(results);
496 /* simulate scan behavior */
497 setTimeout(function() {
498 call.successCB(results);
502 case WS_REQUEST_TYPE.CONNMAN_SERVICE:
503 if (msg.name === 'connect') {
504 if (msg.value[0] === '/net/connman/service/wifi_c8f733acdf96_3558364737_managed_psk' && msg.value[1].Passphrase !== '123') {
505 call.errorCB('Invalid passphrase');
506 } else if (msg.value[0] === '/net/connman/service/wifi_c8f733acdf96_446f75636865626167_managed_psk' && msg.value[1].Passphrase !== '123') {
507 call.errorCB('Invalid passphrase');
510 setTimeout(function() {
511 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Connected", true]);
515 } else if (msg.name === 'disconnect') {
517 setTimeout(function() {
518 fireEvent(WS_EVENT_TYPE.CONNMAN, msg.value[0], 'PropertyChanged', ["Connected", false]);
521 } else if (msg.name === 'autoconnect') {
526 call.errorCB('Unsupported request: ' + msg.name + ', ' + msg.value);
531 case WS_REQUEST_TYPE.DATETIME:
532 if (msg.name === 'is_time_updates_auto' && msg.value !== undefined) {
533 /* default to manual */
534 call.successCB(false);
536 } else if (msg.name === 'is_timezone_updates_auto' && msg.value !== undefined) {
537 /* default to manual */
538 call.successCB(false);
540 } else if (msg.name === 'time' && msg.value !== undefined) {
543 } else if (msg.name === 'timezone' && msg.value !== undefined) {
546 } else if (msg.name === 'time_updates' && msg.value !== undefined) {
549 } else if (msg.name === 'timezone_updates' && msg.value !== undefined) {
554 call.errorCB('Unsupported request: ' + msg.name + ', ' + msg.value);
559 case WS_REQUEST_TYPE.DISPLAY:
560 case WS_REQUEST_TYPE.SOUND:
561 case WS_REQUEST_TYPE.LOCALE:
563 call.errorCB('Request not implemented');
568 call.errorCB('Invalid request type: ' + msg.type);
581 reconnect: reconnect,
582 sendRequest: sendRequest,
583 subscribeEvents: subscribeEvents,
584 unsubscribeEvents: unsubscribeEvents