Simon Hunt | 1e4a001 | 2015-01-21 11:36:08 -0800 | [diff] [blame] | 1 | /* |
| 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 Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 23 | // injected refs |
| 24 | var fs, $log; |
Simon Hunt | 1e4a001 | 2015-01-21 11:36:08 -0800 | [diff] [blame] | 25 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 26 | // internal state |
| 27 | var ws, sws, sid = 0, |
| 28 | handlers = {}; |
Simon Hunt | acf410b | 2015-01-23 10:05:48 -0800 | [diff] [blame] | 29 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 30 | function resetSid() { |
| 31 | sid = 0; |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 32 | } |
| 33 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 34 | // Binds the specified message handlers. |
| 35 | function bindHandlers(handlerMap) { |
| 36 | var m = d3.map(handlerMap), |
| 37 | dups = []; |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 38 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 39 | 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 Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 44 | } |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 45 | |
| 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 Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 55 | } |
| 56 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 57 | // 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 Hunt | acf410b | 2015-01-23 10:05:48 -0800 | [diff] [blame] | 64 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 65 | // 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 Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 111 | } |
| 112 | |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 113 | angular.module('onosRemote') |
Simon Hunt | bb920fd | 2015-01-22 17:06:32 -0800 | [diff] [blame] | 114 | .factory('WebSocketService', |
| 115 | ['$log', '$location', 'UrlFnService', 'FnService', |
| 116 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 117 | function (_$log_, $loc, ufs, _fs_) { |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 118 | fs = _fs_; |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 119 | $log = _$log_; |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 120 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 121 | // Creates a web socket for the given path, returning a "handle". |
Simon Hunt | acf410b | 2015-01-23 10:05:48 -0800 | [diff] [blame] | 122 | // opts contains the event handler callbacks, etc. |
Simon Hunt | bb920fd | 2015-01-22 17:06:32 -0800 | [diff] [blame] | 123 | function createWebSocket(path, opts) { |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 124 | var o = opts || {}, |
| 125 | wsport = opts && opts.wsport, |
Simon Hunt | bb920fd | 2015-01-22 17:06:32 -0800 | [diff] [blame] | 126 | fullUrl = ufs.wsUrl(path, wsport), |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 127 | api = { |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 128 | meta: { path: fullUrl, ws: null }, |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 129 | send: send, |
| 130 | close: close |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 131 | }; |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 132 | |
| 133 | try { |
| 134 | ws = new WebSocket(fullUrl); |
| 135 | api.meta.ws = ws; |
| 136 | } catch (e) { |
| 137 | } |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 138 | |
Simon Hunt | bb920fd | 2015-01-22 17:06:32 -0800 | [diff] [blame] | 139 | $log.debug('Attempting to open websocket to: ' + fullUrl); |
| 140 | |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 141 | if (ws) { |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 142 | ws.onopen = handleOpen; |
| 143 | ws.onmessage = handleMessage; |
| 144 | ws.onclose = handleClose; |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 145 | } |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 146 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 147 | // Sends a formulated event message via the backing web-socket. |
Simon Hunt | acf410b | 2015-01-23 10:05:48 -0800 | [diff] [blame] | 148 | function send(ev) { |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 149 | 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 Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 156 | // Closes the backing web-socket. |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 157 | function close() { |
| 158 | if (ws) { |
| 159 | ws.close(); |
| 160 | ws = null; |
Simon Hunt | 970e7fd | 2015-01-22 17:46:28 -0800 | [diff] [blame] | 161 | api.meta.ws = null; |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 162 | } |
| 163 | } |
| 164 | |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 165 | sws = api; // Make the shared web-socket accessible |
Simon Hunt | 584122a | 2015-01-21 15:32:40 -0800 | [diff] [blame] | 166 | return api; |
Simon Hunt | 1e4a001 | 2015-01-21 11:36:08 -0800 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | return { |
Thomas Vachuska | 329af53 | 2015-03-10 02:08:33 -0700 | [diff] [blame^] | 170 | resetSid: resetSid, |
| 171 | createWebSocket: createWebSocket, |
| 172 | bindHandlers: bindHandlers, |
| 173 | unbindHandlers: unbindHandlers, |
| 174 | sendEvent: sendEvent |
Simon Hunt | 1e4a001 | 2015-01-21 11:36:08 -0800 | [diff] [blame] | 175 | }; |
| 176 | }]); |
| 177 | |
| 178 | }()); |