PageRenderTime 130ms CodeModel.GetById 16ms app.highlight 93ms RepoModel.GetById 3ms app.codeStats 1ms

/app/socket.io.js

https://github.com/tantion/chat
JavaScript | 6155 lines | 3449 code | 950 blank | 1756 comment | 975 complexity | 6775500dd53a94b9084148d96d818431 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.io=e():"undefined"!=typeof global?global.io=e():"undefined"!=typeof self&&(self.io=e())}(function(){var define,module,exports;
   2return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
   3
   4module.exports = require('./lib/');
   5
   6},{"./lib/":2}],2:[function(require,module,exports){
   7
   8/**
   9 * Module dependencies.
  10 */
  11
  12var url = require('./url');
  13var parser = require('socket.io-parser');
  14var Manager = require('./manager');
  15var debug = require('debug')('socket.io-client');
  16
  17/**
  18 * Module exports.
  19 */
  20
  21module.exports = exports = lookup;
  22
  23/**
  24 * Managers cache.
  25 */
  26
  27var cache = exports.managers = {};
  28
  29/**
  30 * Looks up an existing `Manager` for multiplexing.
  31 * If the user summons:
  32 *
  33 *   `io('http://localhost/a');`
  34 *   `io('http://localhost/b');`
  35 *
  36 * We reuse the existing instance based on same scheme/port/host,
  37 * and we initialize sockets for each namespace.
  38 *
  39 * @api public
  40 */
  41
  42function lookup(uri, opts) {
  43  if (typeof uri == 'object') {
  44    opts = uri;
  45    uri = undefined;
  46  }
  47
  48  opts = opts || {};
  49
  50  var parsed = url(uri);
  51  var source = parsed.source;
  52  var id = parsed.id;
  53  var io;
  54
  55  if (opts.forceNew || opts['force new connection'] || false === opts.multiplex) {
  56    debug('ignoring socket cache for %s', source);
  57    io = Manager(source, opts);
  58  } else {
  59    if (!cache[id]) {
  60      debug('new io instance for %s', source);
  61      cache[id] = Manager(source, opts);
  62    }
  63    io = cache[id];
  64  }
  65
  66  return io.socket(parsed.path);
  67}
  68
  69/**
  70 * Protocol version.
  71 *
  72 * @api public
  73 */
  74
  75exports.protocol = parser.protocol;
  76
  77/**
  78 * `connect`.
  79 *
  80 * @param {String} uri
  81 * @api public
  82 */
  83
  84exports.connect = lookup;
  85
  86/**
  87 * Expose constructors for standalone build.
  88 *
  89 * @api public
  90 */
  91
  92exports.Manager = require('./manager');
  93exports.Socket = require('./socket');
  94
  95},{"./manager":3,"./socket":5,"./url":6,"debug":9,"socket.io-parser":40}],3:[function(require,module,exports){
  96
  97/**
  98 * Module dependencies.
  99 */
 100
 101var url = require('./url');
 102var eio = require('engine.io-client');
 103var Socket = require('./socket');
 104var Emitter = require('component-emitter');
 105var parser = require('socket.io-parser');
 106var on = require('./on');
 107var bind = require('component-bind');
 108var object = require('object-component');
 109var debug = require('debug')('socket.io-client:manager');
 110
 111/**
 112 * Module exports
 113 */
 114
 115module.exports = Manager;
 116
 117/**
 118 * `Manager` constructor.
 119 *
 120 * @param {String} engine instance or engine uri/opts
 121 * @param {Object} options
 122 * @api public
 123 */
 124
 125function Manager(uri, opts){
 126  if (!(this instanceof Manager)) return new Manager(uri, opts);
 127  if (uri && ('object' == typeof uri)) {
 128    opts = uri;
 129    uri = undefined;
 130  }
 131  opts = opts || {};
 132
 133  opts.path = opts.path || '/socket.io';
 134  this.nsps = {};
 135  this.subs = [];
 136  this.opts = opts;
 137  this.reconnection(opts.reconnection !== false);
 138  this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
 139  this.reconnectionDelay(opts.reconnectionDelay || 1000);
 140  this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
 141  this.timeout(null == opts.timeout ? 20000 : opts.timeout);
 142  this.readyState = 'closed';
 143  this.uri = uri;
 144  this.connected = 0;
 145  this.attempts = 0;
 146  this.encoding = false;
 147  this.packetBuffer = [];
 148  this.encoder = new parser.Encoder();
 149  this.decoder = new parser.Decoder();
 150  this.open();
 151}
 152
 153/**
 154 * Propagate given event to sockets and emit on `this`
 155 *
 156 * @api private
 157 */
 158
 159Manager.prototype.emitAll = function() {
 160  this.emit.apply(this, arguments);
 161  for (var nsp in this.nsps) {
 162    this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
 163  }
 164};
 165
 166/**
 167 * Mix in `Emitter`.
 168 */
 169
 170Emitter(Manager.prototype);
 171
 172/**
 173 * Sets the `reconnection` config.
 174 *
 175 * @param {Boolean} true/false if it should automatically reconnect
 176 * @return {Manager} self or value
 177 * @api public
 178 */
 179
 180Manager.prototype.reconnection = function(v){
 181  if (!arguments.length) return this._reconnection;
 182  this._reconnection = !!v;
 183  return this;
 184};
 185
 186/**
 187 * Sets the reconnection attempts config.
 188 *
 189 * @param {Number} max reconnection attempts before giving up
 190 * @return {Manager} self or value
 191 * @api public
 192 */
 193
 194Manager.prototype.reconnectionAttempts = function(v){
 195  if (!arguments.length) return this._reconnectionAttempts;
 196  this._reconnectionAttempts = v;
 197  return this;
 198};
 199
 200/**
 201 * Sets the delay between reconnections.
 202 *
 203 * @param {Number} delay
 204 * @return {Manager} self or value
 205 * @api public
 206 */
 207
 208Manager.prototype.reconnectionDelay = function(v){
 209  if (!arguments.length) return this._reconnectionDelay;
 210  this._reconnectionDelay = v;
 211  return this;
 212};
 213
 214/**
 215 * Sets the maximum delay between reconnections.
 216 *
 217 * @param {Number} delay
 218 * @return {Manager} self or value
 219 * @api public
 220 */
 221
 222Manager.prototype.reconnectionDelayMax = function(v){
 223  if (!arguments.length) return this._reconnectionDelayMax;
 224  this._reconnectionDelayMax = v;
 225  return this;
 226};
 227
 228/**
 229 * Sets the connection timeout. `false` to disable
 230 *
 231 * @return {Manager} self or value
 232 * @api public
 233 */
 234
 235Manager.prototype.timeout = function(v){
 236  if (!arguments.length) return this._timeout;
 237  this._timeout = v;
 238  return this;
 239};
 240
 241/**
 242 * Starts trying to reconnect if reconnection is enabled and we have not
 243 * started reconnecting yet
 244 *
 245 * @api private
 246 */
 247
 248Manager.prototype.maybeReconnectOnOpen = function() {
 249  if (!this.openReconnect && !this.reconnecting && this._reconnection) {
 250    // keeps reconnection from firing twice for the same reconnection loop
 251    this.openReconnect = true;
 252    this.reconnect();
 253  }
 254};
 255
 256
 257/**
 258 * Sets the current transport `socket`.
 259 *
 260 * @param {Function} optional, callback
 261 * @return {Manager} self
 262 * @api public
 263 */
 264
 265Manager.prototype.open =
 266Manager.prototype.connect = function(fn){
 267  debug('readyState %s', this.readyState);
 268  if (~this.readyState.indexOf('open')) return this;
 269
 270  debug('opening %s', this.uri);
 271  this.engine = eio(this.uri, this.opts);
 272  var socket = this.engine;
 273  var self = this;
 274  this.readyState = 'opening';
 275
 276  // emit `open`
 277  var openSub = on(socket, 'open', function() {
 278    self.onopen();
 279    fn && fn();
 280  });
 281
 282  // emit `connect_error`
 283  var errorSub = on(socket, 'error', function(data){
 284    debug('connect_error');
 285    self.cleanup();
 286    self.readyState = 'closed';
 287    self.emitAll('connect_error', data);
 288    if (fn) {
 289      var err = new Error('Connection error');
 290      err.data = data;
 291      fn(err);
 292    }
 293
 294    self.maybeReconnectOnOpen();
 295  });
 296
 297  // emit `connect_timeout`
 298  if (false !== this._timeout) {
 299    var timeout = this._timeout;
 300    debug('connect attempt will timeout after %d', timeout);
 301
 302    // set timer
 303    var timer = setTimeout(function(){
 304      debug('connect attempt timed out after %d', timeout);
 305      openSub.destroy();
 306      socket.close();
 307      socket.emit('error', 'timeout');
 308      self.emitAll('connect_timeout', timeout);
 309    }, timeout);
 310
 311    this.subs.push({
 312      destroy: function(){
 313        clearTimeout(timer);
 314      }
 315    });
 316  }
 317
 318  this.subs.push(openSub);
 319  this.subs.push(errorSub);
 320
 321  return this;
 322};
 323
 324/**
 325 * Called upon transport open.
 326 *
 327 * @api private
 328 */
 329
 330Manager.prototype.onopen = function(){
 331  debug('open');
 332
 333  // clear old subs
 334  this.cleanup();
 335
 336  // mark as open
 337  this.readyState = 'open';
 338  this.emit('open');
 339
 340  // add new subs
 341  var socket = this.engine;
 342  this.subs.push(on(socket, 'data', bind(this, 'ondata')));
 343  this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
 344  this.subs.push(on(socket, 'error', bind(this, 'onerror')));
 345  this.subs.push(on(socket, 'close', bind(this, 'onclose')));
 346};
 347
 348/**
 349 * Called with data.
 350 *
 351 * @api private
 352 */
 353
 354Manager.prototype.ondata = function(data){
 355  this.decoder.add(data);
 356};
 357
 358/**
 359 * Called when parser fully decodes a packet.
 360 *
 361 * @api private
 362 */
 363
 364Manager.prototype.ondecoded = function(packet) {
 365  this.emit('packet', packet);
 366};
 367
 368/**
 369 * Called upon socket error.
 370 *
 371 * @api private
 372 */
 373
 374Manager.prototype.onerror = function(err){
 375  debug('error', err);
 376  this.emitAll('error', err);
 377};
 378
 379/**
 380 * Creates a new socket for the given `nsp`.
 381 *
 382 * @return {Socket}
 383 * @api public
 384 */
 385
 386Manager.prototype.socket = function(nsp){
 387  var socket = this.nsps[nsp];
 388  if (!socket) {
 389    socket = new Socket(this, nsp);
 390    this.nsps[nsp] = socket;
 391    var self = this;
 392    socket.on('connect', function(){
 393      self.connected++;
 394    });
 395  }
 396  return socket;
 397};
 398
 399/**
 400 * Called upon a socket close.
 401 *
 402 * @param {Socket} socket
 403 */
 404
 405Manager.prototype.destroy = function(socket){
 406  --this.connected || this.close();
 407};
 408
 409/**
 410 * Writes a packet.
 411 *
 412 * @param {Object} packet
 413 * @api private
 414 */
 415
 416Manager.prototype.packet = function(packet){
 417  debug('writing packet %j', packet);
 418  var self = this;
 419
 420  if (!self.encoding) {
 421    // encode, then write to engine with result
 422    self.encoding = true;
 423    this.encoder.encode(packet, function(encodedPackets) {
 424      for (var i = 0; i < encodedPackets.length; i++) {
 425        self.engine.write(encodedPackets[i]);
 426      }
 427      self.encoding = false;
 428      self.processPacketQueue();
 429    });
 430  } else { // add packet to the queue
 431    self.packetBuffer.push(packet);
 432  }
 433};
 434
 435/**
 436 * If packet buffer is non-empty, begins encoding the
 437 * next packet in line.
 438 *
 439 * @api private
 440 */
 441
 442Manager.prototype.processPacketQueue = function() {
 443  if (this.packetBuffer.length > 0 && !this.encoding) {
 444    var pack = this.packetBuffer.shift();
 445    this.packet(pack);
 446  }
 447};
 448
 449/**
 450 * Clean up transport subscriptions and packet buffer.
 451 *
 452 * @api private
 453 */
 454
 455Manager.prototype.cleanup = function(){
 456  var sub;
 457  while (sub = this.subs.shift()) sub.destroy();
 458
 459  this.packetBuffer = [];
 460  this.encoding = false;
 461
 462  this.decoder.destroy();
 463};
 464
 465/**
 466 * Close the current socket.
 467 *
 468 * @api private
 469 */
 470
 471Manager.prototype.close =
 472Manager.prototype.disconnect = function(){
 473  this.skipReconnect = true;
 474  this.engine.close();
 475};
 476
 477/**
 478 * Called upon engine close.
 479 *
 480 * @api private
 481 */
 482
 483Manager.prototype.onclose = function(reason){
 484  debug('close');
 485  this.cleanup();
 486  this.readyState = 'closed';
 487  this.emit('close', reason);
 488  if (this._reconnection && !this.skipReconnect) {
 489    this.reconnect();
 490  }
 491};
 492
 493/**
 494 * Attempt a reconnection.
 495 *
 496 * @api private
 497 */
 498
 499Manager.prototype.reconnect = function(){
 500  if (this.reconnecting) return this;
 501
 502  var self = this;
 503  this.attempts++;
 504
 505  if (this.attempts > this._reconnectionAttempts) {
 506    debug('reconnect failed');
 507    this.emitAll('reconnect_failed');
 508    this.reconnecting = false;
 509  } else {
 510    var delay = this.attempts * this.reconnectionDelay();
 511    delay = Math.min(delay, this.reconnectionDelayMax());
 512    debug('will wait %dms before reconnect attempt', delay);
 513
 514    this.reconnecting = true;
 515    var timer = setTimeout(function(){
 516      debug('attempting reconnect');
 517      self.emitAll('reconnect_attempt');
 518      self.emitAll('reconnecting', self.attempts);
 519      self.open(function(err){
 520        if (err) {
 521          debug('reconnect attempt error');
 522          self.reconnecting = false;
 523          self.reconnect();
 524          self.emitAll('reconnect_error', err.data);
 525        } else {
 526          debug('reconnect success');
 527          self.onreconnect();
 528        }
 529      });
 530    }, delay);
 531
 532    this.subs.push({
 533      destroy: function(){
 534        clearTimeout(timer);
 535      }
 536    });
 537  }
 538};
 539
 540/**
 541 * Called upon successful reconnect.
 542 *
 543 * @api private
 544 */
 545
 546Manager.prototype.onreconnect = function(){
 547  var attempt = this.attempts;
 548  this.attempts = 0;
 549  this.reconnecting = false;
 550  this.emitAll('reconnect', attempt);
 551};
 552
 553},{"./on":4,"./socket":5,"./url":6,"component-bind":7,"component-emitter":8,"debug":9,"engine.io-client":11,"object-component":37,"socket.io-parser":40}],4:[function(require,module,exports){
 554
 555/**
 556 * Module exports.
 557 */
 558
 559module.exports = on;
 560
 561/**
 562 * Helper for subscriptions.
 563 *
 564 * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
 565 * @param {String} event name
 566 * @param {Function} callback
 567 * @api public
 568 */
 569
 570function on(obj, ev, fn) {
 571  obj.on(ev, fn);
 572  return {
 573    destroy: function(){
 574      obj.removeListener(ev, fn);
 575    }
 576  };
 577}
 578
 579},{}],5:[function(require,module,exports){
 580
 581/**
 582 * Module dependencies.
 583 */
 584
 585var parser = require('socket.io-parser');
 586var Emitter = require('component-emitter');
 587var toArray = require('to-array');
 588var on = require('./on');
 589var bind = require('component-bind');
 590var debug = require('debug')('socket.io-client:socket');
 591var hasBin = require('has-binary-data');
 592var indexOf = require('indexof');
 593
 594/**
 595 * Module exports.
 596 */
 597
 598module.exports = exports = Socket;
 599
 600/**
 601 * Internal events (blacklisted).
 602 * These events can't be emitted by the user.
 603 *
 604 * @api private
 605 */
 606
 607var events = {
 608  connect: 1,
 609  connect_error: 1,
 610  connect_timeout: 1,
 611  disconnect: 1,
 612  error: 1,
 613  reconnect: 1,
 614  reconnect_attempt: 1,
 615  reconnect_failed: 1,
 616  reconnect_error: 1,
 617  reconnecting: 1
 618};
 619
 620/**
 621 * Shortcut to `Emitter#emit`.
 622 */
 623
 624var emit = Emitter.prototype.emit;
 625
 626/**
 627 * `Socket` constructor.
 628 *
 629 * @api public
 630 */
 631
 632function Socket(io, nsp){
 633  this.io = io;
 634  this.nsp = nsp;
 635  this.json = this; // compat
 636  this.ids = 0;
 637  this.acks = {};
 638  this.open();
 639  this.receiveBuffer = [];
 640  this.sendBuffer = [];
 641  this.connected = false;
 642  this.disconnected = true;
 643}
 644
 645/**
 646 * Mix in `Emitter`.
 647 */
 648
 649Emitter(Socket.prototype);
 650
 651/**
 652 * Called upon engine `open`.
 653 *
 654 * @api private
 655 */
 656
 657Socket.prototype.open =
 658Socket.prototype.connect = function(){
 659  if (this.connected) return this;
 660  var io = this.io;
 661  io.open(); // ensure open
 662  this.subs = [
 663    on(io, 'open', bind(this, 'onopen')),
 664    on(io, 'packet', bind(this, 'onpacket')),
 665    on(io, 'close', bind(this, 'onclose'))
 666  ];
 667  if ('open' == this.io.readyState) this.onopen();
 668  return this;
 669};
 670
 671/**
 672 * Sends a `message` event.
 673 *
 674 * @return {Socket} self
 675 * @api public
 676 */
 677
 678Socket.prototype.send = function(){
 679  var args = toArray(arguments);
 680  args.unshift('message');
 681  this.emit.apply(this, args);
 682  return this;
 683};
 684
 685/**
 686 * Override `emit`.
 687 * If the event is in `events`, it's emitted normally.
 688 *
 689 * @param {String} event name
 690 * @return {Socket} self
 691 * @api public
 692 */
 693
 694Socket.prototype.emit = function(ev){
 695  if (events.hasOwnProperty(ev)) {
 696    emit.apply(this, arguments);
 697    return this;
 698  }
 699
 700  var args = toArray(arguments);
 701  var parserType = parser.EVENT; // default
 702  if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
 703  var packet = { type: parserType, data: args };
 704
 705  // event ack callback
 706  if ('function' == typeof args[args.length - 1]) {
 707    debug('emitting packet with ack id %d', this.ids);
 708    this.acks[this.ids] = args.pop();
 709    packet.id = this.ids++;
 710  }
 711
 712  if (this.connected) {
 713    this.packet(packet);
 714  } else {
 715    this.sendBuffer.push(packet);
 716  }
 717
 718  return this;
 719};
 720
 721/**
 722 * Sends a packet.
 723 *
 724 * @param {Object} packet
 725 * @api private
 726 */
 727
 728Socket.prototype.packet = function(packet){
 729  packet.nsp = this.nsp;
 730  this.io.packet(packet);
 731};
 732
 733/**
 734 * "Opens" the socket.
 735 *
 736 * @api private
 737 */
 738
 739Socket.prototype.onopen = function(){
 740  debug('transport is open - connecting');
 741
 742  // write connect packet if necessary
 743  if ('/' != this.nsp) {
 744    this.packet({ type: parser.CONNECT });
 745  }
 746};
 747
 748/**
 749 * Called upon engine `close`.
 750 *
 751 * @param {String} reason
 752 * @api private
 753 */
 754
 755Socket.prototype.onclose = function(reason){
 756  debug('close (%s)', reason);
 757  this.connected = false;
 758  this.disconnected = true;
 759  this.emit('disconnect', reason);
 760};
 761
 762/**
 763 * Called with socket packet.
 764 *
 765 * @param {Object} packet
 766 * @api private
 767 */
 768
 769Socket.prototype.onpacket = function(packet){
 770  if (packet.nsp != this.nsp) return;
 771
 772  switch (packet.type) {
 773    case parser.CONNECT:
 774      this.onconnect();
 775      break;
 776
 777    case parser.EVENT:
 778      this.onevent(packet);
 779      break;
 780
 781    case parser.BINARY_EVENT:
 782      this.onevent(packet);
 783      break;
 784
 785    case parser.ACK:
 786      this.onack(packet);
 787      break;
 788
 789    case parser.BINARY_ACK:
 790      this.onack(packet);
 791      break;
 792
 793    case parser.DISCONNECT:
 794      this.ondisconnect();
 795      break;
 796
 797    case parser.ERROR:
 798      this.emit('error', packet.data);
 799      break;
 800  }
 801};
 802
 803/**
 804 * Called upon a server event.
 805 *
 806 * @param {Object} packet
 807 * @api private
 808 */
 809
 810Socket.prototype.onevent = function(packet){
 811  var args = packet.data || [];
 812  debug('emitting event %j', args);
 813
 814  if (null != packet.id) {
 815    debug('attaching ack callback to event');
 816    args.push(this.ack(packet.id));
 817  }
 818
 819  if (this.connected) {
 820    emit.apply(this, args);
 821  } else {
 822    this.receiveBuffer.push(args);
 823  }
 824};
 825
 826/**
 827 * Produces an ack callback to emit with an event.
 828 *
 829 * @api private
 830 */
 831
 832Socket.prototype.ack = function(id){
 833  var self = this;
 834  var sent = false;
 835  return function(){
 836    // prevent double callbacks
 837    if (sent) return;
 838    sent = true;
 839    var args = toArray(arguments);
 840    debug('sending ack %j', args);
 841
 842    var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
 843    self.packet({
 844      type: type,
 845      id: id,
 846      data: args
 847    });
 848  };
 849};
 850
 851/**
 852 * Called upon a server acknowlegement.
 853 *
 854 * @param {Object} packet
 855 * @api private
 856 */
 857
 858Socket.prototype.onack = function(packet){
 859  debug('calling ack %s with %j', packet.id, packet.data);
 860  var fn = this.acks[packet.id];
 861  fn.apply(this, packet.data);
 862  delete this.acks[packet.id];
 863};
 864
 865/**
 866 * Called upon server connect.
 867 *
 868 * @api private
 869 */
 870
 871Socket.prototype.onconnect = function(){
 872  this.connected = true;
 873  this.disconnected = false;
 874  this.emit('connect');
 875  this.emitBuffered();
 876};
 877
 878/**
 879 * Emit buffered events (received and emitted).
 880 *
 881 * @api private
 882 */
 883
 884Socket.prototype.emitBuffered = function(){
 885  var i;
 886  for (i = 0; i < this.receiveBuffer.length; i++) {
 887    emit.apply(this, this.receiveBuffer[i]);
 888  }
 889  this.receiveBuffer = [];
 890
 891  for (i = 0; i < this.sendBuffer.length; i++) {
 892    this.packet(this.sendBuffer[i]);
 893  }
 894  this.sendBuffer = [];
 895};
 896
 897/**
 898 * Called upon server disconnect.
 899 *
 900 * @api private
 901 */
 902
 903Socket.prototype.ondisconnect = function(){
 904  debug('server disconnect (%s)', this.nsp);
 905  this.destroy();
 906  this.onclose('io server disconnect');
 907};
 908
 909/**
 910 * Called upon forced client/server side disconnections,
 911 * this method ensures the manager stops tracking us and
 912 * that reconnections don't get triggered for this.
 913 *
 914 * @api private.
 915 */
 916
 917Socket.prototype.destroy = function(){
 918  // clean subscriptions to avoid reconnections
 919  for (var i = 0; i < this.subs.length; i++) {
 920    this.subs[i].destroy();
 921  }
 922
 923  this.io.destroy(this);
 924};
 925
 926/**
 927 * Disconnects the socket manually.
 928 *
 929 * @return {Socket} self
 930 * @api public
 931 */
 932
 933Socket.prototype.close =
 934Socket.prototype.disconnect = function(){
 935  if (!this.connected) return this;
 936
 937  debug('performing disconnect (%s)', this.nsp);
 938  this.packet({ type: parser.DISCONNECT });
 939
 940  // remove socket from pool
 941  this.destroy();
 942
 943  // fire events
 944  this.onclose('io client disconnect');
 945  return this;
 946};
 947
 948},{"./on":4,"component-bind":7,"component-emitter":8,"debug":9,"has-binary-data":32,"indexof":36,"socket.io-parser":40,"to-array":43}],6:[function(require,module,exports){
 949var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
 950/**
 951 * Module dependencies.
 952 */
 953
 954var parseuri = require('parseuri');
 955var debug = require('debug')('socket.io-client:url');
 956
 957/**
 958 * Module exports.
 959 */
 960
 961module.exports = url;
 962
 963/**
 964 * URL parser.
 965 *
 966 * @param {String} url
 967 * @param {Object} An object meant to mimic window.location.
 968 *                 Defaults to window.location.
 969 * @api public
 970 */
 971
 972function url(uri, loc){
 973  var obj = uri;
 974
 975  // default to window.location
 976  var loc = loc || global.location;
 977  if (null == uri) uri = loc.protocol + '//' + loc.hostname;
 978
 979  // relative path support
 980  if ('string' == typeof uri) {
 981    if ('/' == uri.charAt(0)) {
 982      if ('undefined' != typeof loc) {
 983        uri = loc.hostname + uri;
 984      }
 985    }
 986
 987    if (!/^(https?|wss?):\/\//.test(uri)) {
 988      debug('protocol-less url %s', uri);
 989      if ('undefined' != typeof loc) {
 990        uri = loc.protocol + '//' + uri;
 991      } else {
 992        uri = 'https://' + uri;
 993      }
 994    }
 995
 996    // parse
 997    debug('parse %s', uri);
 998    obj = parseuri(uri);
 999  }
1000
1001  // make sure we treat `localhost:80` and `localhost` equally
1002  if (!obj.port) {
1003    if (/^(http|ws)$/.test(obj.protocol)) {
1004      obj.port = '80';
1005    }
1006    else if (/^(http|ws)s$/.test(obj.protocol)) {
1007      obj.port = '443';
1008    }
1009  }
1010
1011  obj.path = obj.path || '/';
1012
1013  // define unique id
1014  obj.id = obj.protocol + '://' + obj.host + ':' + obj.port;
1015  // define href
1016  obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
1017
1018  return obj;
1019}
1020
1021},{"debug":9,"parseuri":38}],7:[function(require,module,exports){
1022/**
1023 * Slice reference.
1024 */
1025
1026var slice = [].slice;
1027
1028/**
1029 * Bind `obj` to `fn`.
1030 *
1031 * @param {Object} obj
1032 * @param {Function|String} fn or string
1033 * @return {Function}
1034 * @api public
1035 */
1036
1037module.exports = function(obj, fn){
1038  if ('string' == typeof fn) fn = obj[fn];
1039  if ('function' != typeof fn) throw new Error('bind() requires a function');
1040  var args = slice.call(arguments, 2);
1041  return function(){
1042    return fn.apply(obj, args.concat(slice.call(arguments)));
1043  }
1044};
1045
1046},{}],8:[function(require,module,exports){
1047
1048/**
1049 * Expose `Emitter`.
1050 */
1051
1052module.exports = Emitter;
1053
1054/**
1055 * Initialize a new `Emitter`.
1056 *
1057 * @api public
1058 */
1059
1060function Emitter(obj) {
1061  if (obj) return mixin(obj);
1062};
1063
1064/**
1065 * Mixin the emitter properties.
1066 *
1067 * @param {Object} obj
1068 * @return {Object}
1069 * @api private
1070 */
1071
1072function mixin(obj) {
1073  for (var key in Emitter.prototype) {
1074    obj[key] = Emitter.prototype[key];
1075  }
1076  return obj;
1077}
1078
1079/**
1080 * Listen on the given `event` with `fn`.
1081 *
1082 * @param {String} event
1083 * @param {Function} fn
1084 * @return {Emitter}
1085 * @api public
1086 */
1087
1088Emitter.prototype.on =
1089Emitter.prototype.addEventListener = function(event, fn){
1090  this._callbacks = this._callbacks || {};
1091  (this._callbacks[event] = this._callbacks[event] || [])
1092    .push(fn);
1093  return this;
1094};
1095
1096/**
1097 * Adds an `event` listener that will be invoked a single
1098 * time then automatically removed.
1099 *
1100 * @param {String} event
1101 * @param {Function} fn
1102 * @return {Emitter}
1103 * @api public
1104 */
1105
1106Emitter.prototype.once = function(event, fn){
1107  var self = this;
1108  this._callbacks = this._callbacks || {};
1109
1110  function on() {
1111    self.off(event, on);
1112    fn.apply(this, arguments);
1113  }
1114
1115  on.fn = fn;
1116  this.on(event, on);
1117  return this;
1118};
1119
1120/**
1121 * Remove the given callback for `event` or all
1122 * registered callbacks.
1123 *
1124 * @param {String} event
1125 * @param {Function} fn
1126 * @return {Emitter}
1127 * @api public
1128 */
1129
1130Emitter.prototype.off =
1131Emitter.prototype.removeListener =
1132Emitter.prototype.removeAllListeners =
1133Emitter.prototype.removeEventListener = function(event, fn){
1134  this._callbacks = this._callbacks || {};
1135
1136  // all
1137  if (0 == arguments.length) {
1138    this._callbacks = {};
1139    return this;
1140  }
1141
1142  // specific event
1143  var callbacks = this._callbacks[event];
1144  if (!callbacks) return this;
1145
1146  // remove all handlers
1147  if (1 == arguments.length) {
1148    delete this._callbacks[event];
1149    return this;
1150  }
1151
1152  // remove specific handler
1153  var cb;
1154  for (var i = 0; i < callbacks.length; i++) {
1155    cb = callbacks[i];
1156    if (cb === fn || cb.fn === fn) {
1157      callbacks.splice(i, 1);
1158      break;
1159    }
1160  }
1161  return this;
1162};
1163
1164/**
1165 * Emit `event` with the given args.
1166 *
1167 * @param {String} event
1168 * @param {Mixed} ...
1169 * @return {Emitter}
1170 */
1171
1172Emitter.prototype.emit = function(event){
1173  this._callbacks = this._callbacks || {};
1174  var args = [].slice.call(arguments, 1)
1175    , callbacks = this._callbacks[event];
1176
1177  if (callbacks) {
1178    callbacks = callbacks.slice(0);
1179    for (var i = 0, len = callbacks.length; i < len; ++i) {
1180      callbacks[i].apply(this, args);
1181    }
1182  }
1183
1184  return this;
1185};
1186
1187/**
1188 * Return array of callbacks for `event`.
1189 *
1190 * @param {String} event
1191 * @return {Array}
1192 * @api public
1193 */
1194
1195Emitter.prototype.listeners = function(event){
1196  this._callbacks = this._callbacks || {};
1197  return this._callbacks[event] || [];
1198};
1199
1200/**
1201 * Check if this emitter has `event` handlers.
1202 *
1203 * @param {String} event
1204 * @return {Boolean}
1205 * @api public
1206 */
1207
1208Emitter.prototype.hasListeners = function(event){
1209  return !! this.listeners(event).length;
1210};
1211
1212},{}],9:[function(require,module,exports){
1213
1214/**
1215 * Expose `debug()` as the module.
1216 */
1217
1218module.exports = debug;
1219
1220/**
1221 * Create a debugger with the given `name`.
1222 *
1223 * @param {String} name
1224 * @return {Type}
1225 * @api public
1226 */
1227
1228function debug(name) {
1229  if (!debug.enabled(name)) return function(){};
1230
1231  return function(fmt){
1232    fmt = coerce(fmt);
1233
1234    var curr = new Date;
1235    var ms = curr - (debug[name] || curr);
1236    debug[name] = curr;
1237
1238    fmt = name
1239      + ' '
1240      + fmt
1241      + ' +' + debug.humanize(ms);
1242
1243    // This hackery is required for IE8
1244    // where `console.log` doesn't have 'apply'
1245    window.console
1246      && console.log
1247      && Function.prototype.apply.call(console.log, console, arguments);
1248  }
1249}
1250
1251/**
1252 * The currently active debug mode names.
1253 */
1254
1255debug.names = [];
1256debug.skips = [];
1257
1258/**
1259 * Enables a debug mode by name. This can include modes
1260 * separated by a colon and wildcards.
1261 *
1262 * @param {String} name
1263 * @api public
1264 */
1265
1266debug.enable = function(name) {
1267  try {
1268    localStorage.debug = name;
1269  } catch(e){}
1270
1271  var split = (name || '').split(/[\s,]+/)
1272    , len = split.length;
1273
1274  for (var i = 0; i < len; i++) {
1275    name = split[i].replace('*', '.*?');
1276    if (name[0] === '-') {
1277      debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
1278    }
1279    else {
1280      debug.names.push(new RegExp('^' + name + '$'));
1281    }
1282  }
1283};
1284
1285/**
1286 * Disable debug output.
1287 *
1288 * @api public
1289 */
1290
1291debug.disable = function(){
1292  debug.enable('');
1293};
1294
1295/**
1296 * Humanize the given `ms`.
1297 *
1298 * @param {Number} m
1299 * @return {String}
1300 * @api private
1301 */
1302
1303debug.humanize = function(ms) {
1304  var sec = 1000
1305    , min = 60 * 1000
1306    , hour = 60 * min;
1307
1308  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
1309  if (ms >= min) return (ms / min).toFixed(1) + 'm';
1310  if (ms >= sec) return (ms / sec | 0) + 's';
1311  return ms + 'ms';
1312};
1313
1314/**
1315 * Returns true if the given mode name is enabled, false otherwise.
1316 *
1317 * @param {String} name
1318 * @return {Boolean}
1319 * @api public
1320 */
1321
1322debug.enabled = function(name) {
1323  for (var i = 0, len = debug.skips.length; i < len; i++) {
1324    if (debug.skips[i].test(name)) {
1325      return false;
1326    }
1327  }
1328  for (var i = 0, len = debug.names.length; i < len; i++) {
1329    if (debug.names[i].test(name)) {
1330      return true;
1331    }
1332  }
1333  return false;
1334};
1335
1336/**
1337 * Coerce `val`.
1338 */
1339
1340function coerce(val) {
1341  if (val instanceof Error) return val.stack || val.message;
1342  return val;
1343}
1344
1345// persist
1346
1347try {
1348  if (window.localStorage) debug.enable(localStorage.debug);
1349} catch(e){}
1350
1351},{}],10:[function(require,module,exports){
1352
1353/**
1354 * Module dependencies.
1355 */
1356
1357var index = require('indexof');
1358
1359/**
1360 * Expose `Emitter`.
1361 */
1362
1363module.exports = Emitter;
1364
1365/**
1366 * Initialize a new `Emitter`.
1367 *
1368 * @api public
1369 */
1370
1371function Emitter(obj) {
1372  if (obj) return mixin(obj);
1373};
1374
1375/**
1376 * Mixin the emitter properties.
1377 *
1378 * @param {Object} obj
1379 * @return {Object}
1380 * @api private
1381 */
1382
1383function mixin(obj) {
1384  for (var key in Emitter.prototype) {
1385    obj[key] = Emitter.prototype[key];
1386  }
1387  return obj;
1388}
1389
1390/**
1391 * Listen on the given `event` with `fn`.
1392 *
1393 * @param {String} event
1394 * @param {Function} fn
1395 * @return {Emitter}
1396 * @api public
1397 */
1398
1399Emitter.prototype.on = function(event, fn){
1400  this._callbacks = this._callbacks || {};
1401  (this._callbacks[event] = this._callbacks[event] || [])
1402    .push(fn);
1403  return this;
1404};
1405
1406/**
1407 * Adds an `event` listener that will be invoked a single
1408 * time then automatically removed.
1409 *
1410 * @param {String} event
1411 * @param {Function} fn
1412 * @return {Emitter}
1413 * @api public
1414 */
1415
1416Emitter.prototype.once = function(event, fn){
1417  var self = this;
1418  this._callbacks = this._callbacks || {};
1419
1420  function on() {
1421    self.off(event, on);
1422    fn.apply(this, arguments);
1423  }
1424
1425  fn._off = on;
1426  this.on(event, on);
1427  return this;
1428};
1429
1430/**
1431 * Remove the given callback for `event` or all
1432 * registered callbacks.
1433 *
1434 * @param {String} event
1435 * @param {Function} fn
1436 * @return {Emitter}
1437 * @api public
1438 */
1439
1440Emitter.prototype.off =
1441Emitter.prototype.removeListener =
1442Emitter.prototype.removeAllListeners = function(event, fn){
1443  this._callbacks = this._callbacks || {};
1444
1445  // all
1446  if (0 == arguments.length) {
1447    this._callbacks = {};
1448    return this;
1449  }
1450
1451  // specific event
1452  var callbacks = this._callbacks[event];
1453  if (!callbacks) return this;
1454
1455  // remove all handlers
1456  if (1 == arguments.length) {
1457    delete this._callbacks[event];
1458    return this;
1459  }
1460
1461  // remove specific handler
1462  var i = index(callbacks, fn._off || fn);
1463  if (~i) callbacks.splice(i, 1);
1464  return this;
1465};
1466
1467/**
1468 * Emit `event` with the given args.
1469 *
1470 * @param {String} event
1471 * @param {Mixed} ...
1472 * @return {Emitter}
1473 */
1474
1475Emitter.prototype.emit = function(event){
1476  this._callbacks = this._callbacks || {};
1477  var args = [].slice.call(arguments, 1)
1478    , callbacks = this._callbacks[event];
1479
1480  if (callbacks) {
1481    callbacks = callbacks.slice(0);
1482    for (var i = 0, len = callbacks.length; i < len; ++i) {
1483      callbacks[i].apply(this, args);
1484    }
1485  }
1486
1487  return this;
1488};
1489
1490/**
1491 * Return array of callbacks for `event`.
1492 *
1493 * @param {String} event
1494 * @return {Array}
1495 * @api public
1496 */
1497
1498Emitter.prototype.listeners = function(event){
1499  this._callbacks = this._callbacks || {};
1500  return this._callbacks[event] || [];
1501};
1502
1503/**
1504 * Check if this emitter has `event` handlers.
1505 *
1506 * @param {String} event
1507 * @return {Boolean}
1508 * @api public
1509 */
1510
1511Emitter.prototype.hasListeners = function(event){
1512  return !! this.listeners(event).length;
1513};
1514
1515},{"indexof":36}],11:[function(require,module,exports){
1516
1517module.exports =  require('./lib/');
1518
1519},{"./lib/":12}],12:[function(require,module,exports){
1520
1521module.exports = require('./socket');
1522
1523/**
1524 * Exports parser
1525 *
1526 * @api public
1527 *
1528 */
1529module.exports.parser = require('engine.io-parser');
1530
1531},{"./socket":13,"engine.io-parser":22}],13:[function(require,module,exports){
1532var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};/**
1533 * Module dependencies.
1534 */
1535
1536var transports = require('./transports');
1537var Emitter = require('component-emitter');
1538var debug = require('debug')('engine.io-client:socket');
1539var index = require('indexof');
1540var parser = require('engine.io-parser');
1541var parseuri = require('parseuri');
1542var parsejson = require('parsejson');
1543var parseqs = require('parseqs');
1544
1545/**
1546 * Module exports.
1547 */
1548
1549module.exports = Socket;
1550
1551/**
1552 * Noop function.
1553 *
1554 * @api private
1555 */
1556
1557function noop(){}
1558
1559/**
1560 * Socket constructor.
1561 *
1562 * @param {String|Object} uri or options
1563 * @param {Object} options
1564 * @api public
1565 */
1566
1567function Socket(uri, opts){
1568  if (!(this instanceof Socket)) return new Socket(uri, opts);
1569
1570  opts = opts || {};
1571
1572  if (uri && 'object' == typeof uri) {
1573    opts = uri;
1574    uri = null;
1575  }
1576
1577  if (uri) {
1578    uri = parseuri(uri);
1579    opts.host = uri.host;
1580    opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
1581    opts.port = uri.port;
1582    if (uri.query) opts.query = uri.query;
1583  }
1584
1585  this.secure = null != opts.secure ? opts.secure :
1586    (global.location && 'https:' == location.protocol);
1587
1588  if (opts.host) {
1589    var pieces = opts.host.split(':');
1590    opts.hostname = pieces.shift();
1591    if (pieces.length) opts.port = pieces.pop();
1592  }
1593
1594  this.agent = opts.agent || false;
1595  this.hostname = opts.hostname ||
1596    (global.location ? location.hostname : 'localhost');
1597  this.port = opts.port || (global.location && location.port ?
1598       location.port :
1599       (this.secure ? 443 : 80));
1600  this.query = opts.query || {};
1601  if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
1602  this.upgrade = false !== opts.upgrade;
1603  this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
1604  this.forceJSONP = !!opts.forceJSONP;
1605  this.forceBase64 = !!opts.forceBase64;
1606  this.timestampParam = opts.timestampParam || 't';
1607  this.timestampRequests = opts.timestampRequests;
1608  this.transports = opts.transports || ['polling', 'websocket'];
1609  this.readyState = '';
1610  this.writeBuffer = [];
1611  this.callbackBuffer = [];
1612  this.policyPort = opts.policyPort || 843;
1613  this.rememberUpgrade = opts.rememberUpgrade || false;
1614  this.open();
1615  this.binaryType = null;
1616  this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
1617}
1618
1619Socket.priorWebsocketSuccess = false;
1620
1621/**
1622 * Mix in `Emitter`.
1623 */
1624
1625Emitter(Socket.prototype);
1626
1627/**
1628 * Protocol version.
1629 *
1630 * @api public
1631 */
1632
1633Socket.protocol = parser.protocol; // this is an int
1634
1635/**
1636 * Expose deps for legacy compatibility
1637 * and standalone browser access.
1638 */
1639
1640Socket.Socket = Socket;
1641Socket.Transport = require('./transport');
1642Socket.transports = require('./transports');
1643Socket.parser = require('engine.io-parser');
1644
1645/**
1646 * Creates transport of the given type.
1647 *
1648 * @param {String} transport name
1649 * @return {Transport}
1650 * @api private
1651 */
1652
1653Socket.prototype.createTransport = function (name) {
1654  debug('creating transport "%s"', name);
1655  var query = clone(this.query);
1656
1657  // append engine.io protocol identifier
1658  query.EIO = parser.protocol;
1659
1660  // transport name
1661  query.transport = name;
1662
1663  // session id if we already have one
1664  if (this.id) query.sid = this.id;
1665
1666  var transport = new transports[name]({
1667    agent: this.agent,
1668    hostname: this.hostname,
1669    port: this.port,
1670    secure: this.secure,
1671    path: this.path,
1672    query: query,
1673    forceJSONP: this.forceJSONP,
1674    forceBase64: this.forceBase64,
1675    timestampRequests: this.timestampRequests,
1676    timestampParam: this.timestampParam,
1677    policyPort: this.policyPort,
1678    socket: this
1679  });
1680
1681  return transport;
1682};
1683
1684function clone (obj) {
1685  var o = {};
1686  for (var i in obj) {
1687    if (obj.hasOwnProperty(i)) {
1688      o[i] = obj[i];
1689    }
1690  }
1691  return o;
1692}
1693
1694/**
1695 * Initializes transport to use and starts probe.
1696 *
1697 * @api private
1698 */
1699Socket.prototype.open = function () {
1700  var transport;
1701  if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
1702    transport = 'websocket';
1703  } else {
1704    transport = this.transports[0];
1705  }
1706  this.readyState = 'opening';
1707  var transport = this.createTransport(transport);
1708  transport.open();
1709  this.setTransport(transport);
1710};
1711
1712/**
1713 * Sets the current transport. Disables the existing one (if any).
1714 *
1715 * @api private
1716 */
1717
1718Socket.prototype.setTransport = function(transport){
1719  debug('setting transport %s', transport.name);
1720  var self = this;
1721
1722  if (this.transport) {
1723    debug('clearing existing transport %s', this.transport.name);
1724    this.transport.removeAllListeners();
1725  }
1726
1727  // set up transport
1728  this.transport = transport;
1729
1730  // set up transport listeners
1731  transport
1732  .on('drain', function(){
1733    self.onDrain();
1734  })
1735  .on('packet', function(packet){
1736    self.onPacket(packet);
1737  })
1738  .on('error', function(e){
1739    self.onError(e);
1740  })
1741  .on('close', function(){
1742    self.onClose('transport close');
1743  });
1744};
1745
1746/**
1747 * Probes a transport.
1748 *
1749 * @param {String} transport name
1750 * @api private
1751 */
1752
1753Socket.prototype.probe = function (name) {
1754  debug('probing transport "%s"', name);
1755  var transport = this.createTransport(name, { probe: 1 })
1756    , failed = false
1757    , self = this;
1758
1759  Socket.priorWebsocketSuccess = false;
1760
1761  function onTransportOpen(){
1762    if (self.onlyBinaryUpgrades) {
1763      var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
1764      failed = failed || upgradeLosesBinary;
1765    }
1766    if (failed) return;
1767
1768    debug('probe transport "%s" opened', name);
1769    transport.send([{ type: 'ping', data: 'probe' }]);
1770    transport.once('packet', function (msg) {
1771      if (failed) return;
1772      if ('pong' == msg.type && 'probe' == msg.data) {
1773        debug('probe transport "%s" pong', name);
1774        self.upgrading = true;
1775        self.emit('upgrading', transport);
1776        Socket.priorWebsocketSuccess = 'websocket' == transport.name;
1777
1778        debug('pausing current transport "%s"', self.transport.name);
1779        self.transport.pause(function () {
1780          if (failed) return;
1781          if ('closed' == self.readyState || 'closing' == self.readyState) {
1782            return;
1783          }
1784          debug('changing transport and sending upgrade packet');
1785
1786          cleanup();
1787
1788          self.setTransport(transport);
1789          transport.send([{ type: 'upgrade' }]);
1790          self.emit('upgrade', transport);
1791          transport = null;
1792          self.upgrading = false;
1793          self.flush();
1794        });
1795      } else {
1796        debug('probe transport "%s" failed', name);
1797        var err = new Error('probe error');
1798        err.transport = transport.name;
1799        self.emit('upgradeError', err);
1800      }
1801    });
1802  }
1803
1804  function freezeTransport() {
1805    if (failed) return;
1806
1807    // Any callback called by transport should be ignored since now
1808    failed = true;
1809
1810    cleanup();
1811
1812    transport.close();
1813    transport = null;
1814  }
1815
1816  //Handle any error that happens while probing
1817  function onerror(err) {
1818    var error = new Error('probe error: ' + err);
1819    error.transport = transport.name;
1820
1821    freezeTransport();
1822
1823    debug('probe transport "%s" failed because of error: %s', name, err);
1824
1825    self.emit('upgradeError', error);
1826  }
1827
1828  function onTransportClose(){
1829    onerror("transport closed");
1830  }
1831
1832  //When the socket is closed while we're probing
1833  function onclose(){
1834    onerror("socket closed");
1835  }
1836
1837  //When the socket is upgraded while we're probing
1838  function onupgrade(to){
1839    if (transport && to.name != transport.name) {
1840      debug('"%s" works - aborting "%s"', to.name, transport.name);
1841      freezeTransport();
1842    }
1843  }
1844
1845  //Remove all listeners on the transport and on self
1846  function cleanup(){
1847    transport.removeListener('open', onTransportOpen);
1848    transport.removeListener('error', onerror);
1849    transport.removeListener('close', onTransportClose);
1850    self.removeListener('close', onclose);
1851    self.removeListener('upgrading', onupgrade);
1852  }
1853
1854  transport.once('open', onTransportOpen);
1855  transport.once('error', onerror);
1856  transport.once('close', onTransportClose);
1857
1858  this.once('close', onclose);
1859  this.once('upgrading', onupgrade);
1860
1861  transport.open();
1862
1863};
1864
1865/**
1866 * Called when connection is deemed open.
1867 *
1868 * @api public
1869 */
1870
1871Socket.prototype.onOpen = function () {
1872  debug('socket open');
1873  this.readyState = 'open';
1874  Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
1875  this.emit('open');
1876  this.flush();
1877
1878  // we check for `readyState` in case an `open`
1879  // listener already closed the socket
1880  if ('open' == this.readyState && this.upgrade && this.transport.pause) {
1881    debug('starting upgrade probes');
1882    for (var i = 0, l = this.upgrades.length; i < l; i++) {
1883      this.probe(this.upgrades[i]);
1884    }
1885  }
1886};
1887
1888/**
1889 * Handles a packet.
1890 *
1891 * @api private
1892 */
1893
1894Socket.prototype.onPacket = function (packet) {
1895  if ('opening' == this.readyState || 'open' == this.readyState) {
1896    debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
1897
1898    this.emit('packet', packet);
1899
1900    // Socket is live - any packet counts
1901    this.emit('heartbeat');
1902
1903    switch (packet.type) {
1904      case 'open':
1905        this.onHandshake(parsejson(packet.data));
1906        break;
1907
1908      case 'pong':
1909        this.setPing();
1910        break;
1911
1912      case 'error':
1913        var err = new Error('server error');
1914        err.code = packet.data;
1915        this.emit('error', err);
1916        break;
1917
1918      case 'message':
1919        this.emit('data', packet.data);
1920        this.emit('message', packet.data);
1921        break;
1922    }
1923  } else {
1924    debug('packet received with socket readyState "%s"', this.readyState);
1925  }
1926};
1927
1928/**
1929 * Called upon handshake completion.
1930 *
1931 * @param {Object} handshake obj
1932 * @api private
1933 */
1934
1935Socket.prototype.onHandshake = function (data) {
1936  this.emit('handshake', data);
1937  this.id = data.sid;
1938  this.transport.query.sid = data.sid;
1939  this.upgrades = this.filterUpgrades(data.upgrades);
1940  this.pingInterval = data.pingInterval;
1941  this.pingTimeout = data.pingTimeout;
1942  this.onOpen();
1943  // In case open handler closes socket
1944  if  ('closed' == this.readyState) return;
1945  this.setPing();
1946
1947  // Prolong liveness of socket on heartbeat
1948  this.removeListener('heartbeat', this.onHeartbeat);
1949  this.on('heartbeat', this.onHeartbeat);
1950};
1951
1952/**
1953 * Resets ping timeout.
1954 *
1955 * @api private
1956 */
1957
1958Socket.prototype.onHeartbeat = function (timeout) {
1959  clearTimeout(this.pingTimeoutTimer);
1960  var self = this;
1961  self.pingTimeoutTimer = setTimeout(function () {
1962    if ('closed' == self.readyState) return;
1963    self.onClose('ping timeout');
1964  }, timeout || (self.pingInterval + self.pingTimeout));
1965};
1966
1967/**
1968 * Pings server every `this.pingInterval` and expects response
1969 * within `this.pingTimeout` or closes connection.
1970 *
1971 * @api private
1972 */
1973
1974Socket.prototype.setPing = function () {
1975  var self = this;
1976  clearTimeout(self.pingIntervalTimer);
1977  self.pingIntervalTimer = setTimeout(function () {
1978    debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
1979    self.ping();
1980    self.onHeartbeat(self.pingTimeout);
1981  }, self.pingInterval);
1982};
1983
1984/**
1985* Sends a ping packet.
1986*
1987* @api public
1988*/
1989
1990Socket.prototype.ping = function () {
1991  this.sendPacket('ping');
1992};
1993
1994/**
1995 * Called on `drain` event
1996 *
1997 * @api private
1998 */
1999
2000Socket.prototype.onDrain = function() {
2001  for (var i = 0; i < this.prevBufferLen; i++) {
2002    if (this.callbackBuffer[i]) {
2003      this.callbackBuffer[i]();
2004    }
2005  }
2006
2007  this.writeBuffer.splice(0, this.prevBufferLen);
2008  this.callbackBuffer.splice(0, this.prevBufferLen);
2009
2010  // setting prevBufferLen = 0 is very important
2011  // for example, when upgrading, upgrade packet is sent over,
2012  // and a nonzero prevBufferLen could cause problems on `drain`
2013  this.prevBufferLen = 0;
2014
2015  if (this.writeBuffer.length == 0) {
2016    this.emit('drain');
2017  } else {
2018    this.flush();
2019  }
2020};
2021
2022/**
2023 * Flush write buffers.
2024 *
2025 * @api private
2026 */
2027
2028Socket.prototype.flush = function () {
2029  if ('closed' != this.readyState && this.transport.writable &&
2030    !this.upgrading && this.writeBuffer.length) {
2031    debug('flushing %d packets in socket', this.writeBuffer.length);
2032    this.transport.send(this.writeBuffer);
2033    // keep track of current length of writeBuffer
2034    // splice writeBuffer and callbackBuffer on `drain`
2035    this.prevBufferLen = this.writeBuffer.length;
2036    this.emit('flush');
2037  }
2038};
2039
2040/**
2041 * Sends a message.
2042 *
2043 * @param {String} message.
2044 * @param {Function} callback function.
2045 * @return {Socket} for chaining.
2046 * @api public
2047 */
2048
2049Socket.prototype.write =
2050Socket.prototype.send = function (msg, fn) {
2051  this.sendPacket('message', msg, fn);
2052  return this;
2053};
2054
2055/**
2056 * Sends a packet.
2057 *
2058 * @param {String} packet type.
2059 * @param {String} data.
2060 * @param {Function} callback function.
2061 * @api private
2062 */
2063
2064Socket.prototype.sendPacket = function (type, data, fn) {
2065  var packet = { type: type, data: data };
2066  this.emit('packetCreate', packet);
2067  this.writeBuffer.push(packet);
2068  this.callbackBuffer.push(fn);
2069  this.flush();
2070};
2071
2072/**
2073 * Closes the connection.
2074 *
2075 * @api private
2076 */
2077
2078Socket.prototype.close = function () {
2079  if ('opening' == this.readyState || 'open' == this.readyState) {
2080    this.onClose('forced close');
2081    debug('socket closing - telling transport to close');
2082    this.transport.close();
2083  }
2084
2085  return this;
2086};
2087
2088/**
2089 * Called upon transport error
2090 *
2091 * @api private
2092 */
2093
2094Socket.prototype.onError = function (err) {
2095  debug('socket error %j', err);
2096  Socket.priorWebsocketSuccess = false;
2097  this.emit('error', err);
2098  this.onClose('transport error', err);
2099};
2100
2101/**
2102 * Called upon transport close.
2103 *
2104 * @api private
2105 */
2106
2107Socket.prototype.onClose = function (reason, desc) {
2108  if ('opening' == this.readyState || 'open' == this.readyState) {
2109    debug('socket close with reason: "%s"', reason);
2110    var self = this;
2111
2112    // clear timers
2113    clearTimeout(this.pingIntervalTimer);
2114    clearTimeout(this.pingTimeoutTimer);
2115
2116    // clean buffers in next tick, so developers can still
2117    // grab the buffers on `close` event
2118    setTimeout(function() {
2119      self.writeBuffer = [];
2120      self.callbackBuffer = [];
2121      self.prevBufferLen = 0;
2122    }, 0);
2123
2124    // stop event from firing again for transport
2125    this.transport.removeAllListeners('close');
2126
2127    // ensure transport won't stay open
2128    this.transport.close();
2129
2130    // ignore further transport communication
2131    this.transport.removeAllListeners();
2132
2133    // set ready state
2134    this.readyState = 'closed';
2135
2136    // clear session id
2137    this.id = null;
2138
2139    // emit close event
2140    this.emit('close', reason, desc);
2141  }
2142};
2143
2144/**
2145 * Filters upgrades, returning only those matching client transports.
2146 *
2147 * @param {Array} server upgrades
2148 * @api private
2149 *
2150 */
2151
2152Socket.prototype.filterUpgrades = function (upgrades) {
2153  var filteredUpgrades = [];
2154  for (var i = 0, j = upgrades.length; i<j; i++) {
2155    if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
2156  }
2157  return filteredUpgrades;
2158};
2159
2160},{"./transport":14,"./transports":15,"component-emitter":8,"debug":9,"engine.io-parser":22,"indexof":36,"parsejson":29,"parseqs":30,"parseuri":38}],14:[function(require,module,exports){
2161/**
2162 * Module dependencies.
2163 */
2164
2165var parser = require('engine.io-parser');
2166var Emitter = require('component-emitter');
2167
2168/**
2169 * Module exports.
2170 */
2171
2172module.exports = Transport;
2173
2174/**
2175 * Transport abstract constructor.
2176 *
2177 * @param {Object} options.
2178 * @api private
2179 */
2180
2181function Transport (opts) {
2182  this.path = opts.path;
2183  this.hostname = opts.hostname;
2184  this.port = opts.port;
2185  this.secure = opts.secure;
2186  this.query = opts.query;
2187  this.timestampParam = opts.timestampParam;
2188  this.timestampRequests = opts.timestampRequests;
2189  this.readyState = '';
2190  this.agent = opts.agent || false;
2191  this.socket = opts.socket;
2192}
2193
2194/**
2195 * Mix in `Emitter`.
2196 */
2197
2198Emitter(Transport.prototype);
2199
2200/**
2201 * A counter used to prevent collisions in the timestamps used
2202 * for cache busting.
2203 */
2204
2205Transport.timestamps = 0;
2206
2207/**
2208 * Emits an error.
2209 *
2210 * @param {String} str
2211 * @return {Transport} for chaining
2212 * @api public
2213 */
2214
2215Transport.prototype.onError = function (msg, desc) {
2216  var err = new Error(msg);
2217  err.type = 'TransportError';
2218  err.description = desc;
2219  this.emit('error', err);
2220  return this;
2221};
2222
2223/**
2224 * Opens the transport.
2225 *
2226 * @api public
2227 */
2228
2229Transport.prototype.open = function () {
2230  if ('closed' == this.readyState || '' == this.readyState) {
2231    this.readyState = 'opening';
2232    this.doOpen();
2233  }
2234
2235  return this;
2236};
2237
2238/**
2239 * Closes the transport.
2240 *
2241 * @api private
2242 */
2243
2244Transport.prototype.close = function () {
2245  if ('opening' == this.readyState || 'open' == this.readyState) {
2246    this.doClose();
2247    this.onClose();
2248  }
2249
2250  return this;
2251};
2252
2253/**
2254 * Sends multiple packets.
2255 *
2256 * @param {Array} packets
2257 * @api private
2258 */
2259
2260Transport.prototype.send = function(packets){
2261  if ('open' == this.readyState) {
2262    this.write(packets);
2263  } else {
2264    throw new Error('Transport not open');
2265  }
2266};
2267
2268/**
2269 * Called upon open
2270 *
2271 * @api private
2272 */
2273
2274Transport.prototype.onOpen = function () {
2275  this.readyState = 'open';
2276  this.writable = true;
2277  this.emit('open');
2278};
2279
2280/**
2281 * Called with data.
2282 *
2283 * @param {String} data
2284 * @api private
2285 */
2286
2287Transport.prototype.onData = function (data) {
2288  this.onPacket(parser.decodePacket(data, this.socket.binaryType));
2289};
2290
2291/**
2292 * Called with a decoded packet.
2293 */
2294
2295Transport.prototype.onPacket = function (packet) {
2296  this.emit('packet', packet);
2297};
2298
2299/**
2300 * Called upon close.
2301 *
2302 * @api private
2303 */
2304
2305Transport.prototype.onClose = function () {
2306  this.readyState = 'closed';
2307  this.emit('close');
2308};
2309
2310},{"component-emitter":8,"engine.io-parser":22}],15:[function(require,module,exports){
2311var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};/**
2312 * Module dependencies
2313 */
2314
2315var XMLHttpRequest = require('xmlhttprequest');
2316var XHR = require('./polling-xhr');
2317var JSONP = require('./polling-jsonp');
2318var websocket = require('./websocket');
2319
2320/**
2321 * Export transports.
2322 */
2323
2324exports.polling = polling;
2325exports.websocket = websocket;
2326
2327/**
2328 * Polling transport polymorphic constructor.
2329 * Decides on xhr vs jsonp based on feature detection.
2330 *
2331 * @api private
2332 */
2333
2334function polling(opts){
2335  var xhr;
2336  var xd = false;
2337
2338  if (global.location) {
2339    var isSSL = 'https:' == location.protocol;
2340    var port = location.port;
2341
2342    // some user agents have empty `location.port`
2343    if (!port) {
2344      port = isSSL ? 443 : 80;
2345    }
2346
2347    xd = opts.hostname != location.hostname || port != opts.port;
2348  }
2349
2350  opts.xdomain = xd;
2351  xhr = new XMLHttpRequest(opts);
2352
2353  if ('open' in xhr && !opts.forceJSONP) {
2354    return new XHR(opts);
2355  } else {
2356    return new JSONP(opts);
2357  }
2358}
2359
2360},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(require,module,exports){
2361var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
2362/**
2363 * Module requirements.
2364 */
2365
2366var Polling = require('./polling');
2367var inherit = require('component-inherit');
2368
2369/**
2370 * Module exports.
2371 */
2372
2373module.exports = JSONPPolling;
2374
2375/**
2376 * Cached regular expressions.
2377 */
2378
2379var rNewline = /\n/g;
2380var rEscapedNewline = /\\n/g;
2381
2382/**
2383 * Global JSONP callbacks.
2384 */
2385
2386var callbacks;
2387
2388/**
2389 * Callbacks count.
2390 */
2391
2392var index = 0;
2393
2394/**
2395 * Noop.
2396 */
2397
2398function empty () { }
2399
2400/**
2401 * JSONP Polling constructor.
2402 *
2403 * @param {Object} opts.
2404 * @api public
2405 */
2406
2407function JSONPPolling (opts) {
2408  Polling.call(this, opts);
2409
2410  this.query = this.query || {};
2411
2412  // define global callbacks array if not present
2413  // we do this …

Large files files are truncated, but you can click here to view the full file