blob: 3229250b52efcd23c50af0aeb0fc577f5ed1e52c [file] [log] [blame]
Simon Hunt1e4a0012015-01-21 11:36:08 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Remote -- Web Socket Service
19 */
20(function () {
21 'use strict';
22
Thomas Vachuska329af532015-03-10 02:08:33 -070023 // injected refs
24 var fs, $log;
Simon Hunt1e4a0012015-01-21 11:36:08 -080025
Thomas Vachuska329af532015-03-10 02:08:33 -070026 // internal state
27 var ws, sws, sid = 0,
28 handlers = {};
Simon Huntacf410b2015-01-23 10:05:48 -080029
Thomas Vachuska329af532015-03-10 02:08:33 -070030 function resetSid() {
31 sid = 0;
Simon Hunt970e7fd2015-01-22 17:46:28 -080032 }
33
Thomas Vachuska329af532015-03-10 02:08:33 -070034 // Binds the specified message handlers.
35 function bindHandlers(handlerMap) {
36 var m = d3.map(handlerMap),
37 dups = [];
Simon Hunt970e7fd2015-01-22 17:46:28 -080038
Thomas Vachuska329af532015-03-10 02:08:33 -070039 m.forEach(function (key, value) {
40 var fn = fs.isF(value[key]);
41 if (!fn) {
42 $log.warn(key + ' binding not a function on ' + value);
43 return;
Simon Hunt970e7fd2015-01-22 17:46:28 -080044 }
Thomas Vachuska329af532015-03-10 02:08:33 -070045
46 if (handlers[key]) {
47 dups.push(key);
48 } else {
49 handlers[key] = fn;
50 }
51 });
52 if (dups.length) {
53 $log.warn('duplicate bindings ignored:', dups);
54 }
Simon Hunt970e7fd2015-01-22 17:46:28 -080055 }
56
Thomas Vachuska329af532015-03-10 02:08:33 -070057 // Unbinds the specified message handlers.
58 function unbindHandlers(handlerMap) {
59 var m = d3.map(handlerMap);
60 m.forEach(function (key) {
61 delete handlers[key];
62 });
63 }
Simon Huntacf410b2015-01-23 10:05:48 -080064
Thomas Vachuska329af532015-03-10 02:08:33 -070065 // Formulates an event message and sends it via the shared web-socket.
66 function sendEvent(evType, payload) {
67 var p = payload || {};
68 if (sws) {
69 $log.debug(' *Tx* >> ', evType, payload);
70 sws.send({
71 event: evType,
72 sid: ++sid,
73 payload: p
74 });
75 } else {
76 $log.warn('sendEvent: no websocket open:', evType, payload);
77 }
78 }
79
80
81 // Handles the specified message using handler bindings.
82 function handleMessage(msgEvent) {
83 var ev;
84 try {
85 ev = JSON.parse(msgEvent.data);
86 $log.debug(' *Rx* >> ', ev.event, ev.payload);
87 dispatchToHandler(ev);
88 } catch (e) {
89 $log.error('message is not valid JSON', msgEvent);
90 }
91 }
92
93 // Dispatches the message to the appropriate handler.
94 function dispatchToHandler(event) {
95 var handler = handlers[event.event];
96 if (handler) {
97 handler(event.payload);
98 } else {
99 $log.warn('unhandled event:', event);
100 }
101 }
102
103 function handleOpen() {
104 $log.info('web socket open');
105 // FIXME: implement calling external hooks
106 }
107
108 function handleClose() {
109 $log.info('web socket closed');
110 // FIXME: implement reconnect logic
Simon Hunt970e7fd2015-01-22 17:46:28 -0800111 }
112
Simon Hunt584122a2015-01-21 15:32:40 -0800113 angular.module('onosRemote')
Simon Huntbb920fd2015-01-22 17:06:32 -0800114 .factory('WebSocketService',
115 ['$log', '$location', 'UrlFnService', 'FnService',
116
Thomas Vachuska329af532015-03-10 02:08:33 -0700117 function (_$log_, $loc, ufs, _fs_) {
Simon Hunt584122a2015-01-21 15:32:40 -0800118 fs = _fs_;
Thomas Vachuska329af532015-03-10 02:08:33 -0700119 $log = _$log_;
Simon Hunt584122a2015-01-21 15:32:40 -0800120
Thomas Vachuska329af532015-03-10 02:08:33 -0700121 // Creates a web socket for the given path, returning a "handle".
Simon Huntacf410b2015-01-23 10:05:48 -0800122 // opts contains the event handler callbacks, etc.
Simon Huntbb920fd2015-01-22 17:06:32 -0800123 function createWebSocket(path, opts) {
Simon Hunt970e7fd2015-01-22 17:46:28 -0800124 var o = opts || {},
125 wsport = opts && opts.wsport,
Simon Huntbb920fd2015-01-22 17:06:32 -0800126 fullUrl = ufs.wsUrl(path, wsport),
Simon Hunt584122a2015-01-21 15:32:40 -0800127 api = {
Simon Hunt970e7fd2015-01-22 17:46:28 -0800128 meta: { path: fullUrl, ws: null },
Simon Hunt584122a2015-01-21 15:32:40 -0800129 send: send,
130 close: close
Thomas Vachuska329af532015-03-10 02:08:33 -0700131 };
Simon Hunt970e7fd2015-01-22 17:46:28 -0800132
133 try {
134 ws = new WebSocket(fullUrl);
135 api.meta.ws = ws;
136 } catch (e) {
137 }
Simon Hunt584122a2015-01-21 15:32:40 -0800138
Simon Huntbb920fd2015-01-22 17:06:32 -0800139 $log.debug('Attempting to open websocket to: ' + fullUrl);
140
Simon Hunt970e7fd2015-01-22 17:46:28 -0800141 if (ws) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700142 ws.onopen = handleOpen;
143 ws.onmessage = handleMessage;
144 ws.onclose = handleClose;
Simon Hunt970e7fd2015-01-22 17:46:28 -0800145 }
Simon Hunt584122a2015-01-21 15:32:40 -0800146
Thomas Vachuska329af532015-03-10 02:08:33 -0700147 // Sends a formulated event message via the backing web-socket.
Simon Huntacf410b2015-01-23 10:05:48 -0800148 function send(ev) {
Thomas Vachuska329af532015-03-10 02:08:33 -0700149 if (ev && ws) {
150 ws.send(JSON.stringify(ev));
151 } else if (!ws) {
152 $log.warn('ws.send() no web socket open!', fullUrl, ev);
Simon Hunt584122a2015-01-21 15:32:40 -0800153 }
154 }
155
Thomas Vachuska329af532015-03-10 02:08:33 -0700156 // Closes the backing web-socket.
Simon Hunt584122a2015-01-21 15:32:40 -0800157 function close() {
158 if (ws) {
159 ws.close();
160 ws = null;
Simon Hunt970e7fd2015-01-22 17:46:28 -0800161 api.meta.ws = null;
Simon Hunt584122a2015-01-21 15:32:40 -0800162 }
163 }
164
Thomas Vachuska329af532015-03-10 02:08:33 -0700165 sws = api; // Make the shared web-socket accessible
Simon Hunt584122a2015-01-21 15:32:40 -0800166 return api;
Simon Hunt1e4a0012015-01-21 11:36:08 -0800167 }
168
169 return {
Thomas Vachuska329af532015-03-10 02:08:33 -0700170 resetSid: resetSid,
171 createWebSocket: createWebSocket,
172 bindHandlers: bindHandlers,
173 unbindHandlers: unbindHandlers,
174 sendEvent: sendEvent
Simon Hunt1e4a0012015-01-21 11:36:08 -0800175 };
176 }]);
177
178}());