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