GUI -- Added websock open listeners mechanism.
- made event handler structure parsing a little cleverer.
Change-Id: I15120dabd0aade28e6ee3680faf96f408aed1450
diff --git a/web/gui/src/main/webapp/app/fw/remote/websocket.js b/web/gui/src/main/webapp/app/fw/remote/websocket.js
index ca2840d..cb68098 100644
--- a/web/gui/src/main/webapp/app/fw/remote/websocket.js
+++ b/web/gui/src/main/webapp/app/fw/remote/websocket.js
@@ -30,10 +30,13 @@
sid = 0, // event sequence identifier
handlers = {}, // event handler bindings
pendingEvents = [], // events TX'd while socket not up
+ host, // web socket host
url, // web socket URL
clusterNodes = [], // ONOS instances data for failover
clusterIndex = -1, // the instance to which we are connected
- connectRetries = 0;
+ connectRetries = 0, // limit our attempts at reconnecting
+ openListeners = {}, // registered listeners for websocket open()
+ nextListenerId = 1; // internal ID for open listeners
// =======================
// === Bootstrap Handler
@@ -55,7 +58,7 @@
// === Web socket callbacks
function handleOpen() {
- $log.info('Web socket open');
+ $log.info('Web socket open - ', url);
vs.hide();
$log.debug('Sending ' + pendingEvents.length + ' pending event(s)...');
@@ -66,6 +69,7 @@
connectRetries = 0;
wsUp = true;
+ informListeners(host, url);
}
// Handles the specified (incoming) message using handler bindings.
@@ -78,7 +82,7 @@
$log.error('Message.data is not valid JSON', msgEvent.data, e);
return;
}
- $log.debug(' *Rx* >> ', ev.event, ev.payload);
+ $log.debug(' << *Rx* ', ev.event, ev.payload);
if (h = handlers[ev.event]) {
try {
@@ -129,12 +133,17 @@
return ip;
}
+ function informListeners(host, url) {
+ angular.forEach(openListeners, function(lsnr) {
+ lsnr.cb(host, url);
+ });
+ }
+
function _send(ev) {
$log.debug(' *Tx* >> ', ev.event, ev.payload);
ws.send(JSON.stringify(ev));
}
-
// ===================
// === API Functions
@@ -145,12 +154,14 @@
// Currently supported opts:
// wsport: web socket port (other than default 8181)
- // server: if defined, is the server address to use
- function createWebSocket(opts, server) {
+ // host: if defined, is the host address to use
+ function createWebSocket(opts, _host_) {
var wsport = (opts && opts.wsport) || null;
+
webSockOpts = opts; // preserved for future calls
- url = ufs.wsUrl('core', wsport, server);
+ host = _host_ || $loc.host();
+ url = ufs.wsUrl('core', wsport, _host_);
$log.debug('Attempting to open websocket to: ' + url);
ws = wsock.newWebSocket(url);
@@ -163,15 +174,18 @@
return url;
}
- // Binds the specified message handlers.
- // keys are the event IDs
- // values are the API on which the handler function is a property
+ // Binds the message handlers to their message type (event type) as
+ // specified in the given map. Note that keys are the event IDs; values
+ // are either:
+ // * the event handler function, or
+ // * an API object which has an event handler for the key
+ //
function bindHandlers(handlerMap) {
var m = d3.map(handlerMap),
dups = [];
m.forEach(function (eventId, api) {
- var fn = fs.isF(api[eventId]);
+ var fn = fs.isF(api) || fs.isF(api[eventId]);
if (!fn) {
$log.warn(eventId + ' handler not a function');
return;
@@ -198,6 +212,28 @@
});
}
+ function addOpenListener(callback) {
+ var id = nextListenerId++,
+ cb = fs.isF(callback),
+ o = { id: id, cb: cb };
+
+ if (cb) {
+ openListeners[id] = o;
+ } else {
+ $log.error('WSS.addOpenListener(): callback not a function');
+ o.error = 'No callback defined';
+ }
+ return o;
+ }
+
+ function removeOpenListener(lsnr) {
+ var id = lsnr && lsnr.id,
+ o = openListeners[id];
+ if (o) {
+ delete openListeners[id];
+ }
+ }
+
// Formulates an event message and sends it via the web-socket.
// If the websocket is not up yet, we store it in a pending list.
function sendEvent(evType, payload) {
@@ -230,17 +266,15 @@
wsock = _wsock_;
vs = _vs_;
- // TODO: Consider how to simplify handler structure
- // Now it is an object of key -> object that has a method named 'key'.
- bindHandlers({
- bootstrap: builtinHandlers
- });
+ bindHandlers(builtinHandlers);
return {
resetSid: resetSid,
createWebSocket: createWebSocket,
bindHandlers: bindHandlers,
unbindHandlers: unbindHandlers,
+ addOpenListener: addOpenListener,
+ removeOpenListener: removeOpenListener,
sendEvent: sendEvent
};
}
diff --git a/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
index c4d92c2..7289e9d 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -30,7 +30,8 @@
var $log, wss, tps, tis, tfs, tss, tts;
// internal state
- var handlerMap;
+ var handlerMap,
+ openListener;
// ==========================
@@ -58,6 +59,14 @@
};
}
+ function wsOpen(host, url) {
+ $log.debug('TOPO: web socket open - cluster node:', host, 'URL:', url);
+
+ // TODO: request "instanceUpdate" events for all instances
+ // this should give us the updated uiAttached icon placement
+
+ }
+
angular.module('ovTopo')
.factory('TopoEventService',
['$log', '$location', 'WebSocketService',
@@ -76,6 +85,7 @@
createHandlerMap();
function start() {
+ openListener = wss.addOpenListener(wsOpen);
wss.bindHandlers(handlerMap);
wss.sendEvent('topoStart');
wss.sendEvent('requestSummary');
@@ -85,6 +95,8 @@
function stop() {
wss.sendEvent('topoStop');
wss.unbindHandlers(handlerMap);
+ wss.removeOpenListener(openListener);
+ openListener = null;
$log.debug('topo comms stopped');
}
diff --git a/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js b/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
index 6faedc9..fc1e18d 100644
--- a/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
@@ -46,7 +46,7 @@
it('should define api functions', function () {
expect(fs.areFunctions(wss, [
'resetSid', 'createWebSocket', 'bindHandlers', 'unbindHandlers',
- 'sendEvent'
+ 'addOpenListener', 'removeOpenListener', 'sendEvent'
])).toBeTruthy();
});