PageRenderTime 32ms CodeModel.GetById 121ms app.highlight 81ms RepoModel.GetById 81ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/socket.io-client/lib/socket.js

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
JavaScript | 227 lines | 196 code | 24 blank | 7 comment | 62 complexity | 46a7d84390680c3589a2dd1400ced769 MD5 | raw file
  1/**
  2 * Socket.IO client
  3 * 
  4 * @author Guillermo Rauch <guillermo@learnboost.com>
  5 * @license The MIT license.
  6 * @copyright Copyright (c) 2010 LearnBoost <dev@learnboost.com>
  7 */
  8
  9(function(){
 10	var io = this.io;
 11	
 12	var Socket = io.Socket = function(host, options){
 13		this.host = host || document.domain;
 14		this.options = {
 15			secure: false,
 16			document: document,
 17			port: document.location.port || 80,
 18			resource: 'socket.io',
 19			transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling'],
 20			transportOptions: {
 21				'xhr-polling': {
 22					timeout: 25000 // based on polling duration default
 23				},
 24				'jsonp-polling': {
 25					timeout: 25000
 26				}
 27			},
 28			connectTimeout: 5000,
 29			reconnect: true,
 30			reconnectionDelay: 500,
 31			maxReconnectionAttempts: 10,
 32			tryTransportsOnConnectTimeout: true,
 33			rememberTransport: true
 34		};
 35		io.util.merge(this.options, options);
 36		this.connected = false;
 37		this.connecting = false;
 38		this._events = {};
 39		this.transport = this.getTransport();
 40		if (!this.transport && 'console' in window) console.error('No transport available');
 41	};
 42	
 43	Socket.prototype.getTransport = function(override){
 44		var transports = override || this.options.transports, match;
 45		if (this.options.rememberTransport && !override){
 46			match = this.options.document.cookie.match('(?:^|;)\\s*socketio=([^;]*)');
 47			if (match){
 48				this._rememberedTransport = true;
 49				transports = [decodeURIComponent(match[1])];
 50			}
 51		} 
 52		for (var i = 0, transport; transport = transports[i]; i++){
 53			if (io.Transport[transport] 
 54				&& io.Transport[transport].check() 
 55				&& (!this._isXDomain() || io.Transport[transport].xdomainCheck())){
 56				return new io.Transport[transport](this, this.options.transportOptions[transport] || {});
 57			}
 58		}
 59		return null;
 60	};
 61	
 62	Socket.prototype.connect = function(){
 63		if (this.transport && !this.connected){
 64			if (this.connecting) this.disconnect(true);
 65			this.connecting = true;
 66			this.emit('connecting', [this.transport.type]);
 67			this.transport.connect();
 68			if (this.options.connectTimeout){
 69				var self = this;
 70				this.connectTimeoutTimer = setTimeout(function(){
 71					if (!self.connected){
 72						self.disconnect(true);
 73						if (self.options.tryTransportsOnConnectTimeout && !self._rememberedTransport){
 74							if(!self._remainingTransports) self._remainingTransports = self.options.transports.slice(0);
 75							var transports = self._remainingTransports;
 76							while(transports.length > 0 && transports.splice(0,1)[0] != self.transport.type){}
 77							if(transports.length){
 78								self.transport = self.getTransport(transports);
 79								self.connect();
 80							}
 81						}
 82						if(!self._remainingTransports || self._remainingTransports.length == 0) self.emit('connect_failed');
 83					}
 84					if(self._remainingTransports && self._remainingTransports.length == 0) delete self._remainingTransports;
 85				}, this.options.connectTimeout);
 86			}
 87		}
 88		return this;
 89	};
 90	
 91	Socket.prototype.send = function(data){
 92		if (!this.transport || !this.transport.connected) return this._queue(data);
 93		this.transport.send(data);
 94		return this;
 95	};
 96	
 97	Socket.prototype.disconnect = function(reconnect){
 98    if (this.connectTimeoutTimer) clearTimeout(this.connectTimeoutTimer);
 99		if (!reconnect) this.options.reconnect = false;
100		this.transport.disconnect();
101		return this;
102	};
103	
104	Socket.prototype.on = function(name, fn){
105		if (!(name in this._events)) this._events[name] = [];
106		this._events[name].push(fn);
107		return this;
108	};
109	
110  Socket.prototype.emit = function(name, args){
111    if (name in this._events){
112      var events = this._events[name].concat();
113      for (var i = 0, ii = events.length; i < ii; i++)
114        events[i].apply(this, args === undefined ? [] : args);
115    }
116    return this;
117  };
118
119	Socket.prototype.removeEvent = function(name, fn){
120		if (name in this._events){
121			for (var a = 0, l = this._events[name].length; a < l; a++)
122				if (this._events[name][a] == fn) this._events[name].splice(a, 1);		
123		}
124		return this;
125	};
126	
127	Socket.prototype._queue = function(message){
128		if (!('_queueStack' in this)) this._queueStack = [];
129		this._queueStack.push(message);
130		return this;
131	};
132	
133	Socket.prototype._doQueue = function(){
134		if (!('_queueStack' in this) || !this._queueStack.length) return this;
135		this.transport.send(this._queueStack);
136		this._queueStack = [];
137		return this;
138	};
139	
140	Socket.prototype._isXDomain = function(){
141    var locPort = window.location.port || 80;
142		return this.host !== document.domain || this.options.port != locPort;
143	};
144	
145	Socket.prototype._onConnect = function(){
146		this.connected = true;
147		this.connecting = false;
148		this._doQueue();
149		if (this.options.rememberTransport) this.options.document.cookie = 'socketio=' + encodeURIComponent(this.transport.type);
150		this.emit('connect');
151	};
152	
153	Socket.prototype._onMessage = function(data){
154		this.emit('message', [data]);
155	};
156	
157	Socket.prototype._onDisconnect = function(){
158		var wasConnected = this.connected;
159		this.connected = false;
160		this.connecting = false;
161		this._queueStack = [];
162		if (wasConnected){
163			this.emit('disconnect');
164			if (this.options.reconnect && !this.reconnecting) this._onReconnect();
165		}
166	};
167	
168	Socket.prototype._onReconnect = function(){
169		this.reconnecting = true;
170		this.reconnectionAttempts = 0;
171		this.reconnectionDelay = this.options.reconnectionDelay;
172		
173		var self = this
174			, tryTransportsOnConnectTimeout = this.options.tryTransportsOnConnectTimeout
175			, rememberTransport = this.options.rememberTransport;
176		
177		function reset(){
178			if(self.connected) self.emit('reconnect',[self.transport.type,self.reconnectionAttempts]);
179			self.removeEvent('connect_failed', maybeReconnect).removeEvent('connect', maybeReconnect);
180			delete self.reconnecting;
181			delete self.reconnectionAttempts;
182			delete self.reconnectionDelay;
183			delete self.reconnectionTimer;
184			delete self.redoTransports;
185			self.options.tryTransportsOnConnectTimeout = tryTransportsOnConnectTimeout;
186			self.options.rememberTransport = rememberTransport;
187			
188			return;
189		};
190		
191		function maybeReconnect(){
192			if (!self.reconnecting) return;
193			if (!self.connected){
194				if (self.connecting && self.reconnecting) return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
195				
196				if (self.reconnectionAttempts++ >= self.options.maxReconnectionAttempts){
197					if (!self.redoTransports){
198						self.on('connect_failed', maybeReconnect);
199						self.options.tryTransportsOnConnectTimeout = true;
200						self.transport = self.getTransport(self.options.transports); // overwrite with all enabled transports
201						self.redoTransports = true;
202						self.connect();
203					} else {
204						self.emit('reconnect_failed');
205						reset();
206					}
207				} else {
208					self.reconnectionDelay *= 2; // exponential backoff
209					self.connect();
210					self.emit('reconnecting', [self.reconnectionDelay,self.reconnectionAttempts]);
211					self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
212				}
213			} else {
214				reset();
215			}
216		};
217		this.options.tryTransportsOnConnectTimeout = false;
218		this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
219		
220		this.on('connect', maybeReconnect);
221	};
222
223  Socket.prototype.fire = Socket.prototype.emit;
224	Socket.prototype.addListener = Socket.prototype.addEvent = Socket.prototype.addEventListener = Socket.prototype.on;
225	Socket.prototype.removeListener = Socket.prototype.removeEventListener = Socket.prototype.removeEvent;
226	
227})();