]> Dogcows Code - chaz/chatty/blobdiff - extra/cometd/public_html/meteor.js
import meteord-1.06
[chaz/chatty] / extra / cometd / public_html / meteor.js
diff --git a/extra/cometd/public_html/meteor.js b/extra/cometd/public_html/meteor.js
new file mode 100644 (file)
index 0000000..824c434
--- /dev/null
@@ -0,0 +1,302 @@
+/*\r
+stream: xhrinteractive, iframe, serversent\r
+longpoll\r
+smartpoll\r
+simplepoll\r
+*/\r
+\r
+Meteor = {\r
+\r
+       callbacks: {\r
+               process: function() {},\r
+               reset: function() {},\r
+               eof: function() {},\r
+               statuschanged: function() {},\r
+               changemode: function() {}\r
+       },\r
+       channelcount: 0,\r
+       channels: {},\r
+       debugmode: false,\r
+       frameref: null,\r
+       host: null,\r
+       hostid: null,\r
+       maxpollfreq: 60000,\r
+       minpollfreq: 2000,\r
+       mode: "stream",\r
+       pingtimeout: 20000,\r
+       pingtimer: null,\r
+       pollfreq: 3000,\r
+       port: 80,\r
+       polltimeout: 30000,\r
+       recvtimes: [],\r
+       status: 0,\r
+       updatepollfreqtimer: null,\r
+\r
+       register: function(ifr) {\r
+               ifr.p = Meteor.process;\r
+               ifr.r = Meteor.reset;\r
+               ifr.eof = Meteor.eof;\r
+               ifr.ch = Meteor.channelInfo;\r
+               clearTimeout(Meteor.frameloadtimer);\r
+               Meteor.setstatus(4);\r
+               Meteor.log("Frame registered");\r
+       },\r
+\r
+       joinChannel: function(channelname, backtrack) {\r
+               if (typeof(Meteor.channels[channelname]) != "undefined") throw "Cannot join channel "+channelname+": already subscribed";\r
+               Meteor.channels[channelname] = {backtrack:backtrack, lastmsgreceived:0};\r
+               Meteor.log("Joined channel "+channelname);\r
+               Meteor.channelcount++;\r
+               if (Meteor.status != 0) Meteor.connect();\r
+       },\r
+\r
+       leaveChannel: function(channelname) {\r
+               if (typeof(Meteor.channels[channelname]) == "undefined") throw "Cannot leave channel "+channelname+": not subscribed";\r
+               delete Meteor.channels[channelname];\r
+               Meteor.log("Left channel "+channelname);\r
+               if (Meteor.status != 0) Meteor.connect();\r
+               Meteor.channelcount--;\r
+       },\r
+\r
+       connect: function() {\r
+               Meteor.log("Connecting");\r
+               if (!Meteor.host) throw "Meteor host not specified";\r
+               if (isNaN(Meteor.port)) throw "Meteor port not specified";\r
+               if (!Meteor.channelcount) throw "No channels specified";\r
+               if (Meteor.status) Meteor.disconnect();\r
+               Meteor.setstatus(1);\r
+               var now = new Date();\r
+               var t = now.getTime();\r
+               if (!Meteor.hostid) Meteor.hostid = t+""+Math.floor(Math.random()*1000000)\r
+               document.domain = Meteor.extract_xss_domain(document.domain);\r
+               if (Meteor.mode=="stream") Meteor.mode = Meteor.selectStreamTransport();\r
+               Meteor.log("Selected "+Meteor.mode+" transport");\r
+               if (Meteor.mode=="xhrinteractive" || Meteor.mode=="iframe" || Meteor.mode=="serversent") {\r
+                       if (Meteor.mode == "iframe") {\r
+                               Meteor.loadFrame(Meteor.getSubsUrl());\r
+                       } else {\r
+                               Meteor.loadFrame("http://"+Meteor.host+((Meteor.port==80)?"":":"+Meteor.port)+"/stream.html");\r
+                       }\r
+                       clearTimeout(Meteor.pingtimer);\r
+                       Meteor.pingtimer = setTimeout(Meteor.pollmode, Meteor.pingtimeout);\r
+\r
+               } else {\r
+                       Meteor.loadFrame("http://"+Meteor.host+((Meteor.port==80)?"":":"+Meteor.port)+"/poll.html");\r
+                       Meteor.recvtimes[0] = t;\r
+                       if (Meteor.updatepollfreqtimer) clearTimeout(Meteor.updatepollfreqtimer);\r
+                       if (Meteor.mode=='smartpoll') Meteor.updatepollfreqtimer = setInterval(Meteor.updatepollfreq, 2500);\r
+                       if (Meteor.mode=='longpoll') Meteor.pollfreq = Meteor.minpollfreq;\r
+               }\r
+               Meteor.lastrequest = t;\r
+       },\r
+\r
+       disconnect: function() {\r
+               if (Meteor.status) {\r
+                       clearTimeout(Meteor.pingtimer);\r
+                       clearTimeout(Meteor.updatepollfreqtimer);\r
+                       clearTimeout(Meteor.frameloadtimer);\r
+                       if (typeof CollectGarbage == 'function') CollectGarbage();\r
+                       if (Meteor.status != 6) Meteor.setstatus(0);\r
+                       Meteor.log("Disconnected");\r
+               }\r
+       },\r
+       \r
+       selectStreamTransport: function() {\r
+               try {\r
+                       var test = ActiveXObject;\r
+                       return "iframe";\r
+               } catch (e) {}\r
+               if ((typeof window.addEventStream) == "function") return "iframe";\r
+               return "xhrinteractive";\r
+       },\r
+\r
+       getSubsUrl: function() {\r
+               var surl = "http://" + Meteor.host + ((Meteor.port==80)?"":":"+Meteor.port) + "/push/" + Meteor.hostid + "/" + Meteor.mode;\r
+               for (var c in Meteor.channels) {\r
+                       surl += "/"+c;\r
+                       if (Meteor.channels[c].lastmsgreceived > 0) {\r
+                               surl += ".r"+(Meteor.channels[c].lastmsgreceived+1);\r
+                       } else if (Meteor.channels[c].backtrack > 0) {\r
+                               surl += ".b"+Meteor.channels[c].backtrack;\r
+                       } else if (Meteor.channels[c].backtrack < 0 || isNaN(Meteor.channels[c].backtrack)) {\r
+                               surl += ".h";\r
+                       }\r
+               }\r
+               var now = new Date();\r
+               surl += "?nc="+now.getTime();\r
+               return surl;\r
+       },\r
+\r
+       loadFrame: function(url) {\r
+               try {\r
+                       if (!Meteor.frameref) {\r
+                               var transferDoc = new ActiveXObject("htmlfile");\r
+                               Meteor.frameref = transferDoc;\r
+                       }\r
+                       Meteor.frameref.open();\r
+                       Meteor.frameref.write("<html><script>");\r
+                       Meteor.frameref.write("document.domain=\""+(document.domain)+"\";");\r
+                       Meteor.frameref.write("</"+"script></html>");\r
+                       Meteor.frameref.parentWindow.Meteor = Meteor;\r
+                       Meteor.frameref.close();\r
+                       var ifrDiv = Meteor.frameref.createElement("div");\r
+                       Meteor.frameref.appendChild(ifrDiv);\r
+                       ifrDiv.innerHTML = "<iframe src=\""+url+"\"></iframe>";\r
+               } catch (e) {\r
+                       if (!Meteor.frameref) {\r
+                               var ifr = document.createElement("IFRAME");\r
+                               ifr.style.width = "10px";\r
+                               ifr.style.height = "10px";\r
+                               ifr.style.border = "none";\r
+                               ifr.style.position = "absolute";\r
+                               ifr.style.top = "-10px";\r
+                               ifr.style.marginTop = "-10px";\r
+                               ifr.style.zIndex = "-20";\r
+                               ifr.Meteor = Meteor;\r
+                               document.body.appendChild(ifr);\r
+                               Meteor.frameref = ifr;\r
+                       }\r
+                       Meteor.frameref.setAttribute("src", url);\r
+               }\r
+               Meteor.log("Loading URL '"+url+"' into frame...");\r
+               Meteor.frameloadtimer = setTimeout(Meteor.frameloadtimeout, 5000);\r
+       },\r
+\r
+       pollmode: function() {\r
+               Meteor.log("Ping timeout");\r
+               Meteor.mode="smartpoll";\r
+               clearTimeout(Meteor.pingtimer);\r
+               Meteor.callbacks["changemode"]("poll");\r
+               Meteor.lastpingtime = false;\r
+               Meteor.connect();\r
+       },\r
+\r
+       process: function(id, channel, data) {\r
+               if (id == -1) {\r
+                       Meteor.log("Ping");\r
+                       Meteor.ping();\r
+               } else if (typeof(Meteor.channels[channel]) != "undefined") {\r
+                       Meteor.log("Message "+id+" received on channel "+channel+" (last id on channel: "+Meteor.channels[channel].lastmsgreceived+")\n"+data);\r
+                       Meteor.callbacks["process"](data);\r
+                       Meteor.channels[channel].lastmsgreceived = id;\r
+                       if (Meteor.mode=="smartpoll") {\r
+                               var now = new Date();\r
+                               Meteor.recvtimes[Meteor.recvtimes.length] = now.getTime();\r
+                               while (Meteor.recvtimes.length > 5) Meteor.recvtimes.shift();\r
+                       }\r
+               }\r
+               Meteor.setstatus(5);\r
+       },\r
+\r
+       ping: function() {\r
+               if (Meteor.pingtimer) {\r
+                       clearTimeout(Meteor.pingtimer);\r
+                       Meteor.pingtimer = setTimeout(Meteor.pollmode, Meteor.pingtimeout);\r
+                       var now = new Date();\r
+                       Meteor.lastpingtime = now.getTime();\r
+               }\r
+               Meteor.setstatus(5);\r
+       },\r
+\r
+       reset: function() {\r
+               if (Meteor.status != 6) {\r
+                       Meteor.log("Stream reset");\r
+                       Meteor.ping();\r
+                       Meteor.callbacks["reset"]();\r
+                       var now = new Date();\r
+                       var t = now.getTime();\r
+                       var x = Meteor.pollfreq - (t-Meteor.lastrequest);\r
+                       if (x < 10) x = 10;\r
+                       setTimeout(Meteor.connect, x);\r
+               }\r
+       },\r
+\r
+       eof: function() {\r
+               Meteor.log("Received end of stream, will not reconnect");\r
+               Meteor.callbacks["eof"]();\r
+               Meteor.setstatus(6);\r
+               Meteor.disconnect();\r
+       },\r
+\r
+       channelInfo: function(channel, id) {\r
+               Meteor.channels[channel].lastmsgreceived = id;\r
+               Meteor.log("Received channel info for channel "+channel+": resume from "+id);\r
+       },\r
+\r
+       updatepollfreq: function() {\r
+               var now = new Date();\r
+               var t = now.getTime();\r
+               var avg = 0;\r
+               for (var i=1; i<Meteor.recvtimes.length; i++) {\r
+                       avg += (Meteor.recvtimes[i]-Meteor.recvtimes[i-1]);\r
+               }\r
+               avg += (t-Meteor.recvtimes[Meteor.recvtimes.length-1]);\r
+               avg /= Meteor.recvtimes.length;\r
+               var target = avg/2;\r
+               if (target < Meteor.pollfreq && Meteor.pollfreq > Meteor.minpollfreq) Meteor.pollfreq = Math.ceil(Meteor.pollfreq*0.9);\r
+               if (target > Meteor.pollfreq && Meteor.pollfreq < Meteor.maxpollfreq) Meteor.pollfreq = Math.floor(Meteor.pollfreq*1.05);\r
+       },\r
+\r
+       registerEventCallback: function(evt, funcRef) {\r
+               Function.prototype.andThen=function(g) {\r
+                       var f=this;\r
+                       var a=Meteor.arguments\r
+                       return function(args) {\r
+                               f(a);g(args);\r
+                       }\r
+               };\r
+               if (typeof Meteor.callbacks[evt] == "function") {\r
+                       Meteor.callbacks[evt] = (Meteor.callbacks[evt]).andThen(funcRef);\r
+               } else {\r
+                       Meteor.callbacks[evt] = funcRef;\r
+               }\r
+       },\r
+\r
+       frameloadtimeout: function() {\r
+               Meteor.log("Frame load timeout");\r
+               if (Meteor.frameloadtimer) clearTimeout(Meteor.frameloadtimer);\r
+               Meteor.setstatus(3);\r
+               Meteor.pollmode();\r
+       },\r
+\r
+       extract_xss_domain: function(old_domain) {\r
+               if (old_domain.match(/^(\d{1,3}\.){3}\d{1,3}$/)) return old_domain;\r
+               domain_pieces = old_domain.split('.');\r
+               return domain_pieces.slice(-2, domain_pieces.length).join(".");\r
+       },\r
+\r
+       setstatus: function(newstatus) {\r
+               // Statuses:    0 = Uninitialised,\r
+               //                              1 = Loading stream,\r
+               //                              2 = Loading controller frame,\r
+               //                              3 = Controller frame timeout, retrying.\r
+               //                              4 = Controller frame loaded and ready\r
+               //                              5 = Receiving data\r
+               //                              6 = End of stream, will not reconnect\r
+\r
+               if (Meteor.status != newstatus) {\r
+                       Meteor.status = newstatus;\r
+                       Meteor.callbacks["statuschanged"](newstatus);\r
+               }\r
+       },\r
+\r
+       log: function(logstr) {\r
+               if (Meteor.debugmode) {\r
+                       if (window.console) {\r
+                               window.console.log(logstr);\r
+                       } else if (document.getElementById("meteorlogoutput")) {\r
+                               document.getElementById("meteorlogoutput").innerHTML += logstr+"<br/>";\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+var oldonunload = window.onunload;\r
+if (typeof window.onunload != 'function') {\r
+       window.onunload = Meteor.disconnect;\r
+} else {\r
+       window.onunload = function() {\r
+               if (oldonunload) oldonunload();\r
+               Meteor.disconnect();\r
+       }\r
+}
\ No newline at end of file
This page took 0.029666 seconds and 4 git commands to generate.