/* stream: xhrinteractive, iframe, serversent longpoll smartpoll simplepoll */ Meteor = { callbacks: { process: function() {}, reset: function() {}, eof: function() {}, statuschanged: function() {}, changemode: function() {} }, channelcount: 0, channels: {}, debugmode: false, frameref: null, host: null, hostid: null, maxpollfreq: 60000, minpollfreq: 2000, mode: "stream", pingtimeout: 20000, pingtimer: null, pollfreq: 3000, port: 80, polltimeout: 30000, recvtimes: [], status: 0, updatepollfreqtimer: null, register: function(ifr) { ifr.p = Meteor.process; ifr.r = Meteor.reset; ifr.eof = Meteor.eof; ifr.ch = Meteor.channelInfo; clearTimeout(Meteor.frameloadtimer); Meteor.setstatus(4); Meteor.log("Frame registered"); }, joinChannel: function(channelname, backtrack) { if (typeof(Meteor.channels[channelname]) != "undefined") throw "Cannot join channel "+channelname+": already subscribed"; Meteor.channels[channelname] = {backtrack:backtrack, lastmsgreceived:0}; Meteor.log("Joined channel "+channelname); Meteor.channelcount++; if (Meteor.status != 0) Meteor.connect(); }, leaveChannel: function(channelname) { if (typeof(Meteor.channels[channelname]) == "undefined") throw "Cannot leave channel "+channelname+": not subscribed"; delete Meteor.channels[channelname]; Meteor.log("Left channel "+channelname); if (Meteor.status != 0) Meteor.connect(); Meteor.channelcount--; }, connect: function() { Meteor.log("Connecting"); if (!Meteor.host) throw "Meteor host not specified"; if (isNaN(Meteor.port)) throw "Meteor port not specified"; if (!Meteor.channelcount) throw "No channels specified"; if (Meteor.status) Meteor.disconnect(); Meteor.setstatus(1); var now = new Date(); var t = now.getTime(); if (!Meteor.hostid) Meteor.hostid = t+""+Math.floor(Math.random()*1000000) document.domain = Meteor.extract_xss_domain(document.domain); if (Meteor.mode=="stream") Meteor.mode = Meteor.selectStreamTransport(); Meteor.log("Selected "+Meteor.mode+" transport"); if (Meteor.mode=="xhrinteractive" || Meteor.mode=="iframe" || Meteor.mode=="serversent") { if (Meteor.mode == "iframe") { Meteor.loadFrame(Meteor.getSubsUrl()); } else { Meteor.loadFrame("http://"+Meteor.host+((Meteor.port==80)?"":":"+Meteor.port)+"/stream.html"); } clearTimeout(Meteor.pingtimer); Meteor.pingtimer = setTimeout(Meteor.pollmode, Meteor.pingtimeout); } else { Meteor.loadFrame("http://"+Meteor.host+((Meteor.port==80)?"":":"+Meteor.port)+"/poll.html"); Meteor.recvtimes[0] = t; if (Meteor.updatepollfreqtimer) clearTimeout(Meteor.updatepollfreqtimer); if (Meteor.mode=='smartpoll') Meteor.updatepollfreqtimer = setInterval(Meteor.updatepollfreq, 2500); if (Meteor.mode=='longpoll') Meteor.pollfreq = Meteor.minpollfreq; } Meteor.lastrequest = t; }, disconnect: function() { if (Meteor.status) { clearTimeout(Meteor.pingtimer); clearTimeout(Meteor.updatepollfreqtimer); clearTimeout(Meteor.frameloadtimer); if (typeof CollectGarbage == 'function') CollectGarbage(); if (Meteor.status != 6) Meteor.setstatus(0); Meteor.log("Disconnected"); } }, selectStreamTransport: function() { try { var test = ActiveXObject; return "iframe"; } catch (e) {} if ((typeof window.addEventStream) == "function") return "iframe"; return "xhrinteractive"; }, getSubsUrl: function() { var surl = "http://" + Meteor.host + ((Meteor.port==80)?"":":"+Meteor.port) + "/push/" + Meteor.hostid + "/" + Meteor.mode; for (var c in Meteor.channels) { surl += "/"+c; if (Meteor.channels[c].lastmsgreceived > 0) { surl += ".r"+(Meteor.channels[c].lastmsgreceived+1); } else if (Meteor.channels[c].backtrack > 0) { surl += ".b"+Meteor.channels[c].backtrack; } else if (Meteor.channels[c].backtrack < 0 || isNaN(Meteor.channels[c].backtrack)) { surl += ".h"; } } var now = new Date(); surl += "?nc="+now.getTime(); return surl; }, loadFrame: function(url) { try { if (!Meteor.frameref) { var transferDoc = new ActiveXObject("htmlfile"); Meteor.frameref = transferDoc; } Meteor.frameref.open(); Meteor.frameref.write("