faye 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +12 -0
- data/Manifest.txt +5 -0
- data/README.txt +25 -7
- data/Rakefile +1 -0
- data/build/faye-client-min.js +1 -1
- data/build/faye.js +367 -186
- data/examples/node/faye-client-min.js +1 -1
- data/examples/node/faye.js +367 -186
- data/examples/shared/public/index.html +1 -0
- data/examples/shared/public/mootools.js +4329 -0
- data/examples/shared/public/prototype.js +4874 -0
- data/jake.yml +3 -1
- data/lib/faye-client-min.js +1 -1
- data/lib/faye.rb +5 -2
- data/lib/faye/channel.rb +4 -0
- data/lib/faye/client.rb +53 -29
- data/lib/faye/connection.rb +16 -37
- data/lib/faye/rack_adapter.rb +33 -28
- data/lib/faye/server.rb +24 -23
- data/lib/faye/timeouts.rb +21 -0
- data/lib/faye/transport.rb +17 -4
- data/test/scenario.js +73 -37
- data/test/scenario.rb +104 -0
- data/test/test_channel.rb +7 -1
- data/test/test_clients.js +28 -10
- data/test/test_clients.rb +154 -0
- data/test/test_grammar.rb +1 -1
- data/test/test_server.rb +8 -7
- metadata +17 -11
| @@ -1 +1 @@ | |
| 1 | 
            -
            if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.3.1',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:["long-polling","callback-polling"],ENV:this,random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a);return Math.floor(Math.random()*d).toString(16)},Grammar:{LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Deferrable={callback:function(a,b){if(this._t==='succeeded')return a.apply(b,this._m);this._9=this._9||[];this._9.push([a,b])},setDeferredStatus:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();this._t=c;this._m=b;if(c!=='succeeded')return;if(!this._9)return;Faye.each(this._9,function(a){a[0].apply(a[1],this._m)},this);this._9=[]}};Faye.Observable={on:function(a,b,c){this._0=this._0||{};var d=this._0[a]=this._0[a]||[];d.push([b,c])},stopObserving:function(a,b,c){if(!this._0||!this._0[a])return;if(!b){delete this._0[a];return}var d=this._0[a],f=d.length;while(f--){if(b&&d[f][0]!==b)continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},fire:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._0||!this._0[c])return;Faye.each(this._0[c],function(a){a[0].apply(a[1],b.slice())})}};Faye.Channel=Faye.Class({initialize:function(a){this.__id=this.name=a},push:function(a){this.fire('message',a)}});Faye.extend(Faye.Channel.prototype,Faye.Observable);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Tree:Faye.Class({initialize:function(a){this._1=a;this._5={}},eachChild:function(c,d){Faye.each(this._5,function(a,b){c.call(d,a,b)})},each:function(c,d,f){this.eachChild(function(a,b){a=c.concat(a);b.each(a,d,f)});if(this._1!==undefined)d.call(f,c,this._1)},map:function(c,d){var f=[];this.each([],function(a,b){f.push(c.call(d,a,b))});return f},get:function(a){var b=this.traverse(a);return b?b._1:null},set:function(a,b){var c=this.traverse(a,true);if(c)c._1=b},traverse:function(a,b){if(typeof a==='string')a=Faye.Channel.parse(a);if(a===null)return null;if(a.length===0)return this;var c=this._5[a[0]];if(!c&&!b)return null;if(!c)c=this._5[a[0]]=new Faye.Channel.Tree();return c.traverse(a.slice(1),b)},findOrCreate:function(a){var b=this.get(a);if(b)return b;b=new Faye.Channel(a);this.set(a,b);return b},glob:function(f){if(typeof f==='string')f=Faye.Channel.parse(f);if(f===null)return[];if(f.length===0)return(this._1===undefined)?[]:[this._1];var g=[];if(Faye.enumEqual(f,['*'])){Faye.each(this._5,function(a,b){if(b._1!==undefined)g.push(b._1)});return g}if(Faye.enumEqual(f,['**'])){g=this.map(function(a,b){return b});if(this._1!==undefined)g.pop();return g}Faye.each(this._5,function(b,c){if(b!==f[0]&&b!=='*')return;var d=c.glob(f.slice(1));Faye.each(d,function(a){g.push(a)})});if(this._5['**'])g.push(this._5['**']._1);return g}})});Faye.Namespace=Faye.Class({initialize:function(){this._n={}},generate:function(){var a=Faye.random();while(this._n.hasOwnProperty(a))a=Faye.random();return this._n[a]=a}});Faye.Transport=Faye.extend(Faye.Class({initialize:function(a,b){this._f=a;this._6=b},send:function(c,d,f){if(!(c instanceof Array)&&!c.id)c.id=this._f._o.generate();this.request(c,function(b){if(!d)return;Faye.each([].concat(b),function(a){if(a.id===c.id)d.call(f,a);if(a.advice)this._f.handleAdvice(a.advice);if(a.data&&a.channel)this._f.sendToSubscribers(a)},this)},this)}}),{get:function(c,d){var f=c._6;if(d===undefined)d=this.supportedConnectionTypes();var g=null;Faye.each(this._g,function(a,b){if(Faye.indexOf(d,a)<0)return;if(g)return;if(b.isUsable(f))g=b});if(!g)throw'Could not find a usable connection type for '+f;return new g(c,f)},register:function(a,b){this._g[a]=b;b.prototype.connectionType=a},_g:{},supportedConnectionTypes:function(){var c=[],d;Faye.each(this._g,function(a,b){c.push(a)});return c}});Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',DEFAULT_ENDPOINT:'/bayeux',MAX_DELAY:0.1,INTERVAL:1000.0,initialize:function(a){this._6=a||this.DEFAULT_ENDPOINT;this._4=Faye.Transport.get(this);this._2=this.UNCONNECTED;this._o=new Faye.Namespace();this._h=[];this._a=new Faye.Channel.Tree();this._p=[];this._7={reconnect:this.RETRY,interval:this.INTERVAL};if(!Faye.Event)return;Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},handshake:function(b,c){if(this._7.reconnect===this.NONE)return;if(this._2!==this.UNCONNECTED)return;this._2=this.CONNECTING;var d=this;this._4.send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:Faye.Transport.supportedConnectionTypes()},function(a){if(!a.successful){setTimeout(function(){d.handshake(b,c)},this._7.interval);return this._2=this.UNCONNECTED}this._2=this.CONNECTED;this._8=a.clientId;this._4=Faye.Transport.get(this,a.supportedConnectionTypes);if(b)b.call(c)},this)},connect:function(b,c){if(this._7.reconnect===this.NONE)return;if(this._2===this.DISCONNECTED)return;if(this._7.reconnect===this.HANDSHAKE||this._2===this.UNCONNECTED)return this.handshake(function(){this.connect(b,c)},this);if(this._2===this.CONNECTING)return this.callback(b,c);if(this._2!==this.CONNECTED)return;this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(b)b.call(c);if(this._i)return;this._i=this._o.generate();var d=this;this._4.send({channel:Faye.Channel.CONNECT,clientId:this._8,connectionType:this._4.connectionType,id:this._i},function(a){delete this._i;setTimeout(function(){d.connect()},this._7.interval)},this)},disconnect:function(){if(this._2!==this.CONNECTED)return;this._2=this.DISCONNECTED;this._4.send({channel:Faye.Channel.DISCONNECT,clientId:this._8});this._a=new Faye.Channel.Tree()},subscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._j(c);this._4.send({channel:Faye.Channel.SUBSCRIBE,clientId:this._8,subscription:c},function(b){if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._a.set(a,[d,f])},this)},this)},this)},unsubscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._j(c);this._4.send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._8,subscription:c},function(b){if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._a.set(a,null)},this)},this)},this)},publish:function(b,c){this.connect(function(){this._j([b]);this._u({channel:b,data:c,clientId:this._8});if(this._q)return;var a=this;this._q=setTimeout(function(){delete a._q;a._v()},this.MAX_DELAY*1000)},this)},handleAdvice:function(a){Faye.extend(this._7,a);if(this._7.reconnect===this.HANDSHAKE)this._8=null},sendToSubscribers:function(b){var c=this._a.glob(b.channel);Faye.each(c,function(a){if(!a)return;a[0].call(a[1],b.data)})},_u:function(a){this._h.push(a)},_v:function(){this._4.send(this._h);this._h=[]},_j:function(b){Faye.each(b,function(a){if(!Faye.Channel.isValid(a))throw'"'+a+'" is not a valid channel name';if(!Faye.Channel.isSubscribable(a))throw'Clients may not subscribe to channel "'+a+'"';})}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.Event={_b:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._b.push({_c:a,_k:b,_w:c,_d:d,_r:f})},detach:function(a,b,c,d){var f=this._b.length,g;while(f--){g=this._b[f];if((a&&a!==g._c)||(b&&b!==g._k)||(c&&c!==g._w)||(d&&d!==g._d))continue;if(g._c.removeEventListener)g._c.removeEventListener(g._k,g._r,false);else g._c.detachEvent('on'+g._k,g._r);this._b.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){return this.protocol+this.hostname+':'+this.port+this.pathname+'?'+this.queryString()}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var k=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};k('protocol',/^https?\:\/+/);k('hostname',/^[^\/\:]+/);k('port',/^:[0-9]+/);Faye.extend(g,{protocol:'http://',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),h=i.shift(),l=i.join('?'),n=l?l.split('&'):[],o=n.length,j={};while(o--){i=n[o].split('=');j[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}Faye.extend(j,f);g.pathname=h;g.params=j;return g}});Faye.XHR={request:function(a,b,c,d,f){var g=new this.Request(a,b,c,d,f);g.send();return g},getXhrObject:function(){return Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},Request:Faye.Class({initialize:function(a,b,c,d,f){this._e=a.toUpperCase();this._6=Faye.URI.parse(b,c);this._p=(typeof d==='function')?{success:d}:d;this._d=f||null;this._3=null},send:function(){if(this._l)return;var a=this._6.pathname,b=this._6.queryString();if(this._e==='GET')a+='?'+b;var c=this._e==='POST'?b:'';this._l=true;this._3=Faye.XHR.getXhrObject();this._3.open(this._e,a,true);if(this._e==='POST')this._3.setRequestHeader('Content-Type','application/x-www-form-urlencoded');var d=this,f=function(){if(d._3.readyState!==4)return;if(g){clearInterval(g);g=null}Faye.Event.detach(Faye.ENV,'beforeunload',d.abort,d);d._l=false;d._x();d=null};var g=setInterval(f,10);Faye.Event.on(Faye.ENV,'beforeunload',this.abort,this);this._3.send(c)},abort:function(){this._3.abort()},_x:function(){var a=this._p;if(!a)return;return this.success()?a.success&&a.success.call(this._d,this):a.failure&&a.failure.call(this._d,this)},waiting:function(){return!!this._l},complete:function(){return this._3&&!this.waiting()},success:function(){if(!this.complete())return false;var a=this._3.status;return(a>=200&&a<300)||a===304||a===1223},failure:function(){if(!this.complete())return false;return!this.success()},text:function(){if(!this.complete())return null;return this._3.responseText},status:function(){if(!this.complete())return null;return this._3.status}})};if(!this.JSON){JSON={}}(function(){function l(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,j,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},m;function r(c){o.lastIndex=0;return o.test(c)?'"'+c.replace(o,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,k=j,i,h=b[a];if(h&&typeof h==='object'&&typeof h.toJSON==='function'){h=h.toJSON(a)}if(typeof m==='function'){h=m.call(b,a,h)}switch(typeof h){case'string':return r(h);case'number':return isFinite(h)?String(h):'null';case'boolean':case'null':return String(h);case'object':if(!h){return'null'}j+=p;i=[];if(Object.prototype.toString.apply(h)==='[object Array]'){g=h.length;for(c=0;c<g;c+=1){i[c]=q(c,h)||'null'}f=i.length===0?'[]':j?'[\n'+j+i.join(',\n'+j)+'\n'+k+']':'['+i.join(',')+']';j=k;return f}if(m&&typeof m==='object'){g=m.length;for(c=0;c<g;c+=1){d=m[c];if(typeof d==='string'){f=q(d,h);if(f){i.push(r(d)+(j?': ':':')+f)}}}}else{for(d in h){if(Object.hasOwnProperty.call(h,d)){f=q(d,h);if(f){i.push(r(d)+(j?': ':':')+f)}}}}f=i.length===0?'{}':j?'{\n'+j+i.join(',\n'+j)+'\n'+k+'}':'{'+i.join(',')+'}';j=k;return f}}if(typeof JSON.stringify!=='function'){JSON.stringify=function(a,b,c){var d;j='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}m=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})}}if(typeof JSON.parse!=='function'){JSON.parse=function(g,k){var i;function h(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=h(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return k.call(a,b,f)}n.lastIndex=0;if(n.test(g)){g=g.replace(n,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof k==='function'?h({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.XHRTransport=Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:JSON.stringify(b)};Faye.XHR.request('post',this._6,f,function(a){if(c)c.call(d,JSON.parse(a.text()))})}});Faye.XHRTransport.isUsable=function(a){return Faye.URI.parse(a).isLocal()};Faye.Transport.register('long-polling',Faye.XHRTransport);Faye.JSONPTransport=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:JSON.stringify(b)},g=document.getElementsByTagName('head')[0],k=document.createElement('script'),i=Faye.JSONPTransport.getCallbackName(),h=Faye.URI.parse(this._6,f);Faye.ENV[i]=function(a){Faye.ENV[i]=undefined;try{delete Faye.ENV[i]}catch(e){}g.removeChild(k);if(c)c.call(d,a)};h.params.jsonp=i;k.type='text/javascript';k.src=h.toURL();g.appendChild(k)}}),{_s:0,getCallbackName:function(){this._s+=1;return'__jsonp'+this._s+'__'}});Faye.JSONPTransport.isUsable=function(a){return true};Faye.Transport.register('callback-polling',Faye.JSONPTransport);
         | 
| 1 | 
            +
            if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.3.2',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:["long-polling","callback-polling"],ENV:this,random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a);return Math.floor(Math.random()*d).toString(16)},Grammar:{LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},timestamp:function(){var b=new Date(),c=b.getFullYear(),d=b.getMonth()+1,f=b.getDate(),g=b.getHours(),j=b.getMinutes(),i=b.getSeconds();var h=function(a){return a<10?'0'+a:String(a)};return h(c)+'-'+h(d)+'-'+h(f)+' '+h(g)+':'+h(j)+':'+h(i)}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Deferrable={callback:function(a,b){if(this._w==='succeeded')return a.apply(b,this._o);this._a=this._a||[];this._a.push([a,b])},setDeferredStatus:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();this._w=c;this._o=b;if(c!=='succeeded')return;if(!this._a)return;Faye.each(this._a,function(a){a[0].apply(a[1],this._o)},this);this._a=[]}};Faye.Observable={on:function(a,b,c){this._2=this._2||{};var d=this._2[a]=this._2[a]||[];d.push([b,c])},stopObserving:function(a,b,c){if(!this._2||!this._2[a])return;if(!b){delete this._2[a];return}var d=this._2[a],f=d.length;while(f--){if(b&&d[f][0]!==b)continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},fire:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._2||!this._2[c])return;Faye.each(this._2[c],function(a){a[0].apply(a[1],b.slice())})}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var c=Faye.Logging.LOG_LEVELS;if(c[Faye.Logging.logLevel]>c[b])return;var d='['+b.toUpperCase()+'] [Faye',f=null;for(var g in Faye){if(f)continue;if(typeof Faye[g]!=='function')continue;if(this instanceof Faye[g])f=g}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+' '+d+a)},error:function(a){this.log(a,'error')},warn:function(a){this.log(a,'warn')},info:function(a){this.log(a,'info')},debug:function(a){this.log(a,'debug')}};Faye.Timeouts={addTimeout:function(a,b,c,d){this._6=this._6||{};if(this._6.hasOwnProperty(a))return;var f=this;this._6[a]=setTimeout(function(){delete f._6[a];c.call(d)},1000*b)},removeTimeout:function(a){this._6=this._6||{};var b=this._6[a];if(!b)return;clearTimeout(b);delete this._6[a]}};Faye.Channel=Faye.Class({initialize:function(a){this.__id=this.name=a},push:function(a){this.fire('message',a)}});Faye.extend(Faye.Channel.prototype,Faye.Observable);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Tree:Faye.Class({initialize:function(a){this._3=a;this._8={}},eachChild:function(c,d){Faye.each(this._8,function(a,b){c.call(d,a,b)})},each:function(c,d,f){this.eachChild(function(a,b){a=c.concat(a);b.each(a,d,f)});if(this._3!==undefined)d.call(f,c,this._3)},getKeys:function(){return this.map(function(a,b){return'/'+a.join('/')})},map:function(c,d){var f=[];this.each([],function(a,b){f.push(c.call(d,a,b))});return f},get:function(a){var b=this.traverse(a);return b?b._3:null},set:function(a,b){var c=this.traverse(a,true);if(c)c._3=b},traverse:function(a,b){if(typeof a==='string')a=Faye.Channel.parse(a);if(a===null)return null;if(a.length===0)return this;var c=this._8[a[0]];if(!c&&!b)return null;if(!c)c=this._8[a[0]]=new Faye.Channel.Tree();return c.traverse(a.slice(1),b)},findOrCreate:function(a){var b=this.get(a);if(b)return b;b=new Faye.Channel(a);this.set(a,b);return b},glob:function(f){if(typeof f==='string')f=Faye.Channel.parse(f);if(f===null)return[];if(f.length===0)return(this._3===undefined)?[]:[this._3];var g=[];if(Faye.enumEqual(f,['*'])){Faye.each(this._8,function(a,b){if(b._3!==undefined)g.push(b._3)});return g}if(Faye.enumEqual(f,['**'])){g=this.map(function(a,b){return b});if(this._3!==undefined)g.pop();return g}Faye.each(this._8,function(b,c){if(b!==f[0]&&b!=='*')return;var d=c.glob(f.slice(1));Faye.each(d,function(a){g.push(a)})});if(this._8['**'])g.push(this._8['**']._3);return g}})});Faye.Namespace=Faye.Class({initialize:function(){this._p={}},generate:function(){var a=Faye.random();while(this._p.hasOwnProperty(a))a=Faye.random();return this._p[a]=a}});Faye.Transport=Faye.extend(Faye.Class({initialize:function(a,b){this.debug('Created new transport for '+b);this._b=a;this._4=b},send:function(f,g,j){if(!(f instanceof Array)&&!f.id)f.id=this._b._q.generate();this.debug('Client '+this._b._0+' sending message to '+this._4+': '+Faye.toJSON(f));this.request(f,function(b){this.debug('Client '+this._b._0+' received from '+this._4+': '+Faye.toJSON(b));if(!g)return;var c=[],d=true;Faye.each([].concat(b),function(a){if(a.id===f.id){if(g.call(j,a)===false)d=false}if(a.advice)this._b.handleAdvice(a.advice);if(a.data&&a.channel)c.push(a)},this);if(d)this._b.deliverMessages(c)},this)}}),{get:function(c,d){var f=c._4;if(d===undefined)d=this.supportedConnectionTypes();var g=null;Faye.each(this._i,function(a,b){if(Faye.indexOf(d,a)<0)return;if(g)return;if(b.isUsable(f))g=b});if(!g)throw'Could not find a usable connection type for '+f;return new g(c,f)},register:function(a,b){this._i[a]=b;b.prototype.connectionType=a},_i:{},supportedConnectionTypes:function(){var c=[],d;Faye.each(this._i,function(a,b){c.push(a)});return c}});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_ENDPOINT:'/bayeux',MAX_DELAY:0.1,INTERVAL:1000.0,initialize:function(a,b){this.info('New client created for '+a);this._4=a||this.DEFAULT_ENDPOINT;this._x=b||{};this._r=this._x.timeout||this.CONNECTION_TIMEOUT;this._7=Faye.Transport.get(this);this._1=this.UNCONNECTED;this._q=new Faye.Namespace();this._j=[];this._c=new Faye.Channel.Tree();this._s=[];this._9={reconnect:this.RETRY,interval:this.INTERVAL};if(!Faye.Event)return;Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},handshake:function(b,c){if(this._9.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var d=this;this.info('Initiating handshake with '+this._4);this._7.send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:Faye.Transport.supportedConnectionTypes()},function(a){if(!a.successful){this.info('Handshake unsuccessful');setTimeout(function(){d.handshake(b,c)},this._9.interval);return this._1=this.UNCONNECTED}this._1=this.CONNECTED;this._0=a.clientId;this._7=Faye.Transport.get(this,a.supportedConnectionTypes);this.info('Handshake successful: '+this._0);if(b)b.call(c)},this)},connect:function(b,c){if(this._9.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._9.reconnect===this.HANDSHAKE||this._1===this.UNCONNECTED){this._t();return this.handshake(function(){this.connect(b,c)},this)}if(this._1===this.CONNECTING)return this.callback(b,c);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for '+this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(b)b.call(c);if(this._d)return;this._d=this._q.generate();var d=this;this.info('Initiating connection for '+this._0);this._7.send({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._7.connectionType,id:this._d},this._k(function(a){delete this._d;this.removeTimeout('reconnect');this.info('Closed connection for '+this._0);setTimeout(function(){d.connect()},this._9.interval)}));this._t()},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting '+this._0);this._7.send({channel:Faye.Channel.DISCONNECT,clientId:this._0});this.info('Clearing channel listeners for '+this._0);this._c=new Faye.Channel.Tree()},subscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._l(c);this.info('Client '+this._0+' attempting to subscribe to ['+c.join(', ')+']');this._7.send({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:c},this._k(function(b){if(!b.successful||!d)return;this.info('Subscription acknowledged for '+this._0+' to ['+c.join(', ')+']');c=[].concat(b.subscription);Faye.each(c,function(a){this._c.set(a,[d,f])},this)}))},this)},unsubscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._l(c);this.info('Client '+this._0+' attempting to unsubscribe from ['+c.join(', ')+']');this._7.send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:c},this._k(function(b){if(!b.successful)return;this.info('Unsubscription acknowledged for '+this._0+' from ['+c.join(', ')+']');c=[].concat(b.subscription);Faye.each(c,function(a){this._c.set(a,null)},this)}))},this)},publish:function(a,b){this.connect(function(){this._l([a]);this.info('Client '+this._0+' queueing published message to '+a+': '+Faye.toJSON(b));this._y({channel:a,data:b,clientId:this._0});this.addTimeout('publish',this.MAX_DELAY,this._z,this)},this)},handleAdvice:function(a){Faye.extend(this._9,a);if(this._9.reconnect===this.HANDSHAKE)this._0=null},deliverMessages:function(d){Faye.each(d,function(b){this.info('Client '+this._0+' calling listeners for '+b.channel+' with '+Faye.toJSON(b.data));var c=this._c.glob(b.channel);Faye.each(c,function(a){if(!a)return;a[0].call(a[1],b.data)})},this)},_t:function(){this.addTimeout('reconnect',this._r,function(){delete this._d;delete this._0;this._1=this.UNCONNECTED;this.info('Server took >'+this._r+'s to reply to connection for '+this._0+': attempting to reconnect');this.subscribe(this._c.getKeys())},this)},_y:function(a){this._j.push(a)},_z:function(){this._7.send(this._j);this._j=[]},_l:function(b){Faye.each(b,function(a){if(!Faye.Channel.isValid(a))throw'"'+a+'" is not a valid channel name';if(!Faye.Channel.isSubscribable(a))throw'Clients may not subscribe to channel "'+a+'"';})},_k:function(b){var c=this;return function(a){if(a.clientId!==c._0)return false;b.call(c,a);return true}}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Timeouts);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.Event={_e:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._e.push({_f:a,_m:b,_A:c,_g:d,_u:f})},detach:function(a,b,c,d){var f=this._e.length,g;while(f--){g=this._e[f];if((a&&a!==g._f)||(b&&b!==g._m)||(c&&c!==g._A)||(d&&d!==g._g))continue;if(g._f.removeEventListener)g._f.removeEventListener(g._m,g._u,false);else g._f.detachEvent('on'+g._m,g._u);this._e.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){return this.protocol+this.hostname+':'+this.port+this.pathname+'?'+this.queryString()}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var j=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};j('protocol',/^https?\:\/+/);j('hostname',/^[^\/\:]+/);j('port',/^:[0-9]+/);Faye.extend(g,{protocol:'http://',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),h=i.shift(),l=i.join('?'),n=l?l.split('&'):[],o=n.length,k={};while(o--){i=n[o].split('=');k[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}if(typeof f==='object')Faye.extend(k,f);g.pathname=h;g.params=k;return g}});Faye.XHR={request:function(a,b,c,d,f){var g=new this.Request(a,b,c,d,f);g.send();return g},getXhrObject:function(){return Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},Request:Faye.Class({initialize:function(a,b,c,d,f){this._h=a.toUpperCase();this._4=Faye.URI.parse(b,c);this._B=(typeof c==='string')?c:null;this._s=(typeof d==='function')?{success:d}:d;this._g=f||null;this._5=null},send:function(){if(this._n)return;var a=this._4.pathname,b=this._4.queryString();if(this._h==='GET')a+='?'+b;var c=(this._h==='POST')?(this._B||b):'';this._n=true;this._5=Faye.XHR.getXhrObject();this._5.open(this._h,a,true);if(this._h==='POST')this._5.setRequestHeader('Content-Type','application/json');var d=this,f=function(){if(d._5.readyState!==4)return;if(g){clearInterval(g);g=null}Faye.Event.detach(Faye.ENV,'beforeunload',d.abort,d);d._n=false;d._C();d=null};var g=setInterval(f,10);Faye.Event.on(Faye.ENV,'beforeunload',this.abort,this);this._5.send(c)},abort:function(){this._5.abort()},_C:function(){var a=this._s;if(!a)return;return this.success()?a.success&&a.success.call(this._g,this):a.failure&&a.failure.call(this._g,this)},waiting:function(){return!!this._n},complete:function(){return this._5&&!this.waiting()},success:function(){if(!this.complete())return false;var a=this._5.status;return(a>=200&&a<300)||a===304||a===1223},failure:function(){if(!this.complete())return false;return!this.success()},text:function(){if(!this.complete())return null;return this._5.responseText},status:function(){if(!this.complete())return null;return this._5.status}})};if(!this.JSON){JSON={}}(function(){function l(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,k,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},m;function r(c){o.lastIndex=0;return o.test(c)?'"'+c.replace(o,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,j=k,i,h=b[a];if(h&&typeof h==='object'&&typeof h.toJSON==='function'){h=h.toJSON(a)}if(typeof m==='function'){h=m.call(b,a,h)}switch(typeof h){case'string':return r(h);case'number':return isFinite(h)?String(h):'null';case'boolean':case'null':return String(h);case'object':if(!h){return'null'}k+=p;i=[];if(Object.prototype.toString.apply(h)==='[object Array]'){g=h.length;for(c=0;c<g;c+=1){i[c]=q(c,h)||'null'}f=i.length===0?'[]':k?'[\n'+k+i.join(',\n'+k)+'\n'+j+']':'['+i.join(',')+']';k=j;return f}if(m&&typeof m==='object'){g=m.length;for(c=0;c<g;c+=1){d=m[c];if(typeof d==='string'){f=q(d,h);if(f){i.push(r(d)+(k?': ':':')+f)}}}}else{for(d in h){if(Object.hasOwnProperty.call(h,d)){f=q(d,h);if(f){i.push(r(d)+(k?': ':':')+f)}}}}f=i.length===0?'{}':k?'{\n'+k+i.join(',\n'+k)+'\n'+j+'}':'{'+i.join(',')+'}';k=j;return f}}Faye.stringify=function(a,b,c){var d;k='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}m=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(g,j){var i;function h(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=h(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return j.call(a,b,f)}n.lastIndex=0;if(n.test(g)){g=g.replace(n,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof j==='function'?h({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.XHRTransport=Faye.Class(Faye.Transport,{request:function(b,c,d){Faye.XHR.request('post',this._4,Faye.toJSON(b),function(a){if(c)c.call(d,JSON.parse(a.text()))})}});Faye.XHRTransport.isUsable=function(a){return Faye.URI.parse(a).isLocal()};Faye.Transport.register('long-polling',Faye.XHRTransport);Faye.JSONPTransport=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:Faye.toJSON(b)},g=document.getElementsByTagName('head')[0],j=document.createElement('script'),i=Faye.JSONPTransport.getCallbackName(),h=Faye.URI.parse(this._4,f);Faye.ENV[i]=function(a){Faye.ENV[i]=undefined;try{delete Faye.ENV[i]}catch(e){}g.removeChild(j);if(c)c.call(d,a)};h.params.jsonp=i;j.type='text/javascript';j.src=h.toURL();g.appendChild(j)}}),{_v:0,getCallbackName:function(){this._v+=1;return'__jsonp'+this._v+'__'}});Faye.JSONPTransport.isUsable=function(a){return true};Faye.Transport.register('callback-polling',Faye.JSONPTransport);
         | 
    
        data/examples/node/faye.js
    CHANGED
    
    | @@ -12,7 +12,7 @@ Faye.extend = function(dest, source, overwrite) { | |
| 12 12 | 
             
            };
         | 
| 13 13 |  | 
| 14 14 | 
             
            Faye.extend(Faye, {
         | 
| 15 | 
            -
              VERSION:          '0.3. | 
| 15 | 
            +
              VERSION:          '0.3.2',
         | 
| 16 16 |  | 
| 17 17 | 
             
              BAYEUX_VERSION:   '1.0',
         | 
| 18 18 | 
             
              ID_LENGTH:        128,
         | 
| @@ -143,6 +143,35 @@ Faye.extend(Faye, { | |
| 143 143 | 
             
                  });
         | 
| 144 144 | 
             
                  return result;
         | 
| 145 145 | 
             
                }
         | 
| 146 | 
            +
              },
         | 
| 147 | 
            +
              
         | 
| 148 | 
            +
              // http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/
         | 
| 149 | 
            +
              toJSON: function(object) {
         | 
| 150 | 
            +
                if (this.stringify)
         | 
| 151 | 
            +
                  return this.stringify(object, function(key, value) {
         | 
| 152 | 
            +
                    return (this[key] instanceof Array)
         | 
| 153 | 
            +
                        ? this[key]
         | 
| 154 | 
            +
                        : value;
         | 
| 155 | 
            +
                  });
         | 
| 156 | 
            +
                
         | 
| 157 | 
            +
                return JSON.stringify(object);
         | 
| 158 | 
            +
              },
         | 
| 159 | 
            +
              
         | 
| 160 | 
            +
              timestamp: function() {
         | 
| 161 | 
            +
                var date   = new Date(),
         | 
| 162 | 
            +
                    year   = date.getFullYear(),
         | 
| 163 | 
            +
                    month  = date.getMonth() + 1,
         | 
| 164 | 
            +
                    day    = date.getDate(),
         | 
| 165 | 
            +
                    hour   = date.getHours(),
         | 
| 166 | 
            +
                    minute = date.getMinutes(),
         | 
| 167 | 
            +
                    second = date.getSeconds();
         | 
| 168 | 
            +
                
         | 
| 169 | 
            +
                var pad = function(n) {
         | 
| 170 | 
            +
                  return n < 10 ? '0' + n : String(n);
         | 
| 171 | 
            +
                };
         | 
| 172 | 
            +
                
         | 
| 173 | 
            +
                return pad(year) + '-' + pad(month) + '-' + pad(day) + ' ' +
         | 
| 174 | 
            +
                       pad(hour) + ':' + pad(minute) + ':' + pad(second);
         | 
| 146 175 | 
             
              }
         | 
| 147 176 | 
             
            });
         | 
| 148 177 |  | 
| @@ -233,6 +262,72 @@ Faye.Observable = { | |
| 233 262 | 
             
            };
         | 
| 234 263 |  | 
| 235 264 |  | 
| 265 | 
            +
            Faye.Logging = {
         | 
| 266 | 
            +
              LOG_LEVELS: {
         | 
| 267 | 
            +
                error:  3,
         | 
| 268 | 
            +
                warn:   2,
         | 
| 269 | 
            +
                info:   1,
         | 
| 270 | 
            +
                debug:  0
         | 
| 271 | 
            +
              },
         | 
| 272 | 
            +
              
         | 
| 273 | 
            +
              logLevel: 'error',
         | 
| 274 | 
            +
              
         | 
| 275 | 
            +
              log: function(message, level) {
         | 
| 276 | 
            +
                if (!Faye.logger) return;
         | 
| 277 | 
            +
                
         | 
| 278 | 
            +
                var levels = Faye.Logging.LOG_LEVELS;
         | 
| 279 | 
            +
                if (levels[Faye.Logging.logLevel] > levels[level]) return;
         | 
| 280 | 
            +
                
         | 
| 281 | 
            +
                var banner = '[' + level.toUpperCase() + '] [Faye',
         | 
| 282 | 
            +
                    klass  = null;
         | 
| 283 | 
            +
                
         | 
| 284 | 
            +
                for (var key in Faye) {
         | 
| 285 | 
            +
                  if (klass) continue;
         | 
| 286 | 
            +
                  if (typeof Faye[key] !== 'function') continue;
         | 
| 287 | 
            +
                  if (this instanceof Faye[key]) klass = key;
         | 
| 288 | 
            +
                }
         | 
| 289 | 
            +
                if (klass) banner += '.' + klass;
         | 
| 290 | 
            +
                banner += '] ';
         | 
| 291 | 
            +
                
         | 
| 292 | 
            +
                Faye.logger(Faye.timestamp() + ' ' + banner + message);
         | 
| 293 | 
            +
              },
         | 
| 294 | 
            +
              
         | 
| 295 | 
            +
              error: function(message) {
         | 
| 296 | 
            +
                this.log(message, 'error');
         | 
| 297 | 
            +
              },
         | 
| 298 | 
            +
              warn: function(message) {
         | 
| 299 | 
            +
                this.log(message, 'warn');
         | 
| 300 | 
            +
              },
         | 
| 301 | 
            +
              info: function(message) {
         | 
| 302 | 
            +
                this.log(message, 'info');
         | 
| 303 | 
            +
              },
         | 
| 304 | 
            +
              debug: function(message) {
         | 
| 305 | 
            +
                this.log(message, 'debug');
         | 
| 306 | 
            +
              }
         | 
| 307 | 
            +
            };
         | 
| 308 | 
            +
             | 
| 309 | 
            +
             | 
| 310 | 
            +
            Faye.Timeouts = {
         | 
| 311 | 
            +
              addTimeout: function(name, delay, callback, scope) {
         | 
| 312 | 
            +
                this._timeouts = this._timeouts || {};
         | 
| 313 | 
            +
                if (this._timeouts.hasOwnProperty(name)) return;
         | 
| 314 | 
            +
                var self = this;
         | 
| 315 | 
            +
                this._timeouts[name] = setTimeout(function() {
         | 
| 316 | 
            +
                  delete self._timeouts[name];
         | 
| 317 | 
            +
                  callback.call(scope);
         | 
| 318 | 
            +
                }, 1000 * delay);
         | 
| 319 | 
            +
              },
         | 
| 320 | 
            +
              
         | 
| 321 | 
            +
              removeTimeout: function(name) {
         | 
| 322 | 
            +
                this._timeouts = this._timeouts || {};
         | 
| 323 | 
            +
                var timeout = this._timeouts[name];
         | 
| 324 | 
            +
                if (!timeout) return;
         | 
| 325 | 
            +
                clearTimeout(timeout);
         | 
| 326 | 
            +
                delete this._timeouts[name];
         | 
| 327 | 
            +
              }
         | 
| 328 | 
            +
            };
         | 
| 329 | 
            +
             | 
| 330 | 
            +
             | 
| 236 331 | 
             
            Faye.Channel = Faye.Class({
         | 
| 237 332 | 
             
              initialize: function(name) {
         | 
| 238 333 | 
             
                this.__id = this.name = name;
         | 
| @@ -300,6 +395,10 @@ Faye.extend(Faye.Channel, { | |
| 300 395 | 
             
                  if (this._value !== undefined) block.call(context, prefix, this._value);
         | 
| 301 396 | 
             
                },
         | 
| 302 397 |  | 
| 398 | 
            +
                getKeys: function() {
         | 
| 399 | 
            +
                  return this.map(function(key, value) { return '/' + key.join('/') });
         | 
| 400 | 
            +
                },
         | 
| 401 | 
            +
                
         | 
| 303 402 | 
             
                map: function(block, context) {
         | 
| 304 403 | 
             
                  var result = [];
         | 
| 305 404 | 
             
                  this.each([], function(path, value) {
         | 
| @@ -389,6 +488,7 @@ Faye.Namespace = Faye.Class({ | |
| 389 488 |  | 
| 390 489 | 
             
            Faye.Transport = Faye.extend(Faye.Class({
         | 
| 391 490 | 
             
              initialize: function(client, endpoint) {
         | 
| 491 | 
            +
                this.debug('Created new transport for ' + endpoint);
         | 
| 392 492 | 
             
                this._client   = client;
         | 
| 393 493 | 
             
                this._endpoint = endpoint;
         | 
| 394 494 | 
             
              },
         | 
| @@ -397,20 +497,34 @@ Faye.Transport = Faye.extend(Faye.Class({ | |
| 397 497 | 
             
                if (!(message instanceof Array) && !message.id)
         | 
| 398 498 | 
             
                  message.id = this._client._namespace.generate();
         | 
| 399 499 |  | 
| 500 | 
            +
                this.debug('Client ' + this._client._clientId +
         | 
| 501 | 
            +
                           ' sending message to ' + this._endpoint + ': ' +
         | 
| 502 | 
            +
                           Faye.toJSON(message));
         | 
| 503 | 
            +
                
         | 
| 400 504 | 
             
                this.request(message, function(responses) {
         | 
| 505 | 
            +
                  this.debug('Client ' + this._client._clientId +
         | 
| 506 | 
            +
                             ' received from ' + this._endpoint + ': ' +
         | 
| 507 | 
            +
                             Faye.toJSON(responses));
         | 
| 508 | 
            +
                  
         | 
| 401 509 | 
             
                  if (!callback) return;
         | 
| 510 | 
            +
                  
         | 
| 511 | 
            +
                  var messages = [], deliverable = true;
         | 
| 402 512 | 
             
                  Faye.each([].concat(responses), function(response) {
         | 
| 403 | 
            -
             | 
| 404 | 
            -
                    if (response.id === message.id)
         | 
| 405 | 
            -
                      callback.call(scope, response) | 
| 513 | 
            +
                
         | 
| 514 | 
            +
                    if (response.id === message.id) {
         | 
| 515 | 
            +
                      if (callback.call(scope, response) === false)
         | 
| 516 | 
            +
                        deliverable = false;
         | 
| 517 | 
            +
                    }
         | 
| 406 518 |  | 
| 407 519 | 
             
                    if (response.advice)
         | 
| 408 520 | 
             
                      this._client.handleAdvice(response.advice);
         | 
| 409 521 |  | 
| 410 522 | 
             
                    if (response.data && response.channel)
         | 
| 411 | 
            -
                       | 
| 523 | 
            +
                      messages.push(response);
         | 
| 412 524 |  | 
| 413 525 | 
             
                  }, this);
         | 
| 526 | 
            +
                  
         | 
| 527 | 
            +
                  if (deliverable) this._client.deliverMessages(messages);
         | 
| 414 528 | 
             
                }, this);
         | 
| 415 529 | 
             
              }
         | 
| 416 530 | 
             
            }), {
         | 
| @@ -444,23 +558,32 @@ Faye.Transport = Faye.extend(Faye.Class({ | |
| 444 558 | 
             
              }
         | 
| 445 559 | 
             
            });
         | 
| 446 560 |  | 
| 561 | 
            +
            Faye.extend(Faye.Transport.prototype, Faye.Logging);
         | 
| 562 | 
            +
             | 
| 447 563 |  | 
| 448 564 | 
             
            Faye.Client = Faye.Class({
         | 
| 449 | 
            -
              UNCONNECTED: | 
| 450 | 
            -
              CONNECTING: | 
| 451 | 
            -
              CONNECTED: | 
| 452 | 
            -
              DISCONNECTED: | 
| 565 | 
            +
              UNCONNECTED:          1,
         | 
| 566 | 
            +
              CONNECTING:           2,
         | 
| 567 | 
            +
              CONNECTED:            3,
         | 
| 568 | 
            +
              DISCONNECTED:         4,
         | 
| 569 | 
            +
              
         | 
| 570 | 
            +
              HANDSHAKE:            'handshake',
         | 
| 571 | 
            +
              RETRY:                'retry',
         | 
| 572 | 
            +
              NONE:                 'none',
         | 
| 453 573 |  | 
| 454 | 
            -
               | 
| 455 | 
            -
              RETRY:         'retry',
         | 
| 456 | 
            -
              NONE:          'none',
         | 
| 574 | 
            +
              CONNECTION_TIMEOUT:   60.0,
         | 
| 457 575 |  | 
| 458 | 
            -
              DEFAULT_ENDPOINT: | 
| 459 | 
            -
              MAX_DELAY: | 
| 460 | 
            -
              INTERVAL: | 
| 576 | 
            +
              DEFAULT_ENDPOINT:     '/bayeux',
         | 
| 577 | 
            +
              MAX_DELAY:            0.1,
         | 
| 578 | 
            +
              INTERVAL:             1000.0,
         | 
| 461 579 |  | 
| 462 | 
            -
              initialize: function(endpoint) {
         | 
| 580 | 
            +
              initialize: function(endpoint, options) {
         | 
| 581 | 
            +
                this.info('New client created for ' + endpoint);
         | 
| 582 | 
            +
                
         | 
| 463 583 | 
             
                this._endpoint  = endpoint || this.DEFAULT_ENDPOINT;
         | 
| 584 | 
            +
                this._options   = options || {};
         | 
| 585 | 
            +
                this._timeout   = this._options.timeout || this.CONNECTION_TIMEOUT;
         | 
| 586 | 
            +
                
         | 
| 464 587 | 
             
                this._transport = Faye.Transport.get(this);
         | 
| 465 588 | 
             
                this._state     = this.UNCONNECTED;
         | 
| 466 589 | 
             
                this._namespace = new Faye.Namespace();
         | 
| @@ -500,6 +623,8 @@ Faye.Client = Faye.Class({ | |
| 500 623 | 
             
                this._state = this.CONNECTING;
         | 
| 501 624 | 
             
                var self = this;
         | 
| 502 625 |  | 
| 626 | 
            +
                this.info('Initiating handshake with ' + this._endpoint);
         | 
| 627 | 
            +
                
         | 
| 503 628 | 
             
                this._transport.send({
         | 
| 504 629 | 
             
                  channel:      Faye.Channel.HANDSHAKE,
         | 
| 505 630 | 
             
                  version:      Faye.BAYEUX_VERSION,
         | 
| @@ -508,6 +633,7 @@ Faye.Client = Faye.Class({ | |
| 508 633 | 
             
                }, function(response) {
         | 
| 509 634 |  | 
| 510 635 | 
             
                  if (!response.successful) {
         | 
| 636 | 
            +
                    this.info('Handshake unsuccessful');
         | 
| 511 637 | 
             
                    setTimeout(function() { self.handshake(callback, scope) }, this._advice.interval);
         | 
| 512 638 | 
             
                    return this._state = this.UNCONNECTED;
         | 
| 513 639 | 
             
                  }
         | 
| @@ -516,6 +642,7 @@ Faye.Client = Faye.Class({ | |
| 516 642 | 
             
                  this._clientId  = response.clientId;
         | 
| 517 643 | 
             
                  this._transport = Faye.Transport.get(this, response.supportedConnectionTypes);
         | 
| 518 644 |  | 
| 645 | 
            +
                  this.info('Handshake successful: ' + this._clientId);
         | 
| 519 646 | 
             
                  if (callback) callback.call(scope);
         | 
| 520 647 | 
             
                }, this);
         | 
| 521 648 | 
             
              },
         | 
| @@ -533,14 +660,17 @@ Faye.Client = Faye.Class({ | |
| 533 660 | 
             
                if (this._advice.reconnect === this.NONE) return;
         | 
| 534 661 | 
             
                if (this._state === this.DISCONNECTED) return;
         | 
| 535 662 |  | 
| 536 | 
            -
                if (this._advice.reconnect === this.HANDSHAKE || this._state === this.UNCONNECTED)
         | 
| 663 | 
            +
                if (this._advice.reconnect === this.HANDSHAKE || this._state === this.UNCONNECTED) {
         | 
| 664 | 
            +
                  this._beginReconnectTimeout();
         | 
| 537 665 | 
             
                  return this.handshake(function() { this.connect(callback, scope) }, this);
         | 
| 666 | 
            +
                }
         | 
| 538 667 |  | 
| 539 668 | 
             
                if (this._state === this.CONNECTING)
         | 
| 540 669 | 
             
                  return this.callback(callback, scope);
         | 
| 541 670 |  | 
| 542 671 | 
             
                if (this._state !== this.CONNECTED) return;
         | 
| 543 672 |  | 
| 673 | 
            +
                this.info('Calling deferred actions for ' + this._clientId);
         | 
| 544 674 | 
             
                this.setDeferredStatus('succeeded');
         | 
| 545 675 | 
             
                this.setDeferredStatus('deferred');
         | 
| 546 676 | 
             
                if (callback) callback.call(scope);
         | 
| @@ -548,6 +678,7 @@ Faye.Client = Faye.Class({ | |
| 548 678 | 
             
                if (this._connectionId) return;
         | 
| 549 679 | 
             
                this._connectionId = this._namespace.generate();
         | 
| 550 680 | 
             
                var self = this;
         | 
| 681 | 
            +
                this.info('Initiating connection for ' + this._clientId);
         | 
| 551 682 |  | 
| 552 683 | 
             
                this._transport.send({
         | 
| 553 684 | 
             
                  channel:        Faye.Channel.CONNECT,
         | 
| @@ -555,10 +686,15 @@ Faye.Client = Faye.Class({ | |
| 555 686 | 
             
                  connectionType: this._transport.connectionType,
         | 
| 556 687 | 
             
                  id:             this._connectionId
         | 
| 557 688 |  | 
| 558 | 
            -
                }, function(response) {
         | 
| 689 | 
            +
                }, this._verifyClientId(function(response) {
         | 
| 559 690 | 
             
                  delete this._connectionId;
         | 
| 691 | 
            +
                  this.removeTimeout('reconnect');
         | 
| 692 | 
            +
                  
         | 
| 693 | 
            +
                  this.info('Closed connection for ' + this._clientId);
         | 
| 560 694 | 
             
                  setTimeout(function() { self.connect() }, this._advice.interval);
         | 
| 561 | 
            -
                } | 
| 695 | 
            +
                }));
         | 
| 696 | 
            +
                
         | 
| 697 | 
            +
                this._beginReconnectTimeout();
         | 
| 562 698 | 
             
              },
         | 
| 563 699 |  | 
| 564 700 | 
             
              // Request                              Response
         | 
| @@ -572,11 +708,14 @@ Faye.Client = Faye.Class({ | |
| 572 708 | 
             
                if (this._state !== this.CONNECTED) return;
         | 
| 573 709 | 
             
                this._state = this.DISCONNECTED;
         | 
| 574 710 |  | 
| 711 | 
            +
                this.info('Disconnecting ' + this._clientId);
         | 
| 712 | 
            +
                
         | 
| 575 713 | 
             
                this._transport.send({
         | 
| 576 714 | 
             
                  channel:    Faye.Channel.DISCONNECT,
         | 
| 577 715 | 
             
                  clientId:   this._clientId
         | 
| 578 716 | 
             
                });
         | 
| 579 717 |  | 
| 718 | 
            +
                this.info('Clearing channel listeners for ' + this._clientId);
         | 
| 580 719 | 
             
                this._channels = new Faye.Channel.Tree();
         | 
| 581 720 | 
             
              },
         | 
| 582 721 |  | 
| @@ -596,19 +735,25 @@ Faye.Client = Faye.Class({ | |
| 596 735 | 
             
                  channels = [].concat(channels);
         | 
| 597 736 | 
             
                  this._validateChannels(channels);
         | 
| 598 737 |  | 
| 738 | 
            +
                  this.info('Client ' + this._clientId + ' attempting to subscribe to [' +
         | 
| 739 | 
            +
                            channels.join(', ') + ']');
         | 
| 740 | 
            +
                  
         | 
| 599 741 | 
             
                  this._transport.send({
         | 
| 600 742 | 
             
                    channel:      Faye.Channel.SUBSCRIBE,
         | 
| 601 743 | 
             
                    clientId:     this._clientId,
         | 
| 602 744 | 
             
                    subscription: channels
         | 
| 603 745 |  | 
| 604 | 
            -
                  }, function(response) {
         | 
| 605 | 
            -
                    if (!response.successful) return;
         | 
| 746 | 
            +
                  }, this._verifyClientId(function(response) {
         | 
| 747 | 
            +
                    if (!response.successful || !callback) return;
         | 
| 606 748 |  | 
| 749 | 
            +
                    this.info('Subscription acknowledged for ' + this._clientId + ' to [' +
         | 
| 750 | 
            +
                              channels.join(', ') + ']');
         | 
| 751 | 
            +
                  
         | 
| 607 752 | 
             
                    channels = [].concat(response.subscription);
         | 
| 608 753 | 
             
                    Faye.each(channels, function(channel) {
         | 
| 609 754 | 
             
                      this._channels.set(channel, [callback, scope]);
         | 
| 610 755 | 
             
                    }, this);
         | 
| 611 | 
            -
                  } | 
| 756 | 
            +
                  }));
         | 
| 612 757 |  | 
| 613 758 | 
             
                }, this);
         | 
| 614 759 | 
             
              },
         | 
| @@ -629,19 +774,25 @@ Faye.Client = Faye.Class({ | |
| 629 774 | 
             
                  channels = [].concat(channels);
         | 
| 630 775 | 
             
                  this._validateChannels(channels);
         | 
| 631 776 |  | 
| 777 | 
            +
                  this.info('Client ' + this._clientId + ' attempting to unsubscribe from [' +
         | 
| 778 | 
            +
                            channels.join(', ') + ']');
         | 
| 779 | 
            +
                  
         | 
| 632 780 | 
             
                  this._transport.send({
         | 
| 633 781 | 
             
                    channel:      Faye.Channel.UNSUBSCRIBE,
         | 
| 634 782 | 
             
                    clientId:     this._clientId,
         | 
| 635 783 | 
             
                    subscription: channels
         | 
| 636 784 |  | 
| 637 | 
            -
                  }, function(response) {
         | 
| 785 | 
            +
                  }, this._verifyClientId(function(response) {
         | 
| 638 786 | 
             
                    if (!response.successful) return;
         | 
| 639 787 |  | 
| 788 | 
            +
                    this.info('Unsubscription acknowledged for ' + this._clientId + ' from [' +
         | 
| 789 | 
            +
                              channels.join(', ') + ']');
         | 
| 790 | 
            +
                  
         | 
| 640 791 | 
             
                    channels = [].concat(response.subscription);
         | 
| 641 792 | 
             
                    Faye.each(channels, function(channel) {
         | 
| 642 793 | 
             
                      this._channels.set(channel, null);
         | 
| 643 794 | 
             
                    }, this);
         | 
| 644 | 
            -
                  } | 
| 795 | 
            +
                  }));
         | 
| 645 796 |  | 
| 646 797 | 
             
                }, this);
         | 
| 647 798 | 
             
              },
         | 
| @@ -657,19 +808,16 @@ Faye.Client = Faye.Class({ | |
| 657 808 |  | 
| 658 809 | 
             
                  this._validateChannels([channel]);
         | 
| 659 810 |  | 
| 811 | 
            +
                  this.info('Client ' + this._clientId + ' queueing published message to ' +
         | 
| 812 | 
            +
                            channel + ': ' + Faye.toJSON(data));
         | 
| 813 | 
            +
                  
         | 
| 660 814 | 
             
                  this._enqueue({
         | 
| 661 815 | 
             
                    channel:      channel,
         | 
| 662 816 | 
             
                    data:         data,
         | 
| 663 817 | 
             
                    clientId:     this._clientId
         | 
| 664 818 | 
             
                  });
         | 
| 665 819 |  | 
| 666 | 
            -
                   | 
| 667 | 
            -
                  var self = this;
         | 
| 668 | 
            -
                  
         | 
| 669 | 
            -
                  this._timeout = setTimeout(function() {
         | 
| 670 | 
            -
                    delete self._timeout;
         | 
| 671 | 
            -
                    self._flush();
         | 
| 672 | 
            -
                  }, this.MAX_DELAY * 1000);
         | 
| 820 | 
            +
                  this.addTimeout('publish', this.MAX_DELAY, this._flush, this);
         | 
| 673 821 |  | 
| 674 822 | 
             
                }, this);
         | 
| 675 823 | 
             
              },
         | 
| @@ -679,12 +827,30 @@ Faye.Client = Faye.Class({ | |
| 679 827 | 
             
                if (this._advice.reconnect === this.HANDSHAKE) this._clientId = null;
         | 
| 680 828 | 
             
              },
         | 
| 681 829 |  | 
| 682 | 
            -
               | 
| 683 | 
            -
                 | 
| 684 | 
            -
             | 
| 685 | 
            -
             | 
| 686 | 
            -
                   | 
| 687 | 
            -
             | 
| 830 | 
            +
              deliverMessages: function(messages) {
         | 
| 831 | 
            +
                Faye.each(messages, function(message) {
         | 
| 832 | 
            +
                  this.info('Client ' + this._clientId + ' calling listeners for ' +
         | 
| 833 | 
            +
                            message.channel + ' with ' + Faye.toJSON(message.data));
         | 
| 834 | 
            +
                  
         | 
| 835 | 
            +
                  var channels = this._channels.glob(message.channel);
         | 
| 836 | 
            +
                  Faye.each(channels, function(callback) {
         | 
| 837 | 
            +
                    if (!callback) return;
         | 
| 838 | 
            +
                    callback[0].call(callback[1], message.data);
         | 
| 839 | 
            +
                  });
         | 
| 840 | 
            +
                }, this);
         | 
| 841 | 
            +
              },
         | 
| 842 | 
            +
              
         | 
| 843 | 
            +
              _beginReconnectTimeout: function() {
         | 
| 844 | 
            +
                this.addTimeout('reconnect', this._timeout, function() {
         | 
| 845 | 
            +
                  delete this._connectionId;
         | 
| 846 | 
            +
                  delete this._clientId;
         | 
| 847 | 
            +
                  this._state = this.UNCONNECTED;
         | 
| 848 | 
            +
                  
         | 
| 849 | 
            +
                  this.info('Server took >' + this._timeout + 's to reply to connection for ' +
         | 
| 850 | 
            +
                            this._clientId + ': attempting to reconnect');
         | 
| 851 | 
            +
                  
         | 
| 852 | 
            +
                  this.subscribe(this._channels.getKeys());
         | 
| 853 | 
            +
                }, this);
         | 
| 688 854 | 
             
              },
         | 
| 689 855 |  | 
| 690 856 | 
             
              _enqueue: function(message) {
         | 
| @@ -703,10 +869,21 @@ Faye.Client = Faye.Class({ | |
| 703 869 | 
             
                  if (!Faye.Channel.isSubscribable(channel))
         | 
| 704 870 | 
             
                    throw 'Clients may not subscribe to channel "' + channel + '"';
         | 
| 705 871 | 
             
                });
         | 
| 872 | 
            +
              },
         | 
| 873 | 
            +
              
         | 
| 874 | 
            +
              _verifyClientId: function(callback) {
         | 
| 875 | 
            +
                var self = this;
         | 
| 876 | 
            +
                return function(response) {
         | 
| 877 | 
            +
                  if (response.clientId !== self._clientId) return false;
         | 
| 878 | 
            +
                  callback.call(self, response);
         | 
| 879 | 
            +
                  return true;
         | 
| 880 | 
            +
                };
         | 
| 706 881 | 
             
              }
         | 
| 707 882 | 
             
            });
         | 
| 708 883 |  | 
| 709 884 | 
             
            Faye.extend(Faye.Client.prototype, Faye.Deferrable);
         | 
| 885 | 
            +
            Faye.extend(Faye.Client.prototype, Faye.Timeouts);
         | 
| 886 | 
            +
            Faye.extend(Faye.Client.prototype, Faye.Logging);
         | 
| 710 887 |  | 
| 711 888 |  | 
| 712 889 | 
             
            Faye.Set = Faye.Class({
         | 
| @@ -757,6 +934,7 @@ Faye.Set = Faye.Class({ | |
| 757 934 |  | 
| 758 935 | 
             
            Faye.Server = Faye.Class({
         | 
| 759 936 | 
             
              initialize: function(options) {
         | 
| 937 | 
            +
                this.info('New server created');
         | 
| 760 938 | 
             
                this._options   = options || {};
         | 
| 761 939 | 
             
                this._channels  = new Faye.Channel.Tree();
         | 
| 762 940 | 
             
                this._clients   = {};
         | 
| @@ -770,6 +948,8 @@ Faye.Server = Faye.Class({ | |
| 770 948 | 
             
              },
         | 
| 771 949 |  | 
| 772 950 | 
             
              process: function(messages, local, callback) {
         | 
| 951 | 
            +
                this.debug('Processing messages from ' + (local ? 'LOCAL' : 'REMOTE') + ' client');
         | 
| 952 | 
            +
                
         | 
| 773 953 | 
             
                messages = [].concat(messages);
         | 
| 774 954 | 
             
                var processed = 0, responses = [];
         | 
| 775 955 |  | 
| @@ -777,8 +957,9 @@ Faye.Server = Faye.Class({ | |
| 777 957 | 
             
                  this._handle(message, local, function(reply) {
         | 
| 778 958 | 
             
                    responses = responses.concat(reply);
         | 
| 779 959 | 
             
                    processed += 1;
         | 
| 780 | 
            -
                    if (processed  | 
| 781 | 
            -
             | 
| 960 | 
            +
                    if (processed < messages.length) return;
         | 
| 961 | 
            +
                    callback(responses);
         | 
| 962 | 
            +
                  }, this);
         | 
| 782 963 | 
             
                }, this);
         | 
| 783 964 | 
             
              },
         | 
| 784 965 |  | 
| @@ -803,42 +984,54 @@ Faye.Server = Faye.Class({ | |
| 803 984 | 
             
                delete this._clients[client.id];
         | 
| 804 985 | 
             
              },
         | 
| 805 986 |  | 
| 806 | 
            -
              _handle: function(message, local, callback) {
         | 
| 807 | 
            -
                var  | 
| 808 | 
            -
                    channel  = message.channel,
         | 
| 987 | 
            +
              _handle: function(message, local, callback, scope) {
         | 
| 988 | 
            +
                var channel = message.channel,
         | 
| 809 989 | 
             
                    response;
         | 
| 810 990 |  | 
| 811 991 | 
             
                message.__id = Faye.random();
         | 
| 812 | 
            -
                Faye.each(this._channels.glob(channel), function(c) { | 
| 992 | 
            +
                Faye.each(this._channels.glob(channel), function(c) {
         | 
| 993 | 
            +
                  c.push(message);
         | 
| 994 | 
            +
                  this.info('Publishing message ' + Faye.toJSON(message.data) +
         | 
| 995 | 
            +
                            ' from client ' + clientId + ' to ' + c.name);
         | 
| 996 | 
            +
                }, this);
         | 
| 813 997 |  | 
| 814 998 | 
             
                if (Faye.Channel.isMeta(channel)) {
         | 
| 815 999 | 
             
                  response = this[Faye.Channel.parse(channel)[1]](message, local);
         | 
| 816 1000 |  | 
| 817 | 
            -
                  clientId =  | 
| 1001 | 
            +
                  var clientId = response.clientId;
         | 
| 818 1002 | 
             
                  response.advice = response.advice || {};
         | 
| 819 1003 | 
             
                  Faye.extend(response.advice, {
         | 
| 820 1004 | 
             
                    reconnect:  this._clients.hasOwnProperty(clientId) ? 'retry' : 'handshake',
         | 
| 821 | 
            -
                    interval:   Faye.Connection.INTERVAL * 1000
         | 
| 1005 | 
            +
                    interval:   Math.floor(Faye.Connection.prototype.INTERVAL * 1000)
         | 
| 822 1006 | 
             
                  }, false);
         | 
| 823 1007 |  | 
| 824 | 
            -
                  response.id = message.id;
         | 
| 825 | 
            -
                  
         | 
| 826 1008 | 
             
                  if (response.channel !== Faye.Channel.CONNECT ||
         | 
| 827 1009 | 
             
                      response.successful !== true)
         | 
| 828 | 
            -
                    return callback(response);
         | 
| 1010 | 
            +
                    return callback.call(scope, response);
         | 
| 829 1011 |  | 
| 1012 | 
            +
                  this.info('Accepting connection from ' + response.clientId);
         | 
| 830 1013 | 
             
                  return this._connection(response.clientId).connect(function(events) {
         | 
| 1014 | 
            +
                    this.info('Sending event messages to ' + response.clientId);
         | 
| 1015 | 
            +
                    this.debug('Events for ' + response.clientId + ': ' + Faye.toJSON(events));
         | 
| 831 1016 | 
             
                    Faye.each(events, function(e) { delete e.__id });
         | 
| 832 | 
            -
                    callback([response].concat(events));
         | 
| 833 | 
            -
                  });
         | 
| 1017 | 
            +
                    callback.call(scope, [response].concat(events));
         | 
| 1018 | 
            +
                  }, this);
         | 
| 834 1019 | 
             
                }
         | 
| 835 1020 |  | 
| 836 1021 | 
             
                if (!message.clientId || Faye.Channel.isService(channel))
         | 
| 837 1022 | 
             
                  return callback([]);
         | 
| 838 1023 |  | 
| 839 | 
            -
                 | 
| 840 | 
            -
             | 
| 841 | 
            -
             | 
| 1024 | 
            +
                response = this._makeResponse(message);
         | 
| 1025 | 
            +
                response.successful = true;
         | 
| 1026 | 
            +
                callback(response);
         | 
| 1027 | 
            +
              },
         | 
| 1028 | 
            +
              
         | 
| 1029 | 
            +
              _makeResponse: function(message) {
         | 
| 1030 | 
            +
                var response = {};
         | 
| 1031 | 
            +
                Faye.each(['id', 'clientId', 'channel'], function(field) {
         | 
| 1032 | 
            +
                  if (message[field]) response[field] = message[field];
         | 
| 1033 | 
            +
                });
         | 
| 1034 | 
            +
                return response;
         | 
| 842 1035 | 
             
              },
         | 
| 843 1036 |  | 
| 844 1037 | 
             
              // MUST contain  * version
         | 
| @@ -847,9 +1040,8 @@ Faye.Server = Faye.Class({ | |
| 847 1040 | 
             
              //               * ext
         | 
| 848 1041 | 
             
              //               * id
         | 
| 849 1042 | 
             
              handshake: function(message, local) {
         | 
| 850 | 
            -
                var response =  | 
| 851 | 
            -
             | 
| 852 | 
            -
                                 id:        message.id };
         | 
| 1043 | 
            +
                var response = this._makeResponse(message);
         | 
| 1044 | 
            +
                response.version = Faye.BAYEUX_VERSION;
         | 
| 853 1045 |  | 
| 854 1046 | 
             
                if (!message.version)
         | 
| 855 1047 | 
             
                  response.error = Faye.Error.parameterMissing('version');
         | 
| @@ -876,6 +1068,7 @@ Faye.Server = Faye.Class({ | |
| 876 1068 |  | 
| 877 1069 | 
             
                var clientId = this._namespace.generate();
         | 
| 878 1070 | 
             
                response.clientId = this._connection(clientId).id;
         | 
| 1071 | 
            +
                this.info('Accepting handshake from client ' + response.clientId);
         | 
| 879 1072 | 
             
                return response;
         | 
| 880 1073 | 
             
              },
         | 
| 881 1074 |  | 
| @@ -884,8 +1077,7 @@ Faye.Server = Faye.Class({ | |
| 884 1077 | 
             
              // MAY contain   * ext
         | 
| 885 1078 | 
             
              //               * id
         | 
| 886 1079 | 
             
              connect: function(message, local) {
         | 
| 887 | 
            -
                var response =  | 
| 888 | 
            -
                                 id:        message.id };
         | 
| 1080 | 
            +
                var response = this._makeResponse(message);
         | 
| 889 1081 |  | 
| 890 1082 | 
             
                var clientId = message.clientId,
         | 
| 891 1083 | 
             
                    client   = clientId ? this._clients[clientId] : null,
         | 
| @@ -896,6 +1088,7 @@ Faye.Server = Faye.Class({ | |
| 896 1088 | 
             
                if (!connectionType) response.error = Faye.Error.parameterMissing('connectionType');
         | 
| 897 1089 |  | 
| 898 1090 | 
             
                response.successful = !response.error;
         | 
| 1091 | 
            +
                if (!response.successful) delete response.clientId;
         | 
| 899 1092 | 
             
                if (!response.successful) return response;
         | 
| 900 1093 |  | 
| 901 1094 | 
             
                response.clientId = client.id;
         | 
| @@ -906,8 +1099,7 @@ Faye.Server = Faye.Class({ | |
| 906 1099 | 
             
              // MAY contain   * ext
         | 
| 907 1100 | 
             
              //               * id
         | 
| 908 1101 | 
             
              disconnect: function(message, local) {
         | 
| 909 | 
            -
                var response =  | 
| 910 | 
            -
                                 id:        message.id };
         | 
| 1102 | 
            +
                var response = this._makeResponse(message);
         | 
| 911 1103 |  | 
| 912 1104 | 
             
                var clientId = message.clientId,
         | 
| 913 1105 | 
             
                    client   = clientId ? this._clients[clientId] : null;
         | 
| @@ -916,10 +1108,12 @@ Faye.Server = Faye.Class({ | |
| 916 1108 | 
             
                if (!clientId) response.error = Faye.Error.parameterMissing('clientId');
         | 
| 917 1109 |  | 
| 918 1110 | 
             
                response.successful = !response.error;
         | 
| 1111 | 
            +
                if (!response.successful) delete response.clientId;
         | 
| 919 1112 | 
             
                if (!response.successful) return response;
         | 
| 920 1113 |  | 
| 921 1114 | 
             
                this._destroyClient(client);
         | 
| 922 1115 |  | 
| 1116 | 
            +
                this.info('Disconnected client: ' + clientId);
         | 
| 923 1117 | 
             
                response.clientId = clientId;
         | 
| 924 1118 | 
             
                return response;
         | 
| 925 1119 | 
             
              },
         | 
| @@ -929,9 +1123,7 @@ Faye.Server = Faye.Class({ | |
| 929 1123 | 
             
              // MAY contain   * ext
         | 
| 930 1124 | 
             
              //               * id
         | 
| 931 1125 | 
             
              subscribe: function(message, local) {
         | 
| 932 | 
            -
                var response | 
| 933 | 
            -
                                     clientId:  message.clientId,
         | 
| 934 | 
            -
                                     id:        message.id };
         | 
| 1126 | 
            +
                var response = this._makeResponse(message);
         | 
| 935 1127 |  | 
| 936 1128 | 
             
                var clientId     = message.clientId,
         | 
| 937 1129 | 
             
                    client       = clientId ? this._clients[clientId] : null,
         | 
| @@ -952,6 +1144,8 @@ Faye.Server = Faye.Class({ | |
| 952 1144 |  | 
| 953 1145 | 
             
                  if (response.error) return;
         | 
| 954 1146 | 
             
                  channel = this._channels.findOrCreate(channel);
         | 
| 1147 | 
            +
                  
         | 
| 1148 | 
            +
                  this.info('Subscribing client ' + clientId + ' to ' + channel.name);
         | 
| 955 1149 | 
             
                  client.subscribe(channel);
         | 
| 956 1150 | 
             
                }, this);
         | 
| 957 1151 |  | 
| @@ -964,9 +1158,7 @@ Faye.Server = Faye.Class({ | |
| 964 1158 | 
             
              // MAY contain   * ext
         | 
| 965 1159 | 
             
              //               * id
         | 
| 966 1160 | 
             
              unsubscribe: function(message, local) {
         | 
| 967 | 
            -
                var response | 
| 968 | 
            -
                                     clientId:  message.clientId,
         | 
| 969 | 
            -
                                     id:        message.id };
         | 
| 1161 | 
            +
                var response = this._makeResponse(message);
         | 
| 970 1162 |  | 
| 971 1163 | 
             
                var clientId     = message.clientId,
         | 
| 972 1164 | 
             
                    client       = clientId ? this._clients[clientId] : null,
         | 
| @@ -985,7 +1177,10 @@ Faye.Server = Faye.Class({ | |
| 985 1177 | 
             
                    return response.error = Faye.Error.channelInvalid(channel);
         | 
| 986 1178 |  | 
| 987 1179 | 
             
                  channel = this._channels.get(channel);
         | 
| 988 | 
            -
                  if (channel)  | 
| 1180 | 
            +
                  if (!channel) return;
         | 
| 1181 | 
            +
                  
         | 
| 1182 | 
            +
                  this.info('Unsubscribing client ' + clientId + ' from ' + channel.name);
         | 
| 1183 | 
            +
                  client.unsubscribe(channel);
         | 
| 989 1184 | 
             
                }, this);
         | 
| 990 1185 |  | 
| 991 1186 | 
             
                response.successful = !response.error;
         | 
| @@ -993,6 +1188,8 @@ Faye.Server = Faye.Class({ | |
| 993 1188 | 
             
              }
         | 
| 994 1189 | 
             
            });
         | 
| 995 1190 |  | 
| 1191 | 
            +
            Faye.extend(Faye.Server.prototype, Faye.Logging);
         | 
| 1192 | 
            +
             | 
| 996 1193 |  | 
| 997 1194 | 
             
            Faye.Connection = Faye.Class({
         | 
| 998 1195 | 
             
              MAX_DELAY:  0.1,
         | 
| @@ -1002,12 +1199,10 @@ Faye.Connection = Faye.Class({ | |
| 1002 1199 | 
             
              initialize: function(id, options) {
         | 
| 1003 1200 | 
             
                this.id         = id;
         | 
| 1004 1201 | 
             
                this._options   = options;
         | 
| 1202 | 
            +
                this._timeout   = this._options.timeout || this.TIMEOUT;
         | 
| 1005 1203 | 
             
                this._channels  = new Faye.Set();
         | 
| 1006 1204 | 
             
                this._inbox     = new Faye.Set();
         | 
| 1007 | 
            -
             | 
| 1008 | 
            -
              
         | 
| 1009 | 
            -
              getTimeout: function() {
         | 
| 1010 | 
            -
                return this._options.timeout || this.TIMEOUT;
         | 
| 1205 | 
            +
                this._connected = false
         | 
| 1011 1206 | 
             
              },
         | 
| 1012 1207 |  | 
| 1013 1208 | 
             
              _onMessage: function(event) {
         | 
| @@ -1027,16 +1222,12 @@ Faye.Connection = Faye.Class({ | |
| 1027 1222 | 
             
                channel.stopObserving('message', this._onMessage, this);
         | 
| 1028 1223 | 
             
              },
         | 
| 1029 1224 |  | 
| 1030 | 
            -
              connect: function(callback) {
         | 
| 1031 | 
            -
                this.callback(callback);
         | 
| 1225 | 
            +
              connect: function(callback, scope) {
         | 
| 1226 | 
            +
                this.callback(callback, scope);
         | 
| 1032 1227 | 
             
                if (this._connected) return;
         | 
| 1033 1228 |  | 
| 1034 1229 | 
             
                this._connected = true;
         | 
| 1035 | 
            -
                
         | 
| 1036 | 
            -
                if (this._deletionTimeout) {
         | 
| 1037 | 
            -
                  clearTimeout(this._deletionTimeout);
         | 
| 1038 | 
            -
                  delete this._deletionTimeout;
         | 
| 1039 | 
            -
                }
         | 
| 1230 | 
            +
                this.removeTimeout('deletion');
         | 
| 1040 1231 |  | 
| 1041 1232 | 
             
                this._beginDeliveryTimeout();
         | 
| 1042 1233 | 
             
                this._beginConnectionTimeout();
         | 
| @@ -1059,50 +1250,29 @@ Faye.Connection = Faye.Class({ | |
| 1059 1250 | 
             
              },
         | 
| 1060 1251 |  | 
| 1061 1252 | 
             
              _beginDeliveryTimeout: function() {
         | 
| 1062 | 
            -
                if ( | 
| 1063 | 
            -
             | 
| 1064 | 
            -
                
         | 
| 1065 | 
            -
                var self = this;
         | 
| 1066 | 
            -
                this._deliveryTimeout = setTimeout(function () { self.flush() },
         | 
| 1067 | 
            -
                                                   this.MAX_DELAY * 1000);
         | 
| 1253 | 
            +
                if (!this._connected || this._inbox.isEmpty()) return;
         | 
| 1254 | 
            +
                this.addTimeout('delivery', this.MAX_DELAY, this.flush, this);
         | 
| 1068 1255 | 
             
              },
         | 
| 1069 1256 |  | 
| 1070 1257 | 
             
              _beginConnectionTimeout: function() {
         | 
| 1071 | 
            -
                if ( | 
| 1072 | 
            -
             | 
| 1073 | 
            -
                
         | 
| 1074 | 
            -
                var self = this;
         | 
| 1075 | 
            -
                this._connectionTimeout = setTimeout(function() { self.flush() },
         | 
| 1076 | 
            -
                                                     this.getTimeout() * 1000);
         | 
| 1258 | 
            +
                if (!this._connected) return;
         | 
| 1259 | 
            +
                this.addTimeout('connection', this._timeout, this.flush, this);
         | 
| 1077 1260 | 
             
              },
         | 
| 1078 1261 |  | 
| 1079 1262 | 
             
              _releaseConnection: function() {
         | 
| 1080 | 
            -
                 | 
| 1081 | 
            -
             | 
| 1082 | 
            -
                  delete this._connectionTimeout;
         | 
| 1083 | 
            -
                }
         | 
| 1084 | 
            -
                
         | 
| 1085 | 
            -
                if (this._deliveryTimeout) {
         | 
| 1086 | 
            -
                  clearTimeout(this._deliveryTimeout);
         | 
| 1087 | 
            -
                  delete this._deliveryTimeout;
         | 
| 1088 | 
            -
                }
         | 
| 1089 | 
            -
                
         | 
| 1263 | 
            +
                this.removeTimeout('connection');
         | 
| 1264 | 
            +
                this.removeTimeout('delivery');
         | 
| 1090 1265 | 
             
                this._connected = false;
         | 
| 1091 | 
            -
                this._scheduleForDeletion();
         | 
| 1092 | 
            -
              },
         | 
| 1093 | 
            -
              
         | 
| 1094 | 
            -
              _scheduleForDeletion: function() {
         | 
| 1095 | 
            -
                if (this._deletionTimeout) return;
         | 
| 1096 | 
            -
                var self = this;
         | 
| 1097 1266 |  | 
| 1098 | 
            -
                this. | 
| 1099 | 
            -
                   | 
| 1100 | 
            -
                },  | 
| 1267 | 
            +
                this.addTimeout('deletion', 10 * this.INTERVAL, function() {
         | 
| 1268 | 
            +
                  this.fire('staleClient', this);
         | 
| 1269 | 
            +
                }, this);
         | 
| 1101 1270 | 
             
              }
         | 
| 1102 1271 | 
             
            });
         | 
| 1103 1272 |  | 
| 1104 1273 | 
             
            Faye.extend(Faye.Connection.prototype, Faye.Deferrable);
         | 
| 1105 1274 | 
             
            Faye.extend(Faye.Connection.prototype, Faye.Observable);
         | 
| 1275 | 
            +
            Faye.extend(Faye.Connection.prototype, Faye.Timeouts);
         | 
| 1106 1276 |  | 
| 1107 1277 |  | 
| 1108 1278 | 
             
            Faye.Error = Faye.Class({
         | 
| @@ -1170,53 +1340,6 @@ Faye.Error.serverError = function() { | |
| 1170 1340 |  | 
| 1171 1341 |  | 
| 1172 1342 |  | 
| 1173 | 
            -
            Faye.NodeHttpTransport = Faye.Class(Faye.Transport, {
         | 
| 1174 | 
            -
              request: function(message, callback, scope) {
         | 
| 1175 | 
            -
                var params  = {message: JSON.stringify(message)},
         | 
| 1176 | 
            -
                    request = this.createRequest();
         | 
| 1177 | 
            -
                
         | 
| 1178 | 
            -
                request.write(querystring.stringify(params));
         | 
| 1179 | 
            -
                
         | 
| 1180 | 
            -
                request.addListener('response', function(response) {
         | 
| 1181 | 
            -
                  if (!callback) return;
         | 
| 1182 | 
            -
                  response.addListener('data', function(chunk) {
         | 
| 1183 | 
            -
                    callback.call(scope, JSON.parse(chunk));
         | 
| 1184 | 
            -
                  });
         | 
| 1185 | 
            -
                });
         | 
| 1186 | 
            -
                request.close();
         | 
| 1187 | 
            -
              },
         | 
| 1188 | 
            -
              
         | 
| 1189 | 
            -
              createRequest: function() {
         | 
| 1190 | 
            -
                var uri    = url.parse(this._endpoint),
         | 
| 1191 | 
            -
                    client = http.createClient(uri.port, uri.hostname);
         | 
| 1192 | 
            -
                    
         | 
| 1193 | 
            -
                return client.request('POST', uri.pathname, {
         | 
| 1194 | 
            -
                  'Content-Type': 'application/x-www-form-urlencoded'
         | 
| 1195 | 
            -
                });
         | 
| 1196 | 
            -
              }
         | 
| 1197 | 
            -
            });
         | 
| 1198 | 
            -
             | 
| 1199 | 
            -
            Faye.NodeHttpTransport.isUsable = function(endpoint) {
         | 
| 1200 | 
            -
              return typeof endpoint === 'string';
         | 
| 1201 | 
            -
            };
         | 
| 1202 | 
            -
             | 
| 1203 | 
            -
            Faye.Transport.register('long-polling', Faye.NodeHttpTransport);
         | 
| 1204 | 
            -
             | 
| 1205 | 
            -
            Faye.NodeLocalTransport = Faye.Class(Faye.Transport, {
         | 
| 1206 | 
            -
              request: function(message, callback, scope) {
         | 
| 1207 | 
            -
                this._endpoint.process(message, true, function(response) {
         | 
| 1208 | 
            -
                  callback.call(scope, response);
         | 
| 1209 | 
            -
                });
         | 
| 1210 | 
            -
              }
         | 
| 1211 | 
            -
            });
         | 
| 1212 | 
            -
             | 
| 1213 | 
            -
            Faye.NodeLocalTransport.isUsable = function(endpoint) {
         | 
| 1214 | 
            -
              return endpoint instanceof Faye.Server;
         | 
| 1215 | 
            -
            };
         | 
| 1216 | 
            -
             | 
| 1217 | 
            -
            Faye.Transport.register('in-process', Faye.NodeLocalTransport);
         | 
| 1218 | 
            -
             | 
| 1219 | 
            -
             | 
| 1220 1343 | 
             
            var path  = require('path'),
         | 
| 1221 1344 | 
             
                fs    = require('fs'),
         | 
| 1222 1345 | 
             
                sys   = require('sys'),
         | 
| @@ -1224,19 +1347,31 @@ var path  = require('path'), | |
| 1224 1347 | 
             
                http  = require('http'),
         | 
| 1225 1348 | 
             
                querystring = require('querystring');
         | 
| 1226 1349 |  | 
| 1350 | 
            +
            Faye.logger = function(message) {
         | 
| 1351 | 
            +
              sys.puts(message);
         | 
| 1352 | 
            +
            };
         | 
| 1353 | 
            +
             | 
| 1354 | 
            +
            Faye.withDataFor = function(transport, callback, scope) {
         | 
| 1355 | 
            +
              var data = '';
         | 
| 1356 | 
            +
              transport.addListener('data', function(chunk) { data += chunk });
         | 
| 1357 | 
            +
              transport.addListener('end', function() {
         | 
| 1358 | 
            +
                callback.call(scope, data);
         | 
| 1359 | 
            +
              });
         | 
| 1360 | 
            +
            };
         | 
| 1361 | 
            +
             | 
| 1227 1362 | 
             
            Faye.NodeAdapter = Faye.Class({
         | 
| 1228 1363 | 
             
              DEFAULT_ENDPOINT: '/bayeux',
         | 
| 1229 1364 | 
             
              SCRIPT_PATH:      path.dirname(__filename) + '/faye-client-min.js',
         | 
| 1230 1365 |  | 
| 1231 | 
            -
              TYPE_JSON:    {'Content-Type': ' | 
| 1366 | 
            +
              TYPE_JSON:    {'Content-Type': 'application/json'},
         | 
| 1232 1367 | 
             
              TYPE_SCRIPT:  {'Content-Type': 'text/javascript'},
         | 
| 1233 1368 | 
             
              TYPE_TEXT:    {'Content-Type': 'text/plain'},
         | 
| 1234 1369 |  | 
| 1235 1370 | 
             
              initialize: function(options) {
         | 
| 1236 | 
            -
                this._options | 
| 1237 | 
            -
                this._endpoint | 
| 1238 | 
            -
                this. | 
| 1239 | 
            -
                this._server | 
| 1371 | 
            +
                this._options    = options || {};
         | 
| 1372 | 
            +
                this._endpoint   = this._options.mount || this.DEFAULT_ENDPOINT;
         | 
| 1373 | 
            +
                this._endpointRe = new RegExp('^' + this._endpoint + '(/[^/]+)*(\\.js)?$');
         | 
| 1374 | 
            +
                this._server     = new Faye.Server(this._options);
         | 
| 1240 1375 | 
             
              },
         | 
| 1241 1376 |  | 
| 1242 1377 | 
             
              getClient: function() {
         | 
| @@ -1252,35 +1387,30 @@ Faye.NodeAdapter = Faye.Class({ | |
| 1252 1387 |  | 
| 1253 1388 | 
             
              call: function(request, response) {
         | 
| 1254 1389 | 
             
                var requestUrl = url.parse(request.url, true),
         | 
| 1255 | 
            -
                    self = this;
         | 
| 1390 | 
            +
                    self = this, data;
         | 
| 1391 | 
            +
                
         | 
| 1392 | 
            +
                if (!this._endpointRe.test(requestUrl.pathname))
         | 
| 1393 | 
            +
                  return false;
         | 
| 1256 1394 |  | 
| 1257 | 
            -
                 | 
| 1395 | 
            +
                if (/\.js$/.test(requestUrl.pathname)) {
         | 
| 1396 | 
            +
                  fs.readFile(this.SCRIPT_PATH, function(err, content) {
         | 
| 1397 | 
            +
                    response.sendHeader(200, self.TYPE_SCRIPT);
         | 
| 1398 | 
            +
                    response.write(content);
         | 
| 1399 | 
            +
                    response.close();
         | 
| 1400 | 
            +
                  });
         | 
| 1258 1401 |  | 
| 1259 | 
            -
             | 
| 1260 | 
            -
             | 
| 1261 | 
            -
                    
         | 
| 1262 | 
            -
                    if (isGet)
         | 
| 1263 | 
            -
                      this._callWithParams(request, response, requestUrl.query);
         | 
| 1264 | 
            -
                    
         | 
| 1265 | 
            -
                    else
         | 
| 1266 | 
            -
                      request.addListener('data', function(chunk) {
         | 
| 1267 | 
            -
                        self._callWithParams(request, response, querystring.parse(chunk));
         | 
| 1268 | 
            -
                      });
         | 
| 1269 | 
            -
                    
         | 
| 1270 | 
            -
                    return true;
         | 
| 1271 | 
            -
                    break;
         | 
| 1402 | 
            +
                } else {
         | 
| 1403 | 
            +
                  var isGet = (request.method === 'GET');
         | 
| 1272 1404 |  | 
| 1273 | 
            -
                   | 
| 1274 | 
            -
                     | 
| 1275 | 
            -
                      response.sendHeader(200, self.TYPE_SCRIPT);
         | 
| 1276 | 
            -
                      response.write(content);
         | 
| 1277 | 
            -
                      response.close();
         | 
| 1278 | 
            -
                    });
         | 
| 1279 | 
            -
                    return true;
         | 
| 1280 | 
            -
                    break;
         | 
| 1405 | 
            +
                  if (isGet)
         | 
| 1406 | 
            +
                    this._callWithParams(request, response, requestUrl.query);
         | 
| 1281 1407 |  | 
| 1282 | 
            -
                   | 
| 1408 | 
            +
                  else
         | 
| 1409 | 
            +
                    Faye.withDataFor(request, function(data) {
         | 
| 1410 | 
            +
                      self._callWithParams(request, response, {message: data});
         | 
| 1411 | 
            +
                    });
         | 
| 1283 1412 | 
             
                }
         | 
| 1413 | 
            +
                return true;
         | 
| 1284 1414 | 
             
              },
         | 
| 1285 1415 |  | 
| 1286 1416 | 
             
              _callWithParams: function(request, response, params) {
         | 
| @@ -1308,4 +1438,55 @@ Faye.NodeAdapter = Faye.Class({ | |
| 1308 1438 | 
             
            });
         | 
| 1309 1439 |  | 
| 1310 1440 | 
             
            exports.NodeAdapter = Faye.NodeAdapter;
         | 
| 1311 | 
            -
            exports.Client = Faye.Client;
         | 
| 1441 | 
            +
            exports.Client = Faye.Client;
         | 
| 1442 | 
            +
             | 
| 1443 | 
            +
             | 
| 1444 | 
            +
            Faye.NodeHttpTransport = Faye.Class(Faye.Transport, {
         | 
| 1445 | 
            +
              request: function(message, callback, scope) {
         | 
| 1446 | 
            +
                var request = this.createRequestForMessage(message);
         | 
| 1447 | 
            +
                
         | 
| 1448 | 
            +
                request.addListener('response', function(response) {
         | 
| 1449 | 
            +
                  if (!callback) return;
         | 
| 1450 | 
            +
                  Faye.withDataFor(response, function(data) {
         | 
| 1451 | 
            +
                    callback.call(scope, JSON.parse(data));
         | 
| 1452 | 
            +
                  });
         | 
| 1453 | 
            +
                });
         | 
| 1454 | 
            +
                request.close();
         | 
| 1455 | 
            +
              },
         | 
| 1456 | 
            +
              
         | 
| 1457 | 
            +
              createRequestForMessage: function(message) {
         | 
| 1458 | 
            +
                var content = JSON.stringify(message),
         | 
| 1459 | 
            +
                    uri     = url.parse(this._endpoint),
         | 
| 1460 | 
            +
                    client  = http.createClient(uri.port, uri.hostname);
         | 
| 1461 | 
            +
                
         | 
| 1462 | 
            +
                if (parseInt(uri.port) === 443) client.setSecure('X509_PEM');
         | 
| 1463 | 
            +
                
         | 
| 1464 | 
            +
                var request = client.request('POST', uri.pathname, {
         | 
| 1465 | 
            +
                  'Content-Type':   'application/json',
         | 
| 1466 | 
            +
                  'host':           uri.hostname,
         | 
| 1467 | 
            +
                  'Content-Length': content.length
         | 
| 1468 | 
            +
                });
         | 
| 1469 | 
            +
                request.write(content);
         | 
| 1470 | 
            +
                return request;
         | 
| 1471 | 
            +
              }
         | 
| 1472 | 
            +
            });
         | 
| 1473 | 
            +
             | 
| 1474 | 
            +
            Faye.NodeHttpTransport.isUsable = function(endpoint) {
         | 
| 1475 | 
            +
              return typeof endpoint === 'string';
         | 
| 1476 | 
            +
            };
         | 
| 1477 | 
            +
             | 
| 1478 | 
            +
            Faye.Transport.register('long-polling', Faye.NodeHttpTransport);
         | 
| 1479 | 
            +
             | 
| 1480 | 
            +
            Faye.NodeLocalTransport = Faye.Class(Faye.Transport, {
         | 
| 1481 | 
            +
              request: function(message, callback, scope) {
         | 
| 1482 | 
            +
                this._endpoint.process(message, true, function(response) {
         | 
| 1483 | 
            +
                  callback.call(scope, response);
         | 
| 1484 | 
            +
                });
         | 
| 1485 | 
            +
              }
         | 
| 1486 | 
            +
            });
         | 
| 1487 | 
            +
             | 
| 1488 | 
            +
            Faye.NodeLocalTransport.isUsable = function(endpoint) {
         | 
| 1489 | 
            +
              return endpoint instanceof Faye.Server;
         | 
| 1490 | 
            +
            };
         | 
| 1491 | 
            +
             | 
| 1492 | 
            +
            Faye.Transport.register('in-process', Faye.NodeLocalTransport);
         |