diff --git a/README.md b/README.md index 0cb405294a..ef704f96c2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A Javascript client library for [Ably Realtime](https://www.ably.io), a realtime data delivery platform. -## Version: 1.0.0 +## Version: 1.0.1 This repo contains the Ably Javascript client library, for the browser (including IE8+), Nodejs, React Native, NativeScript and Cordova. diff --git a/bower.json b/bower.json index 38874039c1..f862718f58 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "Ably", - "version": "1.0.0", + "version": "1.0.1", "homepage": "https://www.ably.io/", "authors": [ "Paddy Byers ", diff --git a/browser/fragments/license.js b/browser/fragments/license.js index f5a12dc42f..eeb0ce7014 100644 --- a/browser/fragments/license.js +++ b/browser/fragments/license.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging diff --git a/browser/static/ably-commonjs.js b/browser/static/ably-commonjs.js index 1d5d0cc292..0d2e4b8613 100644 --- a/browser/static/ably-commonjs.js +++ b/browser/static/ably-commonjs.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging @@ -3538,11 +3538,12 @@ var Defaults = { internetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up.txt', jsonpInternetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up-0-9.js', /* Order matters here: the base transport is the leftmost one in the - * intersection of this list and the transports clientOption that's + * intersection of baseTransportOrder and the transports clientOption that's * supported. This is not quite the same as the preference order -- e.g. * xhr_polling is preferred to jsonp, but for browsers that support it we want * the base transport to be xhr_polling, not jsonp */ - transports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + defaultTransports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + baseTransportOrder: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], transportPreferenceOrder: ['jsonp', 'xhr_polling', 'xhr_streaming', 'web_socket'], upgradeTransports: ['xhr_streaming', 'web_socket'], minified: !(function _(){}).name @@ -4076,7 +4077,7 @@ Defaults.TIMEOUTS = { }; Defaults.httpMaxRetryCount = 3; -Defaults.version = '1.0.0'; +Defaults.version = '1.0.1'; Defaults.libstring = 'js-' + Defaults.version; Defaults.apiVersion = '1.0'; @@ -5776,7 +5777,7 @@ var ConnectionManager = (function() { initialized: {state: 'initialized', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, connecting: {state: 'connecting', terminal: false, queueEvents: true, sendEvents: false, retryDelay: connectingTimeout, failState: 'disconnected'}, connected: {state: 'connected', terminal: false, queueEvents: false, sendEvents: true, failState: 'disconnected'}, - synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, + synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, forceQueueEvents: true, failState: 'disconnected'}, disconnected: {state: 'disconnected', terminal: false, queueEvents: true, sendEvents: false, retryDelay: timeouts.disconnectedRetryTimeout, failState: 'disconnected'}, suspended: {state: 'suspended', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.suspendedRetryTimeout, failState: 'suspended'}, closing: {state: 'closing', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.realtimeRequestTimeout, failState: 'closed'}, @@ -5792,12 +5793,12 @@ var ConnectionManager = (function() { this.connectionKey = undefined; this.connectionSerial = undefined; - this.transports = Utils.intersect((options.transports || Defaults.transports), ConnectionManager.supportedTransports); - /* baseTransports selects the leftmost transport in the Defaults.transports list + this.transports = Utils.intersect((options.transports || Defaults.defaultTransports), ConnectionManager.supportedTransports); + /* baseTransports selects the leftmost transport in the Defaults.baseTransportOrder list * that's both requested and supported. Normally this will be xhr_polling; * if xhr isn't supported it will be jsonp. If the user has forced a * transport, it'll just be that one. */ - this.baseTransport = Utils.intersect(Defaults.transports, this.transports)[0]; + this.baseTransport = Utils.intersect(Defaults.baseTransportOrder, this.transports)[0]; this.upgradeTransports = Utils.intersect(this.transports, Defaults.upgradeTransports); /* Map of hosts to an array of transports to not be tried for that host */ this.transportHostBlacklist = {}; @@ -5811,7 +5812,7 @@ var ConnectionManager = (function() { this.lastAutoReconnectAttempt = null; Logger.logAction(Logger.LOG_MINOR, 'Realtime.ConnectionManager()', 'started'); - Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.transports) + ']'); + Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.defaultTransports) + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'available transports = [' + this.transports + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'http hosts = [' + this.httpHosts + ']'); @@ -6194,8 +6195,6 @@ var ConnectionManager = (function() { }); }) - this.emit('transport.active', transport, connectionKey, transport.params); - /* If previously not connected, notify the state change (including any * error). */ if(existingState.state === this.states.connected.state) { @@ -6211,6 +6210,10 @@ var ConnectionManager = (function() { this.errorReason = this.realtime.connection.errorReason = error || null; } + /* Send after the connection state update, as Channels hooks into this to + * resend attaches on a new transport if necessary */ + this.emit('transport.active', transport, connectionKey, transport.params); + /* Gracefully terminate existing protocol */ if(existingActiveProtocol) { if(existingActiveProtocol.messageQueue.count() > 0) { @@ -6338,8 +6341,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -6764,8 +6769,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -6807,8 +6811,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -6953,7 +6958,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -6962,18 +6967,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -9169,13 +9173,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -9211,7 +9209,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -9742,7 +9742,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -9947,8 +9949,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -10054,12 +10059,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -10351,6 +10360,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -10952,6 +10962,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -10970,16 +10990,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -11016,7 +11026,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); @@ -11077,27 +11086,6 @@ var JSONPTransport = (function() { * connectionmanager should ensure this doesn't happen anyway */ var checksInProgress = null; window.JSONPTransport = JSONPTransport - JSONPTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.jsonpInternetUpUrl; - - if(checksInProgress) { - checksInProgress.push(callback); - return; - } - checksInProgress = [callback]; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Sending; ' + upUrl); - - var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); - req.once('complete', function(err, response) { - var result = !err && response; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Result: ' + result); - for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); - checksInProgress = null; - }); - Utils.nextTick(function() { - req.exec(); - }); - }; JSONPTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new JSONPTransport(connectionManager, auth, params); @@ -11241,6 +11229,28 @@ var JSONPTransport = (function() { }); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.jsonpInternetUpUrl; + + if(checksInProgress) { + checksInProgress.push(callback); + return; + } + checksInProgress = [callback]; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Sending; ' + upUrl); + + var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); + req.once('complete', function(err, response) { + var result = !err && response; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Result: ' + result); + for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); + checksInProgress = null; + }); + Utils.nextTick(function() { + req.exec(); + }); + }; } return JSONPTransport; diff --git a/browser/static/ably-commonjs.noencryption.js b/browser/static/ably-commonjs.noencryption.js index 83e6c549b9..3460bbdd7d 100644 --- a/browser/static/ably-commonjs.noencryption.js +++ b/browser/static/ably-commonjs.noencryption.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging @@ -2106,11 +2106,12 @@ var Defaults = { internetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up.txt', jsonpInternetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up-0-9.js', /* Order matters here: the base transport is the leftmost one in the - * intersection of this list and the transports clientOption that's + * intersection of baseTransportOrder and the transports clientOption that's * supported. This is not quite the same as the preference order -- e.g. * xhr_polling is preferred to jsonp, but for browsers that support it we want * the base transport to be xhr_polling, not jsonp */ - transports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + defaultTransports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + baseTransportOrder: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], transportPreferenceOrder: ['jsonp', 'xhr_polling', 'xhr_streaming', 'web_socket'], upgradeTransports: ['xhr_streaming', 'web_socket'], minified: !(function _(){}).name @@ -2644,7 +2645,7 @@ Defaults.TIMEOUTS = { }; Defaults.httpMaxRetryCount = 3; -Defaults.version = '1.0.0'; +Defaults.version = '1.0.1'; Defaults.libstring = 'js-' + Defaults.version; Defaults.apiVersion = '1.0'; @@ -4344,7 +4345,7 @@ var ConnectionManager = (function() { initialized: {state: 'initialized', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, connecting: {state: 'connecting', terminal: false, queueEvents: true, sendEvents: false, retryDelay: connectingTimeout, failState: 'disconnected'}, connected: {state: 'connected', terminal: false, queueEvents: false, sendEvents: true, failState: 'disconnected'}, - synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, + synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, forceQueueEvents: true, failState: 'disconnected'}, disconnected: {state: 'disconnected', terminal: false, queueEvents: true, sendEvents: false, retryDelay: timeouts.disconnectedRetryTimeout, failState: 'disconnected'}, suspended: {state: 'suspended', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.suspendedRetryTimeout, failState: 'suspended'}, closing: {state: 'closing', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.realtimeRequestTimeout, failState: 'closed'}, @@ -4360,12 +4361,12 @@ var ConnectionManager = (function() { this.connectionKey = undefined; this.connectionSerial = undefined; - this.transports = Utils.intersect((options.transports || Defaults.transports), ConnectionManager.supportedTransports); - /* baseTransports selects the leftmost transport in the Defaults.transports list + this.transports = Utils.intersect((options.transports || Defaults.defaultTransports), ConnectionManager.supportedTransports); + /* baseTransports selects the leftmost transport in the Defaults.baseTransportOrder list * that's both requested and supported. Normally this will be xhr_polling; * if xhr isn't supported it will be jsonp. If the user has forced a * transport, it'll just be that one. */ - this.baseTransport = Utils.intersect(Defaults.transports, this.transports)[0]; + this.baseTransport = Utils.intersect(Defaults.baseTransportOrder, this.transports)[0]; this.upgradeTransports = Utils.intersect(this.transports, Defaults.upgradeTransports); /* Map of hosts to an array of transports to not be tried for that host */ this.transportHostBlacklist = {}; @@ -4379,7 +4380,7 @@ var ConnectionManager = (function() { this.lastAutoReconnectAttempt = null; Logger.logAction(Logger.LOG_MINOR, 'Realtime.ConnectionManager()', 'started'); - Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.transports) + ']'); + Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.defaultTransports) + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'available transports = [' + this.transports + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'http hosts = [' + this.httpHosts + ']'); @@ -4762,8 +4763,6 @@ var ConnectionManager = (function() { }); }) - this.emit('transport.active', transport, connectionKey, transport.params); - /* If previously not connected, notify the state change (including any * error). */ if(existingState.state === this.states.connected.state) { @@ -4779,6 +4778,10 @@ var ConnectionManager = (function() { this.errorReason = this.realtime.connection.errorReason = error || null; } + /* Send after the connection state update, as Channels hooks into this to + * resend attaches on a new transport if necessary */ + this.emit('transport.active', transport, connectionKey, transport.params); + /* Gracefully terminate existing protocol */ if(existingActiveProtocol) { if(existingActiveProtocol.messageQueue.count() > 0) { @@ -4906,8 +4909,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -5332,8 +5337,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -5375,8 +5379,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -5521,7 +5526,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -5530,18 +5535,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -7737,13 +7741,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -7779,7 +7777,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -8310,7 +8310,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -8515,8 +8517,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -8622,12 +8627,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -8919,6 +8928,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -9520,6 +9530,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -9538,16 +9558,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -9584,7 +9594,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); @@ -9645,27 +9654,6 @@ var JSONPTransport = (function() { * connectionmanager should ensure this doesn't happen anyway */ var checksInProgress = null; window.JSONPTransport = JSONPTransport - JSONPTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.jsonpInternetUpUrl; - - if(checksInProgress) { - checksInProgress.push(callback); - return; - } - checksInProgress = [callback]; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Sending; ' + upUrl); - - var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); - req.once('complete', function(err, response) { - var result = !err && response; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Result: ' + result); - for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); - checksInProgress = null; - }); - Utils.nextTick(function() { - req.exec(); - }); - }; JSONPTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new JSONPTransport(connectionManager, auth, params); @@ -9809,6 +9797,28 @@ var JSONPTransport = (function() { }); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.jsonpInternetUpUrl; + + if(checksInProgress) { + checksInProgress.push(callback); + return; + } + checksInProgress = [callback]; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Sending; ' + upUrl); + + var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); + req.once('complete', function(err, response) { + var result = !err && response; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Result: ' + result); + for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); + checksInProgress = null; + }); + Utils.nextTick(function() { + req.exec(); + }); + }; } return JSONPTransport; diff --git a/browser/static/ably-nativescript.js b/browser/static/ably-nativescript.js index 18dacf0670..9860911aee 100644 --- a/browser/static/ably-nativescript.js +++ b/browser/static/ably-nativescript.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging @@ -3480,11 +3480,12 @@ var Defaults = { internetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up.txt', jsonpInternetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up-0-9.js', /* Order matters here: the base transport is the leftmost one in the - * intersection of this list and the transports clientOption that's + * intersection of baseTransportOrder and the transports clientOption that's * supported. This is not quite the same as the preference order -- e.g. * xhr_polling is preferred to jsonp, but for browsers that support it we want * the base transport to be xhr_polling, not jsonp */ - transports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + defaultTransports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + baseTransportOrder: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], transportPreferenceOrder: ['jsonp', 'xhr_polling', 'xhr_streaming', 'web_socket'], upgradeTransports: ['xhr_streaming', 'web_socket'], minified: !(function _(){}).name @@ -4018,7 +4019,7 @@ Defaults.TIMEOUTS = { }; Defaults.httpMaxRetryCount = 3; -Defaults.version = '1.0.0'; +Defaults.version = '1.0.1'; Defaults.libstring = 'js-' + Defaults.version; Defaults.apiVersion = '1.0'; @@ -5718,7 +5719,7 @@ var ConnectionManager = (function() { initialized: {state: 'initialized', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, connecting: {state: 'connecting', terminal: false, queueEvents: true, sendEvents: false, retryDelay: connectingTimeout, failState: 'disconnected'}, connected: {state: 'connected', terminal: false, queueEvents: false, sendEvents: true, failState: 'disconnected'}, - synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, + synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, forceQueueEvents: true, failState: 'disconnected'}, disconnected: {state: 'disconnected', terminal: false, queueEvents: true, sendEvents: false, retryDelay: timeouts.disconnectedRetryTimeout, failState: 'disconnected'}, suspended: {state: 'suspended', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.suspendedRetryTimeout, failState: 'suspended'}, closing: {state: 'closing', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.realtimeRequestTimeout, failState: 'closed'}, @@ -5734,12 +5735,12 @@ var ConnectionManager = (function() { this.connectionKey = undefined; this.connectionSerial = undefined; - this.transports = Utils.intersect((options.transports || Defaults.transports), ConnectionManager.supportedTransports); - /* baseTransports selects the leftmost transport in the Defaults.transports list + this.transports = Utils.intersect((options.transports || Defaults.defaultTransports), ConnectionManager.supportedTransports); + /* baseTransports selects the leftmost transport in the Defaults.baseTransportOrder list * that's both requested and supported. Normally this will be xhr_polling; * if xhr isn't supported it will be jsonp. If the user has forced a * transport, it'll just be that one. */ - this.baseTransport = Utils.intersect(Defaults.transports, this.transports)[0]; + this.baseTransport = Utils.intersect(Defaults.baseTransportOrder, this.transports)[0]; this.upgradeTransports = Utils.intersect(this.transports, Defaults.upgradeTransports); /* Map of hosts to an array of transports to not be tried for that host */ this.transportHostBlacklist = {}; @@ -5753,7 +5754,7 @@ var ConnectionManager = (function() { this.lastAutoReconnectAttempt = null; Logger.logAction(Logger.LOG_MINOR, 'Realtime.ConnectionManager()', 'started'); - Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.transports) + ']'); + Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.defaultTransports) + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'available transports = [' + this.transports + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'http hosts = [' + this.httpHosts + ']'); @@ -6136,8 +6137,6 @@ var ConnectionManager = (function() { }); }) - this.emit('transport.active', transport, connectionKey, transport.params); - /* If previously not connected, notify the state change (including any * error). */ if(existingState.state === this.states.connected.state) { @@ -6153,6 +6152,10 @@ var ConnectionManager = (function() { this.errorReason = this.realtime.connection.errorReason = error || null; } + /* Send after the connection state update, as Channels hooks into this to + * resend attaches on a new transport if necessary */ + this.emit('transport.active', transport, connectionKey, transport.params); + /* Gracefully terminate existing protocol */ if(existingActiveProtocol) { if(existingActiveProtocol.messageQueue.count() > 0) { @@ -6280,8 +6283,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -6706,8 +6711,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -6749,8 +6753,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -6895,7 +6900,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -6904,18 +6909,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -9111,13 +9115,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -9153,7 +9151,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -9684,7 +9684,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -9889,8 +9891,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -9996,12 +10001,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -10293,6 +10302,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -10894,6 +10904,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -10912,16 +10932,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -10958,7 +10968,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); diff --git a/browser/static/ably-reactnative.js b/browser/static/ably-reactnative.js index 0aaf0f3a82..99d4be38d5 100644 --- a/browser/static/ably-reactnative.js +++ b/browser/static/ably-reactnative.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging @@ -3509,11 +3509,12 @@ var Defaults = { internetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up.txt', jsonpInternetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up-0-9.js', /* Order matters here: the base transport is the leftmost one in the - * intersection of this list and the transports clientOption that's + * intersection of baseTransportOrder and the transports clientOption that's * supported. This is not quite the same as the preference order -- e.g. * xhr_polling is preferred to jsonp, but for browsers that support it we want * the base transport to be xhr_polling, not jsonp */ - transports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + defaultTransports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + baseTransportOrder: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], transportPreferenceOrder: ['jsonp', 'xhr_polling', 'xhr_streaming', 'web_socket'], upgradeTransports: ['xhr_streaming', 'web_socket'], minified: !(function _(){}).name @@ -4047,7 +4048,7 @@ Defaults.TIMEOUTS = { }; Defaults.httpMaxRetryCount = 3; -Defaults.version = '1.0.0'; +Defaults.version = '1.0.1'; Defaults.libstring = 'js-' + Defaults.version; Defaults.apiVersion = '1.0'; @@ -5747,7 +5748,7 @@ var ConnectionManager = (function() { initialized: {state: 'initialized', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, connecting: {state: 'connecting', terminal: false, queueEvents: true, sendEvents: false, retryDelay: connectingTimeout, failState: 'disconnected'}, connected: {state: 'connected', terminal: false, queueEvents: false, sendEvents: true, failState: 'disconnected'}, - synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, + synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, forceQueueEvents: true, failState: 'disconnected'}, disconnected: {state: 'disconnected', terminal: false, queueEvents: true, sendEvents: false, retryDelay: timeouts.disconnectedRetryTimeout, failState: 'disconnected'}, suspended: {state: 'suspended', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.suspendedRetryTimeout, failState: 'suspended'}, closing: {state: 'closing', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.realtimeRequestTimeout, failState: 'closed'}, @@ -5763,12 +5764,12 @@ var ConnectionManager = (function() { this.connectionKey = undefined; this.connectionSerial = undefined; - this.transports = Utils.intersect((options.transports || Defaults.transports), ConnectionManager.supportedTransports); - /* baseTransports selects the leftmost transport in the Defaults.transports list + this.transports = Utils.intersect((options.transports || Defaults.defaultTransports), ConnectionManager.supportedTransports); + /* baseTransports selects the leftmost transport in the Defaults.baseTransportOrder list * that's both requested and supported. Normally this will be xhr_polling; * if xhr isn't supported it will be jsonp. If the user has forced a * transport, it'll just be that one. */ - this.baseTransport = Utils.intersect(Defaults.transports, this.transports)[0]; + this.baseTransport = Utils.intersect(Defaults.baseTransportOrder, this.transports)[0]; this.upgradeTransports = Utils.intersect(this.transports, Defaults.upgradeTransports); /* Map of hosts to an array of transports to not be tried for that host */ this.transportHostBlacklist = {}; @@ -5782,7 +5783,7 @@ var ConnectionManager = (function() { this.lastAutoReconnectAttempt = null; Logger.logAction(Logger.LOG_MINOR, 'Realtime.ConnectionManager()', 'started'); - Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.transports) + ']'); + Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.defaultTransports) + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'available transports = [' + this.transports + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'http hosts = [' + this.httpHosts + ']'); @@ -6165,8 +6166,6 @@ var ConnectionManager = (function() { }); }) - this.emit('transport.active', transport, connectionKey, transport.params); - /* If previously not connected, notify the state change (including any * error). */ if(existingState.state === this.states.connected.state) { @@ -6182,6 +6181,10 @@ var ConnectionManager = (function() { this.errorReason = this.realtime.connection.errorReason = error || null; } + /* Send after the connection state update, as Channels hooks into this to + * resend attaches on a new transport if necessary */ + this.emit('transport.active', transport, connectionKey, transport.params); + /* Gracefully terminate existing protocol */ if(existingActiveProtocol) { if(existingActiveProtocol.messageQueue.count() > 0) { @@ -6309,8 +6312,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -6735,8 +6740,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -6778,8 +6782,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -6924,7 +6929,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -6933,18 +6938,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -9140,13 +9144,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -9182,7 +9180,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -9713,7 +9713,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -9918,8 +9920,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -10025,12 +10030,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -10322,6 +10331,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -10923,6 +10933,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -10941,16 +10961,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -10987,7 +10997,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); diff --git a/browser/static/ably.js b/browser/static/ably.js index 2662e1203e..2471d8031f 100644 --- a/browser/static/ably.js +++ b/browser/static/ably.js @@ -1,7 +1,7 @@ /** * @license Copyright 2017, Ably * - * Ably JavaScript Library v1.0.0 + * Ably JavaScript Library v1.0.1 * https://github.com/ably/ably-js * * Ably Realtime Messaging @@ -3549,11 +3549,12 @@ var Defaults = { internetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up.txt', jsonpInternetUpUrl: 'https://internet-up.ably-realtime.com/is-the-internet-up-0-9.js', /* Order matters here: the base transport is the leftmost one in the - * intersection of this list and the transports clientOption that's + * intersection of baseTransportOrder and the transports clientOption that's * supported. This is not quite the same as the preference order -- e.g. * xhr_polling is preferred to jsonp, but for browsers that support it we want * the base transport to be xhr_polling, not jsonp */ - transports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + defaultTransports: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], + baseTransportOrder: ['xhr_polling', 'xhr_streaming', 'jsonp', 'web_socket'], transportPreferenceOrder: ['jsonp', 'xhr_polling', 'xhr_streaming', 'web_socket'], upgradeTransports: ['xhr_streaming', 'web_socket'], minified: !(function _(){}).name @@ -4087,7 +4088,7 @@ Defaults.TIMEOUTS = { }; Defaults.httpMaxRetryCount = 3; -Defaults.version = '1.0.0'; +Defaults.version = '1.0.1'; Defaults.libstring = 'js-' + Defaults.version; Defaults.apiVersion = '1.0'; @@ -5787,7 +5788,7 @@ var ConnectionManager = (function() { initialized: {state: 'initialized', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, connecting: {state: 'connecting', terminal: false, queueEvents: true, sendEvents: false, retryDelay: connectingTimeout, failState: 'disconnected'}, connected: {state: 'connected', terminal: false, queueEvents: false, sendEvents: true, failState: 'disconnected'}, - synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, failState: 'disconnected'}, + synchronizing: {state: 'connected', terminal: false, queueEvents: true, sendEvents: false, forceQueueEvents: true, failState: 'disconnected'}, disconnected: {state: 'disconnected', terminal: false, queueEvents: true, sendEvents: false, retryDelay: timeouts.disconnectedRetryTimeout, failState: 'disconnected'}, suspended: {state: 'suspended', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.suspendedRetryTimeout, failState: 'suspended'}, closing: {state: 'closing', terminal: false, queueEvents: false, sendEvents: false, retryDelay: timeouts.realtimeRequestTimeout, failState: 'closed'}, @@ -5803,12 +5804,12 @@ var ConnectionManager = (function() { this.connectionKey = undefined; this.connectionSerial = undefined; - this.transports = Utils.intersect((options.transports || Defaults.transports), ConnectionManager.supportedTransports); - /* baseTransports selects the leftmost transport in the Defaults.transports list + this.transports = Utils.intersect((options.transports || Defaults.defaultTransports), ConnectionManager.supportedTransports); + /* baseTransports selects the leftmost transport in the Defaults.baseTransportOrder list * that's both requested and supported. Normally this will be xhr_polling; * if xhr isn't supported it will be jsonp. If the user has forced a * transport, it'll just be that one. */ - this.baseTransport = Utils.intersect(Defaults.transports, this.transports)[0]; + this.baseTransport = Utils.intersect(Defaults.baseTransportOrder, this.transports)[0]; this.upgradeTransports = Utils.intersect(this.transports, Defaults.upgradeTransports); /* Map of hosts to an array of transports to not be tried for that host */ this.transportHostBlacklist = {}; @@ -5822,7 +5823,7 @@ var ConnectionManager = (function() { this.lastAutoReconnectAttempt = null; Logger.logAction(Logger.LOG_MINOR, 'Realtime.ConnectionManager()', 'started'); - Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.transports) + ']'); + Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'requested transports = [' + (options.transports || Defaults.defaultTransports) + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'available transports = [' + this.transports + ']'); Logger.logAction(Logger.LOG_MICRO, 'Realtime.ConnectionManager()', 'http hosts = [' + this.httpHosts + ']'); @@ -6205,8 +6206,6 @@ var ConnectionManager = (function() { }); }) - this.emit('transport.active', transport, connectionKey, transport.params); - /* If previously not connected, notify the state change (including any * error). */ if(existingState.state === this.states.connected.state) { @@ -6222,6 +6221,10 @@ var ConnectionManager = (function() { this.errorReason = this.realtime.connection.errorReason = error || null; } + /* Send after the connection state update, as Channels hooks into this to + * resend attaches on a new transport if necessary */ + this.emit('transport.active', transport, connectionKey, transport.params); + /* Gracefully terminate existing protocol */ if(existingActiveProtocol) { if(existingActiveProtocol.messageQueue.count() > 0) { @@ -6349,8 +6352,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -6775,8 +6780,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -6818,8 +6822,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -6964,7 +6969,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -6973,18 +6978,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -9180,13 +9184,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -9222,7 +9220,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -9753,7 +9753,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -9958,8 +9960,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -10065,12 +10070,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -10362,6 +10371,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -10963,6 +10973,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -10981,16 +11001,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -11027,7 +11037,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); @@ -11088,27 +11097,6 @@ var JSONPTransport = (function() { * connectionmanager should ensure this doesn't happen anyway */ var checksInProgress = null; window.JSONPTransport = JSONPTransport - JSONPTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.jsonpInternetUpUrl; - - if(checksInProgress) { - checksInProgress.push(callback); - return; - } - checksInProgress = [callback]; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Sending; ' + upUrl); - - var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); - req.once('complete', function(err, response) { - var result = !err && response; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Result: ' + result); - for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); - checksInProgress = null; - }); - Utils.nextTick(function() { - req.exec(); - }); - }; JSONPTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new JSONPTransport(connectionManager, auth, params); @@ -11252,6 +11240,28 @@ var JSONPTransport = (function() { }); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.jsonpInternetUpUrl; + + if(checksInProgress) { + checksInProgress.push(callback); + return; + } + checksInProgress = [callback]; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Sending; ' + upUrl); + + var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); + req.once('complete', function(err, response) { + var result = !err && response; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Result: ' + result); + for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); + checksInProgress = null; + }); + Utils.nextTick(function() { + req.exec(); + }); + }; } return JSONPTransport; diff --git a/browser/static/ably.min.js b/browser/static/ably.min.js index 11a3fca48b..7334768e7b 100644 --- a/browser/static/ably.min.js +++ b/browser/static/ably.min.js @@ -1,7 +1,7 @@ /* Copyright 2017, Ably - Ably JavaScript Library v1.0.0 + Ably JavaScript Library v1.0.1 https://github.com/ably/ably-js Ably Realtime Messaging @@ -9,298 +9,298 @@ Released under the Apache Licence v2.0 */ -(function(){var Y=window.Ably=this,A=A||function(d,c){var b={},a=b.lib={},e=a.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var g=new a;b&&g.mixIn(b);g.hasOwnProperty("init")||(g.init=function(){g.$super.init.apply(this,arguments)});g.init.prototype=g;g.$super=this;return g},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var g in a)a.hasOwnProperty(g)&&(this[g]=a[g]);a.hasOwnProperty("toString")&&(this.toString= -a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),k=a.WordArray=e.extend({init:function(a,g){a=this.words=a||[];this.sigBytes=g!=c?g:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var g=this.words,b=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var n=0;n>>2]|=(b[n>>>2]>>>24-n%4*8&255)<<24-(e+n)%4*8;else if(65535>>2]=b[n>>>2];else g.push.apply(g,b);this.sigBytes+=a;return this}, -clamp:function(){var a=this.words,g=this.sigBytes;a[g>>>2]&=4294967295<<32-g%4*8;a.length=d.ceil(g/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var g=[],b=function(a){var g=987654321;return function(){g=36969*(g&65535)+(g>>16)&4294967295;a=18E3*(a&65535)+(a>>16)&4294967295;var b=(g<<16)+a&4294967295,b=b/4294967296+.5;return b*(.5>>2]>>>24-e%4*8&255;b.push((n>>>4).toString(16));b.push((n&15).toString(16))}return b.join("")},parse:function(a){for(var g=a.length,b=[],e=0;e>>3]|=parseInt(a.substr(e,2),16)<<24-e%8*4;return new k.init(b,g/2)}},p=f.Latin1={stringify:function(a){var g=a.words;a=a.sigBytes;for(var b=[],e=0;e>>2]>>>24-e%4*8&255));return b.join("")}, -parse:function(a){for(var g=a.length,b=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-e%4*8;return new k.init(b,g)}},n=f.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(g){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},g=a.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new k.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=n.parse(a));this._data.concat(a);this._nDataBytes+= -a.sigBytes},_process:function(a){var g=this._data,b=g.words,e=g.sigBytes,n=this.blockSize,f=e/(4*n),f=a?d.ceil(f):d.max((f|0)-this._minBufferSize,0);a=f*n;e=d.min(4*a,e);if(a){for(var t=0;te;)a(g)&&(8>e&&(k[e]=b(d.pow(g,.5))),f[e]=b(d.pow(g,1/3)),e++),g++})();var m=[],b=b.SHA256=e.extend({_doReset:function(){this._hash=new a.init(k.slice(0))},_doProcessBlock:function(a,b){for(var g=this._hash.words,e=g[0],d=g[1],c=g[2],k=g[3],h=g[4],l=g[5],S=g[6],$=g[7],E=0;64>E;E++){if(16>E)m[E]=a[b+E]|0;else{var L=m[E-15],B=m[E-2];m[E]=((L<<25|L>>>7)^(L<<14|L>>>18)^L>>>3)+m[E-7]+((B<<15|B>>>17)^(B<<13|B>>>19)^B>>> -10)+m[E-16]}L=$+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&l^~h&S)+f[E]+m[E];B=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&d^e&c^d&c);$=S;S=l;l=h;h=k+L|0;k=c;c=d;d=e;e=L+B|0}g[0]=g[0]+e|0;g[1]=g[1]+d|0;g[2]=g[2]+c|0;g[3]=g[3]+k|0;g[4]=g[4]+h|0;g[5]=g[5]+l|0;g[6]=g[6]+S|0;g[7]=g[7]+$|0},_doFinalize:function(){var a=this._data,b=a.words,g=8*this._nDataBytes,e=8*a.sigBytes;b[e>>>5]|=128<<24-e%32;b[(e+64>>>9<<4)+14]=d.floor(g/4294967296);b[(e+64>>>9<<4)+15]=g;a.sigBytes=4*b.length;this._process(); -return this._hash},clone:function(){var a=e.clone.call(this);a._hash=this._hash.clone();return a}});c.SHA256=e._createHelper(b);c.HmacSHA256=e._createHmacHelper(b)})(Math);(function(){var d=A,c=d.enc.Utf8;d.algo.HMAC=d.lib.Base.extend({init:function(b,a){b=this._hasher=new b.init;"string"==typeof a&&(a=c.parse(a));var e=b.blockSize,d=4*e;a.sigBytes>d&&(a=b.finalize(a));a.clamp();for(var f=this._oKey=a.clone(),m=this._iKey=a.clone(),p=f.words,n=m.words,g=0;g>>2]>>>24-f%4*8&255)<<16|(a[f+1>>>2]>>>24-(f+1)%4*8&255)<< -8|a[f+2>>>2]>>>24-(f+2)%4*8&255,p=0;4>p&&f+.75*p>>6*(3-p)&63));if(a=d.charAt(64))for(;b.length%4;)b.push(a);return b.join("")},parse:function(b){var a=b.length,e=this._map,d=e.charAt(64);d&&(d=b.indexOf(d),-1!=d&&(a=d));for(var d=[],f=0,m=0;m>>6-m%4*2;d[f>>>2]|=(p|n)<<24-f%4*8;f++}return c.create(d,f)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();A.lib.Cipher||function(d){var c= -A,b=c.lib,a=b.Base,e=b.WordArray,k=b.BufferedBlockAlgorithm,f=c.enc.Base64,m=c.algo.EvpKDF,p=b.Cipher=k.extend({cfg:a.extend(),createEncryptor:function(a,g){return this.create(this._ENC_XFORM_MODE,a,g)},createDecryptor:function(a,g){return this.create(this._DEC_XFORM_MODE,a,g)},init:function(a,g,b){this.cfg=this.cfg.extend(b);this._xformMode=a;this._key=g;this.reset()},reset:function(){k.reset.call(this);this._doReset()},process:function(a){this._append(a);return this._process()},finalize:function(a){a&& -this._append(a);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){return function(a){return{encrypt:function(g,b,e){return("string"==typeof b?H:v).encrypt(a,g,b,e)},decrypt:function(g,b,e){return("string"==typeof b?H:v).decrypt(a,g,b,e)}}}}()});b.StreamCipher=p.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var n=c.mode={},g=b.BlockCipherMode=a.extend({createEncryptor:function(a,g){return this.Encryptor.create(a,g)}, -createDecryptor:function(a,g){return this.Decryptor.create(a,g)},init:function(a,g){this._cipher=a;this._iv=g}}),n=n.CBC=function(){function a(g,b,e){var n=this._iv;n?this._iv=d:n=this._prevBlock;for(var f=0;f>>2]&255}};b.BlockCipher=p.extend({cfg:p.cfg.extend({mode:n,padding:t}),reset:function(){p.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var g=a.createEncryptor;else g=a.createDecryptor,this._minBufferSize= -1;this._mode=g.call(a,this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var s=b.CipherParams=a.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),n=(c.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a= -a.salt;return(a?e.create([1398893684,1701076831]).concat(a).concat(b):b).toString(f)},parse:function(a){a=f.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var g=e.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return s.create({ciphertext:a,salt:g})}},v=b.SerializableCipher=a.extend({cfg:a.extend({format:n}),encrypt:function(a,b,g,e){e=this.cfg.extend(e);var n=a.createEncryptor(g,e);b=n.finalize(b);n=n.cfg;return s.create({ciphertext:b,key:g,iv:n.iv,algorithm:a,mode:n.mode,padding:n.padding, -blockSize:a.blockSize,formatter:e.format})},decrypt:function(a,b,g,e){e=this.cfg.extend(e);b=this._parse(b,e.format);return a.createDecryptor(g,e).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),c=(c.kdf={}).OpenSSL={execute:function(a,b,g,n){n||(n=e.random(8));a=m.create({keySize:b+g}).compute(a,n);g=e.create(a.words.slice(b),4*g);a.sigBytes=4*b;return s.create({key:a,iv:g,salt:n})}},H=b.PasswordBasedCipher=v.extend({cfg:v.cfg.extend({kdf:c}),encrypt:function(a, -b,g,e){e=this.cfg.extend(e);g=e.kdf.execute(g,a.keySize,a.ivSize);e.iv=g.iv;a=v.encrypt.call(this,a,b,g.key,e);a.mixIn(g);return a},decrypt:function(a,b,g,e){e=this.cfg.extend(e);b=this._parse(b,e.format);g=e.kdf.execute(g,a.keySize,a.ivSize,b.salt);e.iv=g.iv;return v.decrypt.call(this,a,b,g.key,e)}})}();(function(){var d=A,c=d.lib.BlockCipher,b=d.algo,a=[],e=[],k=[],f=[],m=[],p=[],n=[],g=[],t=[],s=[];(function(){for(var b=[],d=0;256>d;d++)b[d]=128>d?d<<1:d<<1^283;for(var c=0,h=0,d=0;256>d;d++){var v= -h^h<<1^h<<2^h<<3^h<<4,v=v>>>8^v&255^99;a[c]=v;e[v]=c;var l=b[c],r=b[l],B=b[r],q=257*b[v]^16843008*v;k[c]=q<<24|q>>>8;f[c]=q<<16|q>>>16;m[c]=q<<8|q>>>24;p[c]=q;q=16843009*B^65537*r^257*l^16843008*c;n[v]=q<<24|q>>>8;g[v]=q<<16|q>>>16;t[v]=q<<8|q>>>24;s[v]=q;c?(c=l^b[b[b[B^l]]],h^=b[b[h]]):c=h=1}})();var v=[0,1,2,4,8,16,32,64,128,27,54],b=b.AES=c.extend({_doReset:function(){for(var b=this._key,e=b.words,f=b.sigBytes/4,b=4*((this._nRounds=f+6)+1),d=this._keySchedule=[],c=0;c>>24]<<24|a[m>>>16&255]<<16|a[m>>>8&255]<<8|a[m&255]):(m=m<<8|m>>>24,m=a[m>>>24]<<24|a[m>>>16&255]<<16|a[m>>>8&255]<<8|a[m&255],m^=v[c/f|0]<<24);d[c]=d[c-f]^m}e=this._invKeySchedule=[];for(f=0;ff||4>=c?m:n[a[m>>>24]]^g[a[m>>>16&255]]^t[a[m>>>8&255]]^s[a[m&255]]},encryptBlock:function(b,g){this._doCryptBlock(b,g,this._keySchedule,k,f,m,p,a)},decryptBlock:function(a,b){var f=a[b+1];a[b+1]=a[b+3];a[b+3]=f;this._doCryptBlock(a,b,this._invKeySchedule, -n,g,t,s,e);f=a[b+1];a[b+1]=a[b+3];a[b+3]=f},_doCryptBlock:function(a,b,g,e,n,f,c,d){for(var m=this._nRounds,t=a[b]^g[0],p=a[b+1]^g[1],k=a[b+2]^g[2],s=a[b+3]^g[3],h=4,v=1;v>>24]^n[p>>>16&255]^f[k>>>8&255]^c[s&255]^g[h++],r=e[p>>>24]^n[k>>>16&255]^f[s>>>8&255]^c[t&255]^g[h++],q=e[k>>>24]^n[s>>>16&255]^f[t>>>8&255]^c[p&255]^g[h++],s=e[s>>>24]^n[t>>>16&255]^f[p>>>8&255]^c[k&255]^g[h++],t=l,p=r,k=q;l=(d[t>>>24]<<24|d[p>>>16&255]<<16|d[k>>>8&255]<<8|d[s&255])^g[h++];r=(d[p>>>24]<<24|d[k>>> -16&255]<<16|d[s>>>8&255]<<8|d[t&255])^g[h++];q=(d[k>>>24]<<24|d[s>>>16&255]<<16|d[t>>>8&255]<<8|d[p&255])^g[h++];s=(d[s>>>24]<<24|d[t>>>16&255]<<16|d[p>>>8&255]<<8|d[k&255])^g[h++];a[b]=l;a[b+1]=r;a[b+2]=q;a[b+3]=s},keySize:8});d.AES=c._createHelper(b)})();(function(){if("undefined"!==typeof ArrayBuffer){var d=A.lib.WordArray,c=d.init;(d.init=function(b){if(b instanceof ArrayBuffer)b=new Uint8Array(b);else if(b instanceof Int8Array||"undefined"!==typeof Uint8ClampedArray&&b instanceof Uint8ClampedArray|| -b instanceof Int16Array||b instanceof Uint16Array||b instanceof Int32Array||b instanceof Uint32Array||"undefined"!==typeof Float32Array&&b instanceof Float32Array||"undefined"!==typeof Float64Array&&b instanceof Float64Array)b=new Uint8Array(b.buffer,b.byteOffset,b.byteLength);if(b instanceof Uint8Array){for(var a=b.byteLength,e=[],d=0;d>>2]|=b[d]<<24-d%4*8;c.call(this,e,a)}else c.apply(this,arguments)}).prototype=d}})();var da=function(){function d(){}d.addListener=function(d,b,a){d.addEventListener? -d.addEventListener(b,a,!1):d.attachEvent("on"+b,function(){a.apply(d,arguments)})};d.removeListener=function(d,b,a){d.removeEventListener?d.removeEventListener(b,a,!1):d.detachEvent("on"+b,function(){a.apply(d,arguments)})};d.addMessageListener=function(c,b){d.addListener(c,"message",b)};d.removeMessageListener=function(c,b){d.removeListener(c,"message",b)};d.addUnloadListener=function(c){d.addListener(window,"unload",c)};return d}(),ea=function(){function d(a,b,e){for(var d=0,f=e.length;dc)a.setUint8(b++,c>>>0&127|0);else if(2048>c)a.setUint8(b++,c>>>6&31|192),a.setUint8(b++,c>>>0&63|128);else if(65536>c)a.setUint8(b++,c>>>12&15|224),a.setUint8(b++,c>>>6&63|128),a.setUint8(b++,c>>>0&63|128);else if(1114112>c)a.setUint8(b++,c>>>18&7|240),a.setUint8(b++,c>>>12&63|128),a.setUint8(b++,c>>>6&63|128),a.setUint8(b++,c>>>0&63|128);else throw Error("bad codepoint "+c);}}function c(a,b,e){var d="",f=b;for(b+=e;ff)b+=1;else if(2048>f)b+=2;else if(65536>f)b+=3;else if(1114112> -f)b+=4;else throw Error("bad codepoint "+f);}return b}function a(a,b){this.offset=b||0;this.view=a}function e(a,b){return l.keysArray(a,!0).filter(function(e){e=a[e];return(!b||void 0!==e&&null!==e)&&("function"!==typeof e||!!e.toJSON)})}function k(a,g,f,c){var m=typeof a;if("string"===m){var h=b(a);if(32>h)return g.setUint8(f,h|160),d(g,f+1,a),1+h;if(256>h)return g.setUint8(f,217),g.setUint8(f+1,h),d(g,f+2,a),2+h;if(65536>h)return g.setUint8(f,218),g.setUint16(f+1,h),d(g,f+3,a),3+h;if(4294967296> -h)return g.setUint8(f,219),g.setUint32(f+1,h),d(g,f+5,a),5+h}if(a instanceof ArrayBuffer){h=a.byteLength;if(256>h)return g.setUint8(f,196),g.setUint8(f+1,h),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+2),2+h;if(65536>h)return g.setUint8(f,197),g.setUint16(f+1,h),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+3),3+h;if(4294967296>h)return g.setUint8(f,198),g.setUint32(f+1,h),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+5),5+h}if("number"===m){if(Math.floor(a)!==a)return g.setUint8(f, +(function(){var aa=window.Ably=this,C=C||function(d,c){var b={},a=b.lib={},e=a.Base=function(){function a(){}return{extend:function(b){a.prototype=this;var g=new a;b&&g.mixIn(b);g.hasOwnProperty("init")||(g.init=function(){g.$super.init.apply(this,arguments)});g.init.prototype=g;g.$super=this;return g},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString= +a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),h=a.WordArray=e.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=c?b:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var b=this.words,g=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var n=0;n>>2]|=(g[n>>>2]>>>24-n%4*8&255)<<24-(e+n)%4*8;else if(65535>>2]=g[n>>>2];else b.push.apply(b,g);this.sigBytes+=a;return this}, +clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<<32-b%4*8;a.length=d.ceil(b/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],g=function(a){var b=987654321;return function(){b=36969*(b&65535)+(b>>16)&4294967295;a=18E3*(a&65535)+(a>>16)&4294967295;var g=(b<<16)+a&4294967295,g=g/4294967296+.5;return g*(.5>>2]>>>24-e%4*8&255;g.push((n>>>4).toString(16));g.push((n&15).toString(16))}return g.join("")},parse:function(a){for(var b=a.length,g=[],e=0;e>>3]|=parseInt(a.substr(e,2),16)<<24-e%8*4;return new h.init(g,b/2)}},p=f.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var g=[],e=0;e>>2]>>>24-e%4*8&255));return g.join("")}, +parse:function(a){for(var b=a.length,g=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-e%4*8;return new h.init(g,b)}},n=f.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},g=a.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new h.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=n.parse(a));this._data.concat(a);this._nDataBytes+= +a.sigBytes},_process:function(a){var b=this._data,g=b.words,e=b.sigBytes,n=this.blockSize,f=e/(4*n),f=a?d.ceil(f):d.max((f|0)-this._minBufferSize,0);a=f*n;e=d.min(4*a,e);if(a){for(var u=0;ue;)a(g)&&(8>e&&(h[e]=b(d.pow(g,.5))),f[e]=b(d.pow(g,1/3)),e++),g++})();var m=[],b=b.SHA256=e.extend({_doReset:function(){this._hash=new a.init(h.slice(0))},_doProcessBlock:function(a,b){for(var g=this._hash.words,e=g[0],d=g[1],c=g[2],h=g[3],k=g[4],l=g[5],U=g[6],ba=g[7],G=0;64>G;G++){if(16>G)m[G]=a[b+G]|0;else{var N=m[G-15],J=m[G-2];m[G]=((N<<25|N>>>7)^(N<<14|N>>>18)^N>>>3)+m[G-7]+((J<<15|J>>>17)^(J<<13|J>>>19)^J>>> +10)+m[G-16]}N=ba+((k<<26|k>>>6)^(k<<21|k>>>11)^(k<<7|k>>>25))+(k&l^~k&U)+f[G]+m[G];J=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&d^e&c^d&c);ba=U;U=l;l=k;k=h+N|0;h=c;c=d;d=e;e=N+J|0}g[0]=g[0]+e|0;g[1]=g[1]+d|0;g[2]=g[2]+c|0;g[3]=g[3]+h|0;g[4]=g[4]+k|0;g[5]=g[5]+l|0;g[6]=g[6]+U|0;g[7]=g[7]+ba|0},_doFinalize:function(){var a=this._data,b=a.words,g=8*this._nDataBytes,e=8*a.sigBytes;b[e>>>5]|=128<<24-e%32;b[(e+64>>>9<<4)+14]=d.floor(g/4294967296);b[(e+64>>>9<<4)+15]=g;a.sigBytes=4*b.length;this._process(); +return this._hash},clone:function(){var a=e.clone.call(this);a._hash=this._hash.clone();return a}});c.SHA256=e._createHelper(b);c.HmacSHA256=e._createHmacHelper(b)})(Math);(function(){var d=C,c=d.enc.Utf8;d.algo.HMAC=d.lib.Base.extend({init:function(b,a){b=this._hasher=new b.init;"string"==typeof a&&(a=c.parse(a));var e=b.blockSize,d=4*e;a.sigBytes>d&&(a=b.finalize(a));a.clamp();for(var f=this._oKey=a.clone(),m=this._iKey=a.clone(),p=f.words,n=m.words,g=0;g>>2]>>>24-f%4*8&255)<<16|(a[f+1>>>2]>>>24-(f+1)%4*8&255)<< +8|a[f+2>>>2]>>>24-(f+2)%4*8&255,p=0;4>p&&f+.75*p>>6*(3-p)&63));if(a=d.charAt(64))for(;b.length%4;)b.push(a);return b.join("")},parse:function(b){var a=b.length,e=this._map,d=e.charAt(64);d&&(d=b.indexOf(d),-1!=d&&(a=d));for(var d=[],f=0,m=0;m>>6-m%4*2;d[f>>>2]|=(p|n)<<24-f%4*8;f++}return c.create(d,f)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();C.lib.Cipher||function(d){var c= +C,b=c.lib,a=b.Base,e=b.WordArray,h=b.BufferedBlockAlgorithm,f=c.enc.Base64,m=c.algo.EvpKDF,p=b.Cipher=h.extend({cfg:a.extend(),createEncryptor:function(a,b){return this.create(this._ENC_XFORM_MODE,a,b)},createDecryptor:function(a,b){return this.create(this._DEC_XFORM_MODE,a,b)},init:function(a,b,g){this.cfg=this.cfg.extend(g);this._xformMode=a;this._key=b;this.reset()},reset:function(){h.reset.call(this);this._doReset()},process:function(a){this._append(a);return this._process()},finalize:function(a){a&& +this._append(a);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){return function(a){return{encrypt:function(b,g,e){return("string"==typeof g?D:v).encrypt(a,b,g,e)},decrypt:function(b,g,e){return("string"==typeof g?D:v).decrypt(a,b,g,e)}}}}()});b.StreamCipher=p.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var n=c.mode={},g=b.BlockCipherMode=a.extend({createEncryptor:function(a,b){return this.Encryptor.create(a,b)}, +createDecryptor:function(a,b){return this.Decryptor.create(a,b)},init:function(a,b){this._cipher=a;this._iv=b}}),n=n.CBC=function(){function a(b,g,e){var n=this._iv;n?this._iv=d:n=this._prevBlock;for(var f=0;f>>2]&255}};b.BlockCipher=p.extend({cfg:p.cfg.extend({mode:n,padding:u}),reset:function(){p.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var g=a.createEncryptor;else g=a.createDecryptor,this._minBufferSize= +1;this._mode=g.call(a,this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var t=b.CipherParams=a.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),n=(c.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a= +a.salt;return(a?e.create([1398893684,1701076831]).concat(a).concat(b):b).toString(f)},parse:function(a){a=f.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var g=e.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return t.create({ciphertext:a,salt:g})}},v=b.SerializableCipher=a.extend({cfg:a.extend({format:n}),encrypt:function(a,b,g,e){e=this.cfg.extend(e);var n=a.createEncryptor(g,e);b=n.finalize(b);n=n.cfg;return t.create({ciphertext:b,key:g,iv:n.iv,algorithm:a,mode:n.mode,padding:n.padding, +blockSize:a.blockSize,formatter:e.format})},decrypt:function(a,b,g,e){e=this.cfg.extend(e);b=this._parse(b,e.format);return a.createDecryptor(g,e).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),c=(c.kdf={}).OpenSSL={execute:function(a,b,g,n){n||(n=e.random(8));a=m.create({keySize:b+g}).compute(a,n);g=e.create(a.words.slice(b),4*g);a.sigBytes=4*b;return t.create({key:a,iv:g,salt:n})}},D=b.PasswordBasedCipher=v.extend({cfg:v.cfg.extend({kdf:c}),encrypt:function(a, +b,g,e){e=this.cfg.extend(e);g=e.kdf.execute(g,a.keySize,a.ivSize);e.iv=g.iv;a=v.encrypt.call(this,a,b,g.key,e);a.mixIn(g);return a},decrypt:function(a,b,g,e){e=this.cfg.extend(e);b=this._parse(b,e.format);g=e.kdf.execute(g,a.keySize,a.ivSize,b.salt);e.iv=g.iv;return v.decrypt.call(this,a,b,g.key,e)}})}();(function(){var d=C,c=d.lib.BlockCipher,b=d.algo,a=[],e=[],h=[],f=[],m=[],p=[],n=[],g=[],u=[],t=[];(function(){for(var b=[],d=0;256>d;d++)b[d]=128>d?d<<1:d<<1^283;for(var c=0,k=0,d=0;256>d;d++){var v= +k^k<<1^k<<2^k<<3^k<<4,v=v>>>8^v&255^99;a[c]=v;e[v]=c;var l=b[c],q=b[l],J=b[q],x=257*b[v]^16843008*v;h[c]=x<<24|x>>>8;f[c]=x<<16|x>>>16;m[c]=x<<8|x>>>24;p[c]=x;x=16843009*J^65537*q^257*l^16843008*c;n[v]=x<<24|x>>>8;g[v]=x<<16|x>>>16;u[v]=x<<8|x>>>24;t[v]=x;c?(c=l^b[b[b[J^l]]],k^=b[b[k]]):c=k=1}})();var v=[0,1,2,4,8,16,32,64,128,27,54],b=b.AES=c.extend({_doReset:function(){for(var b=this._key,e=b.words,f=b.sigBytes/4,b=4*((this._nRounds=f+6)+1),d=this._keySchedule=[],c=0;c>>24]<<24|a[m>>>16&255]<<16|a[m>>>8&255]<<8|a[m&255]):(m=m<<8|m>>>24,m=a[m>>>24]<<24|a[m>>>16&255]<<16|a[m>>>8&255]<<8|a[m&255],m^=v[c/f|0]<<24);d[c]=d[c-f]^m}e=this._invKeySchedule=[];for(f=0;ff||4>=c?m:n[a[m>>>24]]^g[a[m>>>16&255]]^u[a[m>>>8&255]]^t[a[m&255]]},encryptBlock:function(b,g){this._doCryptBlock(b,g,this._keySchedule,h,f,m,p,a)},decryptBlock:function(a,b){var f=a[b+1];a[b+1]=a[b+3];a[b+3]=f;this._doCryptBlock(a,b,this._invKeySchedule, +n,g,u,t,e);f=a[b+1];a[b+1]=a[b+3];a[b+3]=f},_doCryptBlock:function(a,b,g,e,n,f,c,d){for(var m=this._nRounds,u=a[b]^g[0],p=a[b+1]^g[1],h=a[b+2]^g[2],t=a[b+3]^g[3],k=4,v=1;v>>24]^n[p>>>16&255]^f[h>>>8&255]^c[t&255]^g[k++],q=e[p>>>24]^n[h>>>16&255]^f[t>>>8&255]^c[u&255]^g[k++],r=e[h>>>24]^n[t>>>16&255]^f[u>>>8&255]^c[p&255]^g[k++],t=e[t>>>24]^n[u>>>16&255]^f[p>>>8&255]^c[h&255]^g[k++],u=l,p=q,h=r;l=(d[u>>>24]<<24|d[p>>>16&255]<<16|d[h>>>8&255]<<8|d[t&255])^g[k++];q=(d[p>>>24]<<24|d[h>>> +16&255]<<16|d[t>>>8&255]<<8|d[u&255])^g[k++];r=(d[h>>>24]<<24|d[t>>>16&255]<<16|d[u>>>8&255]<<8|d[p&255])^g[k++];t=(d[t>>>24]<<24|d[u>>>16&255]<<16|d[p>>>8&255]<<8|d[h&255])^g[k++];a[b]=l;a[b+1]=q;a[b+2]=r;a[b+3]=t},keySize:8});d.AES=c._createHelper(b)})();(function(){if("undefined"!==typeof ArrayBuffer){var d=C.lib.WordArray,c=d.init;(d.init=function(b){if(b instanceof ArrayBuffer)b=new Uint8Array(b);else if(b instanceof Int8Array||"undefined"!==typeof Uint8ClampedArray&&b instanceof Uint8ClampedArray|| +b instanceof Int16Array||b instanceof Uint16Array||b instanceof Int32Array||b instanceof Uint32Array||"undefined"!==typeof Float32Array&&b instanceof Float32Array||"undefined"!==typeof Float64Array&&b instanceof Float64Array)b=new Uint8Array(b.buffer,b.byteOffset,b.byteLength);if(b instanceof Uint8Array){for(var a=b.byteLength,e=[],d=0;d>>2]|=b[d]<<24-d%4*8;c.call(this,e,a)}else c.apply(this,arguments)}).prototype=d}})();var fa=function(){function d(){}d.addListener=function(d,b,a){d.addEventListener? +d.addEventListener(b,a,!1):d.attachEvent("on"+b,function(){a.apply(d,arguments)})};d.removeListener=function(d,b,a){d.removeEventListener?d.removeEventListener(b,a,!1):d.detachEvent("on"+b,function(){a.apply(d,arguments)})};d.addMessageListener=function(c,b){d.addListener(c,"message",b)};d.removeMessageListener=function(c,b){d.removeListener(c,"message",b)};d.addUnloadListener=function(c){d.addListener(window,"unload",c)};return d}(),ga=function(){function d(a,b,e){for(var f=0,d=e.length;fc)a.setUint8(b++,c>>>0&127|0);else if(2048>c)a.setUint8(b++,c>>>6&31|192),a.setUint8(b++,c>>>0&63|128);else if(65536>c)a.setUint8(b++,c>>>12&15|224),a.setUint8(b++,c>>>6&63|128),a.setUint8(b++,c>>>0&63|128);else if(1114112>c)a.setUint8(b++,c>>>18&7|240),a.setUint8(b++,c>>>12&63|128),a.setUint8(b++,c>>>6&63|128),a.setUint8(b++,c>>>0&63|128);else throw Error("bad codepoint "+c);}}function c(a,b,e){var f="",d=b;for(b+=e;dd)b+=1;else if(2048>d)b+=2;else if(65536>d)b+=3;else if(1114112> +d)b+=4;else throw Error("bad codepoint "+d);}return b}function a(a,b){this.offset=b||0;this.view=a}function e(a,b){return l.keysArray(a,!0).filter(function(e){e=a[e];return(!b||void 0!==e&&null!==e)&&("function"!==typeof e||!!e.toJSON)})}function h(a,g,f,c){var m=typeof a;if("string"===m){var k=b(a);if(32>k)return g.setUint8(f,k|160),d(g,f+1,a),1+k;if(256>k)return g.setUint8(f,217),g.setUint8(f+1,k),d(g,f+2,a),2+k;if(65536>k)return g.setUint8(f,218),g.setUint16(f+1,k),d(g,f+3,a),3+k;if(4294967296> +k)return g.setUint8(f,219),g.setUint32(f+1,k),d(g,f+5,a),5+k}if(a instanceof ArrayBuffer){k=a.byteLength;if(256>k)return g.setUint8(f,196),g.setUint8(f+1,k),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+2),2+k;if(65536>k)return g.setUint8(f,197),g.setUint16(f+1,k),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+3),3+k;if(4294967296>k)return g.setUint8(f,198),g.setUint32(f+1,k),(new Uint8Array(g.buffer)).set(new Uint8Array(a),f+5),5+k}if("number"===m){if(Math.floor(a)!==a)return g.setUint8(f, 203),g.setFloat64(f+1,a),9;if(0<=a){if(128>a)return g.setUint8(f,a),1;if(256>a)return g.setUint8(f,204),g.setUint8(f+1,a),2;if(65536>a)return g.setUint8(f,205),g.setUint16(f+1,a),3;if(4294967296>a)return g.setUint8(f,206),g.setUint32(f+1,a),5;if(1.8446744073709552E19>a)return g.setUint8(f,207),f+=1,1.8446744073709552E19>a?(g.setUint32(f,Math.floor(a*p)),g.setInt32(f+4,a&-1)):(g.setUint32(f,4294967295),g.setUint32(f+4,4294967295)),9;throw Error("Number too big 0x"+a.toString(16));}if(-32<=a)return g.setInt8(f, a),1;if(-128<=a)return g.setUint8(f,208),g.setInt8(f+1,a),2;if(-32768<=a)return g.setUint8(f,209),g.setInt16(f+1,a),3;if(-2147483648<=a)return g.setUint8(f,210),g.setInt32(f+1,a),5;if(-9223372036854775808<=a)return g.setUint8(f,211),f+=1,0x7fffffffffffffff>a?(g.setInt32(f,Math.floor(a*p)),g.setInt32(f+4,a&-1)):(g.setUint32(f,2147483647),g.setUint32(f+4,2147483647)),9;throw Error("Number too small -0x"+(-a).toString(16).substr(1));}if("undefined"===m){if(c)return 0;g.setUint8(f,212);g.setUint8(f+1, -0);g.setUint8(f+2,0);return 3}if(null===a){if(c)return 0;g.setUint8(f,192);return 1}if("boolean"===m)return g.setUint8(f,a?195:194),1;if("function"===typeof a.toJSON)return k(a.toJSON(),g,f,c);if("object"===m){var m=0,l=Array.isArray(a);if(l)h=a.length;else var ca=e(a,c),h=ca.length;16>h?(g.setUint8(f,h|(l?144:128)),m=1):65536>h?(g.setUint8(f,l?220:222),g.setUint16(f+1,h),m=3):4294967296>h&&(g.setUint8(f,l?221:223),g.setUint32(f+1,h),m=5);if(l)for(l=0;lc)return 1+c;if(256>c)return 2+c;if(65536>c)return 3+c;if(4294967296>c)return 5+c}if(a instanceof ArrayBuffer){c=a.byteLength;if(256>c)return 2+c;if(65536>c)return 3+c;if(4294967296>c)return 5+c}if("number"===d){if(Math.floor(a)!==a)return 9;if(0<=a){if(128>a)return 1;if(256>a)return 2;if(65536>a)return 3;if(4294967296>a)return 5; +0);g.setUint8(f+2,0);return 3}if(null===a){if(c)return 0;g.setUint8(f,192);return 1}if("boolean"===m)return g.setUint8(f,a?195:194),1;if("function"===typeof a.toJSON)return h(a.toJSON(),g,f,c);if("object"===m){var m=0,l=Array.isArray(a);if(l)k=a.length;else var ea=e(a,c),k=ea.length;16>k?(g.setUint8(f,k|(l?144:128)),m=1):65536>k?(g.setUint8(f,l?220:222),g.setUint16(f+1,k),m=3):4294967296>k&&(g.setUint8(f,l?221:223),g.setUint32(f+1,k),m=5);if(l)for(l=0;lc)return 1+c;if(256>c)return 2+c;if(65536>c)return 3+c;if(4294967296>c)return 5+c}if(a instanceof ArrayBuffer){c=a.byteLength;if(256>c)return 2+c;if(65536>c)return 3+c;if(4294967296>c)return 5+c}if("number"===d){if(Math.floor(a)!==a)return 9;if(0<=a){if(128>a)return 1;if(256>a)return 2;if(65536>a)return 3;if(4294967296>a)return 5; if(1.8446744073709552E19>a)return 9;throw Error("Number too big 0x"+a.toString(16));}if(-32<=a)return 1;if(-128<=a)return 2;if(-32768<=a)return 3;if(-2147483648<=a)return 5;if(-9223372036854775808<=a)return 9;throw Error("Number too small -0x"+a.toString(16).substr(1));}if("boolean"===d)return 1;if(null===a)return g?0:1;if(void 0===a)return g?0:3;if("function"===typeof a.toJSON)return f(a.toJSON(),g);if("object"===d){d=0;if(Array.isArray(a))for(var c=a.length,m=0;mc)return 1+d;if(65536>c)return 3+d;if(4294967296>c)return 5+d;throw Error("Array or object too long 0x"+c.toString(16));}if("function"===d)return 0;throw Error("Unknown type "+d);}var m={inspect:function(a){if(void 0===a)return"undefined";var b,e;a instanceof ArrayBuffer?(e="ArrayBuffer",b=new DataView(a)):a instanceof DataView&&(e="DataView",b=a);if(!b)return JSON.stringify(a);for(var f=[],c=0;c"}};m.utf8Write=d;m.utf8Read=c;m.utf8ByteCount=b;m.encode=function(a,b){var e=f(a,b);if(0!=e){var e=new ArrayBuffer(e),c=new DataView(e);k(a,c,0,b);return e}};m.decode=function(b){var e=new DataView(b),e=new a(e),f=e.parse();if(e.offset!==b.byteLength)throw Error(b.byteLength-e.offset+" trailing bytes");return f};var p=1/4294967296;a.prototype.map=function(a){for(var b={},e=0;ec)return 1+d;if(65536>c)return 3+d;if(4294967296>c)return 5+d;throw Error("Array or object too long 0x"+c.toString(16));}if("function"===d)return 0;throw Error("Unknown type "+d);}var m={inspect:function(a){if(void 0===a)return"undefined";var b,e;a instanceof ArrayBuffer?(e="ArrayBuffer",b=new DataView(a)):a instanceof DataView&&(e="DataView",b=a);if(!b)return JSON.stringify(a);for(var f=[],c=0;c"}};m.utf8Write=d;m.utf8Read=c;m.utf8ByteCount=b;m.encode=function(a,b){var e=f(a,b);if(0!=e){var e=new ArrayBuffer(e),c=new DataView(e);h(a,c,0,b);return e}};m.decode=function(b){var e=new DataView(b),e=new a(e),f=e.parse();if(e.offset!==b.byteLength)throw Error(b.byteLength-e.offset+" trailing bytes");return f};var p=1/4294967296;a.prototype.map=function(a){for(var b={},e=0;e>>2]>>>24-n%4*8&255;return b}throw Error("BufferUtils.toArrayBuffer expected a buffer");};b.toWordArray=function(b){return c(b)?b:a.create(b)};b.base64Encode=function(a){if(h(a)){var b="";a=new Uint8Array(a);for(var e=a.byteLength,k=e%3,e=e-k,g,t,s,l,H=0;H>18,t=(l&258048)>>12,s=(l&4032)>>6,l&=63,b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[g]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[t]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[s]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l];1==k?(l=a[e],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&252)>>2]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l& -3)<<4]+"=="):2==k&&(l=a[e]<<8|a[e+1],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&64512)>>10]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&1008)>>4]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&15)<<2]+"=");return b}if(c(a))return A.enc.Base64.stringify(a)};b.base64Decode=function(a){if(e&&k){a=k(a);for(var b=a.length,c=new Uint8Array(b),d=0;d=b}var b=function(){};c.get=function(a,e,k,f,m){m=m||b;var p="function"==typeof e?e:function(b){return a.baseUri(b)+e},n;n=(n=a.connection)&&"connected"==n.state?[n.connectionManager.host]:q.getHosts(a.options);if(1==n.length)c.getUri(a,p(n[0]),k,f,m);else{var g=function(b){c.getUri(a,p(b.shift()),k,f,function(a){a&&h(a)&& -b.length?g(b):m.apply(null,arguments)})};g(n)}};c.getUri=function(a,e,k,f,m){c.Request(a,e,k,f,null,m||b)};c.post=function(a,e,k,f,m,p){p=p||b;var n="function"==typeof e?e:function(b){return a.baseUri(b)+e},g;g=(g=a.connection)&&"connected"==g.state?[g.connectionManager.host]:q.getHosts(a.options);if(1==g.length)c.postUri(a,n(g[0]),k,f,m,p);else{var t=function(b){c.postUri(a,n(b.shift()),k,f,m,function(a){a&&h(a)&&b.length?t(b):p.apply(null,arguments)})};t(g)}};c.postUri=function(a,e,k,f,m,p){c.Request(a, -e,k,m,f,p||b)};c.supportsAuthHeaders=!1;c.supportsLinkHeaders=!1;return c}(),ha=function(){function c(){this.buffer=[]}function h(a){this._input=a;this._index=-1;this._buffer=[]}function b(a){this._input=a;this._index=-1;this._buffer=[]}c.prototype.append=function(a){this.buffer.push(a);return this};c.prototype.toString=function(){return this.buffer.join("")};var a={codex:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(b){var k=new c,f=a.codex;for(b=new h(b);b.moveNext();){var m= -b.current;b.moveNext();var p=b.current;b.moveNext();var n=b.current,g=m>>2,m=(m&3)<<4|p>>4,t=(p&15)<<2|n>>6,s=n&63;isNaN(p)?t=s=64:isNaN(n)&&(s=64);k.append(f.charAt(g)+f.charAt(m)+f.charAt(t)+f.charAt(s))}return k.toString()},decode:function(a){var k=new c;for(a=new b(a);a.moveNext();){var f=a.current;if(128>f)k.append(String.fromCharCode(f));else if(191f){a.moveNext();var m=a.current;k.append(String.fromCharCode((f&31)<<6|m&63))}else a.moveNext(),m=a.current,a.moveNext(),k.append(String.fromCharCode((f& -15)<<12|(m&63)<<6|a.current&63))}return k.toString()}};h.prototype={current:Number.NaN,moveNext:function(){if(0=this._input.length-1)return this.current=Number.NaN,!1;var a=this._input.charCodeAt(++this._index);13==a&&10==this._input.charCodeAt(this._index+1)&&(a=10,this._index+=2);128>a?this.current=a:(127a?this.current=a>>6|192:(this.current=a>>12|224,this._buffer.push(a>>6&63|128)),this._buffer.push(a&63|128)); +185273099,185273088],11),a.create([202116108,202116108,202116108],12),a.create([218959117,218959117,218959117,218103808],13),a.create([235802126,235802126,235802126,235798528],14),a.create([252645135,252645135,252645135,252645135],15),a.create([269488144,269488144,269488144,269488144],16)];d.CipherParams=k;d.getDefaultParams=function(a){var b;if("function"===typeof a||"string"===typeof a)if(c.deprecated("Crypto.getDefaultParams(key, callback)","Crypto.getDefaultParams({key: key})"),"function"===typeof a)d.generateRandomKey(function(b){a(null, +d.getDefaultParams({key:b}))});else if("function"===typeof arguments[1])arguments[1](null,d.getDefaultParams({key:a}));else throw Error("Invalid arguments for Crypto.getDefaultParams");else{if(!a.key)throw Error("Crypto.getDefaultParams: a key is required");b="string"===typeof a.key?C.enc.Base64.parse(a.key.replace("_","/").replace("-","+")):A.toWordArray(a.key);var e=new k;e.key=b;e.algorithm=a.algorithm||"aes";e.keyLength=32*b.words.length;e.mode=a.mode||"cbc";if(a.keyLength&&a.keyLength!==e.keyLength)throw Error("Crypto.getDefaultParams: a keyLength of "+ +a.keyLength+" was specified, but the key actually has length "+e.keyLength);if("aes"===e.algorithm&&"cbc"===e.mode&&128!==e.keyLength&&256!==e.keyLength)throw Error("Unsupported key length "+e.keyLength+" for aes-cbc encryption. Encryption key must be 128 or 256 bits (16 or 32 ASCII characters)");return e}};d.generateRandomKey=function(a,b){1==arguments.length&&"function"==typeof a&&(b=a,a=void 0);e((a||256)/8,b)};d.getCipher=function(a){var e=a instanceof k?a:d.getDefaultParams(a);return{cipherParams:e, +cipher:new b(e,4,a.iv)}};b.prototype.encrypt=function(a,b){c.logAction(c.LOG_MICRO,"CBCCipher.encrypt()","");a=A.toWordArray(a);var d=a.sigBytes,g=d+16&-16,h=this,t=function(){h.getIv(function(e,c){if(e)b(e);else{var t=h.encryptCipher.process(a.concat(f[g-d])),t=c.concat(t);b(null,t)}})};this.encryptCipher?t():this.iv?(this.encryptCipher=C.algo[this.cjsAlgorithm].createEncryptor(this.key,{iv:this.iv}),t()):e(16,function(a,e){a?b(a):(h.encryptCipher=C.algo[h.cjsAlgorithm].createEncryptor(h.key,{iv:e}), +h.iv=e,t())})};b.prototype.decrypt=function(b){c.logAction(c.LOG_MICRO,"CBCCipher.decrypt()","");b=A.toWordArray(b);var e=this.blockLengthWords,f=b.words;b=a.create(f.slice(0,e));f=a.create(f.slice(e));e=C.algo[this.cjsAlgorithm].createDecryptor(this.key,{iv:b});b=e.process(f);f=e.finalize();e.reset();f&&f.sigBytes&&b.concat(f);return b};b.prototype.getIv=function(a){if(this.iv){var b=this.iv;this.iv=null;a(null,b)}else{var f=this;e(16,function(b,e){b?a(b):a(null,f.encryptCipher.process(e))})}};return d}(), +K=function(){function c(){}function k(a){return a?window.sessionStorage:window.localStorage}function b(a,b,e,c){b={value:b};e&&(b.expires=l.now()+e);return k(c).setItem(a,JSON.stringify(b))}function a(a,b){var e=k(b).getItem(a);if(!e)return null;e=JSON.parse(e);return e.expires&&e.expires>>2]>>>24-n%4*8&255;return b}throw Error("BufferUtils.toArrayBuffer expected a buffer");};b.toWordArray=function(b){return c(b)?b:a.create(b)};b.base64Encode=function(a){if(k(a)){var b="";a=new Uint8Array(a);for(var e=a.byteLength, +h=e%3,e=e-h,g,u,t,l,D=0;D>18,u=(l&258048)>>12,t=(l&4032)>>6,l&=63,b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[g]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[t]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[l];1==h?(l=a[e],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&252)>>2]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l& +3)<<4]+"=="):2==h&&(l=a[e]<<8|a[e+1],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&64512)>>10]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&1008)>>4]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(l&15)<<2]+"=");return b}if(c(a))return C.enc.Base64.stringify(a)};b.base64Decode=function(a){if(e&&h){a=h(a);for(var b=a.length,c=new Uint8Array(b),d=0;d=b}var b=function(){};c.get=function(a,e,h,f,m){m=m||b;var p="function"==typeof e?e:function(b){return a.baseUri(b)+e},n;n=(n=a.connection)&&"connected"==n.state?[n.connectionManager.host]:r.getHosts(a.options);if(1==n.length)c.getUri(a,p(n[0]),h,f,m);else{var g=function(b){c.getUri(a,p(b.shift()),h,f,function(a){a&&k(a)&& +b.length?g(b):m.apply(null,arguments)})};g(n)}};c.getUri=function(a,e,h,f,m){c.Request(a,e,h,f,null,m||b)};c.post=function(a,e,h,f,m,p){p=p||b;var n="function"==typeof e?e:function(b){return a.baseUri(b)+e},g;g=(g=a.connection)&&"connected"==g.state?[g.connectionManager.host]:r.getHosts(a.options);if(1==g.length)c.postUri(a,n(g[0]),h,f,m,p);else{var u=function(b){c.postUri(a,n(b.shift()),h,f,m,function(a){a&&k(a)&&b.length?u(b):p.apply(null,arguments)})};u(g)}};c.postUri=function(a,e,h,f,m,p){c.Request(a, +e,h,m,f,p||b)};c.supportsAuthHeaders=!1;c.supportsLinkHeaders=!1;return c}(),ja=function(){function c(){this.buffer=[]}function k(a){this._input=a;this._index=-1;this._buffer=[]}function b(a){this._input=a;this._index=-1;this._buffer=[]}c.prototype.append=function(a){this.buffer.push(a);return this};c.prototype.toString=function(){return this.buffer.join("")};var a={codex:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(b){var h=new c,f=a.codex;for(b=new k(b);b.moveNext();){var m= +b.current;b.moveNext();var p=b.current;b.moveNext();var n=b.current,g=m>>2,m=(m&3)<<4|p>>4,u=(p&15)<<2|n>>6,t=n&63;isNaN(p)?u=t=64:isNaN(n)&&(t=64);h.append(f.charAt(g)+f.charAt(m)+f.charAt(u)+f.charAt(t))}return h.toString()},decode:function(a){var h=new c;for(a=new b(a);a.moveNext();){var f=a.current;if(128>f)h.append(String.fromCharCode(f));else if(191f){a.moveNext();var m=a.current;h.append(String.fromCharCode((f&31)<<6|m&63))}else a.moveNext(),m=a.current,a.moveNext(),h.append(String.fromCharCode((f& +15)<<12|(m&63)<<6|a.current&63))}return h.toString()}};k.prototype={current:Number.NaN,moveNext:function(){if(0=this._input.length-1)return this.current=Number.NaN,!1;var a=this._input.charCodeAt(++this._index);13==a&&10==this._input.charCodeAt(this._index+1)&&(a=10,this._index+=2);128>a?this.current=a:(127a?this.current=a>>6|192:(this.current=a>>12|224,this._buffer.push(a>>6&63|128)),this._buffer.push(a&63|128)); return!0}};b.prototype={current:64,moveNext:function(){if(0=this._input.length-1)return this.current=64,!1;var b=a.codex.indexOf(this._input.charAt(++this._index)),c=a.codex.indexOf(this._input.charAt(++this._index)),f=a.codex.indexOf(this._input.charAt(++this._index)),d=a.codex.indexOf(this._input.charAt(++this._index)),p=(f&3)<<6|d;this.current=b<<2|c>>4;64!=f&&this._buffer.push((c&15)<<4|f>>2);64!=d&&this._buffer.push(p); -return!0}};return a}();q.protocolVersion=1;q.ENVIRONMENT="";q.REST_HOST="rest.ably.io";q.REALTIME_HOST="realtime.ably.io";q.FALLBACK_HOSTS=["A.ably-realtime.com","B.ably-realtime.com","C.ably-realtime.com","D.ably-realtime.com","E.ably-realtime.com"];q.PORT=80;q.TLS_PORT=443;q.TIMEOUTS={disconnectedRetryTimeout:15E3,suspendedRetryTimeout:3E4,httpRequestTimeout:15E3,channelRetryTimeout:15E3,connectionStateTtl:12E4,realtimeRequestTimeout:1E4,recvTimeout:9E4,preferenceConnectTimeout:6E3,parallelUpgradeDelay:4E3}; -q.httpMaxRetryCount=3;q.version="1.0.0";q.libstring="js-"+q.version;q.apiVersion="1.0";q.getHost=function(c,h,b){return h=b?h==c.restHost&&c.realtimeHost||h||c.realtimeHost:h||c.restHost};q.getPort=function(c,h){return h||c.tls?c.tlsPort:c.port};q.getHttpScheme=function(c){return c.tls?"https://":"http://"};q.getHosts=function(c){var h=[c.restHost],b=c.fallbackHosts;c="undefined"!==typeof c.httpMaxRetryCount?c.httpMaxRetryCount:q.httpMaxRetryCount;b&&(h=h.concat(l.arrChooseN(b,c)));return h};q.normaliseOptions= +return!0}};return a}();r.protocolVersion=1;r.ENVIRONMENT="";r.REST_HOST="rest.ably.io";r.REALTIME_HOST="realtime.ably.io";r.FALLBACK_HOSTS=["A.ably-realtime.com","B.ably-realtime.com","C.ably-realtime.com","D.ably-realtime.com","E.ably-realtime.com"];r.PORT=80;r.TLS_PORT=443;r.TIMEOUTS={disconnectedRetryTimeout:15E3,suspendedRetryTimeout:3E4,httpRequestTimeout:15E3,channelRetryTimeout:15E3,connectionStateTtl:12E4,realtimeRequestTimeout:1E4,recvTimeout:9E4,preferenceConnectTimeout:6E3,parallelUpgradeDelay:4E3}; +r.httpMaxRetryCount=3;r.version="1.0.1";r.libstring="js-"+r.version;r.apiVersion="1.0";r.getHost=function(c,k,b){return k=b?k==c.restHost&&c.realtimeHost||k||c.realtimeHost:k||c.restHost};r.getPort=function(c,k){return k||c.tls?c.tlsPort:c.port};r.getHttpScheme=function(c){return c.tls?"https://":"http://"};r.getHosts=function(c){var k=[c.restHost],b=c.fallbackHosts;c="undefined"!==typeof c.httpMaxRetryCount?c.httpMaxRetryCount:r.httpMaxRetryCount;b&&(k=k.concat(l.arrChooseN(b,c)));return k};r.normaliseOptions= function(d){d.host&&(c.deprecated("host","restHost"),d.restHost=d.host);d.wsHost&&(c.deprecated("wsHost","realtimeHost"),d.realtimeHost=d.wsHost);d.queueEvents&&(c.deprecated("queueEvents","queueMessages"),d.queueMessages=d.queueEvents);!0===d.recover&&(c.deprecated("{recover: true}","{recover: function(lastConnectionDetails, cb) { cb(true); }}"),d.recover=function(a,b){b(!0)});"function"===typeof d.recover&&!0===d.closeOnUnload&&(c.logAction(LOG_ERROR,"Defaults.normaliseOptions","closeOnUnload was true and a session recovery function was set - these are mutually exclusive, so unsetting the latter"), -d.recover=null);d.transports&&l.arrIn(d.transports,"xhr")&&(c.deprecated('transports: ["xhr"]','transports: ["xhr_streaming"]'),l.arrDeleteValue(d.transports,"xhr"),d.transports.push("xhr_streaming"));"queueMessages"in d||(d.queueMessages=!0);var h=!1;if(d.restHost)d.realtimeHost=d.realtimeHost||d.restHost;else{var b=d.environment&&String(d.environment).toLowerCase()||q.ENVIRONMENT,h=!b||"production"===b;d.restHost=h?q.REST_HOST:b+"-"+q.REST_HOST;d.realtimeHost=h?q.REALTIME_HOST:b+"-"+q.REALTIME_HOST}d.fallbackHosts= -h||d.fallbackHostsUseDefault?q.FALLBACK_HOSTS:d.fallbackHosts;d.port=d.port||q.PORT;d.tlsPort=d.tlsPort||q.TLS_PORT;"tls"in d||(d.tls=!0);d.timeouts={};for(var a in q.TIMEOUTS)d.timeouts[a]=d[a]||q.TIMEOUTS[a];d.useBinaryProtocol="useBinaryProtocol"in d?z.supportsBinary&&d.useBinaryProtocol:z.preferBinary;return d};var x=function(){function d(){this.any=[];this.events={};this.anyOnce=[];this.eventsOnce={}}function h(a,b,d){try{b.apply(a,d)}catch(f){c.logAction(c.LOG_ERROR,"EventEmitter.emit()","Unexpected listener exception: "+ +d.recover=null);d.transports&&l.arrIn(d.transports,"xhr")&&(c.deprecated('transports: ["xhr"]','transports: ["xhr_streaming"]'),l.arrDeleteValue(d.transports,"xhr"),d.transports.push("xhr_streaming"));"queueMessages"in d||(d.queueMessages=!0);var k=!1;if(d.restHost)d.realtimeHost=d.realtimeHost||d.restHost;else{var b=d.environment&&String(d.environment).toLowerCase()||r.ENVIRONMENT,k=!b||"production"===b;d.restHost=k?r.REST_HOST:b+"-"+r.REST_HOST;d.realtimeHost=k?r.REALTIME_HOST:b+"-"+r.REALTIME_HOST}d.fallbackHosts= +k||d.fallbackHostsUseDefault?r.FALLBACK_HOSTS:d.fallbackHosts;d.port=d.port||r.PORT;d.tlsPort=d.tlsPort||r.TLS_PORT;"tls"in d||(d.tls=!0);d.timeouts={};for(var a in r.TIMEOUTS)d.timeouts[a]=d[a]||r.TIMEOUTS[a];d.useBinaryProtocol="useBinaryProtocol"in d?w.supportsBinary&&d.useBinaryProtocol:w.preferBinary;return d};var z=function(){function d(){this.any=[];this.events={};this.anyOnce=[];this.eventsOnce={}}function k(a,b,d){try{b.apply(a,d)}catch(f){c.logAction(c.LOG_ERROR,"EventEmitter.emit()","Unexpected listener exception: "+ f+"; stack = "+f.stack)}}function b(a,e,c){var f,d,p,n;for(n=0;n=d?null:c.slice(0,d).join("/"),b.data=m}}};d.fromResponseBody=function(b,a,e){e&&(b="msgpack"==e?h.decode(b):JSON.parse(String(b)));for(e=0;e=d?null:c.slice(0,d).join("/"),b.data=m}}};d.fromResponseBody=function(b,a,e){e&&(b="msgpack"==e?k.decode(b):JSON.parse(String(b)));for(e=0;el.arrIndexOf(p,b.shortName)}function h(a,b,c,e,f){this.options=a;this.host=b;this.mode=c;this.connectionKey=e;this.connectionSerial= -f;this.format=a.useBinaryProtocol?"msgpack":"json"}function b(a,f){x.call(this);this.realtime=a;this.options=f;var d=f.timeouts,n=this;this.states={initialized:{state:"initialized",terminal:!1,queueEvents:!0,sendEvents:!1,failState:"disconnected"},connecting:{state:"connecting",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.preferenceConnectTimeout+d.realtimeRequestTimeout,failState:"disconnected"},connected:{state:"connected",terminal:!1,queueEvents:!1,sendEvents:!0,failState:"disconnected"}, -synchronizing:{state:"connected",terminal:!1,queueEvents:!0,sendEvents:!1,failState:"disconnected"},disconnected:{state:"disconnected",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.disconnectedRetryTimeout,failState:"disconnected"},suspended:{state:"suspended",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.suspendedRetryTimeout,failState:"suspended"},closing:{state:"closing",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.realtimeRequestTimeout,failState:"closed"},closed:{state:"closed", -terminal:!0,queueEvents:!1,sendEvents:!1,failState:"closed"},failed:{state:"failed",terminal:!0,queueEvents:!1,sendEvents:!1,failState:"failed"}};this.state=this.states.initialized;this.errorReason=null;this.queuedMessages=new fa;this.msgSerial=0;this.connectionSerial=this.connectionKey=this.connectionId=void 0;this.transports=l.intersect(f.transports||q.transports,b.supportedTransports);this.baseTransport=l.intersect(q.transports,this.transports)[0];this.upgradeTransports=l.intersect(this.transports, -q.upgradeTransports);this.transportHostBlacklist={};this.transportPreference=null;this.httpHosts=q.getHosts(f);this.activeProtocol=null;this.proposedTransports=[];this.pendingTransports=[];this.lastAutoReconnectAttempt=this.host=null;c.logAction(c.LOG_MINOR,"Realtime.ConnectionManager()","started");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","requested transports = ["+(f.transports||q.transports)+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","available transports = ["+this.transports+ -"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","http hosts = ["+this.httpHosts+"]");if(!this.transports.length)throw c.logAction(c.LOG_ERROR,"realtime.ConnectionManager()","no requested transports available"),Error("no requested transports available");if(d=z.addEventListener)e&&"function"===typeof f.recover&&d("beforeunload",this.persistConnection.bind(this)),!0===f.closeOnUnload&&d("beforeunload",function(){n.requestState({state:"closing"})}),d("online",function(){if(n.state==n.states.disconnected|| -n.state==n.states.suspended)c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018online\u2019 event","reattempting connection"),n.requestState({state:"connecting"})}),d("offline",function(){n.state==n.states.connected&&(c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018offline\u2019 event","disconnecting active transport"),n.disconnectAllTransports())})}var a=!("undefined"===typeof I||!I.get),e=!("undefined"===typeof I||!I.getSession),k=w.Action,f=ga.PendingMessage,m=function(){}, -p=q.transportPreferenceOrder,n=p[p.length-1];h.prototype.getConnectParams=function(a){a=a?l.copy(a):{};var b=this.options;switch(this.mode){case "upgrade":a.upgrade=this.connectionKey;break;case "resume":a.resume=this.connectionKey;void 0!==this.connectionSerial&&(a.connection_serial=this.connectionSerial);break;case "recover":var c=b.recover.split(":");c&&(a.recover=c[0],a.connection_serial=c[1])}void 0!==b.clientId&&(a.clientId=b.clientId);!1===b.echoMessages&&(a.echo="false");void 0!==this.format&& -(a.format=this.format);void 0!==this.stream&&(a.stream=this.stream);void 0!==this.heartbeats&&(a.heartbeats=this.heartbeats);void 0!==b.transportParams&&l.mixin(a,b.transportParams);a.v=q.apiVersion;a.lib=q.libstring;return a};l.inherits(b,x);b.supportedTransports={};b.prototype.getTransportParams=function(a){var b=this;(function(a){if(b.connectionKey)a("resume");else if("string"===typeof b.options.recover)a("recover");else{var g=b.options.recover,f=e&&I.getSession("ably-connection-recovery");f&& -"function"===typeof g?(c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Calling clientOptions-provided recover function with last session data"),g(f,function(c){c?(b.options.recover=f.recoveryKey,a("recover")):a("clean")})):a("clean")}})(function(e){c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Transport recovery mode = "+e+("clean"==e?"":"; connectionKey = "+b.connectionKey+"; connectionSerial = "+b.connectionSerial));a(new h(b.options,null,e,b.connectionKey, -b.connectionSerial))})};b.prototype.tryATransport=function(a,e,f){var d=this,n=a.host;c.logAction(c.LOG_MICRO,"ConnectionManager.tryATransport()","trying "+e);n in this.transportHostBlacklist&&l.arrIn(this.transportHostBlacklist[n],e)?c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()",e+" transport is blacklisted for host "+a.host):b.supportedTransports[e].tryConnect(this,this.realtime.auth,a,function(b,n){var p=d.state;p==d.states.closing||p==d.states.closed||p==d.states.failed?(n&&(c.logAction(c.LOG_MINOR, -"ConnectionManager.tryATransport()","connection "+p.state+" while we were attempting the transport; closing "+n),n.close()),f(!0)):b?(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()","transport "+e+" "+b.event+", err: "+b.error.toString()),M.isTokenErr(b.error)?d.realtime.auth._forceNewToken(null,null,function(b){b?d.actOnErrorFromAuthorize(b):d.tryATransport(a,e,f)}):"failed"===b.event?(d.notifyState({state:"failed",error:b.error}),f(!0)):"disconnected"===b.event&&f(!1)):(c.logAction(c.LOG_MICRO, -"ConnectionManager.chooseTransportForHost()","viable transport "+e+"; setting pending"),d.setTransportPending(n,a),f(null,n))})};b.prototype.setTransportPending=function(a,b){var e=b.mode;c.logAction(c.LOG_MINOR,"ConnectionManager.setTransportPending()","transport = "+a+"; mode = "+e);l.arrDeleteValue(this.proposedTransports,a);this.pendingTransports.push(a);var f=this;a.once("connected",function(c,d,p,k,m){"upgrade"==e&&f.activeProtocol?a.shortName!==n&&l.arrIn(f.getUpgradePossibilities(),n)?setTimeout(function(){f.scheduleTransportActivation(c, -a,d,p,k,m)},f.options.timeouts.parallelUpgradeDelay):f.scheduleTransportActivation(c,a,d,p,k,m):(f.activateTransport(c,a,d,p,k,m),l.nextTick(function(){f.connectImpl(b)}));"recover"===e&&f.options.recover&&(f.options.recover=null,f.unpersistConnection())});a.on(["disconnected","closed","failed"],function(b){f.deactivateTransport(a,this.event,b)});this.emit("transport.pending",a)};b.prototype.scheduleTransportActivation=function(a,b,e,f,n,p){var k=this,m=this.activeProtocol&&this.activeProtocol.getTransport(), -h=function(){b.disconnect();l.arrDeleteValue(k.pendingTransports,b)};this.state!==this.states.connected&&this.state!==this.states.connecting?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+this.state.state+(this.state===this.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName),h()):m&&!d(b,m)?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()", -"Proposed transport "+b.shortName+" is no better than current active transport "+m.shortName+" - abandoning upgrade"),h()):(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Scheduling transport upgrade; transport = "+b),this.realtime.channels.onceNopending(function(d){var m;if(d)c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Unable to activate transport; transport = "+b+"; err = "+d);else if(b.isConnected){if(k.state===k.states.connected)c.logAction(c.LOG_MICRO, -"ConnectionManager.scheduleTransportActivation()","Currently connected, so temporarily pausing events until the upgrade is complete"),k.state=k.states.synchronizing,m=k.activeProtocol;else if(k.state!==k.states.connecting){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+k.state.state+(k.state===k.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName);h();return}var l= -(d=n!==k.connectionId)?f:k.connectionSerial;d&&c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Upgrade resulted in new connectionId; resetting library connectionSerial from "+k.connectionSerial+" to "+l+"; upgrade error was "+a);c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Syncing transport; transport = "+b);k.sync(b,function(f,d,n){if(f)k.state===k.states.synchronizing&&(c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()", -"Unexpected error attempting to sync transport; transport = "+b+"; err = "+f),k.disconnectAllTransports());else if(f=function(){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Activating transport; transport = "+b);k.activateTransport(a,b,e,d,n,p);k.state===k.states.synchronizing?(c.logAction(c.LOG_MICRO,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, sending queued messages on upgraded transport; transport = "+b),k.state=k.states.connected): -c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, but state is now "+k.state.state+", so leaving unchanged");k.state.sendEvents&&k.sendQueuedMessages()},m)m.onceIdle(f);else f()})}else c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Proposed transport "+b.shortName+"is no longer connected; abandoning upgrade"),h()}))};b.prototype.activateTransport=function(a,b,e,f,d,n){c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", -"transport = "+b);a&&c.logAction(c.LOG_ERROR,"ConnectionManager.activateTransport()","error = "+a);e&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionKey = "+e);void 0!==f&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionSerial = "+f);d&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionId = "+d);n&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionDetails = "+JSON.stringify(n));this.persistTransportPreference(b); -var k=this.state,p=this.states.connected.state;c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","current state = "+k.state);if(k.state==this.states.closing.state||k.state==this.states.closed.state||k.state==this.states.failed.state)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","Disconnecting transport and abandoning"),b.disconnect(),!1;l.arrDeleteValue(this.pendingTransports,b);if(!b.isConnected)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", -"Declining to activate transport "+b+" since it appears to no longer be connected"),!1;var m=this.activeProtocol;this.activeProtocol=new ga(b);this.host=b.params.host;e&&this.connectionKey!=e&&this.setConnection(d,e,f);this.onConnectionDetailsUpdate(n,b);var h=this;l.nextTick(function(){b.on("connected",function(a,c,e,g,f){h.onConnectionDetailsUpdate(f,b);h.emit("update",new Q(p,p,null,a))})});this.emit("transport.active",b,e,b.params);k.state===this.states.connected.state?a&&(this.errorReason=this.realtime.connection.errorReason= -a,this.emit("update",new Q(p,p,null,a))):(this.notifyState({state:"connected",error:a}),this.errorReason=this.realtime.connection.errorReason=a||null);m&&(0k?(c.logAction(c.LOG_MICRO,"ConnectionManager.notifyState()","Last reconnect attempt was only "+k+"ms ago, waiting another "+ -(1E3-k)+"ms before trying again"),setTimeout(n,1E3-k)):l.nextTick(n)}else"disconnected"!==b&&"suspended"!==b||this.startRetryTimer(d.retryDelay);("disconnected"===b&&!f||"suspended"===b||d.terminal)&&l.nextTick(function(){e.disconnectAllTransports()});"connected"!=b||this.activeProtocol||c.logAction(c.LOG_ERROR,"ConnectionManager.notifyState()","Broken invariant: attempted to go into connected state, but there is no active protocol");this.enactStateChange(a);this.state.sendEvents?this.sendQueuedMessages(): -this.state.queueEvents||(this.realtime.channels.propogateConnectionInterruption(b,a.reason),this.failQueuedMessages(a.reason))}};b.prototype.requestState=function(a){var b=a.state,e=this;c.logAction(c.LOG_MINOR,"ConnectionManager.requestState()","requested state: "+b+"; current state: "+this.state.state);if(b!=this.state.state&&(this.cancelTransitionTimer(),this.cancelRetryTimer(),this.checkSuspendTimer(b),"connecting"!=b||"connected"!=this.state.state)&&("closing"!=b||"closed"!=this.state.state)){var f= -this.states[b];a=new Q(this.state.state,f.state,null,a.error||J[f.state]);this.enactStateChange(a);"connecting"==b&&l.nextTick(function(){e.startConnect()});"closing"==b&&this.closeImpl()}};b.prototype.startConnect=function(){if(this.state!==this.states.connecting)c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()","Must be in connecting state to connect, but was "+this.state.state);else{var a=this.realtime.auth,b=this,e=function(){b.getTransportParams(function(a){b.connectImpl(a)})};c.logAction(c.LOG_MINOR, -"ConnectionManager.startConnect()","starting connection");this.startSuspendTimer();this.startTransitionTimer(this.states.connecting);if("basic"===a.method)e();else{var f=function(a){a?b.actOnErrorFromAuthorize(a):e()};this.errorReason&&M.isTokenErr(this.errorReason)?a._forceNewToken(null,null,f):a._ensureValidAuthCredentials(f)}}};b.prototype.connectImpl=function(a){var b=this.state.state;b!==this.states.connecting.state&&b!==this.states.connected.state?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()", -"Must be in connecting state to connect (or connected to upgrade), but was "+b):this.pendingTransports.length?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Transports "+this.pendingTransports[0].toString()+" currently pending; taking no action"):b==this.states.connected.state?this.upgradeIfNeeded(a):1a.code)?[w.fromValues({action:w.Action.ERROR,error:a})]:[w.fromValues({action:w.Action.DISCONNECTED,error:a})]}function b(a,b,c){this.timeoutOnIdle=!0; -c.format=void 0;c.heartbeats=!0;P.call(this,a,b,c);this.stream="stream"in c?c.stream:!0;this.pendingItems=this.pendingCallback=this.recvRequest=this.sendRequest=null;this.disposed=!1}l.inherits(b,P);b.REQ_SEND=0;b.REQ_RECV=1;b.REQ_RECV_POLL=2;b.REQ_RECV_STREAM=3;b.prototype.connect=function(){c.logAction(c.LOG_MINOR,"CometTransport.connect()","starting");P.prototype.connect.call(this);var a=this,b=this.params,k=b.options,f=q.getHost(k,b.host),b=q.getPort(k);this.baseUri=(k.tls?"https://":"http://")+ -f+":"+b+"/comet/";var m=this.baseUri+"connect";c.logAction(c.LOG_MINOR,"CometTransport.connect()","uri: "+m);this.auth.getAuthParams(function(b,e){if(b)a.disconnect(b);else{a.authParams=e;var g=a.params.getConnectParams(e);"stream"in g&&(a.stream=g.stream);c.logAction(c.LOG_MINOR,"CometTransport.connect()","connectParams:"+l.toQueryString(g));var k=!1,g=a.recvRequest=a.createRequest(m,null,g,null,a.stream?3:1);g.on("data",function(b){a.recvRequest&&(k||(k=!0,a.emit("preconnect")),a.onData(b))});g.on("complete", -function(b,c,e){d(e,f,a.connectionManager);a.recvRequest||(b=b||new r("Request cancelled",8E4,400));a.recvRequest=null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(h(b));else a.disconnect(b);else l.nextTick(function(){a.recv()})});g.exec()}})};b.prototype.requestClose=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestClose()");this._requestCloseOrDisconnect(!0)};b.prototype.requestDisconnect=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestDisconnect()");this._requestCloseOrDisconnect(!1)}; -b.prototype._requestCloseOrDisconnect=function(a){var b=a?this.closeUri:this.disconnectUri;if(b){var d=this,b=this.createRequest(b,null,this.authParams,null,0);b.on("complete",function(b){b&&(c.logAction(c.LOG_ERROR,"CometTransport.request"+(a?"Close()":"Disconnect()"),"request returned err = "+b),d.finish("disconnected",b))});b.exec()}};b.prototype.dispose=function(){c.logAction(c.LOG_MINOR,"CometTransport.dispose()","");if(!this.disposed){this.disposed=!0;this.recvRequest&&(c.logAction(c.LOG_MINOR, -"CometTransport.dispose()","aborting recv request"),this.recvRequest.abort(),this.recvRequest=null);this.finish("disconnected",J.disconnected);var a=this;l.nextTick(function(){a.emit("disposed")})}};b.prototype.onConnect=function(a){if(!this.disposed){var b=a.connectionKey;P.prototype.onConnect.call(this,a);b=this.baseUri+b;c.logAction(c.LOG_MICRO,"CometTransport.onConnect()","baseUri = "+b+"; connectionKey = "+a.connectionKey);this.sendUri=b+"/send";this.recvUri=b+"/recv";this.closeUri=b+"/close"; -this.disconnectUri=b+"/disconnect"}};b.prototype.send=function(a){if(this.sendRequest)this.pendingItems=this.pendingItems||[],this.pendingItems.push(a);else{var b=this.pendingItems||[];b.push(a);this.pendingItems=null;this.sendItems(b)}};b.prototype.sendAnyPending=function(){var a=this.pendingItems;a&&(this.pendingItems=null,this.sendItems(a))};b.prototype.sendItems=function(a){var b=this;a=this.sendRequest=b.createRequest(b.sendUri,null,b.authParams,this.encodeRequest(a),0);a.on("complete",function(a, -f){a&&c.logAction(c.LOG_ERROR,"CometTransport.sendItems()","on complete: err = "+JSON.stringify(a));b.sendRequest=null;if(f)b.onData(f);else if(a&&a.code)b.onData(h(a));else b.disconnect(a);b.pendingItems&&l.nextTick(function(){b.sendRequest||b.sendAnyPending()})});a.exec()};b.prototype.recv=function(){if(!this.recvRequest&&this.isConnected){var a=this,b=this.recvRequest=this.createRequest(this.recvUri,null,this.authParams,null,a.stream?3:2);b.on("data",function(b){a.onData(b)});b.on("complete",function(b){a.recvRequest= -null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(h(b));else a.disconnect(b);else l.nextTick(function(){a.recv()})});b.exec()}};b.prototype.onData=function(a){try{var b=this.decodeResponse(a);if(b&&b.length)for(a=0;al||300<=l?(c=c&&c.error,c||(c=Error(String(res)),c.statusCode=l),a(c)):a(null,c,d,!0,l))}}}function a(a){var b=[];if(a)for(var c in a)b.push(c+"="+a[c]);return b.join("&")}function e(b,e,d,n){return function(g,k,h,l,r){g?c.logAction(c.LOG_MICRO,"Resource."+e+"()","Received Error; "+(d+(n?"?":"")+a(n))+"; Error: "+JSON.stringify(g)):c.logAction(c.LOG_MICRO, -"Resource."+e+"()","Received; "+(d+(n?"?":"")+a(n))+"; Headers: "+a(h)+"; StatusCode: "+r+"; Body: "+(y.isBuffer(k)?k.toString():k));b&&b(g,k,h,l,r)}}var k=z.msgpack;d.get=function(f,d,k,n,g,l){function s(b,e){c.shouldLog(c.LOG_MICRO)&&c.logAction(c.LOG_MICRO,"Resource.get()","Sending; "+(d+(e?"?":"")+a(e)));u.get(f,d,b,e,function(a,b,c,e,d){a&&M.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?l(a):h(f,k,n,l,s)}):l(a,b,c,e,d)})}c.shouldLog(c.LOG_MICRO)&&(l=e(l,"get",d,n));g&&(l=l&&b(l,g),(n= -n||{}).envelope=g);h(f,k,n,l,s)};d.post=function(f,d,p,n,g,l,s){function v(b,e){if(c.shouldLog(c.LOG_MICRO)){var l=p;if(0<(b["content-type"]||"").indexOf("msgpack"))try{p=k.decode(p)}catch(t){c.logAction(c.LOG_MICRO,"Resource.post()","Sending MsgPack Decoding Error: "+JSON.stringify(t))}c.logAction(c.LOG_MICRO,"Resource.post()","Sending; "+(d+(e?"?":"")+a(e))+"; Body: "+l)}u.post(f,d,b,p,e,function(a,b,c,e,d){a&&M.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?s(a):h(f,n,g,s,v)}):s(a,b,c, -e,d)})}c.shouldLog(c.LOG_MICRO)&&(s=e(s,"post",d,g));l&&(s=b(s,l),g.envelope=l);h(f,n,g,s,v)};return d}(),R=function(){function d(a,b,c,f,d,p){this.rest=a;this.path=b;this.headers=c;this.envelope=f;this.bodyHandler=d;this.useHttpPaginatedResponse=p||!1}function h(a,b,c){this.resource=a;this.items=b;if(c){var f=this;"first"in c&&(this.first=function(a){f.get(c.first,a)});"current"in c&&(this.current=function(a){f.get(c.current,a)});this.next=function(a){"next"in c?f.get(c.next,a):a(null,null)};this.hasNext= -function(){return"next"in c};this.isLast=function(){return!this.hasNext()}}}function b(a,b,c,f,d){h.call(this,a,b,d);this.statusCode=f;this.success=300>f&&200<=f;this.headers=c}d.prototype.get=function(a,b){var c=this;V.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,g){c.handlePage(a,d,p,n,g,b)})};d.prototype.post=function(a,b,c){var d=this;V.post(d.rest,d.path,b,d.headers,a,d.envelope,function(a,b,e,g,h){c&&d.handlePage(a,b,e,g,h,c)})};d.prototype.handlePage=function(a,e,d,f,m,p){if(a)c.logAction(c.LOG_ERROR, -"PaginatedResource.handlePage()","Unexpected error getting resource: err = "+JSON.stringify(a)),p(a);else{var n,g,t;try{n=this.bodyHandler(e,d,f)}catch(s){p(s);return}if(d&&(g=d.Link||d.link)){a=g;"string"==typeof a&&(a=a.split(","));e={};for(f=0;f;\s*rel="(\w+)"$/))&&(t=(t=g[1].match(/^\.\/(\w+)\?(.*)$/))&&l.parseQueryString(t[2]))&&(e[g[2]]=t);t=e}this.useHttpPaginatedResponse?p(null,new b(this,n,d,m,t)):p(null,new h(this,n,t))}};h.prototype.get=function(a, -b){var c=this.resource;V.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,g){c.handlePage(a,d,p,n,g,b)})};l.inherits(b,h);return d}(),M=function(){function d(){}function h(a){if(!a)return"";"string"==typeof a&&(a=JSON.parse(a));var b={},c=l.keysArray(a,!0);if(!c)return"";c.sort();for(var e=0;ek){e(new r("authUrl response exceeded max permitted length", -40170,401));return}try{b=JSON.parse(b)}catch(g){e(new r("Unexpected error processing authURL response; err = "+g.message,40170,401));return}}e(null,b)}else e(new r("authUrl responded with unacceptable content-type "+a+", should be either text/plain or application/json",40170,401));else e(new r("authUrl response is missing a content-type header",40170,401))};c.logAction(c.LOG_MICRO,"Auth.requestToken().tokenRequestCallback","Sending; "+b.authUrl+"; Params: "+JSON.stringify(f));b.authMethod&&"post"=== -b.authMethod.toLowerCase()?(d=d||{},d["content-type"]="application/x-www-form-urlencoded",f=l.toQueryString(f).slice(1),u.postUri(v,b.authUrl,d,f,{},g)):u.getUri(v,b.authUrl,d||{},f,g)};else if(b.key){var q=this;c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with client-side signing");s=function(a,c){q.createTokenRequest(a,b,c)}}else{c.logAction(c.LOG_ERROR,"Auth.requestToken()","Need a new token, but authOptions does not include any way to request one");f(new r("Need a new token, but authOptions does not include any way to request one", -40101,401));return}"capability"in a&&(a.capability=h(a.capability));var v=this.client,Z=function(a,d){var f,g=a.keyName,k=function(a){return v.baseUri(a)+"/keys/"+g+"/requestToken"};u.post?(f=l.defaultPostHeaders(m),b.requestHeaders&&l.mixin(f,b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending POST; "+k+"; Token params: "+JSON.stringify(a)),a="msgpack"==m?e.encode(a,!0):JSON.stringify(a),u.post(v,k,f,a,null,d)):(f=l.defaultGetHeaders(),b.requestHeaders&&l.mixin(f, -b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending GET; "+k+"; Token params: "+JSON.stringify(a)),u.get(v,k,f,a,d))},w=!1,x=this.client.options.timeouts.realtimeRequestTimeout,z=setTimeout(function(){w=!0;var a="Token request callback timed out after "+x/1E3+" seconds";c.logAction(c.LOG_ERROR,"Auth.requestToken()",a);f(new r(a,40170,401))},x);s(a,function(a,b){if(!w)if(clearTimeout(z),a)c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request signing call returned error; err = "+ -l.inspectError(a)),a&&a.code||(a=new r(l.inspectError(a),40170,401)),f(a);else if("string"===typeof b)384k?f(new r("Token request/details object exceeded max permitted stringified size (was "+ -d+" bytes)",40170,401)):"issued"in b?f(null,b):"keyName"in b?Z(b,function(a,b,d,k){a?(c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request API call returned error; err = "+l.inspectError(a)),f(a)):(k||(b="msgpack"==m?e.decode(b):JSON.parse(b)),c.logAction(c.LOG_MINOR,"Auth.getToken()","token received"),f(null,b))}):(d="Expected token request callback to call back with a token string, token request object, or token details object",c.logAction(c.LOG_ERROR,"Auth.requestToken()",d),f(new r(d, -40170,401)))})};a.prototype.createTokenRequest=function(a,b,e){"function"!=typeof a||e?"function"!=typeof b||e||(e=b,b=null):(e=a,b=a=null);b=b||this.authOptions;a=a||l.copy(this.tokenParams);var d=b.key;if(d){var d=d.split(":"),k=d[0],m=d[1];if(m)if(""===a.clientId)e(new r("clientId can\u2019t be an empty string",40012,400));else{a.capability=h(a.capability);var q=l.mixin({keyName:k},a),Z=a.clientId||"",w=a.ttl||"",x=a.capability,y=this;(function(a){q.timestamp?a():y.getTimestamp(b&&b.queryTime, -function(b,c){b?e(b):(q.timestamp=c,a())})})(function(){var a=q.nonce||(q.nonce=("000000"+Math.floor(1E16*Math.random())).slice(-16)),a=q.keyName+"\n"+w+"\n"+x+"\n"+Z+"\n"+q.timestamp+"\n"+a+"\n";q.mac=q.mac||f(a,m);c.logAction(c.LOG_MINOR,"Auth.getTokenRequest()","generated signed request");e(null,q)})}else e(Error("Invalid key specified"))}else e(Error("No key specified"))};a.prototype.getAuthParams=function(a){"basic"==this.method?a(null,{key:this.key}):this._ensureValidAuthCredentials(function(b, -c){b?a(b):a(null,{access_token:c.token})})};a.prototype.getAuthHeaders=function(a){"basic"==this.method?a(null,{authorization:"Basic "+this.basicKey}):this._ensureValidAuthCredentials(function(b,c){b?a(b):a(null,{authorization:"Bearer "+m(c.token)})})};a.prototype.getTimestamp=function(a,b){isNaN(parseInt(this.client.serverTimeOffset))&&(a||this.authOptions.queryTime)?this.client.time(function(a,c){a?b(a):b(null,c)}):b(null,l.now()+(this.client.serverTimeOffset||0))};a.prototype._saveBasicOptions= -function(a){this.method="basic";this.key=a.key;this.basicKey=m(a.key);this.authOptions=a||{};"clientId"in a&&this._userSetClientId(a.clientId)};a.prototype._saveTokenOptions=function(a,b){this.method="token";a&&(this.tokenParams=a);b&&(b.token&&(b.tokenDetails="string"===typeof b.token?{token:b.token}:b.token),b.tokenDetails&&(this.tokenDetails=b.tokenDetails),"clientId"in b&&this._userSetClientId(b.clientId),this.authOptions=b)};a.prototype._ensureValidAuthCredentials=function(a){var b=this,e=this.tokenDetails, -d=function(){b.requestToken(b.tokenParams,b.authOptions,function(c,e){c?a(c):a(null,b.tokenDetails=e)})};e?this._tokenClientIdMismatch(e.clientId)?a(new r("Mismatch between clientId in token ("+e.clientId+") and current clientId ("+this.clientId+")",40102,401)):this.getTimestamp(b.authOptions&&b.authOptions.queryTime,function(f,k){f&&a(f);void 0===e.expires||e.expires>=k?(c.logAction(c.LOG_MINOR,"Auth.getToken()","using cached token; expires = "+e.expires),a(null,e)):(c.logAction(c.LOG_MINOR,"Auth.getToken()", -"deleting expired token"),b.tokenDetails=null,d())}):d()};a.prototype._userSetClientId=function(a){if("string"!==typeof a&&null!==a)throw new r("clientId must be either a string or null",40012,400);if("*"===a)throw new r('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, instantiate the library with {defaultTokenParams: {clientId: "*"}}), or if calling authorize(), pass it in as a tokenParam: authorize({clientId: "*"}, authOptions)', -40012,400);if(a=this._uncheckedSetClientId(a))throw a;};a.prototype._uncheckedSetClientId=function(a){if(this._tokenClientIdMismatch(a)){a="Unexpected clientId mismatch: client has "+this.clientId+", requested "+a;var b=new r(a,40102,401);c.logAction(c.LOG_ERROR,"Auth._uncheckedSetClientId()",a);return b}if("*"===a)this.tokenParams.clientId=a;else return this.clientId=this.tokenParams.clientId=a,null};a.prototype._tokenClientIdMismatch=function(a){return this.clientId&&a&&"*"!==a&&this.clientId!== -a};a.isTokenErr=function(a){return a.code&&40140<=a.code&&40150>a.code};return a}(),F=function(){function d(a){if(!(this instanceof d))return new d(a);if(!a){var b="no options provided";c.logAction(c.LOG_ERROR,"Rest()",b);throw Error(b);}"string"==typeof a&&(a=-1==a.indexOf(":")?{token:a}:{key:a});this.options=q.normaliseOptions(a);if(a.key){b=a.key.match(/^([^:\s]+):([^:.\s]+)$/);if(!b)throw b="invalid key parameter",c.logAction(c.LOG_ERROR,"Rest()",b),Error(b);a.keyName=b[1];a.keySecret=b[2]}if("clientId"in -a){if("string"!==typeof a.clientId&&null!==a.clientId)throw new r("clientId must be either a string or null",40012,400);if("*"===a.clientId)throw new r('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, use {defaultTokenParams: {clientId: "*"}})',40012,400);}a.log&&c.setLog(a.log.level,a.log.handler);c.logAction(c.LOG_MINOR,"Rest()","started");this.baseUri=this.authority=function(b){return q.getHttpScheme(a)+b+":"+ -q.getPort(a,!1)};this.serverTimeOffset=null;this.auth=new M(this,a);this.channels=new h(this)}function h(a){this.rest=a;this.attached={}}var b=function(){};d.prototype.stats=function(a,c){void 0===c&&("function"==typeof a?(c=a,a=null):c=b);var d=l.copy(l.defaultGetHeaders()),f=u.supportsLinkHeaders?void 0:"json";this.options.headers&&l.mixin(d,this.options.headers);(new R(this,"/stats",d,f,function(a,b,c){a=c?a:JSON.parse(a);for(b=0;bb.timestamp;var c=a.parseId(), -d=b.parseId();return c.msgSerial===d.msgSerial?c.index>d.index:c.msgSerial>d.msgSerial}var k=function(){};l.inherits(b,U);b.prototype.enter=function(a,b){if(d(this))throw new r("clientId must be specified to enter a presence channel",40012,400);this._enterOrUpdateClient(void 0,a,b,"enter")};b.prototype.update=function(a,b){if(d(this))throw new r("clientId must be specified to update presence data",40012,400);this._enterOrUpdateClient(void 0,a,b,"update")};b.prototype.enterClient=function(a,b,c){this._enterOrUpdateClient(a, -b,c,"enter")};b.prototype.updateClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"update")};b.prototype._enterOrUpdateClient=function(a,b,d,e){d||("function"===typeof b?(d=b,b=null):d=k);var g=this.channel;if(g.connectionManager.activeState()){c.logAction(c.LOG_MICRO,"RealtimePresence."+e+"Client()",e+"ing; channel = "+g.name+", client = "+a||"(implicit) "+this.channel.realtime.auth.clientId);var h=D.fromValues({action:e,data:b});a&&(h.clientId=a);var l=this;D.encode(h,g.channelOptions,function(a){if(a)d(a); -else switch(g.state){case "attached":g.sendPresence(h,d);break;case "initialized":case "detached":g.autonomousAttach();case "attaching":l.pendingPresence.push({presence:h,callback:d});break;default:a=new r("Unable to "+e+" presence channel (incompatible state)",90001),a.code=90001,d(a)}})}else d(g.connectionManager.getStateError())};b.prototype.leave=function(a,b){if(d(this))throw new r("clientId must have been specified to enter or leave a presence channel",40012,400);this.leaveClient(void 0,a,b)}; -b.prototype.leaveClient=function(a,b,d){d||("function"===typeof b?(d=b,b=null):d=k);var e=this.channel;if(e.connectionManager.activeState())switch(c.logAction(c.LOG_MICRO,"RealtimePresence.leaveClient()","leaving; channel = "+this.channel.name+", client = "+a),b=D.fromValues({action:"leave",data:b}),a&&(b.clientId=a),e.state){case "attached":e.sendPresence(b,d);break;case "attaching":this.pendingPresence.push({presence:b,callback:d});break;case "initialized":case "failed":a=new r("Unable to leave presence channel (incompatible state)", -90001);d(a);break;default:d(J.failed)}else d(e.connectionManager.getStateError())};b.prototype.get=function(){function a(b){d(null,c?b.list(c):b.values())}var b=Array.prototype.slice.call(arguments);1==b.length&&"function"==typeof b[0]&&b.unshift(null);var c=b[0],d=b[1]||k,e=!c||("waitForSync"in c?c.waitForSync:!0);if("suspended"===this.channel.state)e?d(r.fromValues({statusCode:400,code:91005,message:"Presence state is out of sync due to channel being in the SUSPENDED state"})):a(this.members);else{var l= -this;h(this.channel,d,function(){var b=l.members;e?b.waitSync(function(){a(b)}):a(b)})}};b.prototype.history=function(a,b){c.logAction(c.LOG_MICRO,"RealtimePresence.history()","channel = "+this.name);void 0===b&&("function"==typeof a?(b=a,a=null):b=k);a&&a.untilAttach&&("attached"===this.channel.state?(delete a.untilAttach,a.from_serial=this.channel.attachSerial):b(new r("option untilAttach requires the channel to be attached, was: "+this.channel.state,4E4,400)));U.prototype._history.call(this,a, -b)};b.prototype.setPresence=function(a,b,d){c.logAction(c.LOG_MICRO,"RealtimePresence.setPresence()","received presence for "+a.length+" participants; syncChannelSerial = "+d);var e,g,h=this.members,k=this._myMembers,l=[],q=this.channel.connectionManager.connectionId;b&&(this.members.startSync(),d&&(g=d.match(/^[\w\-]+:(.*)$/))&&(e=g[1]));for(d=0;dc)&&0!==m.status){if(void 0===B)if(B=m.status,1223===B&&(B=204),clearTimeout(e),A=400>B,204==B)d.complete(null,null,null,null,B);else{var f;if(f=3==d.requestMode&&A)f=m,f=f.getResponseHeader&&f.getResponseHeader("transfer-encoding")&&!f.getResponseHeader("content-length");z=f}if(3==c&&z)a();else if(4==c)if(z)b();else a:{try{var h=m.getResponseHeader&&m.getResponseHeader("content-type"),k,q=h?"application/json"==h:"text"==m.responseType;u=q?m.responseText:m.response;q&&(u=String(u), -u.length&&(u=JSON.parse(u)),D=!0);if(void 0!==u.response)B=u.statusCode,A=400>B,k=u.headers,u=u.response;else{for(var s=l.trim(m.getAllResponseHeaders()).split("\r\n"),c={},h=0;ha.statusCode||l.isArray(b)?k.complete(null,b,a.headers,a.statusCode):(a=b.error||new r("Error response received from server",null,a.statusCode),k.complete(a)):k.complete(new r("Invalid server response: no envelope detected",null,500))}else k.complete(null,a)};this.timer=setTimeout(function(){k.abort()},this.requestMode==K.REQ_SEND?this.timeouts.httpRequestTimeout:this.timeouts.recvTimeout);f.insertBefore(d,f.firstChild)};h.prototype.complete=function(a, -b,c,d){c=c||{};this.requestComplete||(this.requestComplete=!0,b&&(c["content-type"]="string"==typeof b?"text/plain":"application/json",this.emit("data",b)),this.emit("complete",a,b,c,!0,d),this.dispose())};h.prototype.abort=function(){this.dispose()};h.prototype.dispose=function(){var b=this.timer;b&&(clearTimeout(b),this.timer=null);b=this.script;b.parentNode&&b.parentNode.removeChild(b);delete a[this.id];this.emit("disposed")};u.Request||(u.Request=function(a,b,c,d,e,f){var h=p(b,c,d,e,K.REQ_SEND, -a&&a.options.timeouts);h.once("complete",f);l.nextTick(function(){h.exec()});return h});return d})();"undefined"!==typeof G&&(Y.msgpack=ea,Y.Rest=F,Y.Realtime=G,G.ConnectionManager=N,G.BufferUtils=F.BufferUtils=y,"undefined"!==typeof T&&(G.Crypto=F.Crypto=T),G.Defaults=F.Defaults=q,G.Http=F.Http=u,G.Utils=F.Utils=l,G.Http=F.Http=u,G.Message=F.Message=C,G.PresenceMessage=F.PresenceMessage=D,G.ProtocolMessage=F.ProtocolMessage=w)}).call({}); +h=e[0];if(h){h=h.message.msgSerial;d+=b;if(d>h)for(d=e.splice(0,d-h),b=0;bl.arrIndexOf(p,b.shortName)}function k(a,b,c,e,f){this.options=a;this.host=b;this.mode=c;this.connectionKey=e;this.connectionSerial= +f;this.format=a.useBinaryProtocol?"msgpack":"json"}function b(a,f){z.call(this);this.realtime=a;this.options=f;var d=f.timeouts,n=this;this.states={initialized:{state:"initialized",terminal:!1,queueEvents:!0,sendEvents:!1,failState:"disconnected"},connecting:{state:"connecting",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.preferenceConnectTimeout+d.realtimeRequestTimeout,failState:"disconnected"},connected:{state:"connected",terminal:!1,queueEvents:!1,sendEvents:!0,failState:"disconnected"}, +synchronizing:{state:"connected",terminal:!1,queueEvents:!0,sendEvents:!1,forceQueueEvents:!0,failState:"disconnected"},disconnected:{state:"disconnected",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.disconnectedRetryTimeout,failState:"disconnected"},suspended:{state:"suspended",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.suspendedRetryTimeout,failState:"suspended"},closing:{state:"closing",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.realtimeRequestTimeout,failState:"closed"}, +closed:{state:"closed",terminal:!0,queueEvents:!1,sendEvents:!1,failState:"closed"},failed:{state:"failed",terminal:!0,queueEvents:!1,sendEvents:!1,failState:"failed"}};this.state=this.states.initialized;this.errorReason=null;this.queuedMessages=new ha;this.msgSerial=0;this.connectionSerial=this.connectionKey=this.connectionId=void 0;this.transports=l.intersect(f.transports||r.defaultTransports,b.supportedTransports);this.baseTransport=l.intersect(r.baseTransportOrder,this.transports)[0];this.upgradeTransports= +l.intersect(this.transports,r.upgradeTransports);this.transportHostBlacklist={};this.transportPreference=null;this.httpHosts=r.getHosts(f);this.activeProtocol=null;this.proposedTransports=[];this.pendingTransports=[];this.lastAutoReconnectAttempt=this.host=null;c.logAction(c.LOG_MINOR,"Realtime.ConnectionManager()","started");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","requested transports = ["+(f.transports||r.defaultTransports)+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()", +"available transports = ["+this.transports+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","http hosts = ["+this.httpHosts+"]");if(!this.transports.length)throw c.logAction(c.LOG_ERROR,"realtime.ConnectionManager()","no requested transports available"),Error("no requested transports available");if(d=w.addEventListener)e&&"function"===typeof f.recover&&d("beforeunload",this.persistConnection.bind(this)),!0===f.closeOnUnload&&d("beforeunload",function(){n.requestState({state:"closing"})}), +d("online",function(){if(n.state==n.states.disconnected||n.state==n.states.suspended)c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018online\u2019 event","reattempting connection"),n.requestState({state:"connecting"})}),d("offline",function(){n.state==n.states.connected&&(c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018offline\u2019 event","disconnecting active transport"),n.disconnectAllTransports())})}var a=!("undefined"===typeof K||!K.get),e=!("undefined"===typeof K|| +!K.getSession),h=y.Action,f=ia.PendingMessage,m=function(){},p=r.transportPreferenceOrder,n=p[p.length-1];k.prototype.getConnectParams=function(a){a=a?l.copy(a):{};var b=this.options;switch(this.mode){case "upgrade":a.upgrade=this.connectionKey;break;case "resume":a.resume=this.connectionKey;void 0!==this.connectionSerial&&(a.connection_serial=this.connectionSerial);break;case "recover":var c=b.recover.split(":");c&&(a.recover=c[0],a.connection_serial=c[1])}void 0!==b.clientId&&(a.clientId=b.clientId); +!1===b.echoMessages&&(a.echo="false");void 0!==this.format&&(a.format=this.format);void 0!==this.stream&&(a.stream=this.stream);void 0!==this.heartbeats&&(a.heartbeats=this.heartbeats);void 0!==b.transportParams&&l.mixin(a,b.transportParams);a.v=r.apiVersion;a.lib=r.libstring;return a};l.inherits(b,z);b.supportedTransports={};b.prototype.getTransportParams=function(a){var b=this;(function(a){if(b.connectionKey)a("resume");else if("string"===typeof b.options.recover)a("recover");else{var g=b.options.recover, +f=e&&K.getSession("ably-connection-recovery");f&&"function"===typeof g?(c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Calling clientOptions-provided recover function with last session data"),g(f,function(c){c?(b.options.recover=f.recoveryKey,a("recover")):a("clean")})):a("clean")}})(function(e){c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Transport recovery mode = "+e+("clean"==e?"":"; connectionKey = "+b.connectionKey+"; connectionSerial = "+b.connectionSerial)); +a(new k(b.options,null,e,b.connectionKey,b.connectionSerial))})};b.prototype.tryATransport=function(a,e,f){var d=this,n=a.host;c.logAction(c.LOG_MICRO,"ConnectionManager.tryATransport()","trying "+e);n in this.transportHostBlacklist&&l.arrIn(this.transportHostBlacklist[n],e)?c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()",e+" transport is blacklisted for host "+a.host):b.supportedTransports[e].tryConnect(this,this.realtime.auth,a,function(b,n){var p=d.state;p==d.states.closing||p==d.states.closed|| +p==d.states.failed?(n&&(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()","connection "+p.state+" while we were attempting the transport; closing "+n),n.close()),f(!0)):b?(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()","transport "+e+" "+b.event+", err: "+b.error.toString()),O.isTokenErr(b.error)?d.realtime.auth._forceNewToken(null,null,function(b){b?d.actOnErrorFromAuthorize(b):d.tryATransport(a,e,f)}):"failed"===b.event?(d.notifyState({state:"failed",error:b.error}),f(!0)): +"disconnected"===b.event&&f(!1)):(c.logAction(c.LOG_MICRO,"ConnectionManager.chooseTransportForHost()","viable transport "+e+"; setting pending"),d.setTransportPending(n,a),f(null,n))})};b.prototype.setTransportPending=function(a,b){var e=b.mode;c.logAction(c.LOG_MINOR,"ConnectionManager.setTransportPending()","transport = "+a+"; mode = "+e);l.arrDeleteValue(this.proposedTransports,a);this.pendingTransports.push(a);var f=this;a.once("connected",function(c,d,p,h,m){"upgrade"==e&&f.activeProtocol?a.shortName!== +n&&l.arrIn(f.getUpgradePossibilities(),n)?setTimeout(function(){f.scheduleTransportActivation(c,a,d,p,h,m)},f.options.timeouts.parallelUpgradeDelay):f.scheduleTransportActivation(c,a,d,p,h,m):(f.activateTransport(c,a,d,p,h,m),l.nextTick(function(){f.connectImpl(b)}));"recover"===e&&f.options.recover&&(f.options.recover=null,f.unpersistConnection())});a.on(["disconnected","closed","failed"],function(b){f.deactivateTransport(a,this.event,b)});this.emit("transport.pending",a)};b.prototype.scheduleTransportActivation= +function(a,b,e,f,n,p){var h=this,m=this.activeProtocol&&this.activeProtocol.getTransport(),k=function(){b.disconnect();l.arrDeleteValue(h.pendingTransports,b)};this.state!==this.states.connected&&this.state!==this.states.connecting?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+this.state.state+(this.state===this.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName), +k()):m&&!d(b,m)?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Proposed transport "+b.shortName+" is no better than current active transport "+m.shortName+" - abandoning upgrade"),k()):(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Scheduling transport upgrade; transport = "+b),this.realtime.channels.onceNopending(function(d){var m;if(d)c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Unable to activate transport; transport = "+ +b+"; err = "+d);else if(b.isConnected){if(h.state===h.states.connected)c.logAction(c.LOG_MICRO,"ConnectionManager.scheduleTransportActivation()","Currently connected, so temporarily pausing events until the upgrade is complete"),h.state=h.states.synchronizing,m=h.activeProtocol;else if(h.state!==h.states.connecting){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+h.state.state+(h.state===h.states.synchronizing?", but with an upgrade already in progress": +"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName);k();return}var l=(d=n!==h.connectionId)?f:h.connectionSerial;d&&c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Upgrade resulted in new connectionId; resetting library connectionSerial from "+h.connectionSerial+" to "+l+"; upgrade error was "+a);c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Syncing transport; transport = "+b);h.sync(b,function(f,d,n){if(f)h.state===h.states.synchronizing&& +(c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Unexpected error attempting to sync transport; transport = "+b+"; err = "+f),h.disconnectAllTransports());else if(f=function(){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Activating transport; transport = "+b);h.activateTransport(a,b,e,d,n,p);h.state===h.states.synchronizing?(c.logAction(c.LOG_MICRO,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, sending queued messages on upgraded transport; transport = "+ +b),h.state=h.states.connected):c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, but state is now "+h.state.state+", so leaving unchanged");h.state.sendEvents&&h.sendQueuedMessages()},m)m.onceIdle(f);else f()})}else c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Proposed transport "+b.shortName+"is no longer connected; abandoning upgrade"),k()}))};b.prototype.activateTransport=function(a,b,e,f,d,n){c.logAction(c.LOG_MINOR, +"ConnectionManager.activateTransport()","transport = "+b);a&&c.logAction(c.LOG_ERROR,"ConnectionManager.activateTransport()","error = "+a);e&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionKey = "+e);void 0!==f&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionSerial = "+f);d&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionId = "+d);n&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionDetails = "+ +JSON.stringify(n));this.persistTransportPreference(b);var h=this.state,p=this.states.connected.state;c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","current state = "+h.state);if(h.state==this.states.closing.state||h.state==this.states.closed.state||h.state==this.states.failed.state)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","Disconnecting transport and abandoning"),b.disconnect(),!1;l.arrDeleteValue(this.pendingTransports,b);if(!b.isConnected)return c.logAction(c.LOG_MINOR, +"ConnectionManager.activateTransport()","Declining to activate transport "+b+" since it appears to no longer be connected"),!1;var m=this.activeProtocol;this.activeProtocol=new ia(b);this.host=b.params.host;e&&this.connectionKey!=e&&this.setConnection(d,e,f);this.onConnectionDetailsUpdate(n,b);var k=this;l.nextTick(function(){b.on("connected",function(a,c,e,g,f){k.onConnectionDetailsUpdate(f,b);k.emit("update",new S(p,p,null,a))})});h.state===this.states.connected.state?a&&(this.errorReason=this.realtime.connection.errorReason= +a,this.emit("update",new S(p,p,null,a))):(this.notifyState({state:"connected",error:a}),this.errorReason=this.realtime.connection.errorReason=a||null);this.emit("transport.active",b,e,b.params);m&&(0h?(c.logAction(c.LOG_MICRO,"ConnectionManager.notifyState()","Last reconnect attempt was only "+h+"ms ago, waiting another "+(1E3-h)+"ms before trying again"),setTimeout(n,1E3-h)):l.nextTick(n)}else"disconnected"!==b&&"suspended"!==b||this.startRetryTimer(d.retryDelay);("disconnected"===b&&!f||"suspended"===b||d.terminal)&&l.nextTick(function(){e.disconnectAllTransports()});"connected"!=b||this.activeProtocol||c.logAction(c.LOG_ERROR, +"ConnectionManager.notifyState()","Broken invariant: attempted to go into connected state, but there is no active protocol");this.enactStateChange(a);this.state.sendEvents?this.sendQueuedMessages():this.state.queueEvents||(this.realtime.channels.propogateConnectionInterruption(b,a.reason),this.failQueuedMessages(a.reason))}};b.prototype.requestState=function(a){var b=a.state,e=this;c.logAction(c.LOG_MINOR,"ConnectionManager.requestState()","requested state: "+b+"; current state: "+this.state.state); +if(b!=this.state.state&&(this.cancelTransitionTimer(),this.cancelRetryTimer(),this.checkSuspendTimer(b),"connecting"!=b||"connected"!=this.state.state)&&("closing"!=b||"closed"!=this.state.state)){var f=this.states[b];a=new S(this.state.state,f.state,null,a.error||L[f.state]);this.enactStateChange(a);"connecting"==b&&l.nextTick(function(){e.startConnect()});"closing"==b&&this.closeImpl()}};b.prototype.startConnect=function(){if(this.state!==this.states.connecting)c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()", +"Must be in connecting state to connect, but was "+this.state.state);else{var a=this.realtime.auth,b=this,e=function(){b.getTransportParams(function(a){b.connectImpl(a)})};c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()","starting connection");this.startSuspendTimer();this.startTransitionTimer(this.states.connecting);if("basic"===a.method)e();else{var f=function(a){a?b.actOnErrorFromAuthorize(a):e()};this.errorReason&&O.isTokenErr(this.errorReason)?a._forceNewToken(null,null,f):a._ensureValidAuthCredentials(f)}}}; +b.prototype.connectImpl=function(a){var b=this.state.state;b!==this.states.connecting.state&&b!==this.states.connected.state?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Must be in connecting state to connect (or connected to upgrade), but was "+b):this.pendingTransports.length?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Transports "+this.pendingTransports[0].toString()+" currently pending; taking no action"):b==this.states.connected.state?this.upgradeIfNeeded(a):1a.code)?[y.fromValues({action:y.Action.ERROR,error:a})]:[y.fromValues({action:y.Action.DISCONNECTED,error:a})]}function b(a,b,c){this.timeoutOnIdle=!0;c.format=void 0;c.heartbeats=!0;R.call(this,a,b,c);this.stream="stream"in c?c.stream:!0;this.pendingItems=this.pendingCallback=this.recvRequest=this.sendRequest=null;this.disposed=!1}l.inherits(b,R);b.REQ_SEND=0;b.REQ_RECV=1;b.REQ_RECV_POLL=2;b.REQ_RECV_STREAM=3;b.prototype.connect=function(){c.logAction(c.LOG_MINOR,"CometTransport.connect()", +"starting");R.prototype.connect.call(this);var a=this,b=this.params,h=b.options,f=r.getHost(h,b.host),b=r.getPort(h);this.baseUri=(h.tls?"https://":"http://")+f+":"+b+"/comet/";var m=this.baseUri+"connect";c.logAction(c.LOG_MINOR,"CometTransport.connect()","uri: "+m);this.auth.getAuthParams(function(b,e){if(b)a.disconnect(b);else{a.authParams=e;var g=a.params.getConnectParams(e);"stream"in g&&(a.stream=g.stream);c.logAction(c.LOG_MINOR,"CometTransport.connect()","connectParams:"+l.toQueryString(g)); +var h=!1,g=a.recvRequest=a.createRequest(m,null,g,null,a.stream?3:1);g.on("data",function(b){a.recvRequest&&(h||(h=!0,a.emit("preconnect")),a.onData(b))});g.on("complete",function(b,c,e){d(e,f,a.connectionManager);a.recvRequest||(b=b||new q("Request cancelled",8E4,400));a.recvRequest=null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(k(b));else a.disconnect(b);else l.nextTick(function(){a.recv()})});g.exec()}})};b.prototype.requestClose=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestClose()"); +this._requestCloseOrDisconnect(!0)};b.prototype.requestDisconnect=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestDisconnect()");this._requestCloseOrDisconnect(!1)};b.prototype._requestCloseOrDisconnect=function(a){var b=a?this.closeUri:this.disconnectUri;if(b){var d=this,b=this.createRequest(b,null,this.authParams,null,0);b.on("complete",function(b){b&&(c.logAction(c.LOG_ERROR,"CometTransport.request"+(a?"Close()":"Disconnect()"),"request returned err = "+b),d.finish("disconnected",b))}); +b.exec()}};b.prototype.dispose=function(){c.logAction(c.LOG_MINOR,"CometTransport.dispose()","");if(!this.disposed){this.disposed=!0;this.recvRequest&&(c.logAction(c.LOG_MINOR,"CometTransport.dispose()","aborting recv request"),this.recvRequest.abort(),this.recvRequest=null);this.finish("disconnected",L.disconnected);var a=this;l.nextTick(function(){a.emit("disposed")})}};b.prototype.onConnect=function(a){if(!this.disposed){var b=a.connectionKey;R.prototype.onConnect.call(this,a);b=this.baseUri+b; +c.logAction(c.LOG_MICRO,"CometTransport.onConnect()","baseUri = "+b+"; connectionKey = "+a.connectionKey);this.sendUri=b+"/send";this.recvUri=b+"/recv";this.closeUri=b+"/close";this.disconnectUri=b+"/disconnect"}};b.prototype.send=function(a){if(this.sendRequest)this.pendingItems=this.pendingItems||[],this.pendingItems.push(a);else{var b=this.pendingItems||[];b.push(a);this.pendingItems=null;this.sendItems(b)}};b.prototype.sendAnyPending=function(){var a=this.pendingItems;a&&(this.pendingItems=null, +this.sendItems(a))};b.prototype.sendItems=function(a){var b=this;a=this.sendRequest=b.createRequest(b.sendUri,null,b.authParams,this.encodeRequest(a),0);a.on("complete",function(a,f){a&&c.logAction(c.LOG_ERROR,"CometTransport.sendItems()","on complete: err = "+JSON.stringify(a));b.sendRequest=null;if(f)b.onData(f);else if(a&&a.code)b.onData(k(a));else b.disconnect(a);b.pendingItems&&l.nextTick(function(){b.sendRequest||b.sendAnyPending()})});a.exec()};b.prototype.recv=function(){if(!this.recvRequest&& +this.isConnected){var a=this,b=this.recvRequest=this.createRequest(this.recvUri,null,this.authParams,null,a.stream?3:2);b.on("data",function(b){a.onData(b)});b.on("complete",function(b){a.recvRequest=null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(k(b));else a.disconnect(b);else l.nextTick(function(){a.recv()})});b.exec()}};b.prototype.onData=function(a){try{var b=this.decodeResponse(a);if(b&&b.length)for(a=0;al||300<=l?(c=c&&c.error,c||(c=Error(String(res)),c.statusCode=l),a(c)):a(null,c,d,!0,l))}}}function a(a){var b=[];if(a)for(var c in a)b.push(c+"="+a[c]);return b.join("&")} +function e(b,e,d,n){return function(g,h,k,l,q){g?c.logAction(c.LOG_MICRO,"Resource."+e+"()","Received Error; "+(d+(n?"?":"")+a(n))+"; Error: "+JSON.stringify(g)):c.logAction(c.LOG_MICRO,"Resource."+e+"()","Received; "+(d+(n?"?":"")+a(n))+"; Headers: "+a(k)+"; StatusCode: "+q+"; Body: "+(A.isBuffer(h)?h.toString():h));b&&b(g,h,k,l,q)}}var h=w.msgpack;d.get=function(f,d,p,n,g,h){function l(b,e){c.shouldLog(c.LOG_MICRO)&&c.logAction(c.LOG_MICRO,"Resource.get()","Sending; "+(d+(e?"?":"")+a(e)));B.get(f, +d,b,e,function(a,b,c,e,d){a&&O.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?h(a):k(f,p,n,h,l)}):h(a,b,c,e,d)})}c.shouldLog(c.LOG_MICRO)&&(h=e(h,"get",d,n));g&&(h=h&&b(h,g),(n=n||{}).envelope=g);k(f,p,n,h,l)};d.post=function(f,d,p,n,g,l,t){function v(b,e){if(c.shouldLog(c.LOG_MICRO)){var l=p;if(0<(b["content-type"]||"").indexOf("msgpack"))try{p=h.decode(p)}catch(u){c.logAction(c.LOG_MICRO,"Resource.post()","Sending MsgPack Decoding Error: "+JSON.stringify(u))}c.logAction(c.LOG_MICRO,"Resource.post()", +"Sending; "+(d+(e?"?":"")+a(e))+"; Body: "+l)}B.post(f,d,b,p,e,function(a,b,c,e,d){a&&O.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?t(a):k(f,n,g,t,v)}):t(a,b,c,e,d)})}c.shouldLog(c.LOG_MICRO)&&(t=e(t,"post",d,g));l&&(t=b(t,l),g.envelope=l);k(f,n,g,t,v)};return d}(),T=function(){function d(a,b,c,d,m,p){this.rest=a;this.path=b;this.headers=c;this.envelope=d;this.bodyHandler=m;this.useHttpPaginatedResponse=p||!1}function k(a,b,c){this.resource=a;this.items=b;if(c){var d=this;"first"in c&& +(this.first=function(a){d.get(c.first,a)});"current"in c&&(this.current=function(a){d.get(c.current,a)});this.next=function(a){"next"in c?d.get(c.next,a):a(null,null)};this.hasNext=function(){return"next"in c};this.isLast=function(){return!this.hasNext()}}}function b(a,b,c,d,m){k.call(this,a,b,m);this.statusCode=d;this.success=300>d&&200<=d;this.headers=c}d.prototype.get=function(a,b){var c=this;X.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,g){c.handlePage(a,d,p,n,g,b)})};d.prototype.post= +function(a,b,c){var d=this;X.post(d.rest,d.path,b,d.headers,a,d.envelope,function(a,b,e,g,k){c&&d.handlePage(a,b,e,g,k,c)})};d.prototype.handlePage=function(a,e,d,f,m,p){if(a)c.logAction(c.LOG_ERROR,"PaginatedResource.handlePage()","Unexpected error getting resource: err = "+JSON.stringify(a)),p(a);else{var n,g,u;try{n=this.bodyHandler(e,d,f)}catch(t){p(t);return}if(d&&(g=d.Link||d.link)){a=g;"string"==typeof a&&(a=a.split(","));e={};for(f=0;f;\s*rel="(\w+)"$/))&& +(u=(u=g[1].match(/^\.\/(\w+)\?(.*)$/))&&l.parseQueryString(u[2]))&&(e[g[2]]=u);u=e}this.useHttpPaginatedResponse?p(null,new b(this,n,d,m,u)):p(null,new k(this,n,u))}};k.prototype.get=function(a,b){var c=this.resource;X.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,g){c.handlePage(a,d,p,n,g,b)})};l.inherits(b,k);return d}(),O=function(){function d(){}function k(a){if(!a)return"";"string"==typeof a&&(a=JSON.parse(a));var b={},c=l.keysArray(a,!0);if(!c)return"";c.sort();for(var e=0;eh){e(new q("authUrl response exceeded max permitted length",40170,401));return}try{b=JSON.parse(b)}catch(g){e(new q("Unexpected error processing authURL response; err = "+g.message,40170,401));return}}e(null,b)}else e(new q("authUrl responded with unacceptable content-type "+a+", should be either text/plain or application/json",40170,401));else e(new q("authUrl response is missing a content-type header", +40170,401))};c.logAction(c.LOG_MICRO,"Auth.requestToken().tokenRequestCallback","Sending; "+b.authUrl+"; Params: "+JSON.stringify(f));b.authMethod&&"post"===b.authMethod.toLowerCase()?(d=d||{},d["content-type"]="application/x-www-form-urlencoded",f=l.toQueryString(f).slice(1),B.postUri(v,b.authUrl,d,f,{},g)):B.getUri(v,b.authUrl,d||{},f,g)};else if(b.key){var D=this;c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with client-side signing");t=function(a,c){D.createTokenRequest(a,b, +c)}}else{c.logAction(c.LOG_ERROR,"Auth.requestToken()","Need a new token, but authOptions does not include any way to request one");f(new q("Need a new token, but authOptions does not include any way to request one",40101,401));return}"capability"in a&&(a.capability=k(a.capability));var v=this.client,r=function(a,d){var f,g=a.keyName,h=function(a){return v.baseUri(a)+"/keys/"+g+"/requestToken"};B.post?(f=l.defaultPostHeaders(m),b.requestHeaders&&l.mixin(f,b.requestHeaders),c.logAction(c.LOG_MICRO, +"Auth.requestToken().requestToken","Sending POST; "+h+"; Token params: "+JSON.stringify(a)),a="msgpack"==m?e.encode(a,!0):JSON.stringify(a),B.post(v,h,f,a,null,d)):(f=l.defaultGetHeaders(),b.requestHeaders&&l.mixin(f,b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending GET; "+h+"; Token params: "+JSON.stringify(a)),B.get(v,h,f,a,d))},y=!1,z=this.client.options.timeouts.realtimeRequestTimeout,w=setTimeout(function(){y=!0;var a="Token request callback timed out after "+ +z/1E3+" seconds";c.logAction(c.LOG_ERROR,"Auth.requestToken()",a);f(new q(a,40170,401))},z);t(a,function(a,b){if(!y)if(clearTimeout(w),a)c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request signing call returned error; err = "+l.inspectError(a)),a&&a.code||(a=new q(l.inspectError(a),40170,401)),f(a);else if("string"===typeof b)384h?f(new q("Token request/details object exceeded max permitted stringified size (was "+d+" bytes)",40170,401)):"issued"in b?f(null,b):"keyName"in b?r(b,function(a,b,d,h){a?(c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request API call returned error; err = "+l.inspectError(a)),f(a)):(h||(b="msgpack"==m?e.decode(b):JSON.parse(b)),c.logAction(c.LOG_MINOR,"Auth.getToken()","token received"), +f(null,b))}):(d="Expected token request callback to call back with a token string, token request object, or token details object",c.logAction(c.LOG_ERROR,"Auth.requestToken()",d),f(new q(d,40170,401)))})};a.prototype.createTokenRequest=function(a,b,e){"function"!=typeof a||e?"function"!=typeof b||e||(e=b,b=null):(e=a,b=a=null);b=b||this.authOptions;a=a||l.copy(this.tokenParams);var d=b.key;if(d){var d=d.split(":"),h=d[0],m=d[1];if(m)if(""===a.clientId)e(new q("clientId can\u2019t be an empty string", +40012,400));else{a.capability=k(a.capability);var D=l.mixin({keyName:h},a),r=a.clientId||"",y=a.ttl||"",z=a.capability,A=this;(function(a){D.timestamp?a():A.getTimestamp(b&&b.queryTime,function(b,c){b?e(b):(D.timestamp=c,a())})})(function(){var a=D.nonce||(D.nonce=("000000"+Math.floor(1E16*Math.random())).slice(-16)),a=D.keyName+"\n"+y+"\n"+z+"\n"+r+"\n"+D.timestamp+"\n"+a+"\n";D.mac=D.mac||f(a,m);c.logAction(c.LOG_MINOR,"Auth.getTokenRequest()","generated signed request");e(null,D)})}else e(Error("Invalid key specified"))}else e(Error("No key specified"))}; +a.prototype.getAuthParams=function(a){"basic"==this.method?a(null,{key:this.key}):this._ensureValidAuthCredentials(function(b,c){b?a(b):a(null,{access_token:c.token})})};a.prototype.getAuthHeaders=function(a){"basic"==this.method?a(null,{authorization:"Basic "+this.basicKey}):this._ensureValidAuthCredentials(function(b,c){b?a(b):a(null,{authorization:"Bearer "+m(c.token)})})};a.prototype.getTimestamp=function(a,b){isNaN(parseInt(this.client.serverTimeOffset))&&(a||this.authOptions.queryTime)?this.client.time(function(a, +c){a?b(a):b(null,c)}):b(null,l.now()+(this.client.serverTimeOffset||0))};a.prototype._saveBasicOptions=function(a){this.method="basic";this.key=a.key;this.basicKey=m(a.key);this.authOptions=a||{};"clientId"in a&&this._userSetClientId(a.clientId)};a.prototype._saveTokenOptions=function(a,b){this.method="token";a&&(this.tokenParams=a);b&&(b.token&&(b.tokenDetails="string"===typeof b.token?{token:b.token}:b.token),b.tokenDetails&&(this.tokenDetails=b.tokenDetails),"clientId"in b&&this._userSetClientId(b.clientId), +this.authOptions=b)};a.prototype._ensureValidAuthCredentials=function(a){var b=this,e=this.tokenDetails,d=function(){b.requestToken(b.tokenParams,b.authOptions,function(c,e){c?a(c):a(null,b.tokenDetails=e)})};e?this._tokenClientIdMismatch(e.clientId)?a(new q("Mismatch between clientId in token ("+e.clientId+") and current clientId ("+this.clientId+")",40102,401)):this.getTimestamp(b.authOptions&&b.authOptions.queryTime,function(f,h){f&&a(f);void 0===e.expires||e.expires>=h?(c.logAction(c.LOG_MINOR, +"Auth.getToken()","using cached token; expires = "+e.expires),a(null,e)):(c.logAction(c.LOG_MINOR,"Auth.getToken()","deleting expired token"),b.tokenDetails=null,d())}):d()};a.prototype._userSetClientId=function(a){if("string"!==typeof a&&null!==a)throw new q("clientId must be either a string or null",40012,400);if("*"===a)throw new q('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, instantiate the library with {defaultTokenParams: {clientId: "*"}}), or if calling authorize(), pass it in as a tokenParam: authorize({clientId: "*"}, authOptions)', +40012,400);if(a=this._uncheckedSetClientId(a))throw a;};a.prototype._uncheckedSetClientId=function(a){if(this._tokenClientIdMismatch(a)){a="Unexpected clientId mismatch: client has "+this.clientId+", requested "+a;var b=new q(a,40102,401);c.logAction(c.LOG_ERROR,"Auth._uncheckedSetClientId()",a);return b}if("*"===a)this.tokenParams.clientId=a;else return this.clientId=this.tokenParams.clientId=a,null};a.prototype._tokenClientIdMismatch=function(a){return this.clientId&&a&&"*"!==a&&this.clientId!== +a};a.isTokenErr=function(a){return a.code&&40140<=a.code&&40150>a.code};return a}(),H=function(){function d(a){if(!(this instanceof d))return new d(a);if(!a){var b="no options provided";c.logAction(c.LOG_ERROR,"Rest()",b);throw Error(b);}"string"==typeof a&&(a=-1==a.indexOf(":")?{token:a}:{key:a});this.options=r.normaliseOptions(a);if(a.key){b=a.key.match(/^([^:\s]+):([^:.\s]+)$/);if(!b)throw b="invalid key parameter",c.logAction(c.LOG_ERROR,"Rest()",b),Error(b);a.keyName=b[1];a.keySecret=b[2]}if("clientId"in +a){if("string"!==typeof a.clientId&&null!==a.clientId)throw new q("clientId must be either a string or null",40012,400);if("*"===a.clientId)throw new q('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, use {defaultTokenParams: {clientId: "*"}})',40012,400);}a.log&&c.setLog(a.log.level,a.log.handler);c.logAction(c.LOG_MINOR,"Rest()","started");this.baseUri=this.authority=function(b){return r.getHttpScheme(a)+b+":"+ +r.getPort(a,!1)};this.serverTimeOffset=null;this.auth=new O(this,a);this.channels=new k(this)}function k(a){this.rest=a;this.attached={}}var b=function(){};d.prototype.stats=function(a,c){void 0===c&&("function"==typeof a?(c=a,a=null):c=b);var d=l.copy(l.defaultGetHeaders()),f=B.supportsLinkHeaders?void 0:"json";this.options.headers&&l.mixin(d,this.options.headers);(new T(this,"/stats",d,f,function(a,b,c){a=c?a:JSON.parse(a);for(b=0;bb.timestamp;var c=a.parseId(),d=b.parseId();return c.msgSerial===d.msgSerial?c.index>d.index:c.msgSerial>d.msgSerial}var h=function(){};l.inherits(b,W);b.prototype.enter=function(a,b){if(d(this))throw new q("clientId must be specified to enter a presence channel",40012,400);this._enterOrUpdateClient(void 0,a,b,"enter")};b.prototype.update=function(a,b){if(d(this))throw new q("clientId must be specified to update presence data", +40012,400);this._enterOrUpdateClient(void 0,a,b,"update")};b.prototype.enterClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"enter")};b.prototype.updateClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"update")};b.prototype._enterOrUpdateClient=function(a,b,d,e){d||("function"===typeof b?(d=b,b=null):d=h);var g=this.channel;if(g.connectionManager.activeState()){c.logAction(c.LOG_MICRO,"RealtimePresence."+e+"Client()",e+"ing; channel = "+g.name+", client = "+a||"(implicit) "+this.channel.realtime.auth.clientId); +var k=F.fromValues({action:e,data:b});a&&(k.clientId=a);var l=this;F.encode(k,g.channelOptions,function(a){if(a)d(a);else switch(g.state){case "attached":g.sendPresence(k,d);break;case "initialized":case "detached":g.autonomousAttach();case "attaching":l.pendingPresence.push({presence:k,callback:d});break;default:a=new q("Unable to "+e+" presence channel (incompatible state)",90001),a.code=90001,d(a)}})}else d(g.connectionManager.getStateError())};b.prototype.leave=function(a,b){if(d(this))throw new q("clientId must have been specified to enter or leave a presence channel", +40012,400);this.leaveClient(void 0,a,b)};b.prototype.leaveClient=function(a,b,d){d||("function"===typeof b?(d=b,b=null):d=h);var e=this.channel;if(e.connectionManager.activeState())switch(c.logAction(c.LOG_MICRO,"RealtimePresence.leaveClient()","leaving; channel = "+this.channel.name+", client = "+a),b=F.fromValues({action:"leave",data:b}),a&&(b.clientId=a),e.state){case "attached":e.sendPresence(b,d);break;case "attaching":this.pendingPresence.push({presence:b,callback:d});break;case "initialized":case "failed":a= +new q("Unable to leave presence channel (incompatible state)",90001);d(a);break;default:d(L.failed)}else d(e.connectionManager.getStateError())};b.prototype.get=function(){function a(b){d(null,c?b.list(c):b.values())}var b=Array.prototype.slice.call(arguments);1==b.length&&"function"==typeof b[0]&&b.unshift(null);var c=b[0],d=b[1]||h,e=!c||("waitForSync"in c?c.waitForSync:!0);if("suspended"===this.channel.state)e?d(q.fromValues({statusCode:400,code:91005,message:"Presence state is out of sync due to channel being in the SUSPENDED state"})): +a(this.members);else{var l=this;k(this.channel,d,function(){var b=l.members;e?b.waitSync(function(){a(b)}):a(b)})}};b.prototype.history=function(a,b){c.logAction(c.LOG_MICRO,"RealtimePresence.history()","channel = "+this.name);void 0===b&&("function"==typeof a?(b=a,a=null):b=h);a&&a.untilAttach&&("attached"===this.channel.state?(delete a.untilAttach,a.from_serial=this.channel.attachSerial):b(new q("option untilAttach requires the channel to be attached, was: "+this.channel.state,4E4,400)));W.prototype._history.call(this, +a,b)};b.prototype.setPresence=function(a,b,d){c.logAction(c.LOG_MICRO,"RealtimePresence.setPresence()","received presence for "+a.length+" participants; syncChannelSerial = "+d);var e,g,h=this.members,k=this._myMembers,l=[],q=this.channel.connectionManager.connectionId;b&&(this.members.startSync(),d&&(g=d.match(/^[\w\-]+:(.*)$/))&&(e=g[1]));for(d=0;dc)&&0!==m.status){if(void 0===w)if(w=m.status,1223===w&&(w=204),clearTimeout(e),C=400>w,204==w)d.complete(null,null,null,null,w);else{var f;if(f=3==d.requestMode&&C)f=m,f=f.getResponseHeader&&f.getResponseHeader("transfer-encoding")&&!f.getResponseHeader("content-length");B=f}if(3==c&&B)a();else if(4==c)if(B)b();else a:{try{var h=m.getResponseHeader&&m.getResponseHeader("content-type"),k,t=h?"application/json"==h:"text"==m.responseType;x=t?m.responseText:m.response;t&&(x=String(x), +x.length&&(x=JSON.parse(x)),F=!0);if(void 0!==x.response)w=x.statusCode,C=400>w,k=x.headers,x=x.response;else{for(var r=l.trim(m.getAllResponseHeaders()).split("\r\n"),c={},h=0;ha.statusCode||l.isArray(b)?k.complete(null,b,a.headers,a.statusCode):(a=b.error||new q("Error response received from server",null,a.statusCode),k.complete(a)):k.complete(new q("Invalid server response: no envelope detected",null,500))}else k.complete(null,a)};this.timer=setTimeout(function(){k.abort()},this.requestMode==M.REQ_SEND?this.timeouts.httpRequestTimeout:this.timeouts.recvTimeout);f.insertBefore(d,f.firstChild)};k.prototype.complete= +function(a,b,c,d){c=c||{};this.requestComplete||(this.requestComplete=!0,b&&(c["content-type"]="string"==typeof b?"text/plain":"application/json",this.emit("data",b)),this.emit("complete",a,b,c,!0,d),this.dispose())};k.prototype.abort=function(){this.dispose()};k.prototype.dispose=function(){var b=this.timer;b&&(clearTimeout(b),this.timer=null);b=this.script;b.parentNode&&b.parentNode.removeChild(b);delete a[this.id];this.emit("disposed")};B.Request||(B.Request=function(a,b,c,d,e,f){var h=p(b,c,d, +e,M.REQ_SEND,a&&a.options.timeouts);h.once("complete",f);l.nextTick(function(){h.exec()});return h},B.checkConnectivity=function(a){var b=r.jsonpInternetUpUrl;if(m)m.push(a);else{m=[a];c.logAction(c.LOG_MICRO,"(JSONP)Http.checkConnectivity()","Sending; "+b);var d=new k("isTheInternetUp",b,null,null,null,M.REQ_SEND,r.TIMEOUTS);d.once("complete",function(a,b){var d=!a&&b;c.logAction(c.LOG_MICRO,"(JSONP)Http.checkConnectivity()","Result: "+d);for(var e=0;e 0) { @@ -4917,8 +4920,10 @@ var ConnectionManager = (function() { if(this.connectionId && this.connectionId !== connectionId) { Logger.logAction(Logger.LOG_MINOR, 'ConnectionManager.setConnection()', 'connectionId has changed; resetting msgSerial and reattaching channels'); this.msgSerial = 0; - /* Wait till next tick before reattaching channels so that connection - * state will be updated */ + /* Wait till next tick before reattaching channels, so that connection + * state will be updated and so that it will be applied after + * Channels#onTransportUpdate, else channels will not have an ATTACHED + * sent twice (once from this and once from that). */ Utils.nextTick(function() { self.realtime.channels.reattach(); }); @@ -5343,8 +5348,7 @@ var ConnectionManager = (function() { /* before trying any fallback (or any remaining fallback) we decide if * there is a problem with the ably host, or there is a general connectivity * problem */ - var connectivityCheckTransport = self.baseTransport === 'web_socket' ? 'xhr_polling' : self.baseTransport; - ConnectionManager.supportedTransports[connectivityCheckTransport].checkConnectivity(function(err, connectivity) { + Http.checkConnectivity(function(err, connectivity) { /* we know err won't happen but handle it here anyway */ if(err) { giveUp(err); @@ -5386,8 +5390,9 @@ var ConnectionManager = (function() { return; } - var upgradeTransportParams = new TransportParams(this.options, transportParams.host, 'upgrade', this.connectionKey); Utils.arrForEach(upgradePossibilities, function(upgradeTransport) { + /* Note: the transport may mutate the params, so give each transport a fresh one */ + var upgradeTransportParams = new TransportParams(self.options, transportParams.host, 'upgrade', self.connectionKey); self.tryATransport(upgradeTransportParams, upgradeTransport, noop); }); }; @@ -5532,7 +5537,7 @@ var ConnectionManager = (function() { * event queueing ******************/ - ConnectionManager.prototype.send = function(msg, queueEvents, callback) { + ConnectionManager.prototype.send = function(msg, queueEvent, callback) { callback = callback || noop; var state = this.state; @@ -5541,18 +5546,17 @@ var ConnectionManager = (function() { this.sendImpl(new PendingMessage(msg, callback)); return; } - if(state.queueEvents) { - if(state == this.states.synchronizing || queueEvents) { - if (Logger.shouldLog(Logger.LOG_MICRO)) { - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); - } - this.queue(msg, callback); - } else { - var err = 'rejecting event as queueMessages was disabled; state = ' + state.state; - Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); - callback(this.errorReason || new ErrorInfo(err, 90000, 400)); - } + var shouldQueue = (queueEvent && state.queueEvents) || state.forceQueueEvents; + if(!shouldQueue) { + var err = 'rejecting event, queueEvent was ' + queueEvent + ', state was ' + state.state; + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', err); + callback(this.errorReason || new ErrorInfo(err, 90000, 400)); + return; + } + if(Logger.shouldLog(Logger.LOG_MICRO)) { + Logger.logAction(Logger.LOG_MICRO, 'ConnectionManager.send()', 'queueing msg; ' + ProtocolMessage.stringify(msg)); } + this.queue(msg, callback); }; ConnectionManager.prototype.sendImpl = function(pendingMessage) { @@ -7748,13 +7752,7 @@ var Realtime = (function() { this.realtime = realtime; this.all = {}; this.inProgress = {}; - var self = this; - realtime.connection.connectionManager.on('transport.active', function() { - /* nextTick to allow connectionManager to set the connection state to 'connected' if necessary */ - Utils.nextTick(function() { - self.onTransportActive(); - }); - }); + realtime.connection.connectionManager.on('transport.active', this.onTransportActive.bind(this)); } Utils.inherits(Channels, EventEmitter); @@ -7790,7 +7788,9 @@ var Realtime = (function() { Channels.prototype.reattach = function(reason) { for(var channelId in this.all) { var channel = this.all[channelId]; - if(channel.state === 'attaching' || channel.state === 'attached') { + /* NB this should not trigger for merely attaching channels, as they will + * be reattached anyway through the onTransportActive checkPendingState */ + if(channel.state === 'attached') { channel.requestState('attaching', reason); } } @@ -8321,7 +8321,9 @@ var RealtimeChannel = (function() { /* send sync request */ var syncMessage = ProtocolMessage.fromValues({action: actions.SYNC, channel: this.name}); - syncMessage.channelSerial = this.syncChannelSerial; + if(this.syncChannelSerial) { + syncMessage.channelSerial = this.syncChannelSerial; + } connectionManager.send(syncMessage); }; @@ -8526,8 +8528,11 @@ var RealtimeChannel = (function() { RealtimeChannel.prototype.checkPendingState = function() { /* if can't send events, do nothing */ - if(!this.connectionManager.state.sendEvents) { - Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'not connected'); + var cmState = this.connectionManager.state; + /* Allow attach messages to queue up when synchronizing, since this will be + * the state we'll be in when upgrade transport.active triggers a checkpendingstate */ + if(!(cmState.sendEvents || cmState.forceQueueEvents)) { + Logger.logAction(Logger.LOG_MINOR, 'RealtimeChannel.checkPendingState', 'sendEvents is false; state is ' + this.connectionManager.state.state); return; } @@ -8633,12 +8638,16 @@ var RealtimeChannel = (function() { } if(params && params.untilAttach) { - if(this.state === 'attached') { - delete params.untilAttach; - params.from_serial = this.attachSerial; - } else { + if(this.state !== 'attached') { callback(new ErrorInfo("option untilAttach requires the channel to be attached", 40000, 400)); + return; + } + if(!this.attachSerial) { + callback(new ErrorInfo("untilAttach was specified and channel is attached, but attachSerial is not defined", 40000, 400)); + return; } + delete params.untilAttach; + params.from_serial = this.attachSerial; } Channel.prototype._history.call(this, params, callback); @@ -8930,6 +8939,7 @@ var RealtimePresence = (function() { /* RTP5c2: re-enter our own members if they haven't shown up in the sync */ this._ensureMyMembersPresent(); this.channel.setInProgress(RealtimeChannel.progressOps.sync, false); + this.channel.syncChannelSerial = null; } /* broadcast to listeners */ @@ -9531,6 +9541,16 @@ var XHRRequest = (function() { req.exec(); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.internetUpUrl; + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Sending; ' + upUrl); + Http.Request(null, upUrl, null, null, null, function(err, responseText) { + var result = (!err && responseText.replace(/\n/, '') == 'yes'); + Logger.logAction(Logger.LOG_MICRO, '(XHRRequest)Http.checkConnectivity()', 'Result: ' + result); + callback(null, result); + }); + }; } } @@ -9549,16 +9569,6 @@ var XHRStreamingTransport = (function() { XHRStreamingTransport.isAvailable = XHRRequest.isAvailable; - XHRStreamingTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.internetUpUrl; - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Sending; ' + upUrl); - Http.Request(null, upUrl, null, null, null, function(err, responseText) { - var result = (!err && responseText.replace(/\n/, '') == 'yes'); - Logger.logAction(Logger.LOG_MICRO, 'XHRStreamingTransport.checkConnectivity()', 'Result: ' + result); - callback(null, result); - }); - }; - XHRStreamingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRStreamingTransport(connectionManager, auth, params); var errorCb = function(err) { callback({event: this.event, error: err}); }; @@ -9595,7 +9605,6 @@ var XHRPollingTransport = (function() { Utils.inherits(XHRPollingTransport, CometTransport); XHRPollingTransport.isAvailable = XHRRequest.isAvailable; - XHRPollingTransport.checkConnectivity = XHRStreamingTransport.checkConnectivity; XHRPollingTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new XHRPollingTransport(connectionManager, auth, params); @@ -9656,27 +9665,6 @@ var JSONPTransport = (function() { * connectionmanager should ensure this doesn't happen anyway */ var checksInProgress = null; window.JSONPTransport = JSONPTransport - JSONPTransport.checkConnectivity = function(callback) { - var upUrl = Defaults.jsonpInternetUpUrl; - - if(checksInProgress) { - checksInProgress.push(callback); - return; - } - checksInProgress = [callback]; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Sending; ' + upUrl); - - var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); - req.once('complete', function(err, response) { - var result = !err && response; - Logger.logAction(Logger.LOG_MICRO, 'JSONPTransport.checkConnectivity()', 'Result: ' + result); - for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); - checksInProgress = null; - }); - Utils.nextTick(function() { - req.exec(); - }); - }; JSONPTransport.tryConnect = function(connectionManager, auth, params, callback) { var transport = new JSONPTransport(connectionManager, auth, params); @@ -9820,6 +9808,28 @@ var JSONPTransport = (function() { }); return req; }; + + Http.checkConnectivity = function(callback) { + var upUrl = Defaults.jsonpInternetUpUrl; + + if(checksInProgress) { + checksInProgress.push(callback); + return; + } + checksInProgress = [callback]; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Sending; ' + upUrl); + + var req = new Request('isTheInternetUp', upUrl, null, null, null, CometTransport.REQ_SEND, Defaults.TIMEOUTS); + req.once('complete', function(err, response) { + var result = !err && response; + Logger.logAction(Logger.LOG_MICRO, '(JSONP)Http.checkConnectivity()', 'Result: ' + result); + for(var i = 0; i < checksInProgress.length; i++) checksInProgress[i](null, result); + checksInProgress = null; + }); + Utils.nextTick(function() { + req.exec(); + }); + }; } return JSONPTransport; diff --git a/browser/static/ably.noencryption.min.js b/browser/static/ably.noencryption.min.js index 4a44647094..50a851ca2b 100644 --- a/browser/static/ably.noencryption.min.js +++ b/browser/static/ably.noencryption.min.js @@ -1,7 +1,7 @@ /* Copyright 2017, Ably - Ably JavaScript Library v1.0.0 + Ably JavaScript Library v1.0.1 https://github.com/ably/ably-js Ably Realtime Messaging @@ -9,278 +9,278 @@ Released under the Apache Licence v2.0 */ -(function(){var X=window.Ably=this,D=D||function(d,c){var b={},a=b.lib={},e=a.Base=function(){function a(){}return{extend:function(h){a.prototype=this;var b=new a;h&&b.mixIn(h);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var h in a)a.hasOwnProperty(h)&&(this[h]=a[h]);a.hasOwnProperty("toString")&&(this.toString= -a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),l=a.WordArray=e.extend({init:function(a,h){a=this.words=a||[];this.sigBytes=h!=c?h:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var h=this.words,b=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var n=0;n>>2]|=(b[n>>>2]>>>24-n%4*8&255)<<24-(e+n)%4*8;else if(65535>>2]=b[n>>>2];else h.push.apply(h,b);this.sigBytes+=a;return this}, -clamp:function(){var a=this.words,h=this.sigBytes;a[h>>>2]&=4294967295<<32-h%4*8;a.length=d.ceil(h/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var h=[],b=function(a){var h=987654321;return function(){h=36969*(h&65535)+(h>>16)&4294967295;a=18E3*(a&65535)+(a>>16)&4294967295;var b=(h<<16)+a&4294967295,b=b/4294967296+.5;return b*(.5>>2]>>>24-e%4*8&255;b.push((n>>>4).toString(16));b.push((n&15).toString(16))}return b.join("")},parse:function(a){for(var h=a.length,b=[],e=0;e>>3]|=parseInt(a.substr(e,2),16)<<24-e%8*4;return new l.init(b,h/2)}},p=f.Latin1={stringify:function(a){var h=a.words;a=a.sigBytes;for(var b=[],e=0;e>>2]>>>24-e%4*8&255));return b.join("")}, -parse:function(a){for(var h=a.length,b=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-e%4*8;return new l.init(b,h)}},n=f.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(h){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},h=a.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new l.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=n.parse(a));this._data.concat(a);this._nDataBytes+= -a.sigBytes},_process:function(a){var h=this._data,b=h.words,e=h.sigBytes,n=this.blockSize,f=e/(4*n),f=a?d.ceil(f):d.max((f|0)-this._minBufferSize,0);a=f*n;e=d.min(4*a,e);if(a){for(var u=0;ue;)a(h)&&(8>e&&(l[e]=b(c.pow(h,.5))),f[e]=b(c.pow(h,1/3)),e++),h++})();var m=[],b=b.SHA256=e.extend({_doReset:function(){this._hash=new a.init(l.slice(0))},_doProcessBlock:function(a,b){for(var h=this._hash.words,e=h[0],c=h[1],d=h[2],l=h[3],k=h[4],g=h[5],q=h[6],r=h[7],E=0;64>E;E++){if(16>E)m[E]=a[b+E]|0;else{var L=m[E-15],z=m[E-2];m[E]=((L<<25|L>>>7)^(L<<14|L>>>18)^L>>>3)+m[E-7]+((z<<15|z>>>17)^(z<<13|z>>>19)^z>>> -10)+m[E-16]}L=r+((k<<26|k>>>6)^(k<<21|k>>>11)^(k<<7|k>>>25))+(k&g^~k&q)+f[E]+m[E];z=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&c^e&d^c&d);r=q;q=g;g=k;k=l+L|0;l=d;d=c;c=e;e=L+z|0}h[0]=h[0]+e|0;h[1]=h[1]+c|0;h[2]=h[2]+d|0;h[3]=h[3]+l|0;h[4]=h[4]+k|0;h[5]=h[5]+g|0;h[6]=h[6]+q|0;h[7]=h[7]+r|0},_doFinalize:function(){var a=this._data,b=a.words,h=8*this._nDataBytes,e=8*a.sigBytes;b[e>>>5]|=128<<24-e%32;b[(e+64>>>9<<4)+14]=c.floor(h/4294967296);b[(e+64>>>9<<4)+15]=h;a.sigBytes=4*b.length;this._process(); -return this._hash},clone:function(){var a=e.clone.call(this);a._hash=this._hash.clone();return a}});k.SHA256=e._createHelper(b);k.HmacSHA256=e._createHmacHelper(b)})(Math);(function(){var c=D,k=c.enc.Utf8;c.algo.HMAC=c.lib.Base.extend({init:function(b,a){b=this._hasher=new b.init;"string"==typeof a&&(a=k.parse(a));var e=b.blockSize,c=4*e;a.sigBytes>c&&(a=b.finalize(a));a.clamp();for(var f=this._oKey=a.clone(),d=this._iKey=a.clone(),p=f.words,n=d.words,h=0;h>>2]>>>24-f%4*8&255)<<16|(a[f+1>>>2]>>>24-(f+1)%4*8&255)<< -8|a[f+2>>>2]>>>24-(f+2)%4*8&255,p=0;4>p&&f+.75*p>>6*(3-p)&63));if(a=c.charAt(64))for(;b.length%4;)b.push(a);return b.join("")},parse:function(b){var a=b.length,e=this._map,c=e.charAt(64);c&&(c=b.indexOf(c),-1!=c&&(a=c));for(var c=[],f=0,d=0;d>>6-d%4*2;c[f>>>2]|=(p|n)<<24-f%4*8;f++}return k.create(c,f)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();var aa=function(){function c(){} -c.addListener=function(c,b,a){c.addEventListener?c.addEventListener(b,a,!1):c.attachEvent("on"+b,function(){a.apply(c,arguments)})};c.removeListener=function(c,b,a){c.removeEventListener?c.removeEventListener(b,a,!1):c.detachEvent("on"+b,function(){a.apply(c,arguments)})};c.addMessageListener=function(k,b){c.addListener(k,"message",b)};c.removeMessageListener=function(k,b){c.removeListener(k,"message",b)};c.addUnloadListener=function(k){c.addListener(window,"unload",k)};return c}(),ba=function(){function c(a, -h,b){for(var e=0,f=b.length;ed)a.setUint8(h++,d>>>0&127|0);else if(2048>d)a.setUint8(h++,d>>>6&31|192),a.setUint8(h++,d>>>0&63|128);else if(65536>d)a.setUint8(h++,d>>>12&15|224),a.setUint8(h++,d>>>6&63|128),a.setUint8(h++,d>>>0&63|128);else if(1114112>d)a.setUint8(h++,d>>>18&7|240),a.setUint8(h++,d>>>12&63|128),a.setUint8(h++,d>>>6&63|128),a.setUint8(h++,d>>>0&63|128);else throw Error("bad codepoint "+d);}}function k(a,h,b){var e="",c=h;for(h+=b;cc)h+=1;else if(2048> -c)h+=2;else if(65536>c)h+=3;else if(1114112>c)h+=4;else throw Error("bad codepoint "+c);}return h}function a(a,b){this.offset=b||0;this.view=a}function e(a,b){return g.keysArray(a,!0).filter(function(e){e=a[e];return(!b||void 0!==e&&null!==e)&&("function"!==typeof e||!!e.toJSON)})}function l(a,h,f,m){var k=typeof a;if("string"===k){var g=b(a);if(32>g)return h.setUint8(f,g|160),c(h,f+1,a),1+g;if(256>g)return h.setUint8(f,217),h.setUint8(f+1,g),c(h,f+2,a),2+g;if(65536>g)return h.setUint8(f,218),h.setUint16(f+ +(function(){var X=window.Ably=this,E=E||function(c,k){var b={},a=b.lib={},e=a.Base=function(){function a(){}return{extend:function(h){a.prototype=this;var b=new a;h&&b.mixIn(h);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var h in a)a.hasOwnProperty(h)&&(this[h]=a[h]);a.hasOwnProperty("toString")&&(this.toString= +a.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),l=a.WordArray=e.extend({init:function(a,h){a=this.words=a||[];this.sigBytes=h!=k?h:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var h=this.words,b=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var p=0;p>>2]|=(b[p>>>2]>>>24-p%4*8&255)<<24-(e+p)%4*8;else if(65535>>2]=b[p>>>2];else h.push.apply(h,b);this.sigBytes+=a;return this}, +clamp:function(){var a=this.words,h=this.sigBytes;a[h>>>2]&=4294967295<<32-h%4*8;a.length=c.ceil(h/4)},clone:function(){var a=e.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var h=[],b=function(a){var h=987654321;return function(){h=36969*(h&65535)+(h>>16)&4294967295;a=18E3*(a&65535)+(a>>16)&4294967295;var b=(h<<16)+a&4294967295,b=b/4294967296+.5;return b*(.5>>2]>>>24-e%4*8&255;b.push((p>>>4).toString(16));b.push((p&15).toString(16))}return b.join("")},parse:function(a){for(var h=a.length,b=[],e=0;e>>3]|=parseInt(a.substr(e,2),16)<<24-e%8*4;return new l.init(b,h/2)}},n=f.Latin1={stringify:function(a){var h=a.words;a=a.sigBytes;for(var b=[],e=0;e>>2]>>>24-e%4*8&255));return b.join("")}, +parse:function(a){for(var h=a.length,b=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-e%4*8;return new l.init(b,h)}},p=f.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(h){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}},h=a.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new l.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=p.parse(a));this._data.concat(a);this._nDataBytes+= +a.sigBytes},_process:function(a){var h=this._data,b=h.words,e=h.sigBytes,p=this.blockSize,f=e/(4*p),f=a?c.ceil(f):c.max((f|0)-this._minBufferSize,0);a=f*p;e=c.min(4*a,e);if(a){for(var u=0;ue;)a(h)&&(8>e&&(l[e]=b(c.pow(h,.5))),f[e]=b(c.pow(h,1/3)),e++),h++})();var m=[],b=b.SHA256=e.extend({_doReset:function(){this._hash=new a.init(l.slice(0))},_doProcessBlock:function(a,b){for(var h=this._hash.words,e=h[0],c=h[1],d=h[2],l=h[3],k=h[4],g=h[5],q=h[6],r=h[7],G=0;64>G;G++){if(16>G)m[G]=a[b+G]|0;else{var M=m[G-15],A=m[G-2];m[G]=((M<<25|M>>>7)^(M<<14|M>>>18)^M>>>3)+m[G-7]+((A<<15|A>>>17)^(A<<13|A>>>19)^A>>> +10)+m[G-16]}M=r+((k<<26|k>>>6)^(k<<21|k>>>11)^(k<<7|k>>>25))+(k&g^~k&q)+f[G]+m[G];A=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&c^e&d^c&d);r=q;q=g;g=k;k=l+M|0;l=d;d=c;c=e;e=M+A|0}h[0]=h[0]+e|0;h[1]=h[1]+c|0;h[2]=h[2]+d|0;h[3]=h[3]+l|0;h[4]=h[4]+k|0;h[5]=h[5]+g|0;h[6]=h[6]+q|0;h[7]=h[7]+r|0},_doFinalize:function(){var a=this._data,b=a.words,h=8*this._nDataBytes,e=8*a.sigBytes;b[e>>>5]|=128<<24-e%32;b[(e+64>>>9<<4)+14]=c.floor(h/4294967296);b[(e+64>>>9<<4)+15]=h;a.sigBytes=4*b.length;this._process(); +return this._hash},clone:function(){var a=e.clone.call(this);a._hash=this._hash.clone();return a}});k.SHA256=e._createHelper(b);k.HmacSHA256=e._createHmacHelper(b)})(Math);(function(){var c=E,k=c.enc.Utf8;c.algo.HMAC=c.lib.Base.extend({init:function(b,a){b=this._hasher=new b.init;"string"==typeof a&&(a=k.parse(a));var e=b.blockSize,c=4*e;a.sigBytes>c&&(a=b.finalize(a));a.clamp();for(var f=this._oKey=a.clone(),d=this._iKey=a.clone(),n=f.words,p=d.words,h=0;h>>2]>>>24-f%4*8&255)<<16|(a[f+1>>>2]>>>24-(f+1)%4*8&255)<< +8|a[f+2>>>2]>>>24-(f+2)%4*8&255,n=0;4>n&&f+.75*n>>6*(3-n)&63));if(a=c.charAt(64))for(;b.length%4;)b.push(a);return b.join("")},parse:function(b){var a=b.length,e=this._map,c=e.charAt(64);c&&(c=b.indexOf(c),-1!=c&&(a=c));for(var c=[],f=0,d=0;d>>6-d%4*2;c[f>>>2]|=(n|p)<<24-f%4*8;f++}return k.create(c,f)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();var ba=function(){function c(){} +c.addListener=function(c,b,a){c.addEventListener?c.addEventListener(b,a,!1):c.attachEvent("on"+b,function(){a.apply(c,arguments)})};c.removeListener=function(c,b,a){c.removeEventListener?c.removeEventListener(b,a,!1):c.detachEvent("on"+b,function(){a.apply(c,arguments)})};c.addMessageListener=function(k,b){c.addListener(k,"message",b)};c.removeMessageListener=function(k,b){c.removeListener(k,"message",b)};c.addUnloadListener=function(k){c.addListener(window,"unload",k)};return c}(),ca=function(){function c(a, +h,b){for(var e=0,f=b.length;ed)a.setUint8(h++,d>>>0&127|0);else if(2048>d)a.setUint8(h++,d>>>6&31|192),a.setUint8(h++,d>>>0&63|128);else if(65536>d)a.setUint8(h++,d>>>12&15|224),a.setUint8(h++,d>>>6&63|128),a.setUint8(h++,d>>>0&63|128);else if(1114112>d)a.setUint8(h++,d>>>18&7|240),a.setUint8(h++,d>>>12&63|128),a.setUint8(h++,d>>>6&63|128),a.setUint8(h++,d>>>0&63|128);else throw Error("bad codepoint "+d);}}function k(a,h,b){var e="",f=h;for(h+=b;fc)b+=1;else if(2048> +c)b+=2;else if(65536>c)b+=3;else if(1114112>c)b+=4;else throw Error("bad codepoint "+c);}return b}function a(a,b){this.offset=b||0;this.view=a}function e(a,b){return g.keysArray(a,!0).filter(function(e){e=a[e];return(!b||void 0!==e&&null!==e)&&("function"!==typeof e||!!e.toJSON)})}function l(a,h,f,m){var k=typeof a;if("string"===k){var g=b(a);if(32>g)return h.setUint8(f,g|160),c(h,f+1,a),1+g;if(256>g)return h.setUint8(f,217),h.setUint8(f+1,g),c(h,f+2,a),2+g;if(65536>g)return h.setUint8(f,218),h.setUint16(f+ 1,g),c(h,f+3,a),3+g;if(4294967296>g)return h.setUint8(f,219),h.setUint32(f+1,g),c(h,f+5,a),5+g}if(a instanceof ArrayBuffer){g=a.byteLength;if(256>g)return h.setUint8(f,196),h.setUint8(f+1,g),(new Uint8Array(h.buffer)).set(new Uint8Array(a),f+2),2+g;if(65536>g)return h.setUint8(f,197),h.setUint16(f+1,g),(new Uint8Array(h.buffer)).set(new Uint8Array(a),f+3),3+g;if(4294967296>g)return h.setUint8(f,198),h.setUint32(f+1,g),(new Uint8Array(h.buffer)).set(new Uint8Array(a),f+5),5+g}if("number"===k){if(Math.floor(a)!== -a)return h.setUint8(f,203),h.setFloat64(f+1,a),9;if(0<=a){if(128>a)return h.setUint8(f,a),1;if(256>a)return h.setUint8(f,204),h.setUint8(f+1,a),2;if(65536>a)return h.setUint8(f,205),h.setUint16(f+1,a),3;if(4294967296>a)return h.setUint8(f,206),h.setUint32(f+1,a),5;if(1.8446744073709552E19>a)return h.setUint8(f,207),f+=1,1.8446744073709552E19>a?(h.setUint32(f,Math.floor(a*p)),h.setInt32(f+4,a&-1)):(h.setUint32(f,4294967295),h.setUint32(f+4,4294967295)),9;throw Error("Number too big 0x"+a.toString(16)); -}if(-32<=a)return h.setInt8(f,a),1;if(-128<=a)return h.setUint8(f,208),h.setInt8(f+1,a),2;if(-32768<=a)return h.setUint8(f,209),h.setInt16(f+1,a),3;if(-2147483648<=a)return h.setUint8(f,210),h.setInt32(f+1,a),5;if(-9223372036854775808<=a)return h.setUint8(f,211),f+=1,0x7fffffffffffffff>a?(h.setInt32(f,Math.floor(a*p)),h.setInt32(f+4,a&-1)):(h.setUint32(f,2147483647),h.setUint32(f+4,2147483647)),9;throw Error("Number too small -0x"+(-a).toString(16).substr(1));}if("undefined"===k){if(m)return 0;h.setUint8(f, -212);h.setUint8(f+1,0);h.setUint8(f+2,0);return 3}if(null===a){if(m)return 0;h.setUint8(f,192);return 1}if("boolean"===k)return h.setUint8(f,a?195:194),1;if("function"===typeof a.toJSON)return l(a.toJSON(),h,f,m);if("object"===k){var k=0,C=Array.isArray(a);if(C)g=a.length;else var $=e(a,m),g=$.length;16>g?(h.setUint8(f,g|(C?144:128)),k=1):65536>g?(h.setUint8(f,C?220:222),h.setUint16(f+1,g),k=3):4294967296>g&&(h.setUint8(f,C?221:223),h.setUint32(f+1,g),k=5);if(C)for(C=0;Cd)return 1+d;if(256>d)return 2+d;if(65536>d)return 3+d;if(4294967296>d)return 5+d}if(a instanceof ArrayBuffer){d=a.byteLength;if(256>d)return 2+d;if(65536>d)return 3+d;if(4294967296>d)return 5+d}if("number"===c){if(Math.floor(a)!==a)return 9;if(0<=a){if(128>a)return 1;if(256>a)return 2;if(65536>a)return 3; +a)return h.setUint8(f,203),h.setFloat64(f+1,a),9;if(0<=a){if(128>a)return h.setUint8(f,a),1;if(256>a)return h.setUint8(f,204),h.setUint8(f+1,a),2;if(65536>a)return h.setUint8(f,205),h.setUint16(f+1,a),3;if(4294967296>a)return h.setUint8(f,206),h.setUint32(f+1,a),5;if(1.8446744073709552E19>a)return h.setUint8(f,207),f+=1,1.8446744073709552E19>a?(h.setUint32(f,Math.floor(a*n)),h.setInt32(f+4,a&-1)):(h.setUint32(f,4294967295),h.setUint32(f+4,4294967295)),9;throw Error("Number too big 0x"+a.toString(16)); +}if(-32<=a)return h.setInt8(f,a),1;if(-128<=a)return h.setUint8(f,208),h.setInt8(f+1,a),2;if(-32768<=a)return h.setUint8(f,209),h.setInt16(f+1,a),3;if(-2147483648<=a)return h.setUint8(f,210),h.setInt32(f+1,a),5;if(-9223372036854775808<=a)return h.setUint8(f,211),f+=1,0x7fffffffffffffff>a?(h.setInt32(f,Math.floor(a*n)),h.setInt32(f+4,a&-1)):(h.setUint32(f,2147483647),h.setUint32(f+4,2147483647)),9;throw Error("Number too small -0x"+(-a).toString(16).substr(1));}if("undefined"===k){if(m)return 0;h.setUint8(f, +212);h.setUint8(f+1,0);h.setUint8(f+2,0);return 3}if(null===a){if(m)return 0;h.setUint8(f,192);return 1}if("boolean"===k)return h.setUint8(f,a?195:194),1;if("function"===typeof a.toJSON)return l(a.toJSON(),h,f,m);if("object"===k){var k=0,D=Array.isArray(a);if(D)g=a.length;else var aa=e(a,m),g=aa.length;16>g?(h.setUint8(f,g|(D?144:128)),k=1):65536>g?(h.setUint8(f,D?220:222),h.setUint16(f+1,g),k=3):4294967296>g&&(h.setUint8(f,D?221:223),h.setUint32(f+1,g),k=5);if(D)for(D=0;Dd)return 1+d;if(256>d)return 2+d;if(65536>d)return 3+d;if(4294967296>d)return 5+d}if(a instanceof ArrayBuffer){d=a.byteLength;if(256>d)return 2+d;if(65536>d)return 3+d;if(4294967296>d)return 5+d}if("number"===c){if(Math.floor(a)!==a)return 9;if(0<=a){if(128>a)return 1;if(256>a)return 2;if(65536>a)return 3; if(4294967296>a)return 5;if(1.8446744073709552E19>a)return 9;throw Error("Number too big 0x"+a.toString(16));}if(-32<=a)return 1;if(-128<=a)return 2;if(-32768<=a)return 3;if(-2147483648<=a)return 5;if(-9223372036854775808<=a)return 9;throw Error("Number too small -0x"+a.toString(16).substr(1));}if("boolean"===c)return 1;if(null===a)return h?0:1;if(void 0===a)return h?0:3;if("function"===typeof a.toJSON)return f(a.toJSON(),h);if("object"===c){c=0;if(Array.isArray(a))for(var d=a.length,m=0;md)return 1+c;if(65536>d)return 3+c;if(4294967296>d)return 5+c;throw Error("Array or object too long 0x"+d.toString(16));}if("function"===c)return 0;throw Error("Unknown type "+c);}var m={inspect:function(a){if(void 0===a)return"undefined";var b,e;a instanceof ArrayBuffer?(e="ArrayBuffer",b=new DataView(a)):a instanceof DataView&&(e="DataView",b=a);if(!b)return JSON.stringify(a);for(var f=[],c=0;c"}};m.utf8Write=c;m.utf8Read=k;m.utf8ByteCount=b;m.encode=function(a,b){var e=f(a,b);if(0!=e){var e=new ArrayBuffer(e),c=new DataView(e);l(a,c,0,b);return e}};m.decode=function(b){var e=new DataView(b),e=new a(e),f=e.parse();if(e.offset!==b.byteLength)throw Error(b.byteLength-e.offset+" trailing bytes");return f};var p=1/4294967296;a.prototype.map=function(a){for(var b={},e=0;e< +f(a[m],h);else for(var n=e(a,h),d=n.length,m=0;md)return 1+c;if(65536>d)return 3+c;if(4294967296>d)return 5+c;throw Error("Array or object too long 0x"+d.toString(16));}if("function"===c)return 0;throw Error("Unknown type "+c);}var m={inspect:function(a){if(void 0===a)return"undefined";var b,e;a instanceof ArrayBuffer?(e="ArrayBuffer",b=new DataView(a)):a instanceof DataView&&(e="DataView",b=a);if(!b)return JSON.stringify(a);for(var f=[],c=0;c"}};m.utf8Write=c;m.utf8Read=k;m.utf8ByteCount=b;m.encode=function(a,b){var e=f(a,b);if(0!=e){var e=new ArrayBuffer(e),c=new DataView(e);l(a,c,0,b);return e}};m.decode=function(b){var e=new DataView(b),e=new a(e),f=e.parse();if(e.offset!==b.byteLength)throw Error(b.byteLength-e.offset+" trailing bytes");return f};var n=1/4294967296;a.prototype.map=function(a){for(var b={},e=0;e< a;e++){var f=this.parse();b[f]=this.parse()}return b};a.prototype.bin=a.prototype.buf=function(a){var b=new ArrayBuffer(a);(new Uint8Array(b)).set(new Uint8Array(this.view.buffer,this.offset,a),0);this.offset+=a;return b};a.prototype.str=function(a){var b=k(this.view,this.offset,a);this.offset+=a;return b};a.prototype.array=function(a){for(var b=Array(a),e=0;e>>2]>>>24-n%4*8&255;return b}throw Error("BufferUtils.toArrayBuffer expected a buffer");};b.toWordArray=function(b){return c(b)?b:a.create(b)};b.base64Encode=function(a){if(k(a)){var b="";a=new Uint8Array(a);for(var e=a.byteLength,l=e%3,e=e-l,h,u,w,g,K=0;K>18,u=(g&258048)>>12,w=(g&4032)>>6,g&=63,b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[h]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u]+ -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[w]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[g];1==l?(g=a[e],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&252)>>2]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&3)<<4]+"=="):2==l&&(g=a[e]<<8|a[e+1],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&64512)>>10]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&1008)>> -4]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&15)<<2]+"=");return b}if(c(a))return D.enc.Base64.stringify(a)};b.base64Decode=function(a){if(e&&l){a=l(a);for(var b=a.length,c=new Uint8Array(b),d=0;d>>2]>>>24-p%4*8&255;return b}throw Error("BufferUtils.toArrayBuffer expected a buffer");};b.toWordArray=function(b){return c(b)?b:a.create(b)};b.base64Encode=function(a){if(k(a)){var b="";a=new Uint8Array(a);for(var e=a.byteLength,l=e%3,e=e-l,h,u,w,g,F=0;F>18,u=(g&258048)>>12,w=(g&4032)>>6,g&=63,b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[h]+ +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[w]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[g];1==l?(g=a[e],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&252)>>2]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&3)<<4]+"=="):2==l&&(g=a[e]<<8|a[e+1],b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&64512)>>10]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g& +1008)>>4]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(g&15)<<2]+"=");return b}if(c(a))return E.enc.Base64.stringify(a)};b.base64Decode=function(a){if(e&&l){a=l(a);for(var b=a.length,c=new Uint8Array(b),d=0;d=b}var b=function(){};c.get=function(a,e,l, -f,m){m=m||b;var p="function"==typeof e?e:function(b){return a.baseUri(b)+e},n;n=(n=a.connection)&&"connected"==n.state?[n.connectionManager.host]:r.getHosts(a.options);if(1==n.length)c.getUri(a,p(n[0]),l,f,m);else{var h=function(b){c.getUri(a,p(b.shift()),l,f,function(a){a&&k(a)&&b.length?h(b):m.apply(null,arguments)})};h(n)}};c.getUri=function(a,e,l,f,m){c.Request(a,e,l,f,null,m||b)};c.post=function(a,e,l,f,m,p){p=p||b;var n="function"==typeof e?e:function(b){return a.baseUri(b)+e},h;h=(h=a.connection)&& -"connected"==h.state?[h.connectionManager.host]:r.getHosts(a.options);if(1==h.length)c.postUri(a,n(h[0]),l,f,m,p);else{var u=function(b){c.postUri(a,n(b.shift()),l,f,m,function(a){a&&k(a)&&b.length?u(b):p.apply(null,arguments)})};u(h)}};c.postUri=function(a,e,l,f,m,p){c.Request(a,e,l,m,f,p||b)};c.supportsAuthHeaders=!1;c.supportsLinkHeaders=!1;return c}(),ea=function(){function c(){this.buffer=[]}function k(a){this._input=a;this._index=-1;this._buffer=[]}function b(a){this._input=a;this._index=-1; -this._buffer=[]}c.prototype.append=function(a){this.buffer.push(a);return this};c.prototype.toString=function(){return this.buffer.join("")};var a={codex:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(b){var l=new c,f=a.codex;for(b=new k(b);b.moveNext();){var m=b.current;b.moveNext();var p=b.current;b.moveNext();var n=b.current,h=m>>2,m=(m&3)<<4|p>>4,u=(p&15)<<2|n>>6,w=n&63;isNaN(p)?u=w=64:isNaN(n)&&(w=64);l.append(f.charAt(h)+f.charAt(m)+f.charAt(u)+f.charAt(w))}return l.toString()}, +f,m){m=m||b;var n="function"==typeof e?e:function(b){return a.baseUri(b)+e},p;p=(p=a.connection)&&"connected"==p.state?[p.connectionManager.host]:r.getHosts(a.options);if(1==p.length)c.getUri(a,n(p[0]),l,f,m);else{var h=function(b){c.getUri(a,n(b.shift()),l,f,function(a){a&&k(a)&&b.length?h(b):m.apply(null,arguments)})};h(p)}};c.getUri=function(a,e,l,f,m){c.Request(a,e,l,f,null,m||b)};c.post=function(a,e,l,f,m,n){n=n||b;var p="function"==typeof e?e:function(b){return a.baseUri(b)+e},h;h=(h=a.connection)&& +"connected"==h.state?[h.connectionManager.host]:r.getHosts(a.options);if(1==h.length)c.postUri(a,p(h[0]),l,f,m,n);else{var u=function(b){c.postUri(a,p(b.shift()),l,f,m,function(a){a&&k(a)&&b.length?u(b):n.apply(null,arguments)})};u(h)}};c.postUri=function(a,e,l,f,m,n){c.Request(a,e,l,m,f,n||b)};c.supportsAuthHeaders=!1;c.supportsLinkHeaders=!1;return c}(),fa=function(){function c(){this.buffer=[]}function k(a){this._input=a;this._index=-1;this._buffer=[]}function b(a){this._input=a;this._index=-1; +this._buffer=[]}c.prototype.append=function(a){this.buffer.push(a);return this};c.prototype.toString=function(){return this.buffer.join("")};var a={codex:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(b){var l=new c,f=a.codex;for(b=new k(b);b.moveNext();){var m=b.current;b.moveNext();var n=b.current;b.moveNext();var p=b.current,h=m>>2,m=(m&3)<<4|n>>4,u=(n&15)<<2|p>>6,w=p&63;isNaN(n)?u=w=64:isNaN(p)&&(w=64);l.append(f.charAt(h)+f.charAt(m)+f.charAt(u)+f.charAt(w))}return l.toString()}, decode:function(a){var l=new c;for(a=new b(a);a.moveNext();){var f=a.current;if(128>f)l.append(String.fromCharCode(f));else if(191f){a.moveNext();var m=a.current;l.append(String.fromCharCode((f&31)<<6|m&63))}else a.moveNext(),m=a.current,a.moveNext(),l.append(String.fromCharCode((f&15)<<12|(m&63)<<6|a.current&63))}return l.toString()}};k.prototype={current:Number.NaN,moveNext:function(){if(0=this._input.length- 1)return this.current=Number.NaN,!1;var a=this._input.charCodeAt(++this._index);13==a&&10==this._input.charCodeAt(this._index+1)&&(a=10,this._index+=2);128>a?this.current=a:(127a?this.current=a>>6|192:(this.current=a>>12|224,this._buffer.push(a>>6&63|128)),this._buffer.push(a&63|128));return!0}};b.prototype={current:64,moveNext:function(){if(0=this._input.length-1)return this.current=64,!1;var b=a.codex.indexOf(this._input.charAt(++this._index)), -c=a.codex.indexOf(this._input.charAt(++this._index)),f=a.codex.indexOf(this._input.charAt(++this._index)),d=a.codex.indexOf(this._input.charAt(++this._index)),p=(f&3)<<6|d;this.current=b<<2|c>>4;64!=f&&this._buffer.push((c&15)<<4|f>>2);64!=d&&this._buffer.push(p);return!0}};return a}();r.protocolVersion=1;r.ENVIRONMENT="";r.REST_HOST="rest.ably.io";r.REALTIME_HOST="realtime.ably.io";r.FALLBACK_HOSTS=["A.ably-realtime.com","B.ably-realtime.com","C.ably-realtime.com","D.ably-realtime.com","E.ably-realtime.com"]; -r.PORT=80;r.TLS_PORT=443;r.TIMEOUTS={disconnectedRetryTimeout:15E3,suspendedRetryTimeout:3E4,httpRequestTimeout:15E3,channelRetryTimeout:15E3,connectionStateTtl:12E4,realtimeRequestTimeout:1E4,recvTimeout:9E4,preferenceConnectTimeout:6E3,parallelUpgradeDelay:4E3};r.httpMaxRetryCount=3;r.version="1.0.0";r.libstring="js-"+r.version;r.apiVersion="1.0";r.getHost=function(c,k,b){return k=b?k==c.restHost&&c.realtimeHost||k||c.realtimeHost:k||c.restHost};r.getPort=function(c,k){return k||c.tls?c.tlsPort: +c=a.codex.indexOf(this._input.charAt(++this._index)),f=a.codex.indexOf(this._input.charAt(++this._index)),d=a.codex.indexOf(this._input.charAt(++this._index)),n=(f&3)<<6|d;this.current=b<<2|c>>4;64!=f&&this._buffer.push((c&15)<<4|f>>2);64!=d&&this._buffer.push(n);return!0}};return a}();r.protocolVersion=1;r.ENVIRONMENT="";r.REST_HOST="rest.ably.io";r.REALTIME_HOST="realtime.ably.io";r.FALLBACK_HOSTS=["A.ably-realtime.com","B.ably-realtime.com","C.ably-realtime.com","D.ably-realtime.com","E.ably-realtime.com"]; +r.PORT=80;r.TLS_PORT=443;r.TIMEOUTS={disconnectedRetryTimeout:15E3,suspendedRetryTimeout:3E4,httpRequestTimeout:15E3,channelRetryTimeout:15E3,connectionStateTtl:12E4,realtimeRequestTimeout:1E4,recvTimeout:9E4,preferenceConnectTimeout:6E3,parallelUpgradeDelay:4E3};r.httpMaxRetryCount=3;r.version="1.0.1";r.libstring="js-"+r.version;r.apiVersion="1.0";r.getHost=function(c,k,b){return k=b?k==c.restHost&&c.realtimeHost||k||c.realtimeHost:k||c.restHost};r.getPort=function(c,k){return k||c.tls?c.tlsPort: c.port};r.getHttpScheme=function(c){return c.tls?"https://":"http://"};r.getHosts=function(c){var k=[c.restHost],b=c.fallbackHosts;c="undefined"!==typeof c.httpMaxRetryCount?c.httpMaxRetryCount:r.httpMaxRetryCount;b&&(k=k.concat(g.arrChooseN(b,c)));return k};r.normaliseOptions=function(d){d.host&&(c.deprecated("host","restHost"),d.restHost=d.host);d.wsHost&&(c.deprecated("wsHost","realtimeHost"),d.realtimeHost=d.wsHost);d.queueEvents&&(c.deprecated("queueEvents","queueMessages"),d.queueMessages=d.queueEvents); !0===d.recover&&(c.deprecated("{recover: true}","{recover: function(lastConnectionDetails, cb) { cb(true); }}"),d.recover=function(a,b){b(!0)});"function"===typeof d.recover&&!0===d.closeOnUnload&&(c.logAction(LOG_ERROR,"Defaults.normaliseOptions","closeOnUnload was true and a session recovery function was set - these are mutually exclusive, so unsetting the latter"),d.recover=null);d.transports&&g.arrIn(d.transports,"xhr")&&(c.deprecated('transports: ["xhr"]','transports: ["xhr_streaming"]'),g.arrDeleteValue(d.transports, "xhr"),d.transports.push("xhr_streaming"));"queueMessages"in d||(d.queueMessages=!0);var k=!1;if(d.restHost)d.realtimeHost=d.realtimeHost||d.restHost;else{var b=d.environment&&String(d.environment).toLowerCase()||r.ENVIRONMENT,k=!b||"production"===b;d.restHost=k?r.REST_HOST:b+"-"+r.REST_HOST;d.realtimeHost=k?r.REALTIME_HOST:b+"-"+r.REALTIME_HOST}d.fallbackHosts=k||d.fallbackHostsUseDefault?r.FALLBACK_HOSTS:d.fallbackHosts;d.port=d.port||r.PORT;d.tlsPort=d.tlsPort||r.TLS_PORT;"tls"in d||(d.tls=!0); -d.timeouts={};for(var a in r.TIMEOUTS)d.timeouts[a]=d[a]||r.TIMEOUTS[a];d.useBinaryProtocol="useBinaryProtocol"in d?x.supportsBinary&&d.useBinaryProtocol:x.preferBinary;return d};var v=function(){function d(){this.any=[];this.events={};this.anyOnce=[];this.eventsOnce={}}function k(a,b,d){try{b.apply(a,d)}catch(f){c.logAction(c.LOG_ERROR,"EventEmitter.emit()","Unexpected listener exception: "+f+"; stack = "+f.stack)}}function b(a,e,c){var f,d,p,n;for(n=0;n=d?null:c.slice(0,d).join("/"),b.data=m}}};d.fromResponseBody=function(b,a,e){e&&(b="msgpack"==e?k.decode(b):JSON.parse(String(b)));for(e=0;eg.arrIndexOf(p,b.shortName)}function k(a,b,c,e,f){this.options=a;this.host=b;this.mode=c;this.connectionKey=e;this.connectionSerial=f;this.format=a.useBinaryProtocol?"msgpack": -"json"}function b(a,f){v.call(this);this.realtime=a;this.options=f;var d=f.timeouts,p=this;this.states={initialized:{state:"initialized",terminal:!1,queueEvents:!0,sendEvents:!1,failState:"disconnected"},connecting:{state:"connecting",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.preferenceConnectTimeout+d.realtimeRequestTimeout,failState:"disconnected"},connected:{state:"connected",terminal:!1,queueEvents:!1,sendEvents:!0,failState:"disconnected"},synchronizing:{state:"connected",terminal:!1, -queueEvents:!0,sendEvents:!1,failState:"disconnected"},disconnected:{state:"disconnected",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.disconnectedRetryTimeout,failState:"disconnected"},suspended:{state:"suspended",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.suspendedRetryTimeout,failState:"suspended"},closing:{state:"closing",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.realtimeRequestTimeout,failState:"closed"},closed:{state:"closed",terminal:!0,queueEvents:!1,sendEvents:!1, -failState:"closed"},failed:{state:"failed",terminal:!0,queueEvents:!1,sendEvents:!1,failState:"failed"}};this.state=this.states.initialized;this.errorReason=null;this.queuedMessages=new ca;this.msgSerial=0;this.connectionSerial=this.connectionKey=this.connectionId=void 0;this.transports=g.intersect(f.transports||r.transports,b.supportedTransports);this.baseTransport=g.intersect(r.transports,this.transports)[0];this.upgradeTransports=g.intersect(this.transports,r.upgradeTransports);this.transportHostBlacklist= -{};this.transportPreference=null;this.httpHosts=r.getHosts(f);this.activeProtocol=null;this.proposedTransports=[];this.pendingTransports=[];this.lastAutoReconnectAttempt=this.host=null;c.logAction(c.LOG_MINOR,"Realtime.ConnectionManager()","started");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","requested transports = ["+(f.transports||r.transports)+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","available transports = ["+this.transports+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()", -"http hosts = ["+this.httpHosts+"]");if(!this.transports.length)throw c.logAction(c.LOG_ERROR,"realtime.ConnectionManager()","no requested transports available"),Error("no requested transports available");if(d=x.addEventListener)e&&"function"===typeof f.recover&&d("beforeunload",this.persistConnection.bind(this)),!0===f.closeOnUnload&&d("beforeunload",function(){p.requestState({state:"closing"})}),d("online",function(){if(p.state==p.states.disconnected||p.state==p.states.suspended)c.logAction(c.LOG_MINOR, -"ConnectionManager caught browser \u2018online\u2019 event","reattempting connection"),p.requestState({state:"connecting"})}),d("offline",function(){p.state==p.states.connected&&(c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018offline\u2019 event","disconnecting active transport"),p.disconnectAllTransports())})}var a=!("undefined"===typeof H||!H.get),e=!("undefined"===typeof H||!H.getSession),l=t.Action,f=da.PendingMessage,m=function(){},p=r.transportPreferenceOrder,n=p[p.length-1]; -k.prototype.getConnectParams=function(a){a=a?g.copy(a):{};var b=this.options;switch(this.mode){case "upgrade":a.upgrade=this.connectionKey;break;case "resume":a.resume=this.connectionKey;void 0!==this.connectionSerial&&(a.connection_serial=this.connectionSerial);break;case "recover":var c=b.recover.split(":");c&&(a.recover=c[0],a.connection_serial=c[1])}void 0!==b.clientId&&(a.clientId=b.clientId);!1===b.echoMessages&&(a.echo="false");void 0!==this.format&&(a.format=this.format);void 0!==this.stream&& -(a.stream=this.stream);void 0!==this.heartbeats&&(a.heartbeats=this.heartbeats);void 0!==b.transportParams&&g.mixin(a,b.transportParams);a.v=r.apiVersion;a.lib=r.libstring;return a};g.inherits(b,v);b.supportedTransports={};b.prototype.getTransportParams=function(a){var b=this;(function(a){if(b.connectionKey)a("resume");else if("string"===typeof b.options.recover)a("recover");else{var h=b.options.recover,f=e&&H.getSession("ably-connection-recovery");f&&"function"===typeof h?(c.logAction(c.LOG_MINOR, -"ConnectionManager.getTransportParams()","Calling clientOptions-provided recover function with last session data"),h(f,function(c){c?(b.options.recover=f.recoveryKey,a("recover")):a("clean")})):a("clean")}})(function(e){c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Transport recovery mode = "+e+("clean"==e?"":"; connectionKey = "+b.connectionKey+"; connectionSerial = "+b.connectionSerial));a(new k(b.options,null,e,b.connectionKey,b.connectionSerial))})};b.prototype.tryATransport= -function(a,e,f){var d=this,p=a.host;c.logAction(c.LOG_MICRO,"ConnectionManager.tryATransport()","trying "+e);p in this.transportHostBlacklist&&g.arrIn(this.transportHostBlacklist[p],e)?c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()",e+" transport is blacklisted for host "+a.host):b.supportedTransports[e].tryConnect(this,this.realtime.auth,a,function(b,p){var l=d.state;l==d.states.closing||l==d.states.closed||l==d.states.failed?(p&&(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()", -"connection "+l.state+" while we were attempting the transport; closing "+p),p.close()),f(!0)):b?(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()","transport "+e+" "+b.event+", err: "+b.error.toString()),M.isTokenErr(b.error)?d.realtime.auth._forceNewToken(null,null,function(b){b?d.actOnErrorFromAuthorize(b):d.tryATransport(a,e,f)}):"failed"===b.event?(d.notifyState({state:"failed",error:b.error}),f(!0)):"disconnected"===b.event&&f(!1)):(c.logAction(c.LOG_MICRO,"ConnectionManager.chooseTransportForHost()", -"viable transport "+e+"; setting pending"),d.setTransportPending(p,a),f(null,p))})};b.prototype.setTransportPending=function(a,b){var e=b.mode;c.logAction(c.LOG_MINOR,"ConnectionManager.setTransportPending()","transport = "+a+"; mode = "+e);g.arrDeleteValue(this.proposedTransports,a);this.pendingTransports.push(a);var f=this;a.once("connected",function(c,d,p,l,m){"upgrade"==e&&f.activeProtocol?a.shortName!==n&&g.arrIn(f.getUpgradePossibilities(),n)?setTimeout(function(){f.scheduleTransportActivation(c, -a,d,p,l,m)},f.options.timeouts.parallelUpgradeDelay):f.scheduleTransportActivation(c,a,d,p,l,m):(f.activateTransport(c,a,d,p,l,m),g.nextTick(function(){f.connectImpl(b)}));"recover"===e&&f.options.recover&&(f.options.recover=null,f.unpersistConnection())});a.on(["disconnected","closed","failed"],function(b){f.deactivateTransport(a,this.event,b)});this.emit("transport.pending",a)};b.prototype.scheduleTransportActivation=function(a,b,e,f,p,l){var n=this,m=this.activeProtocol&&this.activeProtocol.getTransport(), -k=function(){b.disconnect();g.arrDeleteValue(n.pendingTransports,b)};this.state!==this.states.connected&&this.state!==this.states.connecting?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+this.state.state+(this.state===this.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName),k()):m&&!d(b,m)?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()", -"Proposed transport "+b.shortName+" is no better than current active transport "+m.shortName+" - abandoning upgrade"),k()):(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Scheduling transport upgrade; transport = "+b),this.realtime.channels.onceNopending(function(d){var m;if(d)c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Unable to activate transport; transport = "+b+"; err = "+d);else if(b.isConnected){if(n.state===n.states.connected)c.logAction(c.LOG_MICRO, -"ConnectionManager.scheduleTransportActivation()","Currently connected, so temporarily pausing events until the upgrade is complete"),n.state=n.states.synchronizing,m=n.activeProtocol;else if(n.state!==n.states.connecting){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+n.state.state+(n.state===n.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName);k();return}var g= -(d=p!==n.connectionId)?f:n.connectionSerial;d&&c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Upgrade resulted in new connectionId; resetting library connectionSerial from "+n.connectionSerial+" to "+g+"; upgrade error was "+a);c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Syncing transport; transport = "+b);n.sync(b,function(f,d,p){if(f)n.state===n.states.synchronizing&&(c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()", -"Unexpected error attempting to sync transport; transport = "+b+"; err = "+f),n.disconnectAllTransports());else if(f=function(){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Activating transport; transport = "+b);n.activateTransport(a,b,e,d,p,l);n.state===n.states.synchronizing?(c.logAction(c.LOG_MICRO,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, sending queued messages on upgraded transport; transport = "+b),n.state=n.states.connected): -c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, but state is now "+n.state.state+", so leaving unchanged");n.state.sendEvents&&n.sendQueuedMessages()},m)m.onceIdle(f);else f()})}else c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Proposed transport "+b.shortName+"is no longer connected; abandoning upgrade"),k()}))};b.prototype.activateTransport=function(a,b,e,f,d,p){c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", -"transport = "+b);a&&c.logAction(c.LOG_ERROR,"ConnectionManager.activateTransport()","error = "+a);e&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionKey = "+e);void 0!==f&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionSerial = "+f);d&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionId = "+d);p&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionDetails = "+JSON.stringify(p));this.persistTransportPreference(b); -var n=this.state,l=this.states.connected.state;c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","current state = "+n.state);if(n.state==this.states.closing.state||n.state==this.states.closed.state||n.state==this.states.failed.state)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","Disconnecting transport and abandoning"),b.disconnect(),!1;g.arrDeleteValue(this.pendingTransports,b);if(!b.isConnected)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", -"Declining to activate transport "+b+" since it appears to no longer be connected"),!1;var m=this.activeProtocol;this.activeProtocol=new da(b);this.host=b.params.host;e&&this.connectionKey!=e&&this.setConnection(d,e,f);this.onConnectionDetailsUpdate(p,b);var k=this;g.nextTick(function(){b.on("connected",function(a,c,e,h,f){k.onConnectionDetailsUpdate(f,b);k.emit("update",new R(l,l,null,a))})});this.emit("transport.active",b,e,b.params);n.state===this.states.connected.state?a&&(this.errorReason=this.realtime.connection.errorReason= -a,this.emit("update",new R(l,l,null,a))):(this.notifyState({state:"connected",error:a}),this.errorReason=this.realtime.connection.errorReason=a||null);m&&(0n?(c.logAction(c.LOG_MICRO,"ConnectionManager.notifyState()","Last reconnect attempt was only "+n+"ms ago, waiting another "+ -(1E3-n)+"ms before trying again"),setTimeout(p,1E3-n)):g.nextTick(p)}else"disconnected"!==b&&"suspended"!==b||this.startRetryTimer(d.retryDelay);("disconnected"===b&&!f||"suspended"===b||d.terminal)&&g.nextTick(function(){e.disconnectAllTransports()});"connected"!=b||this.activeProtocol||c.logAction(c.LOG_ERROR,"ConnectionManager.notifyState()","Broken invariant: attempted to go into connected state, but there is no active protocol");this.enactStateChange(a);this.state.sendEvents?this.sendQueuedMessages(): -this.state.queueEvents||(this.realtime.channels.propogateConnectionInterruption(b,a.reason),this.failQueuedMessages(a.reason))}};b.prototype.requestState=function(a){var b=a.state,e=this;c.logAction(c.LOG_MINOR,"ConnectionManager.requestState()","requested state: "+b+"; current state: "+this.state.state);if(b!=this.state.state&&(this.cancelTransitionTimer(),this.cancelRetryTimer(),this.checkSuspendTimer(b),"connecting"!=b||"connected"!=this.state.state)&&("closing"!=b||"closed"!=this.state.state)){var f= -this.states[b];a=new R(this.state.state,f.state,null,a.error||I[f.state]);this.enactStateChange(a);"connecting"==b&&g.nextTick(function(){e.startConnect()});"closing"==b&&this.closeImpl()}};b.prototype.startConnect=function(){if(this.state!==this.states.connecting)c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()","Must be in connecting state to connect, but was "+this.state.state);else{var a=this.realtime.auth,b=this,e=function(){b.getTransportParams(function(a){b.connectImpl(a)})};c.logAction(c.LOG_MINOR, -"ConnectionManager.startConnect()","starting connection");this.startSuspendTimer();this.startTransitionTimer(this.states.connecting);if("basic"===a.method)e();else{var f=function(a){a?b.actOnErrorFromAuthorize(a):e()};this.errorReason&&M.isTokenErr(this.errorReason)?a._forceNewToken(null,null,f):a._ensureValidAuthCredentials(f)}}};b.prototype.connectImpl=function(a){var b=this.state.state;b!==this.states.connecting.state&&b!==this.states.connected.state?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()", -"Must be in connecting state to connect (or connected to upgrade), but was "+b):this.pendingTransports.length?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Transports "+this.pendingTransports[0].toString()+" currently pending; taking no action"):b==this.states.connected.state?this.upgradeIfNeeded(a):1g.arrIndexOf(n,b.shortName)}function k(a,b,c,e,f){this.options=a;this.host=b;this.mode=c;this.connectionKey=e;this.connectionSerial=f;this.format=a.useBinaryProtocol?"msgpack": +"json"}function b(a,f){x.call(this);this.realtime=a;this.options=f;var d=f.timeouts,n=this;this.states={initialized:{state:"initialized",terminal:!1,queueEvents:!0,sendEvents:!1,failState:"disconnected"},connecting:{state:"connecting",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.preferenceConnectTimeout+d.realtimeRequestTimeout,failState:"disconnected"},connected:{state:"connected",terminal:!1,queueEvents:!1,sendEvents:!0,failState:"disconnected"},synchronizing:{state:"connected",terminal:!1, +queueEvents:!0,sendEvents:!1,forceQueueEvents:!0,failState:"disconnected"},disconnected:{state:"disconnected",terminal:!1,queueEvents:!0,sendEvents:!1,retryDelay:d.disconnectedRetryTimeout,failState:"disconnected"},suspended:{state:"suspended",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.suspendedRetryTimeout,failState:"suspended"},closing:{state:"closing",terminal:!1,queueEvents:!1,sendEvents:!1,retryDelay:d.realtimeRequestTimeout,failState:"closed"},closed:{state:"closed",terminal:!0,queueEvents:!1, +sendEvents:!1,failState:"closed"},failed:{state:"failed",terminal:!0,queueEvents:!1,sendEvents:!1,failState:"failed"}};this.state=this.states.initialized;this.errorReason=null;this.queuedMessages=new da;this.msgSerial=0;this.connectionSerial=this.connectionKey=this.connectionId=void 0;this.transports=g.intersect(f.transports||r.defaultTransports,b.supportedTransports);this.baseTransport=g.intersect(r.baseTransportOrder,this.transports)[0];this.upgradeTransports=g.intersect(this.transports,r.upgradeTransports); +this.transportHostBlacklist={};this.transportPreference=null;this.httpHosts=r.getHosts(f);this.activeProtocol=null;this.proposedTransports=[];this.pendingTransports=[];this.lastAutoReconnectAttempt=this.host=null;c.logAction(c.LOG_MINOR,"Realtime.ConnectionManager()","started");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","requested transports = ["+(f.transports||r.defaultTransports)+"]");c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","available transports = ["+this.transports+"]"); +c.logAction(c.LOG_MICRO,"Realtime.ConnectionManager()","http hosts = ["+this.httpHosts+"]");if(!this.transports.length)throw c.logAction(c.LOG_ERROR,"realtime.ConnectionManager()","no requested transports available"),Error("no requested transports available");if(d=z.addEventListener)e&&"function"===typeof f.recover&&d("beforeunload",this.persistConnection.bind(this)),!0===f.closeOnUnload&&d("beforeunload",function(){n.requestState({state:"closing"})}),d("online",function(){if(n.state==n.states.disconnected|| +n.state==n.states.suspended)c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018online\u2019 event","reattempting connection"),n.requestState({state:"connecting"})}),d("offline",function(){n.state==n.states.connected&&(c.logAction(c.LOG_MINOR,"ConnectionManager caught browser \u2018offline\u2019 event","disconnecting active transport"),n.disconnectAllTransports())})}var a=!("undefined"===typeof J||!J.get),e=!("undefined"===typeof J||!J.getSession),l=v.Action,f=ea.PendingMessage,m=function(){}, +n=r.transportPreferenceOrder,p=n[n.length-1];k.prototype.getConnectParams=function(a){a=a?g.copy(a):{};var b=this.options;switch(this.mode){case "upgrade":a.upgrade=this.connectionKey;break;case "resume":a.resume=this.connectionKey;void 0!==this.connectionSerial&&(a.connection_serial=this.connectionSerial);break;case "recover":var c=b.recover.split(":");c&&(a.recover=c[0],a.connection_serial=c[1])}void 0!==b.clientId&&(a.clientId=b.clientId);!1===b.echoMessages&&(a.echo="false");void 0!==this.format&& +(a.format=this.format);void 0!==this.stream&&(a.stream=this.stream);void 0!==this.heartbeats&&(a.heartbeats=this.heartbeats);void 0!==b.transportParams&&g.mixin(a,b.transportParams);a.v=r.apiVersion;a.lib=r.libstring;return a};g.inherits(b,x);b.supportedTransports={};b.prototype.getTransportParams=function(a){var b=this;(function(a){if(b.connectionKey)a("resume");else if("string"===typeof b.options.recover)a("recover");else{var h=b.options.recover,f=e&&J.getSession("ably-connection-recovery");f&& +"function"===typeof h?(c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Calling clientOptions-provided recover function with last session data"),h(f,function(c){c?(b.options.recover=f.recoveryKey,a("recover")):a("clean")})):a("clean")}})(function(e){c.logAction(c.LOG_MINOR,"ConnectionManager.getTransportParams()","Transport recovery mode = "+e+("clean"==e?"":"; connectionKey = "+b.connectionKey+"; connectionSerial = "+b.connectionSerial));a(new k(b.options,null,e,b.connectionKey, +b.connectionSerial))})};b.prototype.tryATransport=function(a,e,f){var d=this,n=a.host;c.logAction(c.LOG_MICRO,"ConnectionManager.tryATransport()","trying "+e);n in this.transportHostBlacklist&&g.arrIn(this.transportHostBlacklist[n],e)?c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()",e+" transport is blacklisted for host "+a.host):b.supportedTransports[e].tryConnect(this,this.realtime.auth,a,function(b,n){var p=d.state;p==d.states.closing||p==d.states.closed||p==d.states.failed?(n&&(c.logAction(c.LOG_MINOR, +"ConnectionManager.tryATransport()","connection "+p.state+" while we were attempting the transport; closing "+n),n.close()),f(!0)):b?(c.logAction(c.LOG_MINOR,"ConnectionManager.tryATransport()","transport "+e+" "+b.event+", err: "+b.error.toString()),N.isTokenErr(b.error)?d.realtime.auth._forceNewToken(null,null,function(b){b?d.actOnErrorFromAuthorize(b):d.tryATransport(a,e,f)}):"failed"===b.event?(d.notifyState({state:"failed",error:b.error}),f(!0)):"disconnected"===b.event&&f(!1)):(c.logAction(c.LOG_MICRO, +"ConnectionManager.chooseTransportForHost()","viable transport "+e+"; setting pending"),d.setTransportPending(n,a),f(null,n))})};b.prototype.setTransportPending=function(a,b){var e=b.mode;c.logAction(c.LOG_MINOR,"ConnectionManager.setTransportPending()","transport = "+a+"; mode = "+e);g.arrDeleteValue(this.proposedTransports,a);this.pendingTransports.push(a);var f=this;a.once("connected",function(c,d,n,l,m){"upgrade"==e&&f.activeProtocol?a.shortName!==p&&g.arrIn(f.getUpgradePossibilities(),p)?setTimeout(function(){f.scheduleTransportActivation(c, +a,d,n,l,m)},f.options.timeouts.parallelUpgradeDelay):f.scheduleTransportActivation(c,a,d,n,l,m):(f.activateTransport(c,a,d,n,l,m),g.nextTick(function(){f.connectImpl(b)}));"recover"===e&&f.options.recover&&(f.options.recover=null,f.unpersistConnection())});a.on(["disconnected","closed","failed"],function(b){f.deactivateTransport(a,this.event,b)});this.emit("transport.pending",a)};b.prototype.scheduleTransportActivation=function(a,b,e,f,n,p){var l=this,m=this.activeProtocol&&this.activeProtocol.getTransport(), +k=function(){b.disconnect();g.arrDeleteValue(l.pendingTransports,b)};this.state!==this.states.connected&&this.state!==this.states.connecting?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+this.state.state+(this.state===this.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName),k()):m&&!d(b,m)?(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()", +"Proposed transport "+b.shortName+" is no better than current active transport "+m.shortName+" - abandoning upgrade"),k()):(c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Scheduling transport upgrade; transport = "+b),this.realtime.channels.onceNopending(function(d){var m;if(d)c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Unable to activate transport; transport = "+b+"; err = "+d);else if(b.isConnected){if(l.state===l.states.connected)c.logAction(c.LOG_MICRO, +"ConnectionManager.scheduleTransportActivation()","Currently connected, so temporarily pausing events until the upgrade is complete"),l.state=l.states.synchronizing,m=l.activeProtocol;else if(l.state!==l.states.connecting){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Current connection state ("+l.state.state+(l.state===l.states.synchronizing?", but with an upgrade already in progress":"")+") is not valid to upgrade in; abandoning upgrade to "+b.shortName);k();return}var g= +(d=n!==l.connectionId)?f:l.connectionSerial;d&&c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()","Upgrade resulted in new connectionId; resetting library connectionSerial from "+l.connectionSerial+" to "+g+"; upgrade error was "+a);c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Syncing transport; transport = "+b);l.sync(b,function(f,d,n){if(f)l.state===l.states.synchronizing&&(c.logAction(c.LOG_ERROR,"ConnectionManager.scheduleTransportActivation()", +"Unexpected error attempting to sync transport; transport = "+b+"; err = "+f),l.disconnectAllTransports());else if(f=function(){c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Activating transport; transport = "+b);l.activateTransport(a,b,e,d,n,p);l.state===l.states.synchronizing?(c.logAction(c.LOG_MICRO,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, sending queued messages on upgraded transport; transport = "+b),l.state=l.states.connected): +c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Pre-upgrade protocol idle, but state is now "+l.state.state+", so leaving unchanged");l.state.sendEvents&&l.sendQueuedMessages()},m)m.onceIdle(f);else f()})}else c.logAction(c.LOG_MINOR,"ConnectionManager.scheduleTransportActivation()","Proposed transport "+b.shortName+"is no longer connected; abandoning upgrade"),k()}))};b.prototype.activateTransport=function(a,b,e,f,d,n){c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", +"transport = "+b);a&&c.logAction(c.LOG_ERROR,"ConnectionManager.activateTransport()","error = "+a);e&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionKey = "+e);void 0!==f&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionSerial = "+f);d&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionId = "+d);n&&c.logAction(c.LOG_MICRO,"ConnectionManager.activateTransport()","connectionDetails = "+JSON.stringify(n));this.persistTransportPreference(b); +var l=this.state,p=this.states.connected.state;c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","current state = "+l.state);if(l.state==this.states.closing.state||l.state==this.states.closed.state||l.state==this.states.failed.state)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()","Disconnecting transport and abandoning"),b.disconnect(),!1;g.arrDeleteValue(this.pendingTransports,b);if(!b.isConnected)return c.logAction(c.LOG_MINOR,"ConnectionManager.activateTransport()", +"Declining to activate transport "+b+" since it appears to no longer be connected"),!1;var m=this.activeProtocol;this.activeProtocol=new ea(b);this.host=b.params.host;e&&this.connectionKey!=e&&this.setConnection(d,e,f);this.onConnectionDetailsUpdate(n,b);var k=this;g.nextTick(function(){b.on("connected",function(a,c,e,h,f){k.onConnectionDetailsUpdate(f,b);k.emit("update",new R(p,p,null,a))})});l.state===this.states.connected.state?a&&(this.errorReason=this.realtime.connection.errorReason=a,this.emit("update", +new R(p,p,null,a))):(this.notifyState({state:"connected",error:a}),this.errorReason=this.realtime.connection.errorReason=a||null);this.emit("transport.active",b,e,b.params);m&&(0l?(c.logAction(c.LOG_MICRO,"ConnectionManager.notifyState()","Last reconnect attempt was only "+l+"ms ago, waiting another "+(1E3-l)+"ms before trying again"),setTimeout(n,1E3-l)):g.nextTick(n)}else"disconnected"!==b&&"suspended"!==b||this.startRetryTimer(d.retryDelay);("disconnected"===b&&!f||"suspended"===b||d.terminal)&&g.nextTick(function(){e.disconnectAllTransports()});"connected"!=b||this.activeProtocol||c.logAction(c.LOG_ERROR,"ConnectionManager.notifyState()","Broken invariant: attempted to go into connected state, but there is no active protocol"); +this.enactStateChange(a);this.state.sendEvents?this.sendQueuedMessages():this.state.queueEvents||(this.realtime.channels.propogateConnectionInterruption(b,a.reason),this.failQueuedMessages(a.reason))}};b.prototype.requestState=function(a){var b=a.state,e=this;c.logAction(c.LOG_MINOR,"ConnectionManager.requestState()","requested state: "+b+"; current state: "+this.state.state);if(b!=this.state.state&&(this.cancelTransitionTimer(),this.cancelRetryTimer(),this.checkSuspendTimer(b),"connecting"!=b||"connected"!= +this.state.state)&&("closing"!=b||"closed"!=this.state.state)){var f=this.states[b];a=new R(this.state.state,f.state,null,a.error||K[f.state]);this.enactStateChange(a);"connecting"==b&&g.nextTick(function(){e.startConnect()});"closing"==b&&this.closeImpl()}};b.prototype.startConnect=function(){if(this.state!==this.states.connecting)c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()","Must be in connecting state to connect, but was "+this.state.state);else{var a=this.realtime.auth,b=this,e= +function(){b.getTransportParams(function(a){b.connectImpl(a)})};c.logAction(c.LOG_MINOR,"ConnectionManager.startConnect()","starting connection");this.startSuspendTimer();this.startTransitionTimer(this.states.connecting);if("basic"===a.method)e();else{var f=function(a){a?b.actOnErrorFromAuthorize(a):e()};this.errorReason&&N.isTokenErr(this.errorReason)?a._forceNewToken(null,null,f):a._ensureValidAuthCredentials(f)}}};b.prototype.connectImpl=function(a){var b=this.state.state;b!==this.states.connecting.state&& +b!==this.states.connected.state?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Must be in connecting state to connect (or connected to upgrade), but was "+b):this.pendingTransports.length?c.logAction(c.LOG_MINOR,"ConnectionManager.connectImpl()","Transports "+this.pendingTransports[0].toString()+" currently pending; taking no action"):b==this.states.connected.state?this.upgradeIfNeeded(a):1a.code)?[t.fromValues({action:t.Action.ERROR,error:a})]:[t.fromValues({action:t.Action.DISCONNECTED,error:a})]}function b(a,b,c){this.timeoutOnIdle=!0; -c.format=void 0;c.heartbeats=!0;P.call(this,a,b,c);this.stream="stream"in c?c.stream:!0;this.pendingItems=this.pendingCallback=this.recvRequest=this.sendRequest=null;this.disposed=!1}g.inherits(b,P);b.REQ_SEND=0;b.REQ_RECV=1;b.REQ_RECV_POLL=2;b.REQ_RECV_STREAM=3;b.prototype.connect=function(){c.logAction(c.LOG_MINOR,"CometTransport.connect()","starting");P.prototype.connect.call(this);var a=this,b=this.params,l=b.options,f=r.getHost(l,b.host),b=r.getPort(l);this.baseUri=(l.tls?"https://":"http://")+ +b.close()}))};return d})();var L=function(){function d(a,b,c){a&&a.server&&-1a.code)?[v.fromValues({action:v.Action.ERROR,error:a})]:[v.fromValues({action:v.Action.DISCONNECTED,error:a})]}function b(a,b,c){this.timeoutOnIdle=!0; +c.format=void 0;c.heartbeats=!0;Q.call(this,a,b,c);this.stream="stream"in c?c.stream:!0;this.pendingItems=this.pendingCallback=this.recvRequest=this.sendRequest=null;this.disposed=!1}g.inherits(b,Q);b.REQ_SEND=0;b.REQ_RECV=1;b.REQ_RECV_POLL=2;b.REQ_RECV_STREAM=3;b.prototype.connect=function(){c.logAction(c.LOG_MINOR,"CometTransport.connect()","starting");Q.prototype.connect.call(this);var a=this,b=this.params,l=b.options,f=r.getHost(l,b.host),b=r.getPort(l);this.baseUri=(l.tls?"https://":"http://")+ f+":"+b+"/comet/";var m=this.baseUri+"connect";c.logAction(c.LOG_MINOR,"CometTransport.connect()","uri: "+m);this.auth.getAuthParams(function(b,e){if(b)a.disconnect(b);else{a.authParams=e;var h=a.params.getConnectParams(e);"stream"in h&&(a.stream=h.stream);c.logAction(c.LOG_MINOR,"CometTransport.connect()","connectParams:"+g.toQueryString(h));var l=!1,h=a.recvRequest=a.createRequest(m,null,h,null,a.stream?3:1);h.on("data",function(b){a.recvRequest&&(l||(l=!0,a.emit("preconnect")),a.onData(b))});h.on("complete", function(b,c,e){d(e,f,a.connectionManager);a.recvRequest||(b=b||new q("Request cancelled",8E4,400));a.recvRequest=null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(k(b));else a.disconnect(b);else g.nextTick(function(){a.recv()})});h.exec()}})};b.prototype.requestClose=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestClose()");this._requestCloseOrDisconnect(!0)};b.prototype.requestDisconnect=function(){c.logAction(c.LOG_MINOR,"CometTransport.requestDisconnect()");this._requestCloseOrDisconnect(!1)}; b.prototype._requestCloseOrDisconnect=function(a){var b=a?this.closeUri:this.disconnectUri;if(b){var d=this,b=this.createRequest(b,null,this.authParams,null,0);b.on("complete",function(b){b&&(c.logAction(c.LOG_ERROR,"CometTransport.request"+(a?"Close()":"Disconnect()"),"request returned err = "+b),d.finish("disconnected",b))});b.exec()}};b.prototype.dispose=function(){c.logAction(c.LOG_MINOR,"CometTransport.dispose()","");if(!this.disposed){this.disposed=!0;this.recvRequest&&(c.logAction(c.LOG_MINOR, -"CometTransport.dispose()","aborting recv request"),this.recvRequest.abort(),this.recvRequest=null);this.finish("disconnected",I.disconnected);var a=this;g.nextTick(function(){a.emit("disposed")})}};b.prototype.onConnect=function(a){if(!this.disposed){var b=a.connectionKey;P.prototype.onConnect.call(this,a);b=this.baseUri+b;c.logAction(c.LOG_MICRO,"CometTransport.onConnect()","baseUri = "+b+"; connectionKey = "+a.connectionKey);this.sendUri=b+"/send";this.recvUri=b+"/recv";this.closeUri=b+"/close"; +"CometTransport.dispose()","aborting recv request"),this.recvRequest.abort(),this.recvRequest=null);this.finish("disconnected",K.disconnected);var a=this;g.nextTick(function(){a.emit("disposed")})}};b.prototype.onConnect=function(a){if(!this.disposed){var b=a.connectionKey;Q.prototype.onConnect.call(this,a);b=this.baseUri+b;c.logAction(c.LOG_MICRO,"CometTransport.onConnect()","baseUri = "+b+"; connectionKey = "+a.connectionKey);this.sendUri=b+"/send";this.recvUri=b+"/recv";this.closeUri=b+"/close"; this.disconnectUri=b+"/disconnect"}};b.prototype.send=function(a){if(this.sendRequest)this.pendingItems=this.pendingItems||[],this.pendingItems.push(a);else{var b=this.pendingItems||[];b.push(a);this.pendingItems=null;this.sendItems(b)}};b.prototype.sendAnyPending=function(){var a=this.pendingItems;a&&(this.pendingItems=null,this.sendItems(a))};b.prototype.sendItems=function(a){var b=this;a=this.sendRequest=b.createRequest(b.sendUri,null,b.authParams,this.encodeRequest(a),0);a.on("complete",function(a, f){a&&c.logAction(c.LOG_ERROR,"CometTransport.sendItems()","on complete: err = "+JSON.stringify(a));b.sendRequest=null;if(f)b.onData(f);else if(a&&a.code)b.onData(k(a));else b.disconnect(a);b.pendingItems&&g.nextTick(function(){b.sendRequest||b.sendAnyPending()})});a.exec()};b.prototype.recv=function(){if(!this.recvRequest&&this.isConnected){var a=this,b=this.recvRequest=this.createRequest(this.recvUri,null,this.authParams,null,a.stream?3:2);b.on("data",function(b){a.onData(b)});b.on("complete",function(b){a.recvRequest= -null;this.timeoutOnIdle&&this.resetIdleTimeout();if(b)if(b.code)a.onData(k(b));else a.disconnect(b);else g.nextTick(function(){a.recv()})});b.exec()}};b.prototype.onData=function(a){try{var b=this.decodeResponse(a);if(b&&b.length)for(a=0;ag||300<=g?(c=c&&c.error,c||(c=Error(String(res)),c.statusCode=g),a(c)):a(null,c,d,!0,g))}}}function a(a){var b=[];if(a)for(var c in a)b.push(c+"="+a[c]);return b.join("&")}function e(b,e,d,n){return function(h,l,k,g,q){h?c.logAction(c.LOG_MICRO,"Resource."+e+"()","Received Error; "+(d+(n?"?":"")+a(n))+"; Error: "+JSON.stringify(h)):c.logAction(c.LOG_MICRO, -"Resource."+e+"()","Received; "+(d+(n?"?":"")+a(n))+"; Headers: "+a(k)+"; StatusCode: "+q+"; Body: "+(s.isBuffer(l)?l.toString():l));b&&b(h,l,k,g,q)}}var l=x.msgpack;d.get=function(f,d,p,n,h,l){function g(b,e){c.shouldLog(c.LOG_MICRO)&&c.logAction(c.LOG_MICRO,"Resource.get()","Sending; "+(d+(e?"?":"")+a(e)));y.get(f,d,b,e,function(a,b,c,e,d){a&&M.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?l(a):k(f,p,n,l,g)}):l(a,b,c,e,d)})}c.shouldLog(c.LOG_MICRO)&&(l=e(l,"get",d,n));h&&(l=l&&b(l,h),(n= -n||{}).envelope=h);k(f,p,n,l,g)};d.post=function(f,d,p,n,h,g,w){function q(b,e){if(c.shouldLog(c.LOG_MICRO)){var g=p;if(0<(b["content-type"]||"").indexOf("msgpack"))try{p=l.decode(p)}catch(u){c.logAction(c.LOG_MICRO,"Resource.post()","Sending MsgPack Decoding Error: "+JSON.stringify(u))}c.logAction(c.LOG_MICRO,"Resource.post()","Sending; "+(d+(e?"?":"")+a(e))+"; Body: "+g)}y.post(f,d,b,p,e,function(a,b,c,e,d){a&&M.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?w(a):k(f,n,h,w,q)}):w(a,b,c, -e,d)})}c.shouldLog(c.LOG_MICRO)&&(w=e(w,"post",d,h));g&&(w=b(w,g),h.envelope=g);k(f,n,h,w,q)};return d}(),S=function(){function d(a,b,c,f,d,p){this.rest=a;this.path=b;this.headers=c;this.envelope=f;this.bodyHandler=d;this.useHttpPaginatedResponse=p||!1}function k(a,b,c){this.resource=a;this.items=b;if(c){var f=this;"first"in c&&(this.first=function(a){f.get(c.first,a)});"current"in c&&(this.current=function(a){f.get(c.current,a)});this.next=function(a){"next"in c?f.get(c.next,a):a(null,null)};this.hasNext= -function(){return"next"in c};this.isLast=function(){return!this.hasNext()}}}function b(a,b,c,f,d){k.call(this,a,b,d);this.statusCode=f;this.success=300>f&&200<=f;this.headers=c}d.prototype.get=function(a,b){var c=this;U.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,h){c.handlePage(a,d,p,n,h,b)})};d.prototype.post=function(a,b,c){var f=this;U.post(f.rest,f.path,b,f.headers,a,f.envelope,function(a,b,e,d,g){c&&f.handlePage(a,b,e,d,g,c)})};d.prototype.handlePage=function(a,e,d,f,m,p){if(a)c.logAction(c.LOG_ERROR, -"PaginatedResource.handlePage()","Unexpected error getting resource: err = "+JSON.stringify(a)),p(a);else{var n,h,u;try{n=this.bodyHandler(e,d,f)}catch(w){p(w);return}if(d&&(h=d.Link||d.link)){a=h;"string"==typeof a&&(a=a.split(","));e={};for(f=0;f;\s*rel="(\w+)"$/))&&(u=(u=h[1].match(/^\.\/(\w+)\?(.*)$/))&&g.parseQueryString(u[2]))&&(e[h[2]]=u);u=e}this.useHttpPaginatedResponse?p(null,new b(this,n,d,m,u)):p(null,new k(this,n,u))}};k.prototype.get=function(a, -b){var c=this.resource;U.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,p,n,h){c.handlePage(a,d,p,n,h,b)})};g.inherits(b,k);return d}(),M=function(){function d(){}function k(a){if(!a)return"";"string"==typeof a&&(a=JSON.parse(a));var b={},c=g.keysArray(a,!0);if(!c)return"";c.sort();for(var e=0;eg||300<=g?(c=c&&c.error,c||(c=Error(String(res)),c.statusCode=g),a(c)):a(null,c,d,!0,g))}}}function a(a){var b=[];if(a)for(var c in a)b.push(c+"="+a[c]);return b.join("&")}function e(b,e,d,l){return function(h,k,g,q,F){h?c.logAction(c.LOG_MICRO,"Resource."+e+"()","Received Error; "+(d+(l?"?":"")+a(l))+"; Error: "+JSON.stringify(h)):c.logAction(c.LOG_MICRO, +"Resource."+e+"()","Received; "+(d+(l?"?":"")+a(l))+"; Headers: "+a(g)+"; StatusCode: "+F+"; Body: "+(t.isBuffer(k)?k.toString():k));b&&b(h,k,g,q,F)}}var l=z.msgpack;d.get=function(f,d,n,l,h,g){function w(b,e){c.shouldLog(c.LOG_MICRO)&&c.logAction(c.LOG_MICRO,"Resource.get()","Sending; "+(d+(e?"?":"")+a(e)));y.get(f,d,b,e,function(a,b,c,e,d){a&&N.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?g(a):k(f,n,l,g,w)}):g(a,b,c,e,d)})}c.shouldLog(c.LOG_MICRO)&&(g=e(g,"get",d,l));h&&(g=g&&b(g,h),(l= +l||{}).envelope=h);k(f,n,l,g,w)};d.post=function(f,d,n,p,h,g,w){function q(b,e){if(c.shouldLog(c.LOG_MICRO)){var g=n;if(0<(b["content-type"]||"").indexOf("msgpack"))try{n=l.decode(n)}catch(u){c.logAction(c.LOG_MICRO,"Resource.post()","Sending MsgPack Decoding Error: "+JSON.stringify(u))}c.logAction(c.LOG_MICRO,"Resource.post()","Sending; "+(d+(e?"?":"")+a(e))+"; Body: "+g)}y.post(f,d,b,n,e,function(a,b,c,e,d){a&&N.isTokenErr(a)?f.auth.authorize(null,null,function(a){a?w(a):k(f,p,h,w,q)}):w(a,b,c, +e,d)})}c.shouldLog(c.LOG_MICRO)&&(w=e(w,"post",d,h));g&&(w=b(w,g),h.envelope=g);k(f,p,h,w,q)};return d}(),S=function(){function d(a,b,c,f,d,n){this.rest=a;this.path=b;this.headers=c;this.envelope=f;this.bodyHandler=d;this.useHttpPaginatedResponse=n||!1}function k(a,b,c){this.resource=a;this.items=b;if(c){var f=this;"first"in c&&(this.first=function(a){f.get(c.first,a)});"current"in c&&(this.current=function(a){f.get(c.current,a)});this.next=function(a){"next"in c?f.get(c.next,a):a(null,null)};this.hasNext= +function(){return"next"in c};this.isLast=function(){return!this.hasNext()}}}function b(a,b,c,f,d){k.call(this,a,b,d);this.statusCode=f;this.success=300>f&&200<=f;this.headers=c}d.prototype.get=function(a,b){var c=this;U.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,n,p,h){c.handlePage(a,d,n,p,h,b)})};d.prototype.post=function(a,b,c){var f=this;U.post(f.rest,f.path,b,f.headers,a,f.envelope,function(a,b,e,d,g){c&&f.handlePage(a,b,e,d,g,c)})};d.prototype.handlePage=function(a,e,d,f,m,n){if(a)c.logAction(c.LOG_ERROR, +"PaginatedResource.handlePage()","Unexpected error getting resource: err = "+JSON.stringify(a)),n(a);else{var p,h,u;try{p=this.bodyHandler(e,d,f)}catch(w){n(w);return}if(d&&(h=d.Link||d.link)){a=h;"string"==typeof a&&(a=a.split(","));e={};for(f=0;f;\s*rel="(\w+)"$/))&&(u=(u=h[1].match(/^\.\/(\w+)\?(.*)$/))&&g.parseQueryString(u[2]))&&(e[h[2]]=u);u=e}this.useHttpPaginatedResponse?n(null,new b(this,p,d,m,u)):n(null,new k(this,p,u))}};k.prototype.get=function(a, +b){var c=this.resource;U.get(c.rest,c.path,c.headers,a,c.envelope,function(a,d,n,p,h){c.handlePage(a,d,n,p,h,b)})};g.inherits(b,k);return d}(),N=function(){function d(){}function k(a){if(!a)return"";"string"==typeof a&&(a=JSON.parse(a));var b={},c=g.keysArray(a,!0);if(!c)return"";c.sort();for(var e=0;el){e(new q("authUrl response exceeded max permitted length", +e);else e(null,b)})};a.prototype.authorise=function(){c.deprecated("Auth.authorise","Auth.authorize");this.authorize.apply(this,arguments)};a.prototype._forceNewToken=function(a,c,e){var f=this;this.tokenDetails=null;this._saveTokenOptions(a,c);b(this.authOptions);this._ensureValidAuthCredentials(function(a,b){delete f.tokenParams.timestamp;delete f.authOptions.queryTime;e(a,b)})};a.prototype.requestToken=function(a,b,f){"function"!=typeof a||f?"function"!=typeof b||f||(f=b,b=null):(f=a,b=a=null); +b=b||this.authOptions;a=a||g.copy(this.tokenParams);f=f||d;var m=b.format||"json",w,r=this.client;if(b.authCallback)c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with authCallback"),w=b.authCallback;else if(b.authUrl)c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with authUrl"),b.authParams||(w=b.authUrl.indexOf("?"),-1l){e(new q("authUrl response exceeded max permitted length", 40170,401));return}try{b=JSON.parse(b)}catch(h){e(new q("Unexpected error processing authURL response; err = "+h.message,40170,401));return}}e(null,b)}else e(new q("authUrl responded with unacceptable content-type "+a+", should be either text/plain or application/json",40170,401));else e(new q("authUrl response is missing a content-type header",40170,401))};c.logAction(c.LOG_MICRO,"Auth.requestToken().tokenRequestCallback","Sending; "+b.authUrl+"; Params: "+JSON.stringify(d));b.authMethod&&"post"=== -b.authMethod.toLowerCase()?(f=f||{},f["content-type"]="application/x-www-form-urlencoded",d=g.toQueryString(d).slice(1),y.postUri(Q,b.authUrl,f,d,{},h)):y.getUri(Q,b.authUrl,f||{},d,h)};else if(b.key){var r=this;c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with client-side signing");w=function(a,c){r.createTokenRequest(a,b,c)}}else{c.logAction(c.LOG_ERROR,"Auth.requestToken()","Need a new token, but authOptions does not include any way to request one");f(new q("Need a new token, but authOptions does not include any way to request one", -40101,401));return}"capability"in a&&(a.capability=k(a.capability));var Q=this.client,C=function(a,f){var d,h=a.keyName,p=function(a){return Q.baseUri(a)+"/keys/"+h+"/requestToken"};y.post?(d=g.defaultPostHeaders(m),b.requestHeaders&&g.mixin(d,b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending POST; "+p+"; Token params: "+JSON.stringify(a)),a="msgpack"==m?e.encode(a,!0):JSON.stringify(a),y.post(Q,p,d,a,null,f)):(d=g.defaultGetHeaders(),b.requestHeaders&&g.mixin(d, -b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending GET; "+p+"; Token params: "+JSON.stringify(a)),y.get(Q,p,d,a,f))},t=!1,v=this.client.options.timeouts.realtimeRequestTimeout,x=setTimeout(function(){t=!0;var a="Token request callback timed out after "+v/1E3+" seconds";c.logAction(c.LOG_ERROR,"Auth.requestToken()",a);f(new q(a,40170,401))},v);w(a,function(a,b){if(!t)if(clearTimeout(x),a)c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request signing call returned error; err = "+ +b.authMethod.toLowerCase()?(f=f||{},f["content-type"]="application/x-www-form-urlencoded",d=g.toQueryString(d).slice(1),y.postUri(r,b.authUrl,f,d,{},h)):y.getUri(r,b.authUrl,f||{},d,h)};else if(b.key){var F=this;c.logAction(c.LOG_MINOR,"Auth.requestToken()","using token auth with client-side signing");w=function(a,c){F.createTokenRequest(a,b,c)}}else{c.logAction(c.LOG_ERROR,"Auth.requestToken()","Need a new token, but authOptions does not include any way to request one");f(new q("Need a new token, but authOptions does not include any way to request one", +40101,401));return}"capability"in a&&(a.capability=k(a.capability));var r=this.client,D=function(a,f){var d,h=a.keyName,n=function(a){return r.baseUri(a)+"/keys/"+h+"/requestToken"};y.post?(d=g.defaultPostHeaders(m),b.requestHeaders&&g.mixin(d,b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending POST; "+n+"; Token params: "+JSON.stringify(a)),a="msgpack"==m?e.encode(a,!0):JSON.stringify(a),y.post(r,n,d,a,null,f)):(d=g.defaultGetHeaders(),b.requestHeaders&&g.mixin(d, +b.requestHeaders),c.logAction(c.LOG_MICRO,"Auth.requestToken().requestToken","Sending GET; "+n+"; Token params: "+JSON.stringify(a)),y.get(r,n,d,a,f))},v=!1,x=this.client.options.timeouts.realtimeRequestTimeout,z=setTimeout(function(){v=!0;var a="Token request callback timed out after "+x/1E3+" seconds";c.logAction(c.LOG_ERROR,"Auth.requestToken()",a);f(new q(a,40170,401))},x);w(a,function(a,b){if(!v)if(clearTimeout(z),a)c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request signing call returned error; err = "+ g.inspectError(a)),a&&a.code||(a=new q(g.inspectError(a),40170,401)),f(a);else if("string"===typeof b)384l?f(new q("Token request/details object exceeded max permitted stringified size (was "+ -d+" bytes)",40170,401)):"issued"in b?f(null,b):"keyName"in b?C(b,function(a,b,d,p){a?(c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request API call returned error; err = "+g.inspectError(a)),f(a)):(p||(b="msgpack"==m?e.decode(b):JSON.parse(b)),c.logAction(c.LOG_MINOR,"Auth.getToken()","token received"),f(null,b))}):(d="Expected token request callback to call back with a token string, token request object, or token details object",c.logAction(c.LOG_ERROR,"Auth.requestToken()",d),f(new q(d, -40170,401)))})};a.prototype.createTokenRequest=function(a,b,e){"function"!=typeof a||e?"function"!=typeof b||e||(e=b,b=null):(e=a,b=a=null);b=b||this.authOptions;a=a||g.copy(this.tokenParams);var d=b.key;if(d){var d=d.split(":"),l=d[0],m=d[1];if(m)if(""===a.clientId)e(new q("clientId can\u2019t be an empty string",40012,400));else{a.capability=k(a.capability);var r=g.mixin({keyName:l},a),C=a.clientId||"",t=a.ttl||"",v=a.capability,x=this;(function(a){r.timestamp?a():x.getTimestamp(b&&b.queryTime, -function(b,c){b?e(b):(r.timestamp=c,a())})})(function(){var a=r.nonce||(r.nonce=("000000"+Math.floor(1E16*Math.random())).slice(-16)),a=r.keyName+"\n"+t+"\n"+v+"\n"+C+"\n"+r.timestamp+"\n"+a+"\n";r.mac=r.mac||f(a,m);c.logAction(c.LOG_MINOR,"Auth.getTokenRequest()","generated signed request");e(null,r)})}else e(Error("Invalid key specified"))}else e(Error("No key specified"))};a.prototype.getAuthParams=function(a){"basic"==this.method?a(null,{key:this.key}):this._ensureValidAuthCredentials(function(b, +d+" bytes)",40170,401)):"issued"in b?f(null,b):"keyName"in b?D(b,function(a,b,d,n){a?(c.logAction(c.LOG_ERROR,"Auth.requestToken()","token request API call returned error; err = "+g.inspectError(a)),f(a)):(n||(b="msgpack"==m?e.decode(b):JSON.parse(b)),c.logAction(c.LOG_MINOR,"Auth.getToken()","token received"),f(null,b))}):(d="Expected token request callback to call back with a token string, token request object, or token details object",c.logAction(c.LOG_ERROR,"Auth.requestToken()",d),f(new q(d, +40170,401)))})};a.prototype.createTokenRequest=function(a,b,e){"function"!=typeof a||e?"function"!=typeof b||e||(e=b,b=null):(e=a,b=a=null);b=b||this.authOptions;a=a||g.copy(this.tokenParams);var d=b.key;if(d){var d=d.split(":"),l=d[0],m=d[1];if(m)if(""===a.clientId)e(new q("clientId can\u2019t be an empty string",40012,400));else{a.capability=k(a.capability);var r=g.mixin({keyName:l},a),D=a.clientId||"",v=a.ttl||"",x=a.capability,y=this;(function(a){r.timestamp?a():y.getTimestamp(b&&b.queryTime, +function(b,c){b?e(b):(r.timestamp=c,a())})})(function(){var a=r.nonce||(r.nonce=("000000"+Math.floor(1E16*Math.random())).slice(-16)),a=r.keyName+"\n"+v+"\n"+x+"\n"+D+"\n"+r.timestamp+"\n"+a+"\n";r.mac=r.mac||f(a,m);c.logAction(c.LOG_MINOR,"Auth.getTokenRequest()","generated signed request");e(null,r)})}else e(Error("Invalid key specified"))}else e(Error("No key specified"))};a.prototype.getAuthParams=function(a){"basic"==this.method?a(null,{key:this.key}):this._ensureValidAuthCredentials(function(b, c){b?a(b):a(null,{access_token:c.token})})};a.prototype.getAuthHeaders=function(a){"basic"==this.method?a(null,{authorization:"Basic "+this.basicKey}):this._ensureValidAuthCredentials(function(b,c){b?a(b):a(null,{authorization:"Bearer "+m(c.token)})})};a.prototype.getTimestamp=function(a,b){isNaN(parseInt(this.client.serverTimeOffset))&&(a||this.authOptions.queryTime)?this.client.time(function(a,c){a?b(a):b(null,c)}):b(null,g.now()+(this.client.serverTimeOffset||0))};a.prototype._saveBasicOptions= function(a){this.method="basic";this.key=a.key;this.basicKey=m(a.key);this.authOptions=a||{};"clientId"in a&&this._userSetClientId(a.clientId)};a.prototype._saveTokenOptions=function(a,b){this.method="token";a&&(this.tokenParams=a);b&&(b.token&&(b.tokenDetails="string"===typeof b.token?{token:b.token}:b.token),b.tokenDetails&&(this.tokenDetails=b.tokenDetails),"clientId"in b&&this._userSetClientId(b.clientId),this.authOptions=b)};a.prototype._ensureValidAuthCredentials=function(a){var b=this,e=this.tokenDetails, -d=function(){b.requestToken(b.tokenParams,b.authOptions,function(c,e){c?a(c):a(null,b.tokenDetails=e)})};e?this._tokenClientIdMismatch(e.clientId)?a(new q("Mismatch between clientId in token ("+e.clientId+") and current clientId ("+this.clientId+")",40102,401)):this.getTimestamp(b.authOptions&&b.authOptions.queryTime,function(f,l){f&&a(f);void 0===e.expires||e.expires>=l?(c.logAction(c.LOG_MINOR,"Auth.getToken()","using cached token; expires = "+e.expires),a(null,e)):(c.logAction(c.LOG_MINOR,"Auth.getToken()", -"deleting expired token"),b.tokenDetails=null,d())}):d()};a.prototype._userSetClientId=function(a){if("string"!==typeof a&&null!==a)throw new q("clientId must be either a string or null",40012,400);if("*"===a)throw new q('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, instantiate the library with {defaultTokenParams: {clientId: "*"}}), or if calling authorize(), pass it in as a tokenParam: authorize({clientId: "*"}, authOptions)', +f=function(){b.requestToken(b.tokenParams,b.authOptions,function(c,e){c?a(c):a(null,b.tokenDetails=e)})};e?this._tokenClientIdMismatch(e.clientId)?a(new q("Mismatch between clientId in token ("+e.clientId+") and current clientId ("+this.clientId+")",40102,401)):this.getTimestamp(b.authOptions&&b.authOptions.queryTime,function(d,l){d&&a(d);void 0===e.expires||e.expires>=l?(c.logAction(c.LOG_MINOR,"Auth.getToken()","using cached token; expires = "+e.expires),a(null,e)):(c.logAction(c.LOG_MINOR,"Auth.getToken()", +"deleting expired token"),b.tokenDetails=null,f())}):f()};a.prototype._userSetClientId=function(a){if("string"!==typeof a&&null!==a)throw new q("clientId must be either a string or null",40012,400);if("*"===a)throw new q('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, instantiate the library with {defaultTokenParams: {clientId: "*"}}), or if calling authorize(), pass it in as a tokenParam: authorize({clientId: "*"}, authOptions)', 40012,400);if(a=this._uncheckedSetClientId(a))throw a;};a.prototype._uncheckedSetClientId=function(a){if(this._tokenClientIdMismatch(a)){a="Unexpected clientId mismatch: client has "+this.clientId+", requested "+a;var b=new q(a,40102,401);c.logAction(c.LOG_ERROR,"Auth._uncheckedSetClientId()",a);return b}if("*"===a)this.tokenParams.clientId=a;else return this.clientId=this.tokenParams.clientId=a,null};a.prototype._tokenClientIdMismatch=function(a){return this.clientId&&a&&"*"!==a&&this.clientId!== -a};a.isTokenErr=function(a){return a.code&&40140<=a.code&&40150>a.code};return a}(),F=function(){function d(a){if(!(this instanceof d))return new d(a);if(!a){var b="no options provided";c.logAction(c.LOG_ERROR,"Rest()",b);throw Error(b);}"string"==typeof a&&(a=-1==a.indexOf(":")?{token:a}:{key:a});this.options=r.normaliseOptions(a);if(a.key){b=a.key.match(/^([^:\s]+):([^:.\s]+)$/);if(!b)throw b="invalid key parameter",c.logAction(c.LOG_ERROR,"Rest()",b),Error(b);a.keyName=b[1];a.keySecret=b[2]}if("clientId"in +a};a.isTokenErr=function(a){return a.code&&40140<=a.code&&40150>a.code};return a}(),H=function(){function d(a){if(!(this instanceof d))return new d(a);if(!a){var b="no options provided";c.logAction(c.LOG_ERROR,"Rest()",b);throw Error(b);}"string"==typeof a&&(a=-1==a.indexOf(":")?{token:a}:{key:a});this.options=r.normaliseOptions(a);if(a.key){b=a.key.match(/^([^:\s]+):([^:.\s]+)$/);if(!b)throw b="invalid key parameter",c.logAction(c.LOG_ERROR,"Rest()",b),Error(b);a.keyName=b[1];a.keySecret=b[2]}if("clientId"in a){if("string"!==typeof a.clientId&&null!==a.clientId)throw new q("clientId must be either a string or null",40012,400);if("*"===a.clientId)throw new q('Can\u2019t use "*" as a clientId as that string is reserved. (To change the default token request behaviour to use a wildcard clientId, use {defaultTokenParams: {clientId: "*"}})',40012,400);}a.log&&c.setLog(a.log.level,a.log.handler);c.logAction(c.LOG_MINOR,"Rest()","started");this.baseUri=this.authority=function(b){return r.getHttpScheme(a)+b+":"+ -r.getPort(a,!1)};this.serverTimeOffset=null;this.auth=new M(this,a);this.channels=new k(this)}function k(a){this.rest=a;this.attached={}}var b=function(){};d.prototype.stats=function(a,c){void 0===c&&("function"==typeof a?(c=a,a=null):c=b);var d=g.copy(g.defaultGetHeaders()),f=y.supportsLinkHeaders?void 0:"json";this.options.headers&&g.mixin(d,this.options.headers);(new S(this,"/stats",d,f,function(a,b,c){a=c?a:JSON.parse(a);for(b=0;bb.timestamp;var c=a.parseId(), -d=b.parseId();return c.msgSerial===d.msgSerial?c.index>d.index:c.msgSerial>d.msgSerial}var l=function(){};g.inherits(b,T);b.prototype.enter=function(a,b){if(d(this))throw new q("clientId must be specified to enter a presence channel",40012,400);this._enterOrUpdateClient(void 0,a,b,"enter")};b.prototype.update=function(a,b){if(d(this))throw new q("clientId must be specified to update presence data",40012,400);this._enterOrUpdateClient(void 0,a,b,"update")};b.prototype.enterClient=function(a,b,c){this._enterOrUpdateClient(a, -b,c,"enter")};b.prototype.updateClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"update")};b.prototype._enterOrUpdateClient=function(a,b,d,e){d||("function"===typeof b?(d=b,b=null):d=l);var h=this.channel;if(h.connectionManager.activeState()){c.logAction(c.LOG_MICRO,"RealtimePresence."+e+"Client()",e+"ing; channel = "+h.name+", client = "+a||"(implicit) "+this.channel.realtime.auth.clientId);var g=B.fromValues({action:e,data:b});a&&(g.clientId=a);var k=this;B.encode(g,h.channelOptions,function(a){if(a)d(a); -else switch(h.state){case "attached":h.sendPresence(g,d);break;case "initialized":case "detached":h.autonomousAttach();case "attaching":k.pendingPresence.push({presence:g,callback:d});break;default:a=new q("Unable to "+e+" presence channel (incompatible state)",90001),a.code=90001,d(a)}})}else d(h.connectionManager.getStateError())};b.prototype.leave=function(a,b){if(d(this))throw new q("clientId must have been specified to enter or leave a presence channel",40012,400);this.leaveClient(void 0,a,b)}; -b.prototype.leaveClient=function(a,b,d){d||("function"===typeof b?(d=b,b=null):d=l);var e=this.channel;if(e.connectionManager.activeState())switch(c.logAction(c.LOG_MICRO,"RealtimePresence.leaveClient()","leaving; channel = "+this.channel.name+", client = "+a),b=B.fromValues({action:"leave",data:b}),a&&(b.clientId=a),e.state){case "attached":e.sendPresence(b,d);break;case "attaching":this.pendingPresence.push({presence:b,callback:d});break;case "initialized":case "failed":a=new q("Unable to leave presence channel (incompatible state)", -90001);d(a);break;default:d(I.failed)}else d(e.connectionManager.getStateError())};b.prototype.get=function(){function a(b){d(null,c?b.list(c):b.values())}var b=Array.prototype.slice.call(arguments);1==b.length&&"function"==typeof b[0]&&b.unshift(null);var c=b[0],d=b[1]||l,e=!c||("waitForSync"in c?c.waitForSync:!0);if("suspended"===this.channel.state)e?d(q.fromValues({statusCode:400,code:91005,message:"Presence state is out of sync due to channel being in the SUSPENDED state"})):a(this.members);else{var g= -this;k(this.channel,d,function(){var b=g.members;e?b.waitSync(function(){a(b)}):a(b)})}};b.prototype.history=function(a,b){c.logAction(c.LOG_MICRO,"RealtimePresence.history()","channel = "+this.name);void 0===b&&("function"==typeof a?(b=a,a=null):b=l);a&&a.untilAttach&&("attached"===this.channel.state?(delete a.untilAttach,a.from_serial=this.channel.attachSerial):b(new q("option untilAttach requires the channel to be attached, was: "+this.channel.state,4E4,400)));T.prototype._history.call(this,a, -b)};b.prototype.setPresence=function(a,b,d){c.logAction(c.LOG_MICRO,"RealtimePresence.setPresence()","received presence for "+a.length+" participants; syncChannelSerial = "+d);var e,h,g=this.members,k=this._myMembers,l=[],q=this.channel.connectionManager.connectionId;b&&(this.members.startSync(),d&&(h=d.match(/^[\w\-]+:(.*)$/))&&(e=h[1]));for(d=0;db.timestamp;var c=a.parseId(),d=b.parseId();return c.msgSerial===d.msgSerial?c.index>d.index:c.msgSerial>d.msgSerial}var l=function(){};g.inherits(b,T);b.prototype.enter=function(a,b){if(d(this))throw new q("clientId must be specified to enter a presence channel",40012,400);this._enterOrUpdateClient(void 0,a,b,"enter")};b.prototype.update=function(a,b){if(d(this))throw new q("clientId must be specified to update presence data", +40012,400);this._enterOrUpdateClient(void 0,a,b,"update")};b.prototype.enterClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"enter")};b.prototype.updateClient=function(a,b,c){this._enterOrUpdateClient(a,b,c,"update")};b.prototype._enterOrUpdateClient=function(a,b,d,e){d||("function"===typeof b?(d=b,b=null):d=l);var h=this.channel;if(h.connectionManager.activeState()){c.logAction(c.LOG_MICRO,"RealtimePresence."+e+"Client()",e+"ing; channel = "+h.name+", client = "+a||"(implicit) "+this.channel.realtime.auth.clientId); +var g=C.fromValues({action:e,data:b});a&&(g.clientId=a);var k=this;C.encode(g,h.channelOptions,function(a){if(a)d(a);else switch(h.state){case "attached":h.sendPresence(g,d);break;case "initialized":case "detached":h.autonomousAttach();case "attaching":k.pendingPresence.push({presence:g,callback:d});break;default:a=new q("Unable to "+e+" presence channel (incompatible state)",90001),a.code=90001,d(a)}})}else d(h.connectionManager.getStateError())};b.prototype.leave=function(a,b){if(d(this))throw new q("clientId must have been specified to enter or leave a presence channel", +40012,400);this.leaveClient(void 0,a,b)};b.prototype.leaveClient=function(a,b,d){d||("function"===typeof b?(d=b,b=null):d=l);var e=this.channel;if(e.connectionManager.activeState())switch(c.logAction(c.LOG_MICRO,"RealtimePresence.leaveClient()","leaving; channel = "+this.channel.name+", client = "+a),b=C.fromValues({action:"leave",data:b}),a&&(b.clientId=a),e.state){case "attached":e.sendPresence(b,d);break;case "attaching":this.pendingPresence.push({presence:b,callback:d});break;case "initialized":case "failed":a= +new q("Unable to leave presence channel (incompatible state)",90001);d(a);break;default:d(K.failed)}else d(e.connectionManager.getStateError())};b.prototype.get=function(){function a(b){d(null,c?b.list(c):b.values())}var b=Array.prototype.slice.call(arguments);1==b.length&&"function"==typeof b[0]&&b.unshift(null);var c=b[0],d=b[1]||l,e=!c||("waitForSync"in c?c.waitForSync:!0);if("suspended"===this.channel.state)e?d(q.fromValues({statusCode:400,code:91005,message:"Presence state is out of sync due to channel being in the SUSPENDED state"})): +a(this.members);else{var g=this;k(this.channel,d,function(){var b=g.members;e?b.waitSync(function(){a(b)}):a(b)})}};b.prototype.history=function(a,b){c.logAction(c.LOG_MICRO,"RealtimePresence.history()","channel = "+this.name);void 0===b&&("function"==typeof a?(b=a,a=null):b=l);a&&a.untilAttach&&("attached"===this.channel.state?(delete a.untilAttach,a.from_serial=this.channel.attachSerial):b(new q("option untilAttach requires the channel to be attached, was: "+this.channel.state,4E4,400)));T.prototype._history.call(this, +a,b)};b.prototype.setPresence=function(a,b,d){c.logAction(c.LOG_MICRO,"RealtimePresence.setPresence()","received presence for "+a.length+" participants; syncChannelSerial = "+d);var e,h,g=this.members,k=this._myMembers,l=[],q=this.channel.connectionManager.connectionId;b&&(this.members.startSync(),d&&(h=d.match(/^[\w\-]+:(.*)$/))&&(e=h[1]));for(d=0;dc)&&0!==m.status){if(void 0===z)if(z=m.status,1223===z&&(z=204),clearTimeout(e),A=400>z,204==z)d.complete(null,null,null,null,z);else{var f;if(f=3==d.requestMode&&A)f=m,f=f.getResponseHeader&&f.getResponseHeader("transfer-encoding")&&!f.getResponseHeader("content-length");y=f}if(3==c&&y)a();else if(4==c)if(y)b();else a:{try{var k=m.getResponseHeader&&m.getResponseHeader("content-type"),l,r=k?"application/json"==k:"text"==m.responseType;s=r?m.responseText:m.response;r&&(s=String(s), -s.length&&(s=JSON.parse(s)),D=!0);if(void 0!==s.response)z=s.statusCode,A=400>z,l=s.headers,s=s.response;else{for(var w=g.trim(m.getAllResponseHeaders()).split("\r\n"),c={},k=0;ka.statusCode||g.isArray(b)?l.complete(null,b,a.headers,a.statusCode):(a=b.error||new q("Error response received from server",null,a.statusCode),l.complete(a)):l.complete(new q("Invalid server response: no envelope detected",null,500))}else l.complete(null,a)};this.timer=setTimeout(function(){l.abort()},this.requestMode==J.REQ_SEND?this.timeouts.httpRequestTimeout:this.timeouts.recvTimeout);f.insertBefore(d,f.firstChild)};k.prototype.complete=function(a, -b,c,d){c=c||{};this.requestComplete||(this.requestComplete=!0,b&&(c["content-type"]="string"==typeof b?"text/plain":"application/json",this.emit("data",b)),this.emit("complete",a,b,c,!0,d),this.dispose())};k.prototype.abort=function(){this.dispose()};k.prototype.dispose=function(){var b=this.timer;b&&(clearTimeout(b),this.timer=null);b=this.script;b.parentNode&&b.parentNode.removeChild(b);delete a[this.id];this.emit("disposed")};y.Request||(y.Request=function(a,b,c,d,e,f){var k=p(b,c,d,e,J.REQ_SEND, -a&&a.options.timeouts);k.once("complete",f);g.nextTick(function(){k.exec()});return k});return d})();"undefined"!==typeof G&&(X.msgpack=ba,X.Rest=F,X.Realtime=G,G.ConnectionManager=N,G.BufferUtils=F.BufferUtils=s,"undefined"!==typeof Crypto&&(G.Crypto=F.Crypto=Crypto),G.Defaults=F.Defaults=r,G.Http=F.Http=y,G.Utils=F.Utils=g,G.Http=F.Http=y,G.Message=F.Message=A,G.PresenceMessage=F.PresenceMessage=B,G.ProtocolMessage=F.ProtocolMessage=t)}).call({}); +c.logAction(c.LOG_MINOR,"PresenceMap.waitSync()","channel = "+this.presence.channel.name+"; syncInProgress = "+b);if(b)this.once("sync",a);else a()};a.prototype.clear=function(a){this.map={};this.syncInProgress=!1;this.residualMembers=null};return b}(),W=function(){function d(){for(var a in e)e[a].dispose()}function k(b,c,d,k,l,m){x.call(this);d=d||{};d.rnd=g.randStr();var q,r;if(r=f)r=q=(q=navigator.userAgent.toString().match(/MSIE\s([\d.]+)/))&&Number(q[1]);r&&10===q&&!d.envelope&&(d.envelope="json"); +this.uri=b+g.toQueryString(d);this.headers=c||{};this.body=k;this.requestMode=l;this.timeouts=m;this.requestComplete=this.timedOut=!1;e[this.id=String(++a)]=this}var b=function(){},a=0,e={},l=z.xhrSupported,f="undefined"!==typeof window&&window.XDomainRequest;g.inherits(k,x);k.isAvailable=function(){return l};var m=k.createRequest=function(a,b,c,d,e,f){f=this&&this.timeouts||f||r.TIMEOUTS;return new k(a,b,g.copy(c),d,e,f)};k.prototype.complete=function(a,b,c,d,e){this.requestComplete||(this.requestComplete= +!0,b&&this.emit("data",b),this.emit("complete",a,b,c,d,e),this.dispose())};k.prototype.abort=function(){this.dispose()};k.prototype.exec=function(){function a(){t=m.responseText;for(var b=t.length-1,c,e;Cc)&&0!==m.status){if(void 0===A)if(A=m.status,1223===A&&(A=204),clearTimeout(e),B=400>A,204==A)d.complete(null,null,null,null,A);else{var f;if(f=3==d.requestMode&&B)f=m,f=f.getResponseHeader&&f.getResponseHeader("transfer-encoding")&&!f.getResponseHeader("content-length");z=f}if(3==c&&z)a();else if(4==c)if(z)b();else a:{try{var k=m.getResponseHeader&&m.getResponseHeader("content-type"),l,r=k?"application/json"==k:"text"==m.responseType;t=r?m.responseText:m.response;r&&(t=String(t), +t.length&&(t=JSON.parse(t)),E=!0);if(void 0!==t.response)A=t.statusCode,B=400>A,l=t.headers,t=t.response;else{for(var w=g.trim(m.getAllResponseHeaders()).split("\r\n"),c={},k=0;ka.statusCode||g.isArray(b)?l.complete(null,b,a.headers,a.statusCode):(a=b.error||new q("Error response received from server",null,a.statusCode),l.complete(a)):l.complete(new q("Invalid server response: no envelope detected",null,500))}else l.complete(null,a)};this.timer=setTimeout(function(){l.abort()},this.requestMode==L.REQ_SEND?this.timeouts.httpRequestTimeout:this.timeouts.recvTimeout);f.insertBefore(d,f.firstChild)};k.prototype.complete= +function(a,b,c,d){c=c||{};this.requestComplete||(this.requestComplete=!0,b&&(c["content-type"]="string"==typeof b?"text/plain":"application/json",this.emit("data",b)),this.emit("complete",a,b,c,!0,d),this.dispose())};k.prototype.abort=function(){this.dispose()};k.prototype.dispose=function(){var b=this.timer;b&&(clearTimeout(b),this.timer=null);b=this.script;b.parentNode&&b.parentNode.removeChild(b);delete a[this.id];this.emit("disposed")};y.Request||(y.Request=function(a,b,c,d,e,f){var k=n(b,c,d, +e,L.REQ_SEND,a&&a.options.timeouts);k.once("complete",f);g.nextTick(function(){k.exec()});return k},y.checkConnectivity=function(a){var b=r.jsonpInternetUpUrl;if(m)m.push(a);else{m=[a];c.logAction(c.LOG_MICRO,"(JSONP)Http.checkConnectivity()","Sending; "+b);var d=new k("isTheInternetUp",b,null,null,null,L.REQ_SEND,r.TIMEOUTS);d.once("complete",function(a,b){var d=!a&&b;c.logAction(c.LOG_MICRO,"(JSONP)Http.checkConnectivity()","Result: "+d);for(var e=0;e