From a78e28402c8f7f495e74e99622f5335bd4c2882c Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 8 Nov 2012 12:36:16 -0500 Subject: [PATCH] LP#1268619: websocket JS additions Signed-off-by: Bill Erickson --- src/javascript/opensrf.js | 21 ++---- src/javascript/opensrf_ws.js | 157 ++++++++++++++++++++++++++++++------------- 2 files changed, 117 insertions(+), 61 deletions(-) diff --git a/src/javascript/opensrf.js b/src/javascript/opensrf.js index 408f0af..4287a57 100644 --- a/src/javascript/opensrf.js +++ b/src/javascript/opensrf.js @@ -206,9 +206,8 @@ OpenSRF.Session = function() { this.state = OSRF_APP_SESSION_DISCONNECTED; }; -OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_WS; -if (true || typeof WebSocket == 'undefined') - OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_XHR; +//OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_WS; +OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_XHR; OpenSRF.Session.cache = {}; OpenSRF.Session.find_session = function(thread_trace) { @@ -238,17 +237,11 @@ OpenSRF.Session.prototype.send_xhr = function(osrf_msg, args) { }; OpenSRF.Session.prototype.send_ws = function(osrf_msg, args) { - args.session = this; - if (this.websocket) { - this.websocket.args = args; // callbacks - this.websocket.send(osrf_msg); - } else { - this.websocket = new OpenSRF.WSRequest( - this, args, function(wsreq) { - wsreq.send(osrf_msg); - } - ); - } + new OpenSRF.WSRequest( + this, args, function(wsreq) { + wsreq.send(osrf_msg); + } + ); }; OpenSRF.Session.prototype.send_xmpp = function(osrf_msg, args) { diff --git a/src/javascript/opensrf_ws.js b/src/javascript/opensrf_ws.js index d522834..808e10c 100644 --- a/src/javascript/opensrf_ws.js +++ b/src/javascript/opensrf_ws.js @@ -13,91 +13,154 @@ * GNU General Public License for more details. * ----------------------------------------------------------------------- */ -var WS_PATH = '/osrf-websocket'; +var WEBSOCKET_URL_PATH = '/osrf-websocket-translator'; +var WEBSOCKET_PORT = 7680; +var WEBSOCKET_PORT_SSL = 7682; +var wsConnections = {}; + + +// Create the websocket and connect to the server +// args.onopen is required +// if args.default is true, use the default handle inst +OpenSRF.WebSocketConnection = function(handlers, connectArgs) { + connectArgs = connectArgs || {}; + this.handlers = handlers; + + var secure = (connectArgs.ssl || location.protocol == 'https'); + var path = connectArgs.path || WEBSOCKET_URL_PATH; + var port = connectArgs.port || (secure ? WEBSOCKET_PORT_SSL : WEBSOCKET_PORT); + var host = connectArgs.host || location.host; + this.path = proto + '://' + host + ':' + port + path; + + this.setupSocket(); + wsConnection[connectArgs.name] = this; +} /** - * onopen is required. no data can be sent - * until the async connection dance completes. + * create a new WebSocket. useful for new connections or + * applying a new socket to an existing connection (whose + * socket was disconnected) */ -OpenSRF.WSRequest = function(session, args, onopen) { - this.session = session; - this.args = args; - - var proto = location.protocol == 'https' ? 'wss' : 'ws'; - - var path = proto + '://' + location.host + - WS_PATH + '?service=' + this.session.service; +OpenSRF.WebSocketConnection.prototype.setupSocket = function() { try { - this.ws = new WebSocket(path); + this.socket = new WebSocket(this.path); } catch(e) { - throw new Error("WebSocket() not supported in this browser " + e); + throw new Error("WebSocket() not supported in this browser: " + e); } + this.socket.onopen = this.handlers.onopen; + this.socket.onmessage = this.handlers.onmessage; + this.socket.onerror = this.handlers.onerror; + this.socket.onclose = this.handlers.onclose; +} + +/** shut it down */ +OpenSRF.WebSocketConnection.prototype.destroy = function() { + if (this.socket.readyState == this.socket.OPEN) { + this.socket.close(); + delete wsConnections[this.name]; +} + +/** + * Creates the request object, but does not connect or send anything + * until the first call to send(). + */ +OpenSRF.WebSocketRequest = function(session, handlers, connectionArgs) { var self = this; + this.session = session; + this.handlers = handlers; + this.setupConnection(connectionArgs || {}); +} - this.ws.onopen = function(evt) { - onopen(self); - } +OpenSRF.WebSocketRequest.prototype.setupConnection = function(connectionArgs) { - this.ws.onmessage = function(evt) { - self.core_handler(evt.data); - } + var cname = connectionArgs.name || 'default'; + this.wsc = wsConnections[cname]; - this.ws.onerror = function(evt) { - self.transport_error_handler(evt.data); - } + if (this.wsc) { // we have a WebSocketConnection. + + if (this.wsc.socket.readyState == this.wsc.socket.CLOSED) { + // reset the connection + this.wsc.setupSocket(); + + } else { + + if (this.handlers.onopen) { + // socket is already open, but the user is expecting an onopen event + this.handlers.onopen(this); + } + } - this.ws.onclose = function(evt) { + } else { // no connection found + + if (cname == 'default' || connectionArgs.useDefaultHandlers) { // create the default handle + + this.wsc = new OpenSRF.WebSocketConnection(cname, { + onopen : function(evt) { + if (self.handlers.onopen) + self.handlers.onopen(self); + }, + onmessage : function(evt) { + self.core_handler(evt.data); + }, + onerror : function(evt) { + self.transport_error_handler(evt.data); + }, + onclose : function(evt) { + if (self.onclose) self.onclose(self); + } + }); + + } else { + throw new Error("No such WebSocketConnection '" + cname + "'"); + } } -}; +} -OpenSRF.WSRequest.prototype.send = function(message) { - //console.log('sending: ' + js2JSON([message.serialize()])); + +OpenSRF.WebSocketRequest.prototype.send = function(message) { + console.log('sending: ' + js2JSON([message.serialize()])); this.last_message = message; - this.ws.send(js2JSON([message.serialize()])); + this.wsc.socket.send(js2JSON([message.serialize()])); return this; }; -OpenSRF.WSRequest.prototype.close = function() { - try { this.ws.close(); } catch(e) {} -} - -OpenSRF.WSRequest.prototype.core_handler = function(json) { - //console.log('received: ' + json); +OpenSRF.WebSocketRequest.prototype.core_handler = function(json) { + console.log('received: ' + json); OpenSRF.Stack.push( new OpenSRF.NetMessage(null, null, '', json), { - onresponse : this.args.onresponse, - oncomplete : this.args.oncomplete, - onerror : this.args.onerror, + onresponse : this.handlers.onresponse, + oncomplete : this.handlers.oncomplete, + onerror : this.handlers.onerror, onmethoderror : this.method_error_handler() }, - this.args.session + this.handlers.session ); }; -OpenSRF.WSRequest.prototype.method_error_handler = function() { +OpenSRF.WebSocketRequest.prototype.method_error_handler = function() { var self = this; return function(req, status, status_text) { - if(self.args.onmethoderror) - self.args.onmethoderror(req, status, status_text); + if(self.handlers.onmethoderror) + self.handlers.onmethoderror(req, status, status_text); - if(self.args.onerror) { - self.args.onerror( + if(self.handlers.onerror) { + self.handlers.onerror( self.last_message, self.session.service, ''); } }; }; -OpenSRF.WSRequest.prototype.transport_error_handler = function(msg) { - if(this.args.ontransporterror) { - this.args.ontransporterror(msg); +OpenSRF.WebSocketRequest.prototype.transport_error_handler = function(msg) { + if(this.handlers.ontransporterror) { + this.handlers.ontransporterror(msg); } - if(this.args.onerror) { - this.args.onerror(msg, this.session.service, ''); + if(this.handlers.onerror) { + this.handlers.onerror(msg, this.session.service, ''); } }; -- 2.11.0