dojo.require('opensrf.JSON_v1', true);
dojo.require('opensrf.opensrf', true);
dojo.require('opensrf.opensrf_xhr', true);
+ dojo.require('opensrf.opensrf_ws', true);
OpenSRF.session_cache = {};
OpenSRF.CachedClientSession = function ( app ) {
/* types of transport layers */
var OSRF_TRANSPORT_TYPE_XHR = 1;
var OSRF_TRANSPORT_TYPE_XMPP = 2;
+var OSRF_TRANSPORT_TYPE_WS = 3;
/* message types */
var OSRF_MESSAGE_TYPE_REQUEST = 'REQUEST';
this.state = OSRF_APP_SESSION_DISCONNECTED;
};
-OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_XHR; /* default to XHR */
+OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_WS;
+if (true || typeof WebSocket == 'undefined')
+ OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_XHR;
+
OpenSRF.Session.cache = {};
OpenSRF.Session.find_session = function(thread_trace) {
return OpenSRF.Session.cache[thread_trace];
OpenSRF.Session.prototype.send = function(osrf_msg, args) {
args = (args) ? args : {};
switch(OpenSRF.Session.transport) {
+ case OSRF_TRANSPORT_TYPE_WS:
+ return this.send_ws(osrf_msg, args);
case OSRF_TRANSPORT_TYPE_XHR:
return this.send_xhr(osrf_msg, args);
case OSRF_TRANSPORT_TYPE_XMPP:
new OpenSRF.XHRequest(osrf_msg, args).send();
};
+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);
+ }
+ );
+ }
+};
+
OpenSRF.Session.prototype.send_xmpp = function(osrf_msg, args) {
- alert('xmpp transport not yet implemented');
+ alert('xmpp transport not implemented');
};
args = (args) ? args : {};
this.remote_id = null;
- if(args.onconnect)
+ if (this.state == OSRF_APP_SESSION_CONNECTED) {
+ if (args.onconnect) args.onconnect();
+ return true;
+ }
+
+ if(args.onconnect) {
this.onconnect = args.onconnect;
- /* if no handler is provided, make this a synchronous call */
- if(!this.onconnect)
+ } else {
+ /* if no handler is provided, make this a synchronous call */
this.timeout = (args.timeout) ? args.timeout : 5;
+ }
message = new osrfMessage({
- 'threadTrace' : this.reqid,
+ 'threadTrace' : this.last_id++,
'type' : OSRF_MESSAGE_TYPE_CONNECT
});
if(this.onconnect || this.state == OSRF_APP_SESSION_CONNECTED)
return true;
+
return false;
};
OpenSRF.ClientSession.prototype.disconnect = function(args) {
- this.send(
- new osrfMessage({
- 'threadTrace' : this.reqid,
- 'type' : OSRF_MESSAGE_TYPE_DISCONNECT
- })
- );
+
+ if (this.state == OSRF_APP_SESSION_CONNECTED) {
+ this.send(
+ new osrfMessage({
+ 'threadTrace' : this.last_id++,
+ 'type' : OSRF_MESSAGE_TYPE_DISCONNECT
+ })
+ );
+ }
+
this.remote_id = null;
+ this.state = OSRF_APP_SESSION_DISCONNECTED;
+
+ if (this.websocket) {
+ this.websocket.close();
+ delete this.websocket;
+ }
};
}
}
-OpenSRF.Stack.push = function(net_msg, callbacks) {
- var ses = OpenSRF.Session.find_session(net_msg.thread);
- if(!ses) return;
+// ses may be passed to us by the network handler
+OpenSRF.Stack.push = function(net_msg, callbacks, ses) {
+ if (!ses) ses = OpenSRF.Session.find_session(net_msg.thread);
+ if (!ses) return;
ses.remote_id = net_msg.from;
osrf_msgs = [];
--- /dev/null
+/* -----------------------------------------------------------------------
+ * Copyright (C) 2012 Equinox Software, Inc.
+ * Bill Erickson <berick@esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * ----------------------------------------------------------------------- */
+
+var WS_PATH = '/osrf-websocket';
+
+/**
+ * onopen is required. no data can be sent
+ * until the async connection dance completes.
+ */
+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;
+
+ try {
+ this.ws = new WebSocket(path);
+ } catch(e) {
+ throw new Error("WebSocket() not supported in this browser " + e);
+ }
+
+ var self = this;
+
+ this.ws.onopen = function(evt) {
+ onopen(self);
+ }
+
+ this.ws.onmessage = function(evt) {
+ self.core_handler(evt.data);
+ }
+
+ this.ws.onerror = function(evt) {
+ self.transport_error_handler(evt.data);
+ }
+
+ this.ws.onclose = function(evt) {
+ }
+};
+
+OpenSRF.WSRequest.prototype.send = function(message) {
+ //console.log('sending: ' + js2JSON([message.serialize()]));
+ this.last_message = message;
+ this.ws.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.Stack.push(
+ new OpenSRF.NetMessage(null, null, '', json),
+ {
+ onresponse : this.args.onresponse,
+ oncomplete : this.args.oncomplete,
+ onerror : this.args.onerror,
+ onmethoderror : this.method_error_handler()
+ },
+ this.args.session
+ );
+};
+
+
+OpenSRF.WSRequest.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.args.onerror) {
+ self.args.onerror(
+ self.last_message, self.session.service, '');
+ }
+ };
+};
+
+OpenSRF.WSRequest.prototype.transport_error_handler = function(msg) {
+ if(this.args.ontransporterror) {
+ this.args.ontransporterror(msg);
+ }
+ if(this.args.onerror) {
+ this.args.onerror(msg, this.session.service, '');
+ }
+};
+
+