123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- function bullet(url) {
- var CONNECTING = 0;
- var OPEN = 1;
- var CLOSING = 2;
- var CLOSED = 3;
- var transports = {
- websocket: function() {
- var transport = null;
- if (window.WebSocket) { transport = window.WebSocket; }
- if (window.MozWebSocket) { transport = window.MozWebSocket; }
- if (transport) { return {'heart': true, 'transport': transport}; }
- return null;
- },
- xhrPolling: function() {
- var timeout;
- var xhr;
- nextPoll();
- var fake = {
- readyState: CONNECTING,
- receive: function(data) {
- if (fake.readyState == CONNECTING) { fake.readyState = OPEN; fake.onopen(fake); }
- if (data.length != 0) { fake.onmessage({'data': data }); }
- if (fake.readyState == OPEN) { nextPoll(); }
- },
- send: function(data) {
- if (this.readyState != CONNECTING && this.readyState != OPEN) return false;
- var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:');
- var request = new XMLHttpRequest();
- request.open('POST',fakeurl,true);
- request.setRequestHeader('Content-Type',
- 'application/x-www-form-urlencoded; charset=utf-8');
- request.setRequestHeader('X-Socket-Transport','xhrPolling');
- request.onload = function() { fake.receive(request.response); }
- request.send(data);
- return true;
- },
- close: function(){
- this.readyState = CLOSED;
- xhr.abort();
- clearTimeout(timeout);
- fake.onclose();
- },
- onopen: function(){},
- onmessage: function(){},
- onerror: function(){},
- onclose: function(){}
- };
- function poll(pooling){
- var fakeurl = url.replace('ws:', 'http:').replace('wss:', 'https:');
- var request = new XMLHttpRequest();
- request.open('GET',fakeurl,true);
- request.setRequestHeader('Content-Type',
- 'application/x-www-form-urlencoded; charset=utf-8');
- request.setRequestHeader('X-Socket-Transport','xhrPolling');
- request.onload = function() { fake.receive(request.response); }
- request.onerror = function() { fake.onerror(); }
- request.send({});
- }
- function nextPoll() { timeout = setTimeout(function(){poll();}, 1000); }
- return {'heart': false, 'transport': function(){ return fake; fake.nextPoll(); }};
- }
- };
- var tn = 0;
- function next() {
- var c = 0;
- for (var f in transports) {
- if (tn == c) {
- var t = transports[f]();
- if (t) { var ret = new t.transport(url); ret.heart = t.heart; return ret; }
- tn++;
- }
- c++;
- }
- return false;
- }
- var stream = new function() {
- var isClosed = true;
- var readyState = CLOSED;
- var heartbeat;
- var delay = 80;
- var delayDefault = 80;
- var delayMax = 10000;
- var transport;
- function init() {
- isClosed = false;
- readyState = CONNECTING;
- transport = next();
- if (!transport) {
- delay = delayDefault;
- tn = 0;
- stream.ondisconnect();
- setTimeout(function(){init();}, delayMax);
- return false;
- }
- transport.onopen = function() {
- delay = delayDefault;
- if (transport.heart) {
- heartbeat = setInterval(function(){stream.onheartbeat();}, 4000);
- }
- if (readyState != OPEN) { readyState = OPEN; stream.onopen(); }
- };
- transport.onclose = function() {
- if (isClosed) { return; }
- transport = null;
- clearInterval(heartbeat);
- if (readyState == CLOSING){
- readyState = CLOSED;
- stream.onclose();
- } else {
- if (readyState == CONNECTING) tn++;
- delay *= 2;
- if (delay > delayMax) { delay = delayMax; }
- isClosed = true;
- setTimeout(function() { init(); }, delay);
- }
- };
- transport.onerror = transport.onclose;
- transport.onmessage = function(e){
- stream.onmessage(e);
- };
- }
- init();
- this.onopen = function(){}; this.oninit = function(){};
- this.onmessage = function(){}; this.ondisconnect = function(){ initialized = false; };
- this.onclose = function(){}; this.onheartbeat = function(){ return this.send('PING'); };
- this.setURL = function(newURL) { url = newURL; };
- this.send = function(data){
- if (transport) return transport.send(data); else return false;
- };
- this.close = function(){
- readyState = CLOSING;
- if (transport) transport.close();
- };
- };
- return stream;
- }
|