GUI -- Added websock open listeners mechanism.
- made event handler structure parsing a little cleverer. Change-Id: I15120dabd0aade28e6ee3680faf96f408aed1450
Showing
3 changed files
with
64 additions
and
18 deletions
| ... | @@ -30,10 +30,13 @@ | ... | @@ -30,10 +30,13 @@ |
| 30 | sid = 0, // event sequence identifier | 30 | sid = 0, // event sequence identifier |
| 31 | handlers = {}, // event handler bindings | 31 | handlers = {}, // event handler bindings |
| 32 | pendingEvents = [], // events TX'd while socket not up | 32 | pendingEvents = [], // events TX'd while socket not up |
| 33 | + host, // web socket host | ||
| 33 | url, // web socket URL | 34 | url, // web socket URL |
| 34 | clusterNodes = [], // ONOS instances data for failover | 35 | clusterNodes = [], // ONOS instances data for failover |
| 35 | clusterIndex = -1, // the instance to which we are connected | 36 | clusterIndex = -1, // the instance to which we are connected |
| 36 | - connectRetries = 0; | 37 | + connectRetries = 0, // limit our attempts at reconnecting |
| 38 | + openListeners = {}, // registered listeners for websocket open() | ||
| 39 | + nextListenerId = 1; // internal ID for open listeners | ||
| 37 | 40 | ||
| 38 | // ======================= | 41 | // ======================= |
| 39 | // === Bootstrap Handler | 42 | // === Bootstrap Handler |
| ... | @@ -55,7 +58,7 @@ | ... | @@ -55,7 +58,7 @@ |
| 55 | // === Web socket callbacks | 58 | // === Web socket callbacks |
| 56 | 59 | ||
| 57 | function handleOpen() { | 60 | function handleOpen() { |
| 58 | - $log.info('Web socket open'); | 61 | + $log.info('Web socket open - ', url); |
| 59 | vs.hide(); | 62 | vs.hide(); |
| 60 | 63 | ||
| 61 | $log.debug('Sending ' + pendingEvents.length + ' pending event(s)...'); | 64 | $log.debug('Sending ' + pendingEvents.length + ' pending event(s)...'); |
| ... | @@ -66,6 +69,7 @@ | ... | @@ -66,6 +69,7 @@ |
| 66 | 69 | ||
| 67 | connectRetries = 0; | 70 | connectRetries = 0; |
| 68 | wsUp = true; | 71 | wsUp = true; |
| 72 | + informListeners(host, url); | ||
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | // Handles the specified (incoming) message using handler bindings. | 75 | // Handles the specified (incoming) message using handler bindings. |
| ... | @@ -78,7 +82,7 @@ | ... | @@ -78,7 +82,7 @@ |
| 78 | $log.error('Message.data is not valid JSON', msgEvent.data, e); | 82 | $log.error('Message.data is not valid JSON', msgEvent.data, e); |
| 79 | return; | 83 | return; |
| 80 | } | 84 | } |
| 81 | - $log.debug(' *Rx* >> ', ev.event, ev.payload); | 85 | + $log.debug(' << *Rx* ', ev.event, ev.payload); |
| 82 | 86 | ||
| 83 | if (h = handlers[ev.event]) { | 87 | if (h = handlers[ev.event]) { |
| 84 | try { | 88 | try { |
| ... | @@ -129,12 +133,17 @@ | ... | @@ -129,12 +133,17 @@ |
| 129 | return ip; | 133 | return ip; |
| 130 | } | 134 | } |
| 131 | 135 | ||
| 136 | + function informListeners(host, url) { | ||
| 137 | + angular.forEach(openListeners, function(lsnr) { | ||
| 138 | + lsnr.cb(host, url); | ||
| 139 | + }); | ||
| 140 | + } | ||
| 141 | + | ||
| 132 | function _send(ev) { | 142 | function _send(ev) { |
| 133 | $log.debug(' *Tx* >> ', ev.event, ev.payload); | 143 | $log.debug(' *Tx* >> ', ev.event, ev.payload); |
| 134 | ws.send(JSON.stringify(ev)); | 144 | ws.send(JSON.stringify(ev)); |
| 135 | } | 145 | } |
| 136 | 146 | ||
| 137 | - | ||
| 138 | // =================== | 147 | // =================== |
| 139 | // === API Functions | 148 | // === API Functions |
| 140 | 149 | ||
| ... | @@ -145,12 +154,14 @@ | ... | @@ -145,12 +154,14 @@ |
| 145 | 154 | ||
| 146 | // Currently supported opts: | 155 | // Currently supported opts: |
| 147 | // wsport: web socket port (other than default 8181) | 156 | // wsport: web socket port (other than default 8181) |
| 148 | - // server: if defined, is the server address to use | 157 | + // host: if defined, is the host address to use |
| 149 | - function createWebSocket(opts, server) { | 158 | + function createWebSocket(opts, _host_) { |
| 150 | var wsport = (opts && opts.wsport) || null; | 159 | var wsport = (opts && opts.wsport) || null; |
| 160 | + | ||
| 151 | webSockOpts = opts; // preserved for future calls | 161 | webSockOpts = opts; // preserved for future calls |
| 152 | 162 | ||
| 153 | - url = ufs.wsUrl('core', wsport, server); | 163 | + host = _host_ || $loc.host(); |
| 164 | + url = ufs.wsUrl('core', wsport, _host_); | ||
| 154 | 165 | ||
| 155 | $log.debug('Attempting to open websocket to: ' + url); | 166 | $log.debug('Attempting to open websocket to: ' + url); |
| 156 | ws = wsock.newWebSocket(url); | 167 | ws = wsock.newWebSocket(url); |
| ... | @@ -163,15 +174,18 @@ | ... | @@ -163,15 +174,18 @@ |
| 163 | return url; | 174 | return url; |
| 164 | } | 175 | } |
| 165 | 176 | ||
| 166 | - // Binds the specified message handlers. | 177 | + // Binds the message handlers to their message type (event type) as |
| 167 | - // keys are the event IDs | 178 | + // specified in the given map. Note that keys are the event IDs; values |
| 168 | - // values are the API on which the handler function is a property | 179 | + // are either: |
| 180 | + // * the event handler function, or | ||
| 181 | + // * an API object which has an event handler for the key | ||
| 182 | + // | ||
| 169 | function bindHandlers(handlerMap) { | 183 | function bindHandlers(handlerMap) { |
| 170 | var m = d3.map(handlerMap), | 184 | var m = d3.map(handlerMap), |
| 171 | dups = []; | 185 | dups = []; |
| 172 | 186 | ||
| 173 | m.forEach(function (eventId, api) { | 187 | m.forEach(function (eventId, api) { |
| 174 | - var fn = fs.isF(api[eventId]); | 188 | + var fn = fs.isF(api) || fs.isF(api[eventId]); |
| 175 | if (!fn) { | 189 | if (!fn) { |
| 176 | $log.warn(eventId + ' handler not a function'); | 190 | $log.warn(eventId + ' handler not a function'); |
| 177 | return; | 191 | return; |
| ... | @@ -198,6 +212,28 @@ | ... | @@ -198,6 +212,28 @@ |
| 198 | }); | 212 | }); |
| 199 | } | 213 | } |
| 200 | 214 | ||
| 215 | + function addOpenListener(callback) { | ||
| 216 | + var id = nextListenerId++, | ||
| 217 | + cb = fs.isF(callback), | ||
| 218 | + o = { id: id, cb: cb }; | ||
| 219 | + | ||
| 220 | + if (cb) { | ||
| 221 | + openListeners[id] = o; | ||
| 222 | + } else { | ||
| 223 | + $log.error('WSS.addOpenListener(): callback not a function'); | ||
| 224 | + o.error = 'No callback defined'; | ||
| 225 | + } | ||
| 226 | + return o; | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + function removeOpenListener(lsnr) { | ||
| 230 | + var id = lsnr && lsnr.id, | ||
| 231 | + o = openListeners[id]; | ||
| 232 | + if (o) { | ||
| 233 | + delete openListeners[id]; | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + | ||
| 201 | // Formulates an event message and sends it via the web-socket. | 237 | // Formulates an event message and sends it via the web-socket. |
| 202 | // If the websocket is not up yet, we store it in a pending list. | 238 | // If the websocket is not up yet, we store it in a pending list. |
| 203 | function sendEvent(evType, payload) { | 239 | function sendEvent(evType, payload) { |
| ... | @@ -230,17 +266,15 @@ | ... | @@ -230,17 +266,15 @@ |
| 230 | wsock = _wsock_; | 266 | wsock = _wsock_; |
| 231 | vs = _vs_; | 267 | vs = _vs_; |
| 232 | 268 | ||
| 233 | - // TODO: Consider how to simplify handler structure | 269 | + bindHandlers(builtinHandlers); |
| 234 | - // Now it is an object of key -> object that has a method named 'key'. | ||
| 235 | - bindHandlers({ | ||
| 236 | - bootstrap: builtinHandlers | ||
| 237 | - }); | ||
| 238 | 270 | ||
| 239 | return { | 271 | return { |
| 240 | resetSid: resetSid, | 272 | resetSid: resetSid, |
| 241 | createWebSocket: createWebSocket, | 273 | createWebSocket: createWebSocket, |
| 242 | bindHandlers: bindHandlers, | 274 | bindHandlers: bindHandlers, |
| 243 | unbindHandlers: unbindHandlers, | 275 | unbindHandlers: unbindHandlers, |
| 276 | + addOpenListener: addOpenListener, | ||
| 277 | + removeOpenListener: removeOpenListener, | ||
| 244 | sendEvent: sendEvent | 278 | sendEvent: sendEvent |
| 245 | }; | 279 | }; |
| 246 | } | 280 | } | ... | ... |
| ... | @@ -30,7 +30,8 @@ | ... | @@ -30,7 +30,8 @@ |
| 30 | var $log, wss, tps, tis, tfs, tss, tts; | 30 | var $log, wss, tps, tis, tfs, tss, tts; |
| 31 | 31 | ||
| 32 | // internal state | 32 | // internal state |
| 33 | - var handlerMap; | 33 | + var handlerMap, |
| 34 | + openListener; | ||
| 34 | 35 | ||
| 35 | // ========================== | 36 | // ========================== |
| 36 | 37 | ||
| ... | @@ -58,6 +59,14 @@ | ... | @@ -58,6 +59,14 @@ |
| 58 | }; | 59 | }; |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 62 | + function wsOpen(host, url) { | ||
| 63 | + $log.debug('TOPO: web socket open - cluster node:', host, 'URL:', url); | ||
| 64 | + | ||
| 65 | + // TODO: request "instanceUpdate" events for all instances | ||
| 66 | + // this should give us the updated uiAttached icon placement | ||
| 67 | + | ||
| 68 | + } | ||
| 69 | + | ||
| 61 | angular.module('ovTopo') | 70 | angular.module('ovTopo') |
| 62 | .factory('TopoEventService', | 71 | .factory('TopoEventService', |
| 63 | ['$log', '$location', 'WebSocketService', | 72 | ['$log', '$location', 'WebSocketService', |
| ... | @@ -76,6 +85,7 @@ | ... | @@ -76,6 +85,7 @@ |
| 76 | createHandlerMap(); | 85 | createHandlerMap(); |
| 77 | 86 | ||
| 78 | function start() { | 87 | function start() { |
| 88 | + openListener = wss.addOpenListener(wsOpen); | ||
| 79 | wss.bindHandlers(handlerMap); | 89 | wss.bindHandlers(handlerMap); |
| 80 | wss.sendEvent('topoStart'); | 90 | wss.sendEvent('topoStart'); |
| 81 | wss.sendEvent('requestSummary'); | 91 | wss.sendEvent('requestSummary'); |
| ... | @@ -85,6 +95,8 @@ | ... | @@ -85,6 +95,8 @@ |
| 85 | function stop() { | 95 | function stop() { |
| 86 | wss.sendEvent('topoStop'); | 96 | wss.sendEvent('topoStop'); |
| 87 | wss.unbindHandlers(handlerMap); | 97 | wss.unbindHandlers(handlerMap); |
| 98 | + wss.removeOpenListener(openListener); | ||
| 99 | + openListener = null; | ||
| 88 | $log.debug('topo comms stopped'); | 100 | $log.debug('topo comms stopped'); |
| 89 | } | 101 | } |
| 90 | 102 | ... | ... |
| ... | @@ -46,7 +46,7 @@ describe('factory: fw/remote/websocket.js', function () { | ... | @@ -46,7 +46,7 @@ describe('factory: fw/remote/websocket.js', function () { |
| 46 | it('should define api functions', function () { | 46 | it('should define api functions', function () { |
| 47 | expect(fs.areFunctions(wss, [ | 47 | expect(fs.areFunctions(wss, [ |
| 48 | 'resetSid', 'createWebSocket', 'bindHandlers', 'unbindHandlers', | 48 | 'resetSid', 'createWebSocket', 'bindHandlers', 'unbindHandlers', |
| 49 | - 'sendEvent' | 49 | + 'addOpenListener', 'removeOpenListener', 'sendEvent' |
| 50 | ])).toBeTruthy(); | 50 | ])).toBeTruthy(); |
| 51 | }); | 51 | }); |
| 52 | 52 | ... | ... |
-
Please register or login to post a comment