"); transferDoc.parentWindow.PushStream = PushStream; transferDoc.close(); var ifrDiv = transferDoc.createElement("div"); transferDoc.appendChild(ifrDiv); ifrDiv.innerHTML = ""; this.connection = ifrDiv.getElementsByTagName("IFRAME")[0]; this.connection.onload = linker(onerrorCallback, this); this.transferDoc = transferDoc; } catch (e) { var ifr = document.createElement("IFRAME"); ifr.style.width = "1px"; ifr.style.height = "1px"; ifr.style.border = "none"; ifr.style.position = "absolute"; ifr.style.top = "-10px"; ifr.style.marginTop = "-10px"; ifr.style.zIndex = "-20"; ifr.PushStream = PushStream; document.body.appendChild(ifr); ifr.setAttribute("src", url); ifr.onload = linker(onerrorCallback, this); this.connection = ifr; } this.connection.setAttribute("id", this.iframeId); this.frameloadtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.timeout); }, register: function (iframeWindow) { this.frameloadtimer = clearTimer(this.frameloadtimer); iframeWindow.p = linker(this.process, this); this.connection.onload = linker(this._onframeloaded, this); this.pushstream._onopen(); this.setPingTimer(); Log4js.info("[Stream] frame registered"); }, process: function (id, channel, data, eventid) { this.pingtimer = clearTimer(this.pingtimer); Log4js.info("[Stream] message received", arguments); this.pushstream._onmessage(unescapeText(data), id, channel, eventid, true); this.setPingTimer(); }, _onframeloaded: function () { Log4js.info("[Stream] frame loaded (disconnected by server)"); this.connection.onload = null; this.disconnect(); }, setPingTimer: function () { if (this.pingtimer) { clearTimer(this.pingtimer); } this.pingtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.pingtimeout); } }; var LongPollingWrapper = function (pushstream) { this.type = LongPollingWrapper.TYPE; this.pushstream = pushstream; this.connection = null; this.lastModified = null; this.etag = 0; this.connectionEnabled = false; this.opentimer = null; this.messagesQueue = []; this._linkedInternalListen = linker(this._internalListen, this); this.xhrSettings = { timeout: this.pushstream.longPollingTimeout, data: {}, url: null, success: linker(this.onmessage, this), error: linker(this.onerror, this), load: linker(this.onload, this), beforeOpen: linker(this.beforeOpen, this), beforeSend: linker(this.beforeSend, this), afterReceive: linker(this.afterReceive, this) }; }; LongPollingWrapper.TYPE = "LongPolling"; LongPollingWrapper.prototype = { connect: function () { this.messagesQueue = []; this._closeCurrentConnection(); this.connectionEnabled = true; this.xhrSettings.url = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixLongpolling); var domain = extract_xss_domain(this.pushstream.host); var currentDomain = extract_xss_domain(window.location.hostname); var port = this.pushstream.port; var currentPort = window.location.port || (this.pushstream.useSSL ? 443 : 80); this.useJSONP = (domain !== currentDomain) || (port !== currentPort) || this.pushstream.longPollingUseJSONP; this.xhrSettings.scriptId = "PushStreamManager_" + this.pushstream.id; if (this.useJSONP) { this.pushstream.longPollingByHeaders = false; this.xhrSettings.data.callback = "PushStreamManager[" + this.pushstream.id + "].wrapper.onmessage"; } this._internalListen(); this.opentimer = window.setTimeout(linker(onopenCallback, this), 5000); Log4js.info("[LongPolling] connecting to:", this.xhrSettings.url); }, _listen: function () { if (this._internalListenTimeout) { clearTimer(this._internalListenTimeout); } this._internalListenTimeout = window.setTimeout(this._linkedInternalListen, this.pushstream.longPollingInterval); }, _internalListen: function () { if (this.connectionEnabled) { this.xhrSettings.data = extend({}, this.pushstream.extraParams(), this.xhrSettings.data); if (this.useJSONP) { Ajax.jsonp(this.xhrSettings); } else if (!this.connection) { this.connection = Ajax.load(this.xhrSettings); } } }, disconnect: function () { this.connectionEnabled = false; if (this.connection) { Log4js.debug("[LongPolling] closing connection to:", this.xhrSettings.url); this._closeCurrentConnection(); this.pushstream._onclose(); } }, _closeCurrentConnection: function () { this.opentimer = clearTimer(this.opentimer); if (this.connection) { try { this.connection.abort(); } catch (e) { /* ignore error on closing */ } this.connection = null; this.lastModified = null; this.xhrSettings.url = null; } }, beforeOpen: function (xhr) { if (this.lastModified === null) { var date = new Date(); if (this.pushstream.secondsAgo) { date.setTime(date.getTime() - (this.pushstream.secondsAgo * 1000)); } this.lastModified = dateToUTCString(date); } if (!this.pushstream.longPollingByHeaders) { this.xhrSettings.data[this.pushstream.longPollingTagArgument] = this.etag; this.xhrSettings.data[this.pushstream.longPollingTimeArgument] = this.lastModified; } }, beforeSend: function (xhr) { if (this.pushstream.longPollingByHeaders) { xhr.setRequestHeader("If-None-Match", this.etag); xhr.setRequestHeader("If-Modified-Since", this.lastModified); } }, afterReceive: function (xhr) { if (this.pushstream.longPollingByHeaders) { this.etag = xhr.getResponseHeader('Etag'); this.lastModified = xhr.getResponseHeader('Last-Modified'); } this.connection = null; }, onerror: function (status) { if (this.connectionEnabled) { /* abort(), called by disconnect(), call this callback, but should be ignored */ if (status === 304) { this._listen(); } else { Log4js.info("[LongPolling] error (disconnected by server):", status); this._closeCurrentConnection(); this.pushstream._onerror({ type: (status === 403) ? "load" : "timeout" }); } } }, onload: function () { this._listen(); }, onmessage: function (responseText) { Log4js.info("[LongPolling] message received", responseText); var lastMessage = null; var messages = isArray(responseText) ? responseText : responseText.split("\r\n"); for (var i = 0; i < messages.length; i++) { if (messages[i]) { lastMessage = parseMessage(messages[i], this.pushstream); this.messagesQueue.push(lastMessage); if (!this.pushstream.longPollingByHeaders && lastMessage.time) { this.etag = lastMessage.tag; this.lastModified = lastMessage.time; } } } this._listen(); while (this.messagesQueue.length > 0) { var message = this.messagesQueue.shift(); this.pushstream._onmessage(message.data, message.id, message.channel, message.eventid, (this.messagesQueue.length === 0)); } } }; /* mains class */ var PushStreamManager = []; var PushStream = function (settings) { settings = settings || {}; this.id = PushStreamManager.push(this) - 1; this.useSSL = settings.useSSL || false; this.host = settings.host || window.location.hostname; this.port = settings.port || (this.useSSL ? 443 : 80); this.timeout = settings.timeout || 15000; this.pingtimeout = settings.pingtimeout || 30000; this.reconnecttimeout = settings.reconnecttimeout || 3000; this.checkChannelAvailabilityInterval = settings.checkChannelAvailabilityInterval || 60000; this.secondsAgo = Number(settings.secondsAgo); this.longPollingByHeaders = (settings.longPollingByHeaders === undefined) ? true : settings.longPollingByHeaders; this.longPollingTagArgument = settings.longPollingTagArgument || 'tag'; this.longPollingTimeArgument = settings.longPollingTimeArgument || 'time'; this.longPollingUseJSONP = settings.longPollingUseJSONP || false; this.longPollingTimeout = settings.longPollingTimeout || 30000; this.longPollingInterval = settings.longPollingInterval || 100; this.reconnecttimer = null; this.urlPrefixPublisher = settings.urlPrefixPublisher || '/pub'; this.urlPrefixStream = settings.urlPrefixStream || '/sub'; this.urlPrefixEventsource = settings.urlPrefixEventsource || '/ev'; this.urlPrefixLongpolling = settings.urlPrefixLongpolling || '/lp'; this.urlPrefixWebsocket = settings.urlPrefixWebsocket || '/ws'; this.jsonIdKey = settings.jsonIdKey || 'id'; this.jsonChannelKey = settings.jsonChannelKey || 'channel'; this.jsonDataKey = settings.jsonDataKey || 'text'; this.jsonTagKey = settings.jsonTagKey || 'tag'; this.jsonTimeKey = settings.jsonTimeKey || 'time'; this.jsonEventIdKey = settings.jsonEventIdKey || 'eventid'; this.modes = (settings.modes || 'eventsource|websocket|stream|longpolling').split('|'); this.wrappers = []; this.wrapper = null; this.onopen = null; this.onmessage = null; this.onerror = null; this.onstatuschange = null; this.channels = {}; this.channelsCount = 0; this.channelsByArgument = settings.channelsByArgument || false; this.channelsArgument = settings.channelsArgument || 'channels'; this.extraParams = settings.extraParams || this.extraParams; for (var i = 0; i < this.modes.length; i++) { try { var wrapper = null; switch (this.modes[i]) { case "websocket": wrapper = new WebSocketWrapper(this); break; case "eventsource": wrapper = new EventSourceWrapper(this); break; case "longpolling": wrapper = new LongPollingWrapper(this); break; case "stream": wrapper = new StreamWrapper(this); break; } this.wrappers[this.wrappers.length] = wrapper; } catch (e) { Log4js.info(e); } } this._setState(0); }; /* constants */ PushStream.LOG_LEVEL = 'error'; /* debug, info, error */ PushStream.LOG_OUTPUT_ELEMENT_ID = 'Log4jsLogOutput'; /* status codes */ PushStream.CLOSED = 0; PushStream.CONNECTING = 1; PushStream.OPEN = 2; /* main code */ PushStream.prototype = { extraParams: function () { return {}; }, addChannel: function (channel, options) { if (escapeText(channel) !== channel) { throw "Invalid channel name! Channel has to be a set of [a-zA-Z0-9]"; } Log4js.debug("entering addChannel"); if (typeof (this.channels[channel]) !== "undefined") { throw "Cannot add channel " + channel + ": already subscribed"; } options = options || {}; Log4js.info("adding channel", channel, options); this.channels[channel] = options; this.channelsCount++; if (this.readyState !== PushStream.CLOSED) { this.connect(); } Log4js.debug("leaving addChannel"); }, removeChannel: function (channel) { if (this.channels[channel]) { Log4js.info("removing channel", channel); delete this.channels[channel]; this.channelsCount--; } }, removeAllChannels: function () { Log4js.info("removing all channels"); this.channels = {}; this.channelsCount = 0; }, _setState: function (state) { if (this.readyState !== state) { Log4js.info("status changed", state); this.readyState = state; if (this.onstatuschange) { this.onstatuschange(this.readyState); } } }, connect: function () { Log4js.debug("entering connect"); if (!this.host) { throw "PushStream host not specified"; } if (isNaN(this.port)) { throw "PushStream port not specified"; } if (!this.channelsCount) { throw "No channels specified"; } if (this.wrappers.length === 0) { throw "No available support for this browser"; } this._keepConnected = true; this._lastUsedMode = 0; this._connect(); Log4js.debug("leaving connect"); }, disconnect: function () { Log4js.debug("entering disconnect"); this._keepConnected = false; this._disconnect(); this._setState(PushStream.CLOSED); Log4js.info("disconnected"); Log4js.debug("leaving disconnect"); }, _connect: function () { this._disconnect(); this._setState(PushStream.CONNECTING); this.wrapper = this.wrappers[this._lastUsedMode++ % this.wrappers.length]; try { this.wrapper.connect(); } catch (e) { //each wrapper has a cleanup routine at disconnect method if (this.wrapper) { this.wrapper.disconnect(); } } }, _disconnect: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); if (this.wrapper) { this.wrapper.disconnect(); } }, _onopen: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); this._setState(PushStream.OPEN); if (this._lastUsedMode > 0) { this._lastUsedMode--; //use same mode on next connection } }, _onclose: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); this._setState(PushStream.CLOSED); this._reconnect(this.reconnecttimeout); }, _onmessage: function (data, id, channel, eventid, isLastMessageFromBatch) { Log4js.debug("message", data, id, channel, eventid, isLastMessageFromBatch); if (id === -2) { if (this.onchanneldeleted) { this.onchanneldeleted(channel); } } else if ((id > 0) && (typeof (this.channels[channel]) !== "undefined")) { if (this.onmessage) { this.onmessage(data, id, channel, eventid, isLastMessageFromBatch); } } }, _onerror: function (error) { this._setState(PushStream.CLOSED); this._reconnect((error.type === "timeout") ? this.reconnecttimeout : this.checkChannelAvailabilityInterval); if (this.onerror) { this.onerror(error); } }, _reconnect: function (timeout) { if (this._keepConnected && !this.reconnecttimer && (this.readyState !== PushStream.CONNECTING)) { Log4js.info("trying to reconnect in", timeout); this.reconnecttimer = window.setTimeout(linker(this._connect, this), timeout); } }, sendMessage: function (message, successCallback, errorCallback) { message = escapeText(message); if (this.wrapper.type === WebSocketWrapper.TYPE) { this.wrapper.sendMessage(message); if (successCallback) { successCallback(); } } else { Ajax.post({ url: getPublisherUrl(this), data: message, success: successCallback, error: errorCallback }); } } }; PushStream.sendMessage = function (url, message, successCallback, errorCallback) { Ajax.post({ url: url, data: escapeText(message), success: successCallback, error: errorCallback }); }; // to make server header template more clear, it calls register and // by a url parameter we find the stream wrapper instance PushStream.register = function (iframe) { var matcher = iframe.window.location.href.match(/streamid=([0-9]*)&?/); if (matcher[1] && PushStreamManager[matcher[1]]) { PushStreamManager[matcher[1]].wrapper.register(iframe); } }; PushStream.unload = function () { for (var i = 0; i < PushStreamManager.length; i++) { try { PushStreamManager[i].disconnect(); } catch (e) {} } }; /* make class public */ window.PushStream = PushStream; window.PushStreamManager = PushStreamManager; if (window.attachEvent) { window.attachEvent("onunload", PushStream.unload); } if (window.addEventListener) { window.addEventListener.call(window, "unload", PushStream.unload, false); } })(window, document); //]]>
Sorry, the page you were looking for in this blog does not exist.
Sorry, the page you were looking for in this blog does not exist.