Deprecating old web-socket stuff and adding ability for client-side message handler registration. Failover still to be done and same for the async hooks.
Change-Id: I6029c91eb1a04e01401e495b9673ddaea728e215
diff --git a/web/gui/src/main/webapp/WEB-INF/web.xml b/web/gui/src/main/webapp/WEB-INF/web.xml
index 511ceac..5371354 100644
--- a/web/gui/src/main/webapp/WEB-INF/web.xml
+++ b/web/gui/src/main/webapp/WEB-INF/web.xml
@@ -151,12 +151,24 @@
<servlet>
<servlet-name>Web Socket Service</servlet-name>
- <servlet-class>org.onosproject.ui.impl.GuiWebSocketServlet</servlet-class>
+ <servlet-class>org.onosproject.ui.impl.UiWebSocketServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Web Socket Service</servlet-name>
+ <url-pattern>/websock/*</url-pattern>
+ </servlet-mapping>
+
+
+ <servlet>
+ <servlet-name>Legacy Web Socket Service</servlet-name>
+ <servlet-class>org.onosproject.ui.impl.GuiWebSocketServlet</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Legacy Web Socket Service</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
diff --git a/web/gui/src/main/webapp/app/fw/remote/urlfn.js b/web/gui/src/main/webapp/app/fw/remote/urlfn.js
index fe43267..c2addef 100644
--- a/web/gui/src/main/webapp/app/fw/remote/urlfn.js
+++ b/web/gui/src/main/webapp/app/fw/remote/urlfn.js
@@ -22,7 +22,7 @@
var uiContext = '/onos/ui/',
rsSuffix = uiContext + 'rs/',
- wsSuffix = uiContext + 'ws/';
+ wsSuffix = uiContext + 'websock/';
angular.module('onosRemote')
.factory('UrlFnService', ['$location', function ($loc) {
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 abe6025..3229250 100644
--- a/web/gui/src/main/webapp/app/fw/remote/websocket.js
+++ b/web/gui/src/main/webapp/app/fw/remote/websocket.js
@@ -20,62 +20,105 @@
(function () {
'use strict';
- var fs;
+ // injected refs
+ var fs, $log;
- function fnOpen(f) {
- // wrap the onOpen function; we will handle any housekeeping here...
- if (!fs.isF(f)) {
- return null;
- }
+ // internal state
+ var ws, sws, sid = 0,
+ handlers = {};
- return function (openEvent) {
- // NOTE: nothing worth passing to the caller?
- f();
- };
+ function resetSid() {
+ sid = 0;
}
- function fnMessage(f) {
- // wrap the onMessage function; we will attempt to decode the
- // message event payload as JSON and pass that in...
- if (!fs.isF(f)) {
- return null;
- }
+ // Binds the specified message handlers.
+ function bindHandlers(handlerMap) {
+ var m = d3.map(handlerMap),
+ dups = [];
- return function (msgEvent) {
- var ev;
- try {
- ev = JSON.parse(msgEvent.data);
- } catch (e) {
- ev = {
- error: 'Failed to parse JSON',
- e: e
- };
+ m.forEach(function (key, value) {
+ var fn = fs.isF(value[key]);
+ if (!fn) {
+ $log.warn(key + ' binding not a function on ' + value);
+ return;
}
- f(ev);
- };
+
+ if (handlers[key]) {
+ dups.push(key);
+ } else {
+ handlers[key] = fn;
+ }
+ });
+ if (dups.length) {
+ $log.warn('duplicate bindings ignored:', dups);
+ }
}
- function fnClose(f) {
- // wrap the onClose function; we will handle any parameters to the
- // close event here...
- if (!fs.isF(f)) {
- return null;
- }
+ // Unbinds the specified message handlers.
+ function unbindHandlers(handlerMap) {
+ var m = d3.map(handlerMap);
+ m.forEach(function (key) {
+ delete handlers[key];
+ });
+ }
- return function (closeEvent) {
- // NOTE: only seen {reason == ""} so far, nevertheless...
- f(closeEvent.reason);
- };
+ // Formulates an event message and sends it via the shared web-socket.
+ function sendEvent(evType, payload) {
+ var p = payload || {};
+ if (sws) {
+ $log.debug(' *Tx* >> ', evType, payload);
+ sws.send({
+ event: evType,
+ sid: ++sid,
+ payload: p
+ });
+ } else {
+ $log.warn('sendEvent: no websocket open:', evType, payload);
+ }
+ }
+
+
+ // Handles the specified message using handler bindings.
+ function handleMessage(msgEvent) {
+ var ev;
+ try {
+ ev = JSON.parse(msgEvent.data);
+ $log.debug(' *Rx* >> ', ev.event, ev.payload);
+ dispatchToHandler(ev);
+ } catch (e) {
+ $log.error('message is not valid JSON', msgEvent);
+ }
+ }
+
+ // Dispatches the message to the appropriate handler.
+ function dispatchToHandler(event) {
+ var handler = handlers[event.event];
+ if (handler) {
+ handler(event.payload);
+ } else {
+ $log.warn('unhandled event:', event);
+ }
+ }
+
+ function handleOpen() {
+ $log.info('web socket open');
+ // FIXME: implement calling external hooks
+ }
+
+ function handleClose() {
+ $log.info('web socket closed');
+ // FIXME: implement reconnect logic
}
angular.module('onosRemote')
.factory('WebSocketService',
['$log', '$location', 'UrlFnService', 'FnService',
- function ($log, $loc, ufs, _fs_) {
+ function (_$log_, $loc, ufs, _fs_) {
fs = _fs_;
+ $log = _$log_;
- // creates a web socket for the given path, returning a "handle".
+ // Creates a web socket for the given path, returning a "handle".
// opts contains the event handler callbacks, etc.
function createWebSocket(path, opts) {
var o = opts || {},
@@ -85,8 +128,7 @@
meta: { path: fullUrl, ws: null },
send: send,
close: close
- },
- ws;
+ };
try {
ws = new WebSocket(fullUrl);
@@ -97,23 +139,21 @@
$log.debug('Attempting to open websocket to: ' + fullUrl);
if (ws) {
- ws.onopen = fnOpen(o.onOpen);
- ws.onmessage = fnMessage(o.onMessage);
- ws.onclose = fnClose(o.onClose);
+ ws.onopen = handleOpen;
+ ws.onmessage = handleMessage;
+ ws.onclose = handleClose;
}
- // messages are expected to be event objects..
+ // Sends a formulated event message via the backing web-socket.
function send(ev) {
- if (ev) {
- if (ws) {
- ws.send(JSON.stringify(ev));
- } else {
- $log.warn('ws.send() no web socket open!',
- fullUrl, ev);
- }
+ if (ev && ws) {
+ ws.send(JSON.stringify(ev));
+ } else if (!ws) {
+ $log.warn('ws.send() no web socket open!', fullUrl, ev);
}
}
+ // Closes the backing web-socket.
function close() {
if (ws) {
ws.close();
@@ -122,11 +162,16 @@
}
}
+ sws = api; // Make the shared web-socket accessible
return api;
}
return {
- createWebSocket: createWebSocket
+ resetSid: resetSid,
+ createWebSocket: createWebSocket,
+ bindHandlers: bindHandlers,
+ unbindHandlers: unbindHandlers,
+ sendEvent: sendEvent
};
}]);
diff --git a/web/gui/src/main/webapp/app/fw/remote/wsevent.js b/web/gui/src/main/webapp/app/fw/remote/wsevent.js
index bf04b86..02d71b5 100644
--- a/web/gui/src/main/webapp/app/fw/remote/wsevent.js
+++ b/web/gui/src/main/webapp/app/fw/remote/wsevent.js
@@ -15,6 +15,7 @@
*/
/*
+ DEPRECATED: to be deleted
ONOS GUI -- Remote -- Web Socket Event Service
*/
(function () {
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index 4463936..3dd8d6e 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -263,7 +263,7 @@
// Cleanup on destroyed scope..
$scope.$on('$destroy', function () {
$log.log('OvTopoCtrl is saying Buh-Bye!');
- tes.closeSock();
+ tes.stop();
tps.destroyPanels();
tis.destroyInst();
tfs.destroyForce();
@@ -291,7 +291,7 @@
tfs.initForce(svg, forceG, uplink, dim);
tis.initInst({ showMastership: tfs.showMastership });
tps.initPanels({ sendEvent: tes.sendEvent });
- tes.openSock();
+ tes.start();
$log.log('OvTopoCtrl has been created');
}]);
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 099ba4e..10b6909 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -27,15 +27,15 @@
'use strict';
// injected refs
- var $log, wss, wes, vs, tps, tis, tfs, tss, tts;
+ var $log, vs, wss, tps, tis, tfs, tss, tts;
// internal state
- var wsock, evApis;
+ var handlers;
// ==========================
- function bindApis() {
- evApis = {
+ function createHandlers() {
+ handlers = {
showSummary: tps,
showDetails: tss,
@@ -58,103 +58,43 @@
};
}
- var nilApi = {},
- dispatcher = {
- handleEvent: function (ev) {
- var eid = ev.event,
- api = evApis[eid] || nilApi,
- eh = api[eid];
-
- if (eh) {
- $log.debug(' << *Rx* ', eid, ev.payload);
- eh(ev.payload);
- } else {
- $log.warn('Unknown event (ignored):', ev);
- }
- },
-
- sendEvent: function (evType, payload) {
- if (wsock) {
- $log.debug(' *Tx* >> ', evType, payload);
- wes.sendEvent(wsock, evType, payload);
- } else {
- $log.warn('sendEvent: no websocket open:', evType, payload);
- }
- }
- };
-
- // === Web Socket functions ===
-
- function onWsOpen() {
- $log.debug('web socket opened...');
- // start by requesting periodic summary data...
- dispatcher.sendEvent('requestSummary');
- vs.hide();
- }
-
- function onWsMessage(ev) {
- dispatcher.handleEvent(ev);
- }
-
- function onWsClose(reason) {
- $log.log('web socket closed; reason=', reason);
- wsock = null;
- vs.lostServer('OvTopoCtrl', [
- 'Oops!',
- 'Web-socket connection to server closed...',
- 'Try refreshing the page.'
- ]);
- }
-
- // ==========================
+ var nilApi = {};
angular.module('ovTopo')
.factory('TopoEventService',
- ['$log', '$location', 'WebSocketService', 'WsEventService', 'VeilService',
+ ['$log', '$location', 'VeilService', 'WebSocketService',
'TopoPanelService', 'TopoInstService', 'TopoForceService',
'TopoSelectService', 'TopoTrafficService',
- function (_$log_, $loc, _wss_, _wes_, _vs_,
- _tps_, _tis_, _tfs_, _tss_, _tts_) {
+ function (_$log_, $loc, _vs_, _wss_, _tps_, _tis_, _tfs_, _tss_, _tts_) {
$log = _$log_;
- wss = _wss_;
- wes = _wes_;
vs = _vs_;
+ wss = _wss_;
tps = _tps_;
tis = _tis_;
tfs = _tfs_;
tss = _tss_;
tts = _tts_;
- bindApis();
+ createHandlers();
- // TODO: handle "guiSuccessor" functionality (replace host)
- // TODO: implement retry on close functionality
-
- function openSock() {
- wsock = wss.createWebSocket('topology', {
- onOpen: onWsOpen,
- onMessage: onWsMessage,
- onClose: onWsClose,
- wsport: $loc.search().wsport
- });
- $log.debug('web socket opened:', wsock);
+ // FIXME: need to handle async socket open to avoid race
+ function start() {
+ wss.bindHandlers(handlers);
+ wss.sendEvent('topoStart');
+ $log.debug('topo comms started');
}
- function closeSock() {
- var path;
- if (wsock) {
- path = wsock.meta.path;
- wsock.close();
- wsock = null;
- $log.debug('web socket closed. path:', path);
- }
+ function stop() {
+ wss.unbindHandlers();
+ wss.sendEvent('topoStop');
+ $log.debug('topo comms stopped');
}
return {
- openSock: openSock,
- closeSock: closeSock,
- sendEvent: dispatcher.sendEvent
+ start: start,
+ stop: stop,
+ sendEvent: wss.sendEvent
};
}]);
}());
diff --git a/web/gui/src/main/webapp/onos.js b/web/gui/src/main/webapp/onos.js
index 0f049e9..97f3d06 100644
--- a/web/gui/src/main/webapp/onos.js
+++ b/web/gui/src/main/webapp/onos.js
@@ -64,10 +64,10 @@
.controller('OnosCtrl', [
'$log', '$route', '$routeParams', '$location',
'KeyService', 'ThemeService', 'GlyphService', 'PanelService',
- 'FlashService', 'QuickHelpService',
+ 'FlashService', 'QuickHelpService', 'WebSocketService',
function ($log, $route, $routeParams, $location,
- ks, ts, gs, ps, flash, qhs) {
+ ks, ts, gs, ps, flash, qhs, wss) {
var self = this;
self.$route = $route;
@@ -84,6 +84,13 @@
flash.initFlash();
qhs.initQuickHelp();
+ // TODO: register handlers for initial messages: instances, settings, etc.
+
+ // TODO: opts?
+ wss.createWebSocket('core', {
+ wsport: $location.search().wsport
+ });
+
$log.log('OnosCtrl has been created');
$log.debug('route: ', self.$route);