faye 0.3.2 → 0.3.3
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 +7 -0
- data/Manifest.txt +1 -0
- data/build/faye-client-min.js +1 -1
- data/build/faye.js +115 -121
- data/examples/node/app.js +3 -3
- data/examples/node/faye-client-min.js +1 -1
- data/examples/node/faye.js +115 -121
- data/jake.yml +1 -1
- data/lib/faye-client-min.js +1 -1
- data/lib/faye.rb +12 -4
- data/lib/faye/client.rb +45 -10
- data/lib/faye/connection.rb +1 -1
- data/lib/faye/logging.rb +52 -0
- data/lib/faye/rack_adapter.rb +0 -1
- data/lib/faye/server.rb +68 -45
- data/lib/faye/transport.rb +8 -1
- data/test/scenario.js +5 -2
- data/test/scenario.rb +13 -1
- metadata +85 -35
data/jake.yml
CHANGED
data/lib/faye-client-min.js
CHANGED
@@ -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.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);
|
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.3',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._v==='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._v=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)}},trigger: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 a=Array.prototype.slice.apply(a),d=' ['+b.toUpperCase()+'] [Faye',f=null,g=a.shift().replace(/\?/g,function(){return Faye.toJSON(a.shift())});for(var j in Faye){if(f)continue;if(typeof Faye[j]!=='function')continue;if(this instanceof Faye[j])f=j}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+d+g)}};Faye.each(Faye.Logging.LOG_LEVELS,function(a,b){Faye.Logging[a]=function(){this.log(arguments,a)}});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.trigger('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 ? sending message to ?: ?',this._b._0,this._4,f);this.request(f,function(b){this.debug('Client ? received from ?: ?',this._b._0,this._4,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._w=b||{};this._r=this._w.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._9={reconnect:this.RETRY,interval:this.INTERVAL};if(Faye.Event)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._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)}else{this.info('Handshake unsuccessful');setTimeout(function(){d.handshake(b,c)},this._9.interval);this._1=this.UNCONNECTED}},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._s();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){this._d=null;this.removeTimeout('reconnect');this.info('Closed connection for ?',this._0);setTimeout(function(){d.connect()},this._9.interval)}));this._s()},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();this.removeTimeout('reconnect')},subscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._l(c);this.info('Client ? attempting to subscribe to ?',this._0,c);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 ? to ?',this._0,c);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 ? attempting to unsubscribe from ?',this._0,c);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 ? from ?',this._0,c);c=[].concat(b.subscription);Faye.each(c,function(a){this._c.set(a,undefined)},this)}))},this)},publish:function(a,b){this.connect(function(){this._l([a]);this.info('Client ? queueing published message to ?: ?',this._0,a,b);this._x({channel:a,data:b,clientId:this._0});this.addTimeout('publish',this.MAX_DELAY,this._y,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 ? calling listeners for ? with ?',this._0,b.channel,b.data);var c=this._c.glob(b.channel);Faye.each(c,function(a){a[0].call(a[1],b.data)})},this)},_s:function(){this.addTimeout('reconnect',this._r,function(){this._d=null;this._0=null;this._1=this.UNCONNECTED;this.info('Server took >?s to reply to connection for ?: attempting to reconnect',this._r,this._0);this.subscribe(this._c.getKeys())},this)},_x:function(a){this._j.push(a)},_y: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,_z:c,_g:d,_t: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._z)||(d&&d!==g._g))continue;if(g._f.removeEventListener)g._f.removeEventListener(g._m,g._t,false);else g._f.detachEvent('on'+g._m,g._t);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._A=(typeof c==='string')?c:null;this._B=(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._A||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._B;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)}}),{_u:0,getCallbackName:function(){this._u+=1;return'__jsonp'+this._u+'__'}});Faye.JSONPTransport.isUsable=function(a){return true};Faye.Transport.register('callback-polling',Faye.JSONPTransport);
|
data/lib/faye.rb
CHANGED
@@ -3,9 +3,10 @@ require 'observer'
|
|
3
3
|
require 'set'
|
4
4
|
require 'rubygems'
|
5
5
|
require 'eventmachine'
|
6
|
+
require 'json'
|
6
7
|
|
7
8
|
module Faye
|
8
|
-
VERSION = '0.3.
|
9
|
+
VERSION = '0.3.3'
|
9
10
|
|
10
11
|
ROOT = File.expand_path(File.dirname(__FILE__))
|
11
12
|
|
@@ -14,9 +15,8 @@ module Faye
|
|
14
15
|
JSONP_CALLBACK = 'jsonpcallback'
|
15
16
|
CONNECTION_TYPES = %w[long-polling callback-polling]
|
16
17
|
|
17
|
-
%w[ timeouts grammar namespace
|
18
|
-
|
19
|
-
error client transport
|
18
|
+
%w[ logging timeouts grammar namespace server
|
19
|
+
channel connection error client transport
|
20
20
|
].each do |lib|
|
21
21
|
require File.join(ROOT, 'faye', lib)
|
22
22
|
end
|
@@ -28,5 +28,13 @@ module Faye
|
|
28
28
|
strlen = bitlength / 4
|
29
29
|
("%0#{strlen}s" % rand(field).to_s(16)).gsub(' ', '0')
|
30
30
|
end
|
31
|
+
|
32
|
+
def self.to_json(value)
|
33
|
+
case value
|
34
|
+
when Hash, Array then JSON.unparse(value)
|
35
|
+
when String, NilClass then value.inspect
|
36
|
+
else value.to_s
|
37
|
+
end
|
38
|
+
end
|
31
39
|
end
|
32
40
|
|
data/lib/faye/client.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Faye
|
2
2
|
class Client
|
3
|
+
|
3
4
|
include EventMachine::Deferrable
|
4
5
|
include Timeouts
|
6
|
+
include Logging
|
5
7
|
|
6
8
|
UNCONNECTED = 1
|
7
9
|
CONNECTING = 2
|
@@ -14,9 +16,11 @@ module Faye
|
|
14
16
|
|
15
17
|
CONNECTION_TIMEOUT = 60.0
|
16
18
|
|
17
|
-
attr_reader :endpoint, :namespace
|
19
|
+
attr_reader :endpoint, :client_id, :namespace
|
18
20
|
|
19
21
|
def initialize(endpoint = nil, options = {})
|
22
|
+
info('New client created for ?', endpoint)
|
23
|
+
|
20
24
|
@endpoint = endpoint || RackAdapter::DEFAULT_ENDPOINT
|
21
25
|
@options = options
|
22
26
|
@timeout = @options[:timeout] || CONNECTION_TIMEOUT
|
@@ -55,6 +59,8 @@ module Faye
|
|
55
59
|
|
56
60
|
@state = CONNECTING
|
57
61
|
|
62
|
+
info('Initiating handshake with ?', @endpoint)
|
63
|
+
|
58
64
|
@transport.send({
|
59
65
|
'channel' => Channel::HANDSHAKE,
|
60
66
|
'version' => BAYEUX_VERSION,
|
@@ -62,16 +68,19 @@ module Faye
|
|
62
68
|
|
63
69
|
}) do |response|
|
64
70
|
|
65
|
-
|
71
|
+
if response['successful']
|
72
|
+
@state = CONNECTED
|
73
|
+
@client_id = response['clientId']
|
74
|
+
@transport = Transport.get(self, response['supportedConnectionTypes'])
|
75
|
+
|
76
|
+
info('Handshake successful: ?', @client_id)
|
77
|
+
block.call if block_given?
|
78
|
+
|
79
|
+
else
|
80
|
+
info('Handshake unsuccessful')
|
66
81
|
EventMachine.add_timer(@advice['interval'] / 1000.0) { handshake(&block) }
|
67
|
-
|
82
|
+
@state = UNCONNECTED
|
68
83
|
end
|
69
|
-
|
70
|
-
@state = CONNECTED
|
71
|
-
@client_id = response['clientId']
|
72
|
-
@transport = Transport.get(self, response['supportedConnectionTypes'])
|
73
|
-
|
74
|
-
block.call if block_given?
|
75
84
|
end
|
76
85
|
end
|
77
86
|
|
@@ -96,12 +105,14 @@ module Faye
|
|
96
105
|
return callback(&block) if @state == CONNECTING
|
97
106
|
return unless @state == CONNECTED
|
98
107
|
|
108
|
+
info('Calling deferred actions for ?', @client_id)
|
99
109
|
set_deferred_status(:succeeded)
|
100
110
|
set_deferred_status(:deferred)
|
101
111
|
block.call if block_given?
|
102
112
|
|
103
113
|
return unless @connection_id.nil?
|
104
114
|
@connection_id = @namespace.generate
|
115
|
+
info('Initiating connection for ?', @client_id)
|
105
116
|
|
106
117
|
@transport.send({
|
107
118
|
'channel' => Channel::CONNECT,
|
@@ -112,6 +123,8 @@ module Faye
|
|
112
123
|
}, &verify_client_id { |response|
|
113
124
|
@connection_id = nil
|
114
125
|
remove_timeout(:reconnect)
|
126
|
+
|
127
|
+
info('Closed connection for ?', @client_id)
|
115
128
|
EventMachine.add_timer(@advice['interval'] / 1000.0) { connect }
|
116
129
|
})
|
117
130
|
|
@@ -127,14 +140,18 @@ module Faye
|
|
127
140
|
# * id
|
128
141
|
def disconnect
|
129
142
|
return unless @state == CONNECTED
|
130
|
-
@state =
|
143
|
+
@state = DISCONNECTED
|
144
|
+
|
145
|
+
info('Disconnecting ?', @client_id)
|
131
146
|
|
132
147
|
@transport.send({
|
133
148
|
'channel' => Channel::DISCONNECT,
|
134
149
|
'clientId' => @client_id
|
135
150
|
})
|
136
151
|
|
152
|
+
info('Clearing channel listeners for ?', @client_id)
|
137
153
|
@channels = Channel::Tree.new
|
154
|
+
remove_timeout(:reconnect)
|
138
155
|
end
|
139
156
|
|
140
157
|
# Request Response
|
@@ -152,6 +169,8 @@ module Faye
|
|
152
169
|
channels = [channels].flatten
|
153
170
|
validate_channels(channels)
|
154
171
|
|
172
|
+
info('Client ? attempting to subscribe to ?', @client_id, channels)
|
173
|
+
|
155
174
|
@transport.send({
|
156
175
|
'channel' => Channel::SUBSCRIBE,
|
157
176
|
'clientId' => @client_id,
|
@@ -159,6 +178,9 @@ module Faye
|
|
159
178
|
|
160
179
|
}, &verify_client_id { |response|
|
161
180
|
if response['successful'] and block
|
181
|
+
|
182
|
+
info('Subscription acknowledged for ? to ?', @client_id, channels)
|
183
|
+
|
162
184
|
channels = [response['subscription']].flatten
|
163
185
|
channels.each { |channel| @channels[channel] = block }
|
164
186
|
end
|
@@ -181,6 +203,8 @@ module Faye
|
|
181
203
|
channels = [channels].flatten
|
182
204
|
validate_channels(channels)
|
183
205
|
|
206
|
+
info('Client ? attempting to unsubscribe from ?', @client_id, channels)
|
207
|
+
|
184
208
|
@transport.send({
|
185
209
|
'channel' => Channel::UNSUBSCRIBE,
|
186
210
|
'clientId' => @client_id,
|
@@ -188,6 +212,9 @@ module Faye
|
|
188
212
|
|
189
213
|
}, &verify_client_id { |response|
|
190
214
|
if response['successful']
|
215
|
+
|
216
|
+
info('Unsubscription acknowledged for ? from ?', @client_id, channels)
|
217
|
+
|
191
218
|
channels = [response['subscription']].flatten
|
192
219
|
channels.each { |channel| @channels[channel] = nil }
|
193
220
|
end
|
@@ -205,6 +232,8 @@ module Faye
|
|
205
232
|
connect {
|
206
233
|
validate_channels([channel])
|
207
234
|
|
235
|
+
info('Client ? queueing published message to ?: ?', @client_id, channel, data)
|
236
|
+
|
208
237
|
enqueue({
|
209
238
|
'channel' => channel,
|
210
239
|
'data' => data,
|
@@ -222,6 +251,8 @@ module Faye
|
|
222
251
|
|
223
252
|
def deliver_messages(messages)
|
224
253
|
messages.each do |message|
|
254
|
+
info('Client ? calling listeners for ? with ?', @client_id, message['channel'], message['data'])
|
255
|
+
|
225
256
|
channels = @channels.glob(message['channel'])
|
226
257
|
channels.each { |callback| callback.call(message['data']) }
|
227
258
|
end
|
@@ -234,6 +265,10 @@ module Faye
|
|
234
265
|
@connection_id = nil
|
235
266
|
@client_id = nil
|
236
267
|
@state = UNCONNECTED
|
268
|
+
|
269
|
+
info('Server took >?s to reply to connection for ?: attempting to reconnect',
|
270
|
+
@timeout, @client_id)
|
271
|
+
|
237
272
|
subscribe(@channels.keys)
|
238
273
|
end
|
239
274
|
end
|
data/lib/faye/connection.rb
CHANGED
data/lib/faye/logging.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Faye
|
2
|
+
|
3
|
+
class << self
|
4
|
+
attr_accessor :logger
|
5
|
+
end
|
6
|
+
|
7
|
+
module Logging
|
8
|
+
|
9
|
+
DEFAULT_LOG_LEVEL = :error
|
10
|
+
|
11
|
+
LOG_LEVELS = {
|
12
|
+
:error => 3,
|
13
|
+
:warn => 2,
|
14
|
+
:info => 1,
|
15
|
+
:debug => 0
|
16
|
+
}
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_writer :log_level
|
20
|
+
|
21
|
+
def log_level
|
22
|
+
@log_level || DEFAULT_LOG_LEVEL
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_writer :log_level
|
27
|
+
|
28
|
+
def log_level
|
29
|
+
@log_level || Logging.log_level
|
30
|
+
end
|
31
|
+
|
32
|
+
def log(message_args, level)
|
33
|
+
return unless Faye.logger
|
34
|
+
return if LOG_LEVELS[log_level] > LOG_LEVELS[level]
|
35
|
+
|
36
|
+
message = message_args.shift.gsub(/\?/) do
|
37
|
+
Faye.to_json(message_args.shift)
|
38
|
+
end
|
39
|
+
|
40
|
+
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
41
|
+
banner = " [#{ level.to_s.upcase }] [#{ self.class.name }] "
|
42
|
+
|
43
|
+
puts(timestamp + banner + message)
|
44
|
+
end
|
45
|
+
|
46
|
+
LOG_LEVELS.each do |level, value|
|
47
|
+
define_method(level) { |*args| log(args, level) }
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/lib/faye/rack_adapter.rb
CHANGED
data/lib/faye/server.rb
CHANGED
@@ -1,23 +1,29 @@
|
|
1
1
|
module Faye
|
2
2
|
class Server
|
3
|
+
|
4
|
+
include Logging
|
5
|
+
|
3
6
|
def initialize(options = {})
|
4
|
-
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
7
|
+
info('New server created')
|
8
|
+
@options = options
|
9
|
+
@channels = Channel::Tree.new
|
10
|
+
@connections = {}
|
11
|
+
@namespace = Namespace.new
|
8
12
|
end
|
9
13
|
|
10
14
|
# Notifies the server of stale connections that should be deleted
|
11
|
-
def update(message,
|
12
|
-
return unless message == :
|
13
|
-
|
15
|
+
def update(message, connection)
|
16
|
+
return unless message == :stale_connection
|
17
|
+
destroy_connection(connection)
|
14
18
|
end
|
15
19
|
|
16
20
|
def client_ids
|
17
|
-
@
|
21
|
+
@connections.keys
|
18
22
|
end
|
19
23
|
|
20
24
|
def process(messages, local = false, &callback)
|
25
|
+
debug('Processing messages from ? client', local ? 'LOCAL' : 'REMOTE')
|
26
|
+
|
21
27
|
messages = [messages].flatten
|
22
28
|
processed, responses = 0, []
|
23
29
|
|
@@ -33,51 +39,59 @@ module Faye
|
|
33
39
|
|
34
40
|
def flush_connection(messages)
|
35
41
|
[messages].flatten.each do |message|
|
36
|
-
|
37
|
-
|
42
|
+
connection = @connections[message['clientId']]
|
43
|
+
connection.flush! if connection
|
38
44
|
end
|
39
45
|
end
|
40
46
|
|
41
47
|
private
|
42
48
|
|
43
49
|
def connection(id)
|
44
|
-
return @
|
45
|
-
|
46
|
-
|
47
|
-
@
|
50
|
+
return @connections[id] if @connections.has_key?(id)
|
51
|
+
connection = Connection.new(id, @options)
|
52
|
+
connection.add_observer(self)
|
53
|
+
@connections[id] = connection
|
48
54
|
end
|
49
55
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
@
|
56
|
+
def destroy_connection(connection)
|
57
|
+
connection.disconnect!
|
58
|
+
connection.delete_observer(self)
|
59
|
+
@connections.delete(connection.id)
|
54
60
|
end
|
55
61
|
|
56
62
|
def handle(message, local = false, &callback)
|
57
|
-
|
58
|
-
|
63
|
+
channel_name = message['channel']
|
64
|
+
|
65
|
+
@channels.glob(channel_name).each do |channel|
|
66
|
+
channel << message
|
67
|
+
info('Publishing message ? from client ? to ?', message['data'], message['clientId'], channel.name)
|
68
|
+
end
|
59
69
|
|
60
|
-
if Channel.meta?(
|
61
|
-
response = __send__(Channel.parse(
|
70
|
+
if Channel.meta?(channel_name)
|
71
|
+
response = __send__(Channel.parse(channel_name)[1], message, local)
|
62
72
|
|
63
73
|
client_id = response['clientId']
|
64
74
|
response['advice'] ||= {}
|
65
|
-
response['advice']['reconnect'] ||= @
|
75
|
+
response['advice']['reconnect'] ||= @connections.has_key?(client_id) ? 'retry' : 'handshake'
|
66
76
|
response['advice']['interval'] ||= (Connection::INTERVAL * 1000).floor
|
67
77
|
|
68
|
-
return callback
|
69
|
-
|
78
|
+
return callback.call(response) unless response['channel'] == Channel::CONNECT and
|
79
|
+
response['successful'] == true
|
80
|
+
|
81
|
+
info('Accepting connection from ?', response['clientId'])
|
70
82
|
|
71
83
|
return connection(response['clientId']).connect do |events|
|
72
|
-
|
84
|
+
info('Sending event messages to ?', response['clientId'])
|
85
|
+
debug('Events for ?: ?', response['clientId'], events)
|
86
|
+
callback.call([response] + events)
|
73
87
|
end
|
74
88
|
end
|
75
89
|
|
76
|
-
return callback[
|
90
|
+
return callback.call([]) if message['clientId'].nil? or Channel.service?(channel_name)
|
77
91
|
|
78
92
|
response = make_response(message)
|
79
93
|
response['successful'] = true
|
80
|
-
callback
|
94
|
+
callback.call(response)
|
81
95
|
end
|
82
96
|
|
83
97
|
def make_response(message)
|
@@ -101,10 +115,11 @@ module Faye
|
|
101
115
|
|
102
116
|
response['error'] = Error.parameter_missing('version') if message['version'].nil?
|
103
117
|
|
118
|
+
client_conns = message['supportedConnectionTypes']
|
119
|
+
|
104
120
|
unless local
|
105
121
|
response['supportedConnectionTypes'] = CONNECTION_TYPES
|
106
122
|
|
107
|
-
client_conns = message['supportedConnectionTypes']
|
108
123
|
if client_conns
|
109
124
|
common_conns = client_conns.select { |c| CONNECTION_TYPES.include?(c) }
|
110
125
|
response['error'] = Error.conntype_mismatch(*client_conns) if common_conns.empty?
|
@@ -118,6 +133,7 @@ module Faye
|
|
118
133
|
|
119
134
|
client_id = @namespace.generate
|
120
135
|
response['clientId'] = connection(client_id).id
|
136
|
+
info('Accepting handshake from client ?', response['clientId'])
|
121
137
|
response
|
122
138
|
end
|
123
139
|
|
@@ -128,18 +144,19 @@ module Faye
|
|
128
144
|
def connect(message, local = false)
|
129
145
|
response = make_response(message)
|
130
146
|
|
131
|
-
client_id
|
132
|
-
|
147
|
+
client_id = message['clientId']
|
148
|
+
connection = client_id ? @connections[client_id] : nil
|
149
|
+
connection_type = message['connectionType']
|
133
150
|
|
134
|
-
response['error'] = Error.client_unknown(client_id) if
|
151
|
+
response['error'] = Error.client_unknown(client_id) if connection.nil?
|
135
152
|
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
136
|
-
response['error'] = Error.parameter_missing('connectionType') if
|
153
|
+
response['error'] = Error.parameter_missing('connectionType') if connection_type.nil?
|
137
154
|
|
138
155
|
response['successful'] = response['error'].nil?
|
139
156
|
response.delete('clientId') unless response['successful']
|
140
157
|
return response unless response['successful']
|
141
158
|
|
142
|
-
response['clientId'] =
|
159
|
+
response['clientId'] = connection.id
|
143
160
|
response
|
144
161
|
end
|
145
162
|
|
@@ -149,18 +166,19 @@ module Faye
|
|
149
166
|
def disconnect(message, local = false)
|
150
167
|
response = make_response(message)
|
151
168
|
|
152
|
-
client_id
|
153
|
-
|
169
|
+
client_id = message['clientId']
|
170
|
+
connection = client_id ? @connections[client_id] : nil
|
154
171
|
|
155
|
-
response['error'] = Error.client_unknown(client_id) if
|
172
|
+
response['error'] = Error.client_unknown(client_id) if connection.nil?
|
156
173
|
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
157
174
|
|
158
175
|
response['successful'] = response['error'].nil?
|
159
176
|
response.delete('clientId') unless response['successful']
|
160
177
|
return response unless response['successful']
|
161
178
|
|
162
|
-
|
179
|
+
destroy_connection(connection)
|
163
180
|
|
181
|
+
info('Disconnected client: ?', client_id)
|
164
182
|
response['clientId'] = client_id
|
165
183
|
response
|
166
184
|
end
|
@@ -173,12 +191,12 @@ module Faye
|
|
173
191
|
response = make_response(message)
|
174
192
|
|
175
193
|
client_id = message['clientId']
|
176
|
-
|
194
|
+
connection = client_id ? @connections[client_id] : nil
|
177
195
|
|
178
196
|
subscription = message['subscription']
|
179
197
|
subscription = [subscription].flatten
|
180
198
|
|
181
|
-
response['error'] = Error.client_unknown(client_id) if
|
199
|
+
response['error'] = Error.client_unknown(client_id) if connection.nil?
|
182
200
|
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
183
201
|
response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
|
184
202
|
|
@@ -191,7 +209,9 @@ module Faye
|
|
191
209
|
|
192
210
|
next if response['error']
|
193
211
|
channel = @channels[channel] ||= Channel.new(channel)
|
194
|
-
|
212
|
+
|
213
|
+
info('Subscribing client ? to ?', client_id, channel.name)
|
214
|
+
connection.subscribe(channel)
|
195
215
|
end
|
196
216
|
|
197
217
|
response['successful'] = response['error'].nil?
|
@@ -206,12 +226,12 @@ module Faye
|
|
206
226
|
response = make_response(message)
|
207
227
|
|
208
228
|
client_id = message['clientId']
|
209
|
-
|
229
|
+
connection = client_id ? @connections[client_id] : nil
|
210
230
|
|
211
231
|
subscription = message['subscription']
|
212
232
|
subscription = [subscription].flatten
|
213
233
|
|
214
|
-
response['error'] = Error.client_unknown(client_id) if
|
234
|
+
response['error'] = Error.client_unknown(client_id) if connection.nil?
|
215
235
|
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
216
236
|
response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
|
217
237
|
|
@@ -220,13 +240,16 @@ module Faye
|
|
220
240
|
subscription.each do |channel|
|
221
241
|
next if response['error']
|
222
242
|
|
223
|
-
|
243
|
+
unless Channel.valid?(channel)
|
224
244
|
response['error'] = Error.channel_invalid(channel)
|
225
245
|
next
|
226
246
|
end
|
227
247
|
|
228
248
|
channel = @channels[channel]
|
229
|
-
|
249
|
+
next unless channel
|
250
|
+
|
251
|
+
info('Unsubscribing client ? from ?', client_id, channel.name)
|
252
|
+
connection.unsubscribe(channel)
|
230
253
|
end
|
231
254
|
|
232
255
|
response['successful'] = response['error'].nil?
|