summaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js')
-rw-r--r--trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js920
1 files changed, 0 insertions, 920 deletions
diff --git a/trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js b/trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js
deleted file mode 100644
index 3bfa227..0000000
--- a/trunk/infrastructure/net.appjet.ajstdlib/streaming-client.js
+++ /dev/null
@@ -1,920 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS-IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var host = window.location.host;
-
-function WebSocket(id) {
- var self = this;
- var socket = this;
- var version = 2;
-
- var timeouts = {};
-
- this.onopen = function() { }
- this.onclosed = function() { }
- this.onmessage = function() { }
- this.onhiccup = function() { }
- this.onlogmessage = function() { }
- this.CONNECTING = 0;
- this.OPEN = 1;
- this.CLOSED = 2;
- this.readyState = -1;
-
- var hiccupsLastMinute = 0;
- var hiccupResetInterval = setInterval(function() {
- hiccupsLastMinute = 0;
- if (self.readyState == self.CLOSED)
- clearInterval(hiccupResetInterval);
- }, 60*1000);
-
- var isHiccuping = false;
- function hiccup(channel) {
- if (channel != officialChannel && channel != self) return;
- if (isHiccuping) return;
- log("hiccup: "+channel.name);
- if (hiccupsLastMinute++ > 10) {
- doDisconnect({reconnect: true, reason: "Too many hiccups!"});
- return;
- }
- closeAllChannels();
- timeout(timeouts, "hiccup", 15000, function() {
- isHiccuping = false;
- doDisconnect({reconnect: false, reason: "Couldn't contact server to hiccup."});
- });
- isHiccuping = true;
- function tryHiccup() {
- if (! isHiccuping) return;
- self.onhiccup({connected: false});
- log("trying hiccup");
- timeout(timeouts, "singleHiccup", 5000, function() {
- tryHiccup();
- });
- simpleXhr('post', postPath(), true, [{key: "oob", value: "hiccup"}], function(sc, msg) {
- if (! isHiccuping) return;
- if (msg.substring(0, "restart-fail".length) == "restart-fail") {
- doDisconnect({reconnect: true, reason: "Server restarted or socket timed out on server."});
- } else if (sc != 200 || msg.substring(0, 2) != "ok") {
- log("Failed to hiccup with error: "+sc+" / "+msg);
- setTimeout(tryHiccup, 500);
- } else {
- isHiccuping = false;
- timeouts.singleHiccup();
- timeouts.hiccup();
- doConnect();
- }
- });
- }
- tryHiccup();
- }
- function closeAllChannels() {
- for (var i in activeChannels) {
- if (activeChannels.hasOwnProperty(i)) {
- activeChannels[i].disconnect();
- }
- }
- officialChannel = undefined;
- }
-
- function doDisconnect(obj, silent, sync) {
- log("disconnected: "+obj.reason+" / "+(obj.data !== undefined ? "data: "+obj.data : ""));
- logAll();
- closeAllChannels();
- if (longPollingIFrame && longPollingIFrame.div) {
- longPollingIFrame.div.innerHTML = "";
- }
- if (self.readyState != self.CLOSED) {
- self.readyState = self.CLOSED;
- if (! silent) {
- postSingleMessageNow(true, "kill:"+obj.reason, sync, true);
- }
- self.onclosed(obj);
- }
- }
-
- this.disconnect = function(sync) {
- doDisconnect({reason: "Closed by client."}, false, sync);
- }
-
-
- function doBasicConnect() {
- var type = getBasicChannel();
- log("basic connect on type: "+type);
- var channel = activeChannels[type] = new channelConstructors[type]();
- channel.connect();
- }
-
- function doOtherConnect() {
- var channels = getOtherChannels();
- var channel; var type;
- for (var i = 0; i < channels.length; ++i) {
- type = channels[i];
- log("other connect on type: "+type);
- channel = activeChannels[type] = new channelConstructors[type]();
- channel.connect();
- }
- }
- function doConnect() {
- log("doing connect!");
- timeout(timeouts, "connect", 15000, function() {
- doDisconnect({reconnect: false, reason: "Timeout connecting to server: no channel type was able to connect."});
- });
- doBasicConnect();
- }
-
- this.connect = function() {
- log("socket connecting: "+id);
- doConnect();
- }
-
- // util
- function nicetime() { return Math.floor((new Date()).valueOf() / 100) % 10000000; }
- function log(s) { self.onlogmessage("(comet @t: "+nicetime()+") "+s); }
- function logAll() {
- log(self.describe())
- }
- this.describe = function() {
- function describeChannels() {
- out = [];
- for (var i in activeChannels) {
- if (activeChannels.hasOwnProperty(i)) {
- out.push(i+": "+activeChannels[i].describe());
- }
- }
- return "[ "+out.join(", ")+" ]";
- }
- return ("socket state: { id: "+id+", readyState: "+self.readyState+", isHiccuping: "+isHiccuping+", timeouts: "+describeTimeouts(timeouts)+", officialChannel: "+(officialChannel?officialChannel.name:"none")+", channels: "+describeChannels()+", isPosting: "+isPosting+", lastReceivedSeqNumber: "+lastReceivedSeqNumber+", lastPost: "+lastPost+", postTimeouts: "+describeTimeouts(postTimeouts)+", channelSeq: "+channelSeq+" }");
- }
-
- function wrapMethod(obj, method) {
- return function() {
- var arr = [];
- for (var i=0; i < arguments.length; i++) {
- arr.push(arguments[i]);
- }
- method.apply(obj, arr);
- }
- }
- var _wm = wrapMethod;
-
- // cb should take statusCode, responseText, and optionally request
- function simpleXhr(method, uri, async, params, cb, makeXhr) {
-// log("making simple Xhr: "+[method, uri, async, params].join(", "));
- var request = (makeXhr || newRequestObject)();
- request.open(method, uri, async);
- if (async) {
- request.onreadystatechange = function() {
- if (request.readyState != 4) return;
- var status;
- var responseText;
- try {
- status = request.status;
- responseText = request.responseText;
- } catch (e) { /* absorb ff error accessing request properties */ }
- cb(status, responseText, request);
- }
- }
- var data = null;
- if (params) {
- data = [];
- for (var i = 0; i < params.length; ++i) {
- data.push(encodeURIComponent(params[i].key)+"="+encodeURIComponent(params[i].value));
- }
- data = data.join("&");
- request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
- }
- try {
- request.send(data);
- } catch (e) { request.abort(); cb(500, "Error sending data!", request); }
- if (! async) {
- var status;
- var responseText;
- try {
- status = request.status;
- responseText = request.responseText;
- } catch (e) { /* absorb ff error accessing request properties */ }
- cb(status, responseText, request);
- }
- return request;
- }
-
- var timeout_noop = function() { }
- function timeout(timeoutObject, timeoutName, millis, timeoutCallback) {
- function clearIt(timeoutObject, timeoutName) {
- if (timeoutObject[timeoutName]) {
- timeoutObject[timeoutName]();
- timeoutObject[timeoutName] = timeout_noop;
- }
- }
- var timeoutId = setTimeout(function() { clearIt(timeoutObject, timeoutName); timeoutCallback(); }, millis);
- var f = function() {
- clearTimeout(timeoutId);
- }
- clearIt(timeoutObject, timeoutName);
- timeoutObject[timeoutName] = f;
- return f;
- }
-
- // handling messages
- var lastReceivedSeqNumber = 0;
-
- function dataHandler(msg) {
- if (msg.seqNumber > lastReceivedSeqNumber+1) {
- log("bad sequence number. expecting: "+(lastReceivedSeqNumber+1)+", got: "+msg.seqNumber);
- hiccup(self);
- return false;
- }
- if (msg.seqNumber < lastReceivedSeqNumber+1) return true;
- lastReceivedSeqNumber = msg.seqNumber;
- if (! msg.isControl) {
- self.onmessage({ data: msg.content });
- return true;
- } else {
- if (msg.content == "kill") {
- doDisconnect({reconnect: false, reason: "Killed by server."});
- return false;
- }
- }
- }
-
- // client-server comm
- var postPath = function() {
- return "%contextPath%/post?r="+randomVar()+"&v="+version+"&id="+id+"&seq="+lastReceivedSeqNumber;
- }
-
- function SimpleQueue() {
- var base = [];
- var head = 0;
- var tail = 0;
- this.offer = function(data) {
- base[tail++] = data;
- }
- this.poll = function() {
- if (this.length() > 0) {
- var n = base[head];
- delete base[head++];
- return n;
- }
- }
- this.clear = function() {
- head = 0;
- tail = 0;
- var oldBase = base;
- base = [];
- return oldBase;
- }
- this.length = function() {
- return tail - head;
- }
- }
- var outgoingMessageQueue = new SimpleQueue();
- var isPosting = false;
- var postTimeouts = {};
- var lastPost;
-
- function postSingleMessageNow(isControl, data, sync, force, cb) {
- doPostMessages([{oob: isControl, data: data, cb: cb}], sync, force)
- }
-
- function doPostMessages(messages, sync, force, cb) {
- if (! force && self.readyState == self.CLOSED) return;
- if (messages.length == 0) {
- if (cb) cb();
- return;
- }
- var data = [];
- var callbacks = [];
- for (var i = 0; i < messages.length; ++i) {
- data.push({key: (messages[i].oob ? "oob" : "m"),
- value: messages[i].data});
- if (messages[i].cb)
- callbacks.push(messages[i].cb);
- }
- function postFailed(sc, msg, req, src) {
- var str = "";
- try {
- str = sc + ": "+req.statusText+" - "+msg+" ("+src+")";
- } catch (e) { /* absorb potential Firefox error accessing req */ }
- doDisconnect({reconnect: true, reason: "Posting message failed.", data: str});
- for (var i = 0; i < callbacks.length; ++i) {
- callbacks[i](false, str);
- }
- }
- function postCallback(sc, msg, request) {
- postTimeouts.post();
- if (sc != 200 || msg.substring(0, 2) != "ok") {
- postFailed(sc, msg, request, "1");
- } else {
- for (var i = 0; i < callbacks.length; ++i) {
- callbacks[i](true);
- }
- if (cb) cb();
- }
- }
- timeout(postTimeouts, "post", 15000, function() {
- doDisconnect({reconnect: true, reason: "Posting message timed out."});
- });
- simpleXhr('post', postPath(), ! sync, data, postCallback);
- }
-
- function postPendingMessages() {
- if (isPosting == true)
- return;
- var messages = outgoingMessageQueue.clear();
- if (messages.length == 0) {
- return;
- }
- isPosting = true;
- doPostMessages(messages, false, false, function() { isPosting = false; setTimeout(postPendingMessages, 0); });
- lastPost = nicetime();
- }
- this.postMessage = function(data, cb) {
- if (self.readyState != self.OPEN) {
- return;
- }
- outgoingMessageQueue.offer({data: data, cb: cb});
- setTimeout(function() { postPendingMessages() }, 0);
- }
-
- // transports
- function getValidChannels() {
- var channels = [];
- for (var i = 0; i < validChannels.length; ++i) {
- var type = validChannels[i];
- if (window.location.hash.length > 0) {
- if (window.location.hash != "#"+type) {
- continue;
- }
- }
- if ($ && $.browser.opera && type != 'shortpolling' && type != 'streaming') {
- continue;
- }
- channels.push(type);
- }
- return channels;
- }
- function getBasicChannel() {
- return getValidChannels()[0];
- }
-
- function getOtherChannels() {
- return getValidChannels().slice(1);
- }
-
- var officialChannel;
- this.getTransportType = function() {
- return (officialChannel ? officialChannel.name : "none");
- }
- var validChannels = "%acceptableChannelTypes%";
- var canUseSubdomains = "%canUseSubdomains%";
- var activeChannels = {};
- var channelConstructors = {
- shortpolling: ShortPollingChannel,
- longpolling: LongPollingChannel,
- streaming: StreamingChannel
- }
-
- function describeTimeouts(timeouts) {
- var out = [];
- for (var i in timeouts) {
- if (timeouts.hasOwnProperty(i)) {
- out.push(i+": "+(timeouts[i] == timeout_noop ? "unset" : "set"));
- }
- }
- return "{ "+out.join(", ")+" }";
- }
-
- var channelSeq = 1;
- function notifyConnect(channel) {
- timeouts.connect();
- if (! officialChannel || channel.weight > officialChannel.weight) {
- log("switching to use channel: "+channel.name);
- var oldChannel = officialChannel;
- officialChannel = channel;
- setTimeout(function() {
- postSingleMessageNow(true, "useChannel:"+(channelSeq++)+":"+channel.name, false, false, function(success, msg) {
- if (success) {
- if (oldChannel) {
- oldChannel.disconnect();
- } else {
- // there was no old channel, so try connecting the other channels.
- doOtherConnect();
- }
- if (self.readyState != self.OPEN) {
- self.readyState = self.OPEN;
- self.onopen({});
- } else {
- self.onhiccup({connected: true});
- }
- } else {
- doDisconnect({reconnect: true, reason: "Failed to select channel on server.", data: msg});
- }
- });
- }, 0);
- return true;
- } else {
- return false;
- }
- }
-
- function randomVar() {
- return String(Math.round(Math.random()*1e12));
- }
-
- function channelPath() {
- return "%contextPath%/channel?v="+version+"&r="+randomVar()+"&id="+id;
- }
-
- function newRequestObject() {
- var xmlhttp=false;
- try {
- xmlhttp = (window.ActiveXObject && new ActiveXObject("Msxml2.XMLHTTP"))
- } catch (e) {
- try {
- xmlhttp = (window.ActiveXObject && new ActiveXObject("Microsoft.XMLHTTP"));
- } catch (E) {
- xmlhttp = false;
- }
- }
- if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
- try {
- xmlhttp = new XMLHttpRequest();
- } catch (e) {
- xmlhttp=false;
- }
- }
- if (!xmlhttp && window.createRequest) {
- try {
- xmlhttp = window.createRequest();
- } catch (e) {
- xmlhttp=false;
- }
- }
- return xmlhttp
- }
-
- function DataFormatError(message) {
- this.message = message;
- }
-
- function readMessage(data, startIndex) {
- if (! startIndex) startIndex = 0;
- var sep = data.indexOf(":", startIndex);
- if (sep < 0) return; // don't have all the bytes for this yet.
- var chars = Number(data.substring(startIndex, sep));
- if (isNaN(chars))
- throw new DataFormatError("Bad length: "+data.substring(startIndex, sep));
- if (data.length < sep+1+chars) return; // don't have all the bytes for this yet.
- var msg = data.substr(sep+1, chars);
- return { message: msg, lastConsumedChar: sep+1+chars }
- }
-
- function iframeReader(data, startIndex) {
- if (startIndex == 0)
- return { message: data, lastConsumedChar: data.length }
- }
-
- function parseWireFormat(data, startIndex, reader) {
- if (! startIndex) startIndex = 0;
- var msgs = [];
- var readThroughIndex = startIndex;
- while (true) {
- var msgObj = (reader || readMessage)(data, readThroughIndex)
- if (! msgObj) break;
- readThroughIndex = msgObj.lastConsumedChar;
- var msg = msgObj.message;
- var split = msg.split(":");
- if (split[0] == 'oob') {
- msgs.push({oob: split.slice(1).join(":")});
- continue;
- }
- var seq = Number(split[0]);
- if (isNaN(seq))
- throw new DataFormatError("Bad sequence number: "+split[0]);
- var control = Number(split[1]);
- if (isNaN(control))
- throw new DataFormatError("Bad control: "+split[1]);
- var msgContent = split.slice(2).join(":");
- msgs.push({seqNumber: seq, isControl: (control == 1), content: msgContent});
- }
- return { messages: msgs, lastConsumedChar: readThroughIndex }
- }
-
- function handleMessages(data, cursor, channel, reader) {
- try {
- messages = parseWireFormat(data, cursor, reader);
- } catch (e) {
- if (e instanceof DataFormatError) {
- log("Data format error: "+e.message);
- hiccup(channel);
- return;
- } else {
- log(e.toString()+" on line: "+e.lineNumber);
- }
- }
- for (var i=0; i < messages.messages.length; i++) {
- var oob = messages.messages[i].oob;
- if (oob) {
- if (oob == "restart-fail") {
- doDisconnect({reconnect: true, reason: "Server restarted or socket timed out on server."});
- return;
- }
- } else {
- if (! dataHandler(messages.messages[i]))
- break;
- }
- }
- return messages.lastConsumedChar;
- }
-
- function ShortPollingChannel() {
- this.weight = 0;
- this.name = "shortpolling";
-
- this.isConnected = false;
- this.isClosed = false;
- this.request;
- this.clearRequest = function() {
- if (this.request) {
- this.request.abort();
- this.request = null;
- }
- }
- this.timeouts = {};
-
- this.describe = function() {
- return "{ isConnected: "+this.isConnected+", isClosed: "+this.isClosed+", timeouts: "+describeTimeouts(this.timeouts)+", request: "+(this.request?"set":"not set")+" }"
- }
-
- this.pollDataHandler = function(sc, response, request) {
- if (request.readyState != 4) return;
- if (this.timeouts.poll) this.timeouts.poll();
- var messages;
- if (! this.isConnected) {
- this.timeouts.connectAttempt();
- if (sc != 200) {
- log(this.name+" connect failed: "+sc+" / "+response);
- setTimeout(_wm(this, this.attemptConnect), 500);
- return;
- }
- var msg = (response ? readMessage(response) : undefined);
- if (msg && msg.message == "oob:ok") {
- this.timeouts.initialConnect();
- this.isConnected = true;
- log(this.name+" transport connected!");
- if (! notifyConnect(this)) {
- // there are better options connected.
- log(this.name+" transport not chosen for activation.");
- this.disconnect();
- return;
- }
- this.doPoll();
- return;
- } else {
- log(this.name+" connect didn't get ok: "+sc+" / "+response);
- setTimeout(_wm(this, this.attemptConnect), 500);
- return;
- }
- }
- var chars = handleMessages(request.responseText, 0, this);
- if (sc != 200 || ((! chars) && this.emptyResponseBad)) {
- hiccup(this);
- }
- setTimeout(_wm(this, this.doPoll), this.pollDelay);
- this.clearRequest();
- }
-
- this.keepRetryingConnection = true;
- this.cancelConnect = function() {
- this.clearRequest();
- this.keepRetryingConnection = false;
- }
- this.cancelPoll = function() {
- this.clearRequest();
- log("poll timed out.");
- hiccup(this);
- }
-
- this.doPoll = function() {
- if (this.isClosed) return;
- timeout(this.timeouts, "poll", this.pollTimeout, _wm(this, this.cancelPoll));
- this.request =
- simpleXhr('GET',
- channelPath()+"&channel="+this.name+"&seq="+lastReceivedSeqNumber+this.pollParams(),
- true, undefined, _wm(this, this.pollDataHandler), this.xhrGenerator);
- }
-
- this.pollParams = function() {
- return "";
- }
- this.pollTimeout = 5000;
- this.pollDelay = 500;
-
- this.attemptConnect = function() {
- if (! this.keepRetryingConnection) return;
- log(this.name+" attempting connect");
- this.clearRequest();
- timeout(this.timeouts, "connectAttempt", 5000, _wm(this, this.attemptConnect));
- this.request = simpleXhr('GET', channelPath()+"&channel="+this.name+"&new=yes&create="+(socket.readyState == socket.OPEN ? "no" : "yes")+"&seq="+lastReceivedSeqNumber,
- true, undefined, _wm(this, this.pollDataHandler), this.xhrGenerator);
- }
- this.connect = function() {
- this.attemptConnect();
- timeout(this.timeouts, "initialConnect", 15000, _wm(this, this.cancelConnect));
- }
- this.disconnect = function() {
- log(this.name+" disconnected");
- this.isClosed = true;
- this.clearRequest();
- }
- }
-
- function StreamingChannel() {
- this.weight = 2;
- this.name = "streaming";
- var self = this;
-
- var isConnected = false;
- var request;
- function clearRequest() {
- if (request) {
- request.abort();
- request = null;
- if (theStream) theStream = null;
- if (ifrDiv) {
- ifrDiv.innerHTML = "";
- ifrDiv = null;
- }
- }
- }
- var isClosed = false;
- var timeouts = {};
- var cursor = 0;
-
- this.describe = function() {
- return "{ isConnected: "+isConnected+", isClosed: "+isClosed+", timeouts: "+describeTimeouts(timeouts)+", request: "+(request?"set":"not set")+", cursor: "+cursor+" }";
- };
-
- function connectOk() {
- isConnected = true;
- timeouts.initialConnect();
- if (! notifyConnect(self)) {
- log("streaming transport not chosen for activation");
- self.disconnect();
- return;
- }
- }
-
- function streamDataHandler() {
- if (timeouts.data) timeouts.data();
- if (isClosed) return;
- try {
- if (! request.responseText) return;
- } catch (e) { return; }
- if (! isConnected) {
- var msg = readMessage(request.responseText, cursor);
- if (! msg) return;
- cursor = msg.lastReceivedSeqNumber;
- if (msg.message == "oob:ok") {
- connectOk();
- } else {
- log("stream: incorrect channel connect message:"+msg.message);
- self.disconnect();
- return;
- }
- } else {
- cursor = handleMessages(request.responseText, cursor, self);
- }
- if (! request || request.readyState == 4) {
- clearRequest();
- if (isConnected) {
- log("stream connection unexpectedly closed.");
- hiccup(self);
- return;
- }
- }
- timeout(timeouts, "data", 60*1000, function() { hiccup(self); });
- }
-
- function iframeDataHandler(data) {
- if (isClosed) return;
- if (! isConnected) {
- if (data == "oob:ok") {
- connectOk();
- } else {
- log("iframe stream: unexpected data on connect - "+data);
- }
- } else {
- handleMessages(data, 0, self, iframeReader);
- }
- }
-
- function cancelConnect() {
- isClosed = true;
- clearRequest();
- log("stream: failed to connect.");
- }
-
- // IE Stuff.
- var theStream;
- var ifrDiv;
- var iframeTestCount = 0;
- function testIframe() {
- var state;
- try {
- state = ifrDiv.firstChild.readyState;
- } catch (e) {
- hiccup(self);
- return;
- }
- if (state == 'interactive' || iframeTestCount > 10) {
- try { var tmp = ifrDiv.firstChild.contentWindow.document.getElementById("thebody") }
- catch (e) { hiccup(self); }
- } else {
- iframeTestCount++;
- setTimeout(testIframe, 500);
- }
- }
-
- this.connect = function() {
- timeout(timeouts, "initialConnect", 15000, cancelConnect)
-
- if (canUseSubdomains) {
- var streamurl = "//"+randomVar()+".comet."+host+channelPath()+"&channel=streaming&type=iframe&new=yes&create="+(socket.readyState == socket.OPEN ? "no" : "yes")+"&seq="+lastReceivedSeqNumber;
- log("stream to: "+streamurl);
- if ($ && $.browser.opera) {
- // set up the opera stream; requires jquery because, why not?
- ifrDiv = $('<div style="display: none;"></div>').get(0);
- $('body').append(ifrDiv);
- window.comet = {
- pass_data: iframeDataHandler,
- disconnect: function() { hiccup(self); }
- }
- $(ifrDiv).append($("<iframe src='"+streamurl+"'></iframe>"));
- iframeTestCount = 0;
- setTimeout(testIframe, 2000);
- // if event-source supported disconnect notifications, fuck yeah we'd use it.
-// theStream = $('<event-source>');
-// var streamurl = channelPath()+"&channel=streaming&type=opera&new=yes&create="+(socket.readyState == socket.OPEN ? "no" : "yes")+"&seq="+lastReceivedSeqNumber;
-// theStream.get(0).addEventListener('message', function(event) {
-// iframeDataHandler(event.data);
-// }, false);
-// theStream.attr('src', streamurl);
- log("stream connect sent!");
- return;
- }
- try { // TODO: remove reference to both theStream and ifrDiv on unload!
- theStream = (window.ActiveXObject && new ActiveXObject("htmlfile"));
- if (theStream) {
- theStream.open();
- theStream.write("<html><head><title>f<\/title><\/head><body>")
- theStream.write("<s"+"cript>document.domain='"+document.domain+"';<\/s"+"cript>")
- theStream.write("<\/body><\/html>")
- theStream.close();
- ifrDiv = theStream.createElement("div")
- theStream.appendChild(ifrDiv)
- theStream.parentWindow.comet = {
- pass_data: iframeDataHandler,
- disconnect: function() { hiccup(self); }
- }
- ifrDiv.innerHTML = "<iframe src='"+streamurl+"'></iframe>";
- iframeTestCount = 0;
- setTimeout(testIframe, 2000);
- }
- } catch (e) {
- theStream = false
- }
- } else if ($ && $.browser.opera) {
- // opera thinks it can do a normal stream, but it can't.
- log("opera - not trying xhr");
- return;
- }
- // End IE Stuff.
- if (! theStream) {
- request = newRequestObject();
- request.open('get', channelPath()+"&channel=streaming&new=yes&create="+(socket.readyState == socket.OPEN ? "no" : "yes")+"&seq="+lastReceivedSeqNumber);
- request.onreadystatechange = streamDataHandler;
- try {
- request.send(null);
- } catch (e) { }
- }
- log("stream connect sent!");
- }
-
- this.disconnect = function() {
- log("stream disconnected");
- isClosed = true;
- clearRequest();
- }
- log("new streamchannel");
- }
-
- // long-polling related stuff.
- function iframePath(key) {
- return "//"+key+".comet."+host+"%contextPath%/xhrXdFrame";
- }
-
- function createHiddenDiv() {
- if (! document.getElementById('newcomethidden')) {
- var d = document.createElement('div');
- d.setAttribute('id', 'newcomethidden');
- d.style.display = 'none';
- document.body.appendChild(d);
- }
- return document.getElementById('newcomethidden');
- }
-
- function ExtHostXHR(iframe) {
- this.open = function(method, uri, async) {
- this.method = method;
- this.uri = uri;
- this.async = async;
- }
- var headers = {};
- this.setRequestHeader = function(name, value) {
- headers[name] = value;
- }
- this.send = function(data) {
- var self = this;
- this.xhr = iframe.iframe.contentWindow.doAction(this.method, this.uri, this.async, headers, data || null, function(status, response) {
- self.readyState = 4;
- self.status = status;
- self.responseText = response;
- self.onreadystatechange();
- });
- }
- this.abort = function() {
- if (this.xhr)
- iframe.contentWindow.doAbort(this.xhr);
- }
- }
-
- function createRequestIframe(cb) {
- var randomKey = randomVar();
- try {
- var activeXControl = (window.ActiveXObject && new ActiveXObject("htmlfile"));
- var htmlfileDiv;
- if (activeXControl) {
- activeXControl.open();
- activeXControl.write('<html><head><title>f</title></head><body>');
- activeXControl.write('<scr'+'ipt>document.domain=\''+document.domain+'\';</scr'+'ipt>');
- activeXControl.write('</body></html>');
- activeXControl.close();
- htmlfileDiv = activeXControl.createElement('div');
- activeXControl.appendChild(htmlfileDiv);
- activeXControl.parentWindow["done_"+randomKey] = cb;
- htmlfileDiv.innerHTML = "<iframe src='"+iframePath(randomKey)+"'></iframe>";
- return {iframe: htmlfileDiv.firstChild /* should be an iframe */, axc: activeXControl, div: htmlfileDiv};
- }
- } catch (e) {
- activeXControl = false;
- }
- log("Not using IE setup.");
- var requestIframe = document.createElement('iframe');
- createHiddenDiv().appendChild(requestIframe);
- window["done_"+randomKey] = function() { try { delete window["done_"+randomKey]; } catch (e) { }; cb(); }
- requestIframe.src = iframePath(randomKey);
- return {iframe: requestIframe};
- }
-
- function createIframeRequestObject() {
- if (! longPollingIFrame) throw Error("WebSocket isn't properly set up!");
- return new ExtHostXHR(longPollingIFrame);
- }
-
- var longPollingIFrame;
- function LongPollingChannel() {
- ShortPollingChannel.apply(this); // sets up other state.
- this.weight = 1;
- this.name = "longpolling";
-
- this.pollDelay = 0;
- this.pollTimeout = 15000;
- this.pollParams = function() {
- return "&timeout="+(this.pollTimeout-5000);
- }
- var connect = this.connect;
- this.connect = function() {
- if (! longPollingIFrame) {
- longPollingIFrame =
- createRequestIframe(_wm(this, connect)); // specifically *not* this.connect. we want the old one!
- } else {
- connect.apply(this);
- }
- }
- this.xhrGenerator = createIframeRequestObject;
- this.emptyResponseBad = true;
- }
-} \ No newline at end of file