LP#1268619: websocket JS
authorBill Erickson <berick@esilibrary.com>
Fri, 9 Nov 2012 15:52:48 +0000 (10:52 -0500)
committerBill Erickson <berick@esilibrary.com>
Sun, 4 May 2014 20:10:33 +0000 (16:10 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
src/javascript/opensrf.js
src/javascript/opensrf_ws.js

index 4287a57..c4ccd2e 100644 (file)
@@ -237,9 +237,14 @@ OpenSRF.Session.prototype.send_xhr = function(osrf_msg, args) {
 };
 
 OpenSRF.Session.prototype.send_ws = function(osrf_msg, args) {
-    new OpenSRF.WSRequest(
-        this, args, function(wsreq) {
-            wsreq.send(osrf_msg);
+    new OpenSRF.WebSocketRequest(
+        this, {
+            onopen : function(wsreq) { wsreq.send(osrf_msg) },
+            onresponse : args.onresponse,
+            oncomplete : args.oncomplete,
+            onerror : args.onerror,
+            onmethoderror : args.onmethoderror,
+            ontransporterror : args.ontransporterror,
         }
     );
 };
@@ -255,9 +260,9 @@ OpenSRF.ClientSession = function(service) {
     this.remote_id = null;
     this.locale = OpenSRF.locale || 'en-US';
     this.last_id = 0;
-    this.thread = Math.random() + '' + new Date().getTime();
     this.requests = [];
     this.onconnect = null;
+    this.thread = Math.random() + '' + new Date().getTime();
     OpenSRF.Session.cache[this.thread] = this;
 };
 OpenSRF.set_subclass('OpenSRF.ClientSession', 'OpenSRF.Session');
@@ -437,6 +442,11 @@ OpenSRF.Stack.push = function(net_msg, callbacks, ses) {
     try {
         osrf_msgs = JSON2js(net_msg.body);
 
+        if (OpenSRF.Session.transport == OSRF_TRANSPORT_TYPE_WS) {
+            // WebSocketRequests wrap the content
+            osrf_msgs = osrf_msgs.osrf_msg;
+        }
+
     } catch(E) {
         log('Error parsing OpenSRF message body as JSON: ' + net_msg.body + '\n' + E);
 
@@ -510,8 +520,9 @@ OpenSRF.Stack.handle_message = function(ses, osrf_msg, callbacks) {
         req = ses.find_request(osrf_msg.threadTrace());
         if(req) {
             req.response_queue.push(osrf_msg.payload());
-            if(callbacks.onresponse) 
+            if(callbacks.onresponse) {
                 return callbacks.onresponse(req);
+            }
         }
     }
 };
index 808e10c..79c80f4 100644 (file)
  * GNU General Public License for more details.
  * ----------------------------------------------------------------------- */
 
+// opensrf defaults
 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) {
+OpenSRF.WebSocketConnection = function(connectArgs, handlers) {
     connectArgs = connectArgs || {};
     this.handlers = handlers;
 
@@ -30,10 +30,18 @@ OpenSRF.WebSocketConnection = function(handlers, connectArgs) {
     var path = connectArgs.path || WEBSOCKET_URL_PATH;
     var port = connectArgs.port || (secure ? WEBSOCKET_PORT_SSL : WEBSOCKET_PORT);
     var host = connectArgs.host || location.host;
+    var proto = (secure) ? 'wss' : 'ws';
     this.path = proto + '://' + host + ':' + port + path;
 
     this.setupSocket();
-    wsConnection[connectArgs.name] = this;
+    OpenSRF.WebSocketConnection.pool[connectArgs.name] = this;
+};
+
+// global pool of connection objects; name => connection map
+OpenSRF.WebSocketConnection.pool = {};
+
+OpenSRF.WebSocketConnection.defaultConnection = function() {
+    return OpenSRF.WebSocketConnection.pool['default'];
 }
 
 /**
@@ -53,14 +61,13 @@ OpenSRF.WebSocketConnection.prototype.setupSocket = function() {
     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];
-}
+    this.socket.close();
+    delete OpenSRF.WebSocketConnection.pool[this.name];
+};
 
 /**
  * Creates the request object, but does not connect or send anything
@@ -74,43 +81,61 @@ OpenSRF.WebSocketRequest = function(session, handlers, connectionArgs) {
 }
 
 OpenSRF.WebSocketRequest.prototype.setupConnection = function(connectionArgs) {
+    var self = this;
 
     var cname = connectionArgs.name || 'default';
-    this.wsc = wsConnections[cname];
+    this.wsc = OpenSRF.WebSocketConnection.pool[cname];
 
     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
+        console.log('socket readySate = ' + this.wsc.socket.readyState);
+        switch (this.wsc.socket.readyState) {
+
+            case this.wsc.socket.CONNECTING:
+                // replace the original onopen handler with a new combined handler
+                var orig_open = this.wsc.socket.onopen;
+                this.wsc.socket.onopen = function() {
+                    console.log('combined onopen');
+                    orig_open();
+                    console.log('combined onopen 2');
+                    self.handlers.onopen(self);
+                    console.log('combined onopen ' + self.handlers.onopen);
+                };
+                break;
+
+            case this.wsc.socket.OPEN:
+                // user is expecting an onopen event.  socket is 
+                // already open, so we have to manufacture one.
                 this.handlers.onopen(this);
-            }
+                break;
+
+            default:
+                console.log('WebSocket is no longer connecting; reconnecting');
+                this.wsc.setupSocket();
         }
 
     } 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); 
-                }
-            });
+            this.wsc = new OpenSRF.WebSocketConnection(
+                {name : 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.handlers.onclose) 
+                            self.handlers.onclose(self); 
+                    }
+                } 
+            );
 
         } else {
             throw new Error("No such WebSocketConnection '" + cname + "'");
@@ -120,24 +145,32 @@ OpenSRF.WebSocketRequest.prototype.setupConnection = function(connectionArgs) {
 
 
 OpenSRF.WebSocketRequest.prototype.send = function(message) {
-    console.log('sending: ' + js2JSON([message.serialize()]));
     this.last_message = message;
-    this.wsc.socket.send(js2JSON([message.serialize()]));
+
+    var wrapper = {
+        service : this.session.service,
+        thread : this.session.thread,
+        osrf_msg : [message.serialize()]
+    };
+
+    var json = js2JSON(wrapper);
+    console.log('sending: ' + json);
+
+    // drop it on the wire
+    this.wsc.socket.send(json);
     return this;
 };
 
 OpenSRF.WebSocketRequest.prototype.core_handler = function(json) {
-    console.log('received: ' + json);
-
     OpenSRF.Stack.push(
-        new OpenSRF.NetMessage(null, null, '', json),
+        new OpenSRF.NetMessage(null, null, this.session.thread, json),
         {
             onresponse : this.handlers.onresponse,
             oncomplete : this.handlers.oncomplete,
             onerror : this.handlers.onerror,
             onmethoderror : this.method_error_handler()
         },
-        this.handlers.session
+        this.session
     );
 };