PageRenderTime 171ms CodeModel.GetById 6ms app.highlight 125ms RepoModel.GetById 1ms app.codeStats 2ms

/client/www/js/lib/socket.io.js

https://github.com/Panoptico/NetSense
JavaScript | 6172 lines | 3458 code | 953 blank | 1761 comment | 975 complexity | b7f1f9f5bf365f2b451e737440125134 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', self.attempts);
 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  this.subEvents();
 644}
 645
 646/**
 647 * Mix in `Emitter`.
 648 */
 649
 650Emitter(Socket.prototype);
 651
 652/**
 653 * Subscribe to open, close and packet events
 654 *
 655 * @api private
 656 */
 657
 658Socket.prototype.subEvents = function() {
 659  var io = this.io;
 660  this.subs = [
 661    on(io, 'open', bind(this, 'onopen')),
 662    on(io, 'packet', bind(this, 'onpacket')),
 663    on(io, 'close', bind(this, 'onclose'))
 664  ];
 665};
 666
 667/**
 668 * Called upon engine `open`.
 669 *
 670 * @api private
 671 */
 672
 673Socket.prototype.open =
 674Socket.prototype.connect = function(){
 675  if (this.connected) return this;
 676
 677  this.io.open(); // ensure open
 678  if ('open' == this.io.readyState) this.onopen();
 679  return this;
 680};
 681
 682/**
 683 * Sends a `message` event.
 684 *
 685 * @return {Socket} self
 686 * @api public
 687 */
 688
 689Socket.prototype.send = function(){
 690  var args = toArray(arguments);
 691  args.unshift('message');
 692  this.emit.apply(this, args);
 693  return this;
 694};
 695
 696/**
 697 * Override `emit`.
 698 * If the event is in `events`, it's emitted normally.
 699 *
 700 * @param {String} event name
 701 * @return {Socket} self
 702 * @api public
 703 */
 704
 705Socket.prototype.emit = function(ev){
 706  if (events.hasOwnProperty(ev)) {
 707    emit.apply(this, arguments);
 708    return this;
 709  }
 710
 711  var args = toArray(arguments);
 712  var parserType = parser.EVENT; // default
 713  if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
 714  var packet = { type: parserType, data: args };
 715
 716  // event ack callback
 717  if ('function' == typeof args[args.length - 1]) {
 718    debug('emitting packet with ack id %d', this.ids);
 719    this.acks[this.ids] = args.pop();
 720    packet.id = this.ids++;
 721  }
 722
 723  if (this.connected) {
 724    this.packet(packet);
 725  } else {
 726    this.sendBuffer.push(packet);
 727  }
 728
 729  return this;
 730};
 731
 732/**
 733 * Sends a packet.
 734 *
 735 * @param {Object} packet
 736 * @api private
 737 */
 738
 739Socket.prototype.packet = function(packet){
 740  packet.nsp = this.nsp;
 741  this.io.packet(packet);
 742};
 743
 744/**
 745 * "Opens" the socket.
 746 *
 747 * @api private
 748 */
 749
 750Socket.prototype.onopen = function(){
 751  debug('transport is open - connecting');
 752
 753  // write connect packet if necessary
 754  if ('/' != this.nsp) {
 755    this.packet({ type: parser.CONNECT });
 756  }
 757};
 758
 759/**
 760 * Called upon engine `close`.
 761 *
 762 * @param {String} reason
 763 * @api private
 764 */
 765
 766Socket.prototype.onclose = function(reason){
 767  debug('close (%s)', reason);
 768  this.connected = false;
 769  this.disconnected = true;
 770  this.emit('disconnect', reason);
 771};
 772
 773/**
 774 * Called with socket packet.
 775 *
 776 * @param {Object} packet
 777 * @api private
 778 */
 779
 780Socket.prototype.onpacket = function(packet){
 781  if (packet.nsp != this.nsp) return;
 782
 783  switch (packet.type) {
 784    case parser.CONNECT:
 785      this.onconnect();
 786      break;
 787
 788    case parser.EVENT:
 789      this.onevent(packet);
 790      break;
 791
 792    case parser.BINARY_EVENT:
 793      this.onevent(packet);
 794      break;
 795
 796    case parser.ACK:
 797      this.onack(packet);
 798      break;
 799
 800    case parser.BINARY_ACK:
 801      this.onack(packet);
 802      break;
 803
 804    case parser.DISCONNECT:
 805      this.ondisconnect();
 806      break;
 807
 808    case parser.ERROR:
 809      this.emit('error', packet.data);
 810      break;
 811  }
 812};
 813
 814/**
 815 * Called upon a server event.
 816 *
 817 * @param {Object} packet
 818 * @api private
 819 */
 820
 821Socket.prototype.onevent = function(packet){
 822  var args = packet.data || [];
 823  debug('emitting event %j', args);
 824
 825  if (null != packet.id) {
 826    debug('attaching ack callback to event');
 827    args.push(this.ack(packet.id));
 828  }
 829
 830  if (this.connected) {
 831    emit.apply(this, args);
 832  } else {
 833    this.receiveBuffer.push(args);
 834  }
 835};
 836
 837/**
 838 * Produces an ack callback to emit with an event.
 839 *
 840 * @api private
 841 */
 842
 843Socket.prototype.ack = function(id){
 844  var self = this;
 845  var sent = false;
 846  return function(){
 847    // prevent double callbacks
 848    if (sent) return;
 849    sent = true;
 850    var args = toArray(arguments);
 851    debug('sending ack %j', args);
 852
 853    var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
 854    self.packet({
 855      type: type,
 856      id: id,
 857      data: args
 858    });
 859  };
 860};
 861
 862/**
 863 * Called upon a server acknowlegement.
 864 *
 865 * @param {Object} packet
 866 * @api private
 867 */
 868
 869Socket.prototype.onack = function(packet){
 870  debug('calling ack %s with %j', packet.id, packet.data);
 871  var fn = this.acks[packet.id];
 872  fn.apply(this, packet.data);
 873  delete this.acks[packet.id];
 874};
 875
 876/**
 877 * Called upon server connect.
 878 *
 879 * @api private
 880 */
 881
 882Socket.prototype.onconnect = function(){
 883  this.connected = true;
 884  this.disconnected = false;
 885  this.emit('connect');
 886  this.emitBuffered();
 887};
 888
 889/**
 890 * Emit buffered events (received and emitted).
 891 *
 892 * @api private
 893 */
 894
 895Socket.prototype.emitBuffered = function(){
 896  var i;
 897  for (i = 0; i < this.receiveBuffer.length; i++) {
 898    emit.apply(this, this.receiveBuffer[i]);
 899  }
 900  this.receiveBuffer = [];
 901
 902  for (i = 0; i < this.sendBuffer.length; i++) {
 903    this.packet(this.sendBuffer[i]);
 904  }
 905  this.sendBuffer = [];
 906};
 907
 908/**
 909 * Called upon server disconnect.
 910 *
 911 * @api private
 912 */
 913
 914Socket.prototype.ondisconnect = function(){
 915  debug('server disconnect (%s)', this.nsp);
 916  this.destroy();
 917  this.onclose('io server disconnect');
 918};
 919
 920/**
 921 * Called upon forced client/server side disconnections,
 922 * this method ensures the manager stops tracking us and
 923 * that reconnections don't get triggered for this.
 924 *
 925 * @api private.
 926 */
 927
 928Socket.prototype.destroy = function(){
 929  // clean subscriptions to avoid reconnections
 930  for (var i = 0; i < this.subs.length; i++) {
 931    this.subs[i].destroy();
 932  }
 933
 934  this.io.destroy(this);
 935};
 936
 937/**
 938 * Disconnects the socket manually.
 939 *
 940 * @return {Socket} self
 941 * @api public
 942 */
 943
 944Socket.prototype.close =
 945Socket.prototype.disconnect = function(){
 946  if (!this.connected) return this;
 947
 948  debug('performing disconnect (%s)', this.nsp);
 949  this.packet({ type: parser.DISCONNECT });
 950
 951  // remove socket from pool
 952  this.destroy();
 953
 954  // fire events
 955  this.onclose('io client disconnect');
 956  return this;
 957};
 958
 959},{"./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){
 960var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
 961/**
 962 * Module dependencies.
 963 */
 964
 965var parseuri = require('parseuri');
 966var debug = require('debug')('socket.io-client:url');
 967
 968/**
 969 * Module exports.
 970 */
 971
 972module.exports = url;
 973
 974/**
 975 * URL parser.
 976 *
 977 * @param {String} url
 978 * @param {Object} An object meant to mimic window.location.
 979 *                 Defaults to window.location.
 980 * @api public
 981 */
 982
 983function url(uri, loc){
 984  var obj = uri;
 985
 986  // default to window.location
 987  var loc = loc || global.location;
 988  if (null == uri) uri = loc.protocol + '//' + loc.hostname;
 989
 990  // relative path support
 991  if ('string' == typeof uri) {
 992    if ('/' == uri.charAt(0)) {
 993      if ('undefined' != typeof loc) {
 994        uri = loc.hostname + uri;
 995      }
 996    }
 997
 998    if (!/^(https?|wss?):\/\//.test(uri)) {
 999      debug('protocol-less url %s', uri);
1000      if ('undefined' != typeof loc) {
1001        uri = loc.protocol + '//' + uri;
1002      } else {
1003        uri = 'https://' + uri;
1004      }
1005    }
1006
1007    // parse
1008    debug('parse %s', uri);
1009    obj = parseuri(uri);
1010  }
1011
1012  // make sure we treat `localhost:80` and `localhost` equally
1013  if (!obj.port) {
1014    if (/^(http|ws)$/.test(obj.protocol)) {
1015      obj.port = '80';
1016    }
1017    else if (/^(http|ws)s$/.test(obj.protocol)) {
1018      obj.port = '443';
1019    }
1020  }
1021
1022  obj.path = obj.path || '/';
1023
1024  // define unique id
1025  obj.id = obj.protocol + '://' + obj.host + ':' + obj.port;
1026  // define href
1027  obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
1028
1029  return obj;
1030}
1031
1032},{"debug":9,"parseuri":38}],7:[function(require,module,exports){
1033/**
1034 * Slice reference.
1035 */
1036
1037var slice = [].slice;
1038
1039/**
1040 * Bind `obj` to `fn`.
1041 *
1042 * @param {Object} obj
1043 * @param {Function|String} fn or string
1044 * @return {Function}
1045 * @api public
1046 */
1047
1048module.exports = function(obj, fn){
1049  if ('string' == typeof fn) fn = obj[fn];
1050  if ('function' != typeof fn) throw new Error('bind() requires a function');
1051  var args = slice.call(arguments, 2);
1052  return function(){
1053    return fn.apply(obj, args.concat(slice.call(arguments)));
1054  }
1055};
1056
1057},{}],8:[function(require,module,exports){
1058
1059/**
1060 * Expose `Emitter`.
1061 */
1062
1063module.exports = Emitter;
1064
1065/**
1066 * Initialize a new `Emitter`.
1067 *
1068 * @api public
1069 */
1070
1071function Emitter(obj) {
1072  if (obj) return mixin(obj);
1073};
1074
1075/**
1076 * Mixin the emitter properties.
1077 *
1078 * @param {Object} obj
1079 * @return {Object}
1080 * @api private
1081 */
1082
1083function mixin(obj) {
1084  for (var key in Emitter.prototype) {
1085    obj[key] = Emitter.prototype[key];
1086  }
1087  return obj;
1088}
1089
1090/**
1091 * Listen on the given `event` with `fn`.
1092 *
1093 * @param {String} event
1094 * @param {Function} fn
1095 * @return {Emitter}
1096 * @api public
1097 */
1098
1099Emitter.prototype.on =
1100Emitter.prototype.addEventListener = function(event, fn){
1101  this._callbacks = this._callbacks || {};
1102  (this._callbacks[event] = this._callbacks[event] || [])
1103    .push(fn);
1104  return this;
1105};
1106
1107/**
1108 * Adds an `event` listener that will be invoked a single
1109 * time then automatically removed.
1110 *
1111 * @param {String} event
1112 * @param {Function} fn
1113 * @return {Emitter}
1114 * @api public
1115 */
1116
1117Emitter.prototype.once = function(event, fn){
1118  var self = this;
1119  this._callbacks = this._callbacks || {};
1120
1121  function on() {
1122    self.off(event, on);
1123    fn.apply(this, arguments);
1124  }
1125
1126  on.fn = fn;
1127  this.on(event, on);
1128  return this;
1129};
1130
1131/**
1132 * Remove the given callback for `event` or all
1133 * registered callbacks.
1134 *
1135 * @param {String} event
1136 * @param {Function} fn
1137 * @return {Emitter}
1138 * @api public
1139 */
1140
1141Emitter.prototype.off =
1142Emitter.prototype.removeListener =
1143Emitter.prototype.removeAllListeners =
1144Emitter.prototype.removeEventListener = function(event, fn){
1145  this._callbacks = this._callbacks || {};
1146
1147  // all
1148  if (0 == arguments.length) {
1149    this._callbacks = {};
1150    return this;
1151  }
1152
1153  // specific event
1154  var callbacks = this._callbacks[event];
1155  if (!callbacks) return this;
1156
1157  // remove all handlers
1158  if (1 == arguments.length) {
1159    delete this._callbacks[event];
1160    return this;
1161  }
1162
1163  // remove specific handler
1164  var cb;
1165  for (var i = 0; i < callbacks.length; i++) {
1166    cb = callbacks[i];
1167    if (cb === fn || cb.fn === fn) {
1168      callbacks.splice(i, 1);
1169      break;
1170    }
1171  }
1172  return this;
1173};
1174
1175/**
1176 * Emit `event` with the given args.
1177 *
1178 * @param {String} event
1179 * @param {Mixed} ...
1180 * @return {Emitter}
1181 */
1182
1183Emitter.prototype.emit = function(event){
1184  this._callbacks = this._callbacks || {};
1185  var args = [].slice.call(arguments, 1)
1186    , callbacks = this._callbacks[event];
1187
1188  if (callbacks) {
1189    callbacks = callbacks.slice(0);
1190    for (var i = 0, len = callbacks.length; i < len; ++i) {
1191      callbacks[i].apply(this, args);
1192    }
1193  }
1194
1195  return this;
1196};
1197
1198/**
1199 * Return array of callbacks for `event`.
1200 *
1201 * @param {String} event
1202 * @return {Array}
1203 * @api public
1204 */
1205
1206Emitter.prototype.listeners = function(event){
1207  this._callbacks = this._callbacks || {};
1208  return this._callbacks[event] || [];
1209};
1210
1211/**
1212 * Check if this emitter has `event` handlers.
1213 *
1214 * @param {String} event
1215 * @return {Boolean}
1216 * @api public
1217 */
1218
1219Emitter.prototype.hasListeners = function(event){
1220  return !! this.listeners(event).length;
1221};
1222
1223},{}],9:[function(require,module,exports){
1224
1225/**
1226 * Expose `debug()` as the module.
1227 */
1228
1229module.exports = debug;
1230
1231/**
1232 * Create a debugger with the given `name`.
1233 *
1234 * @param {String} name
1235 * @return {Type}
1236 * @api public
1237 */
1238
1239function debug(name) {
1240  if (!debug.enabled(name)) return function(){};
1241
1242  return function(fmt){
1243    fmt = coerce(fmt);
1244
1245    var curr = new Date;
1246    var ms = curr - (debug[name] || curr);
1247    debug[name] = curr;
1248
1249    fmt = name
1250      + ' '
1251      + fmt
1252      + ' +' + debug.humanize(ms);
1253
1254    // This hackery is required for IE8
1255    // where `console.log` doesn't have 'apply'
1256    window.console
1257      && console.log
1258      && Function.prototype.apply.call(console.log, console, arguments);
1259  }
1260}
1261
1262/**
1263 * The currently active debug mode names.
1264 */
1265
1266debug.names = [];
1267debug.skips = [];
1268
1269/**
1270 * Enables a debug mode by name. This can include modes
1271 * separated by a colon and wildcards.
1272 *
1273 * @param {String} name
1274 * @api public
1275 */
1276
1277debug.enable = function(name) {
1278  try {
1279    localStorage.debug = name;
1280  } catch(e){}
1281
1282  var split = (name || '').split(/[\s,]+/)
1283    , len = split.length;
1284
1285  for (var i = 0; i < len; i++) {
1286    name = split[i].replace('*', '.*?');
1287    if (name[0] === '-') {
1288      debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
1289    }
1290    else {
1291      debug.names.push(new RegExp('^' + name + '$'));
1292    }
1293  }
1294};
1295
1296/**
1297 * Disable debug output.
1298 *
1299 * @api public
1300 */
1301
1302debug.disable = function(){
1303  debug.enable('');
1304};
1305
1306/**
1307 * Humanize the given `ms`.
1308 *
1309 * @param {Number} m
1310 * @return {String}
1311 * @api private
1312 */
1313
1314debug.humanize = function(ms) {
1315  var sec = 1000
1316    , min = 60 * 1000
1317    , hour = 60 * min;
1318
1319  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
1320  if (ms >= min) return (ms / min).toFixed(1) + 'm';
1321  if (ms >= sec) return (ms / sec | 0) + 's';
1322  return ms + 'ms';
1323};
1324
1325/**
1326 * Returns true if the given mode name is enabled, false otherwise.
1327 *
1328 * @param {String} name
1329 * @return {Boolean}
1330 * @api public
1331 */
1332
1333debug.enabled = function(name) {
1334  for (var i = 0, len = debug.skips.length; i < len; i++) {
1335    if (debug.skips[i].test(name)) {
1336      return false;
1337    }
1338  }
1339  for (var i = 0, len = debug.names.length; i < len; i++) {
1340    if (debug.names[i].test(name)) {
1341      return true;
1342    }
1343  }
1344  return false;
1345};
1346
1347/**
1348 * Coerce `val`.
1349 */
1350
1351function coerce(val) {
1352  if (val instanceof Error) return val.stack || val.message;
1353  return val;
1354}
1355
1356// persist
1357
1358try {
1359  if (window.localStorage) debug.enable(localStorage.debug);
1360} catch(e){}
1361
1362},{}],10:[function(require,module,exports){
1363
1364/**
1365 * Module dependencies.
1366 */
1367
1368var index = require('indexof');
1369
1370/**
1371 * Expose `Emitter`.
1372 */
1373
1374module.exports = Emitter;
1375
1376/**
1377 * Initialize a new `Emitter`.
1378 *
1379 * @api public
1380 */
1381
1382function Emitter(obj) {
1383  if (obj) return mixin(obj);
1384};
1385
1386/**
1387 * Mixin the emitter properties.
1388 *
1389 * @param {Object} obj
1390 * @return {Object}
1391 * @api private
1392 */
1393
1394function mixin(obj) {
1395  for (var key in Emitter.prototype) {
1396    obj[key] = Emitter.prototype[key];
1397  }
1398  return obj;
1399}
1400
1401/**
1402 * Listen on the given `event` with `fn`.
1403 *
1404 * @param {String} event
1405 * @param {Function} fn
1406 * @return {Emitter}
1407 * @api public
1408 */
1409
1410Emitter.prototype.on = function(event, fn){
1411  this._callbacks = this._callbacks || {};
1412  (this._callbacks[event] = this._callbacks[event] || [])
1413    .push(fn);
1414  return this;
1415};
1416
1417/**
1418 * Adds an `event` listener that will be invoked a single
1419 * time then automatically removed.
1420 *
1421 * @param {String} event
1422 * @param {Function} fn
1423 * @return {Emitter}
1424 * @api public
1425 */
1426
1427Emitter.prototype.once = function(event, fn){
1428  var self = this;
1429  this._callbacks = this._callbacks || {};
1430
1431  function on() {
1432    self.off(event, on);
1433    fn.apply(this, arguments);
1434  }
1435
1436  fn._off = on;
1437  this.on(event, on);
1438  return this;
1439};
1440
1441/**
1442 * Remove the given callback for `event` or all
1443 * registered callbacks.
1444 *
1445 * @param {String} event
1446 * @param {Function} fn
1447 * @return {Emitter}
1448 * @api public
1449 */
1450
1451Emitter.prototype.off =
1452Emitter.prototype.removeListener =
1453Emitter.prototype.removeAllListeners = function(event, fn){
1454  this._callbacks = this._callbacks || {};
1455
1456  // all
1457  if (0 == arguments.length) {
1458    this._callbacks = {};
1459    return this;
1460  }
1461
1462  // specific event
1463  var callbacks = this._callbacks[event];
1464  if (!callbacks) return this;
1465
1466  // remove all handlers
1467  if (1 == arguments.length) {
1468    delete this._callbacks[event];
1469    return this;
1470  }
1471
1472  // remove specific handler
1473  var i = index(callbacks, fn._off || fn);
1474  if (~i) callbacks.splice(i, 1);
1475  return this;
1476};
1477
1478/**
1479 * Emit `event` with the given args.
1480 *
1481 * @param {String} event
1482 * @param {Mixed} ...
1483 * @return {Emitter}
1484 */
1485
1486Emitter.prototype.emit = function(event){
1487  this._callbacks = this._callbacks || {};
1488  var args = [].slice.call(arguments, 1)
1489    , callbacks = this._callbacks[event];
1490
1491  if (callbacks) {
1492    callbacks = callbacks.slice(0);
1493    for (var i = 0, len = callbacks.length; i < len; ++i) {
1494      callbacks[i].apply(this, args);
1495    }
1496  }
1497
1498  return this;
1499};
1500
1501/**
1502 * Return array of callbacks for `event`.
1503 *
1504 * @param {String} event
1505 * @return {Array}
1506 * @api public
1507 */
1508
1509Emitter.prototype.listeners = function(event){
1510  this._callbacks = this._callbacks || {};
1511  return this._callbacks[event] || [];
1512};
1513
1514/**
1515 * Check if this emitter has `event` handlers.
1516 *
1517 * @param {String} event
1518 * @return {Boolean}
1519 * @api public
1520 */
1521
1522Emitter.prototype.hasListeners = function(event){
1523  return !! this.listeners(event).length;
1524};
1525
1526},{"indexof":36}],11:[function(require,module,exports){
1527
1528module.exports =  require('./lib/');
1529
1530},{"./lib/":12}],12:[function(require,module,exports){
1531
1532module.exports = require('./socket');
1533
1534/**
1535 * Exports parser
1536 *
1537 * @api public
1538 *
1539 */
1540module.exports.parser = require('engine.io-parser');
1541
1542},{"./socket":13,"engine.io-parser":22}],13:[function(require,module,exports){
1543var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};/**
1544 * Module dependencies.
1545 */
1546
1547var transports = require('./transports');
1548var Emitter = require('component-emitter');
1549var debug = require('debug')('engine.io-client:socket');
1550var index = require('indexof');
1551var parser = require('engine.io-parser');
1552var parseuri = require('parseuri');
1553var parsejson = require('parsejson');
1554var parseqs = require('parseqs');
1555
1556/**
1557 * Module exports.
1558 */
1559
1560module.exports = Socket;
1561
1562/**
1563 * Noop function.
1564 *
1565 * @api private
1566 */
1567
1568function noop(){}
1569
1570/**
1571 * Socket constructor.
1572 *
1573 * @param {String|Object} uri or options
1574 * @param {Object} options
1575 * @api public
1576 */
1577
1578function Socket(uri, opts){
1579  if (!(this instanceof Socket)) return new Socket(uri, opts);
1580
1581  opts = opts || {};
1582
1583  if (uri && 'object' == typeof uri) {
1584    opts = uri;
1585    uri = null;
1586  }
1587
1588  if (uri) {
1589    uri = parseuri(uri);
1590    opts.host = uri.host;
1591    opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
1592    opts.port = uri.port;
1593    if (uri.query) opts.query = uri.query;
1594  }
1595
1596  this.secure = null != opts.secure ? opts.secure :
1597    (global.location && 'https:' == location.protocol);
1598
1599  if (opts.host) {
1600    var pieces = opts.host.split(':');
1601    opts.hostname = pieces.shift();
1602    if (pieces.length) opts.port = pieces.pop();
1603  }
1604
1605  this.agent = opts.agent || false;
1606  this.hostname = opts.hostname ||
1607    (global.location ? location.hostname : 'localhost');
1608  this.port = opts.port || (global.location && location.port ?
1609       location.port :
1610       (this.secure ? 443 : 80));
1611  this.query = opts.query || {};
1612  if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
1613  this.upgrade = false !== opts.upgrade;
1614  this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
1615  this.forceJSONP = !!opts.forceJSONP;
1616  this.forceBase64 = !!opts.forceBase64;
1617  this.timestampParam = opts.timestampParam || 't';
1618  this.timestampRequests = opts.timestampRequests;
1619  this.transports = opts.transports || ['polling', 'websocket'];
1620  this.readyState = '';
1621  this.writeBuffer = [];
1622  this.callbackBuffer = [];
1623  this.policyPort = opts.policyPort || 843;
1624  this.rememberUpgrade = opts.rememberUpgrade || false;
1625  this.open();
1626  this.binaryType = null;
1627  this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
1628}
1629
1630Socket.priorWebsocketSuccess = false;
1631
1632/**
1633 * Mix in `Emitter`.
1634 */
1635
1636Emitter(Socket.prototype);
1637
1638/**
1639 * Protocol version.
1640 *
1641 * @api public
1642 */
1643
1644Socket.protocol = parser.protocol; // this is an int
1645
1646/**
1647 * Expose deps for legacy compatibility
1648 * and standalone browser access.
1649 */
1650
1651Socket.Socket = Socket;
1652Socket.Transport = require('./transport');
1653Socket.transports = require('./transports');
1654Socket.parser = require('engine.io-parser');
1655
1656/**
1657 * Creates transport of the given type.
1658 *
1659 * @param {String} transport name
1660 * @return {Transport}
1661 * @api private
1662 */
1663
1664Socket.prototype.createTransport = function (name) {
1665  debug('creating transport "%s"', name);
1666  var query = clone(this.query);
1667
1668  // append engine.io protocol identifier
1669  query.EIO = parser.protocol;
1670
1671  // transport name
1672  query.transport = name;
1673
1674  // session id if we already have one
1675  if (this.id) query.sid = this.id;
1676
1677  var transport = new transports[name]({
1678    agent: this.agent,
1679    hostname: this.hostname,
1680    port: this.port,
1681    secure: this.secure,
1682    path: this.path,
1683    query: query,
1684    forceJSONP: this.forceJSONP,
1685    forceBase64: this.forceBase64,
1686    timestampRequests: this.timestampRequests,
1687    timestampParam: this.timestampParam,
1688    policyPort: this.policyPort,
1689    socket: this
1690  });
1691
1692  return transport;
1693};
1694
1695function clone (obj) {
1696  var o = {};
1697  for (var i in obj) {
1698    if (obj.hasOwnProperty(i)) {
1699      o[i] = obj[i];
1700    }
1701  }
1702  return o;
1703}
1704
1705/**
1706 * Initializes transport to use and starts probe.
1707 *
1708 * @api private
1709 */
1710Socket.prototype.open = function () {
1711  var transport;
1712  if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
1713    transport = 'websocket';
1714  } else {
1715    transport = this.transports[0];
1716  }
1717  this.readyState = 'opening';
1718  var transport = this.createTransport(transport);
1719  transport.open();
1720  this.setTransport(transport);
1721};
1722
1723/**
1724 * Sets the current transport. Disables the existing one (if any).
1725 *
1726 * @api private
1727 */
1728
1729Socket.prototype.setTransport = function(transport){
1730  debug('setting transport %s', transport.name);
1731  var self = this;
1732
1733  if (this.transport) {
1734    debug('clearing existing transport %s', this.transport.name);
1735    this.transport.removeAllListeners();
1736  }
1737
1738  // set up transport
1739  this.transport = transport;
1740
1741  // set up transport listeners
1742  transport
1743  .on('drain', function(){
1744    self.onDrain();
1745  })
1746  .on('packet', function(packet){
1747    self.onPacket(packet);
1748  })
1749  .on('error', function(e){
1750    self.onError(e);
1751  })
1752  .on('close', function(){
1753    self.onClose('transport close');
1754  });
1755};
1756
1757/**
1758 * Probes a transport.
1759 *
1760 * @param {String} transport name
1761 * @api private
1762 */
1763
1764Socket.prototype.probe = function (name) {
1765  debug('probing transport "%s"', name);
1766  var transport = this.createTransport(name, { probe: 1 })
1767    , failed = false
1768    , self = this;
1769
1770  Socket.priorWebsocketSuccess = false;
1771
1772  function onTransportOpen(){
1773    if (self.onlyBinaryUpgrades) {
1774      var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
1775      failed = failed || upgradeLosesBinary;
1776    }
1777    if (failed) return;
1778
1779    debug('probe transport "%s" opened', name);
1780    transport.send([{ type: 'ping', data: 'probe' }]);
1781    transport.once('packet', function (msg) {
1782      if (failed) return;
1783      if ('pong' == msg.type && 'probe' == msg.data) {
1784        debug('probe transport "%s" pong', name);
1785        self.upgrading = true;
1786        self.emit('upgrading', transport);
1787        Socket.priorWebsocketSuccess = 'websocket' == transport.name;
1788
1789        debug('pausing current transport "%s"', self.transport.name);
1790        self.transport.pause(function () {
1791          if (failed) return;
1792          if ('closed' == self.readyState || 'closing' == self.readyState) {
1793            return;
1794          }
1795          debug('changing transport and sending upgrade packet');
1796
1797          cleanup();
1798
1799          self.setTransport(transport);
1800          transport.send([{ type: 'upgrade' }]);
1801          self.emit('upgrade', transport);
1802          transport = null;
1803          self.upgrading = false;
1804          self.flush();
1805        });
1806      } else {
1807        debug('probe transport "%s" failed', name);
1808        var err = new Error('probe error');
1809        err.transport = transport.name;
1810        self.emit('upgradeError', err);
1811      }
1812    });
1813  }
1814
1815  function freezeTransport() {
1816    if (failed) return;
1817
1818    // Any callback called by transport should be ignored since now
1819    failed = true;
1820
1821    cleanup();
1822
1823    transport.close();
1824    transport = null;
1825  }
1826
1827  //Handle any error that happens while probing
1828  function onerror(err) {
1829    var error = new Error('probe error: ' + err);
1830    error.transport = transport.name;
1831
1832    freezeTransport();
1833
1834    debug('probe transport "%s" failed because of error: %s', name, err);
1835
1836    self.emit('upgradeError', error);
1837  }
1838
1839  function onTransportClose(){
1840    onerror("transport closed");
1841  }
1842
1843  //When the socket is closed while we're probing
1844  function onclose(){
1845    onerror("socket closed");
1846  }
1847
1848  //When the socket is upgraded while we're probing
1849  function onupgrade(to){
1850    if (transport && to.name != transport.name) {
1851      debug('"%s" works - aborting "%s"', to.name, transport.name);
1852      freezeTransport();
1853    }
1854  }
1855
1856  //Remove all listeners on the transport and on self
1857  function cleanup(){
1858    transport.removeListener('open', onTransportOpen);
1859    transport.removeListener('error', onerror);
1860    transport.removeListener('close', onTransportClose);
1861    self.removeListener('close', onclose);
1862    self.removeListener('upgrading', onupgrade);
1863  }
1864
1865  transport.once('open', onTransportOpen);
1866  transport.once('error', onerror);
1867  transport.once('close', onTransportClose);
1868
1869  this.once('close', onclose);
1870  this.once('upgrading', onupgrade);
1871
1872  transport.open();
1873
1874};
1875
1876/**
1877 * Called when connection is deemed open.
1878 *
1879 * @api public
1880 */
1881
1882Socket.prototype.onOpen = function () {
1883  debug('socket open');
1884  this.readyState = 'open';
1885  Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
1886  this.emit('open');
1887  this.flush();
1888
1889  // we check for `readyState` in case an `open`
1890  // listener already closed the socket
1891  if ('open' == this.readyState && this.upgrade && this.transport.pause) {
1892    debug('starting upgrade probes');
1893    for (var i = 0, l = this.upgrades.length; i < l; i++) {
1894      this.probe(this.upgrades[i]);
1895    }
1896  }
1897};
1898
1899/**
1900 * Handles a packet.
1901 *
1902 * @api private
1903 */
1904
1905Socket.prototype.onPacket = function (packet) {
1906  if ('opening' == this.readyState || 'open' == this.readyState) {
1907    debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
1908
1909    this.emit('packet', packet);
1910
1911    // Socket is live - any packet counts
1912    this.emit('heartbeat');
1913
1914    switch (packet.type) {
1915      case 'open':
1916        this.onHandshake(parsejson(packet.data));
1917        break;
1918
1919      case 'pong':
1920        this.setPing();
1921        break;
1922
1923      case 'error':
1924        var err = new Error('server error');
1925        err.code = packet.data;
1926        this.emit('error', err);
1927        break;
1928
1929      case 'message':
1930        this.emit('data', packet.data);
1931        this.emit('message', packet.data);
1932        break;
1933    }
1934  } else {
1935    debug('packet received with socket readyState "%s"', this.readyState);
1936  }
1937};
1938
1939/**
1940 * Called upon handshake completion.
1941 *
1942 * @param {Object} handshake obj
1943 * @api private
1944 */
1945
1946Socket.prototype.onHandshake = function (data) {
1947  this.emit('handshake', data);
1948  this.id = data.sid;
1949  this.transport.query.sid = data.sid;
1950  this.upgrades = this.filterUpgrades(data.upgrades);
1951  this.pingInterval = data.pingInterval;
1952  this.pingTimeout = data.pingTimeout;
1953  this.onOpen();
1954  // In case open handler closes socket
1955  if  ('closed' == this.readyState) return;
1956  this.setPing();
1957
1958  // Prolong liveness of socket on heartbeat
1959  this.removeListener('heartbeat', this.onHeartbeat);
1960  this.on('heartbeat', this.onHeartbeat);
1961};
1962
1963/**
1964 * Resets ping timeout.
1965 *
1966 * @api private
1967 */
1968
1969Socket.prototype.onHeartbeat = function (timeout) {
1970  clearTimeout(this.pingTimeoutTimer);
1971  var self = this;
1972  self.pingTimeoutTimer = setTimeout(function () {
1973    if ('closed' == self.readyState) return;
1974    self.onClose('ping timeout');
1975  }, timeout || (self.pingInterval + self.pingTimeout));
1976};
1977
1978/**
1979 * Pings server every `this.pingInterval` and expects response
1980 * within `this.pingTimeout` or closes connection.
1981 *
1982 * @api private
1983 */
1984
1985Socket.prototype.setPing = function () {
1986  var self = this;
1987  clearTimeout(self.pingIntervalTimer);
1988  self.pingIntervalTimer = setTimeout(function () {
1989    debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
1990    self.ping();
1991    self.onHeartbeat(self.pingTimeout);
1992  }, self.pingInterval);
1993};
1994
1995/**
1996* Sends a ping packet.
1997*
1998* @api public
1999*/
2000
2001Socket.prototype.ping = function () {
2002  this.sendPacket('ping');
2003};
2004
2005/**
2006 * Called on `drain` event
2007 *
2008 * @api private
2009 */
2010
2011Socket.prototype.onDrain = function() {
2012  for (var i = 0; i < this.prevBufferLen; i++) {
2013    if (this.callbackBuffer[i]) {
2014      this.callbackBuffer[i]();
2015    }
2016  }
2017
2018  this.writeBuffer.splice(0, this.prevBufferLen);
2019  this.callbackBuffer.splice(0, this.prevBufferLen);
2020
2021  // setting prevBufferLen = 0 is very important
2022  // for example, when upgrading, upgrade packet is sent over,
2023  // and a nonzero prevBufferLen could cause problems on `drain`
2024  this.prevBufferLen = 0;
2025
2026  if (this.writeBuffer.length == 0) {
2027    this.emit('drain');
2028  } else {
2029    this.flush();
2030  }
2031};
2032
2033/**
2034 * Flush write buffers.
2035 *
2036 * @api private
2037 */
2038
2039Socket.prototype.flush = function () {
2040  if ('closed' != this.readyState && this.transport.writable &&
2041    !this.upgrading && this.writeBuffer.length) {
2042    debug('flushing %d packets in socket', this.writeBuffer.length);
2043    this.transport.send(this.writeBuffer);
2044    // keep track of current length of writeBuffer
2045    // splice writeBuffer and callbackBuffer on `drain`
2046    this.prevBufferLen = this.writeBuffer.length;
2047    this.emit('flush');
2048  }
2049};
2050
2051/**
2052 * Sends a message.
2053 *
2054 * @param {String} message.
2055 * @param {Function} callback function.
2056 * @return {Socket} for chaining.
2057 * @api public
2058 */
2059
2060Socket.prototype.write =
2061Socket.prototype.send = function (msg, fn) {
2062  this.sendPacket('message', msg, fn);
2063  return this;
2064};
2065
2066/**
2067 * Sends a packet.
2068 *
2069 * @param {String} packet type.
2070 * @param {String} data.
2071 * @param {Function} callback function.
2072 * @api private
2073 */
2074
2075Socket.prototype.sendPacket = function (type, data, fn) {
2076  var packet = { type: type, data: data };
2077  this.emit('packetCreate', packet);
2078  this.writeBuffer.push(packet);
2079  this.callbackBuffer.push(fn);
2080  this.flush();
2081};
2082
2083/**
2084 * Closes the connection.
2085 *
2086 * @api private
2087 */
2088
2089Socket.prototype.close = function () {
2090  if ('opening' == this.readyState || 'open' == this.readyState) {
2091    this.onClose('forced close');
2092    debug('socket closing - telling transport to close');
2093    this.transport.close();
2094  }
2095
2096  return this;
2097};
2098
2099/**
2100 * Called upon transport error
2101 *
2102 * @api private
2103 */
2104
2105Socket.prototype.onError = function (err) {
2106  debug('socket error %j', err);
2107  Socket.priorWebsocketSuccess = false;
2108  this.emit('error', err);
2109  this.onClose('transport error', err);
2110};
2111
2112/**
2113 * Called upon transport close.
2114 *
2115 * @api private
2116 */
2117
2118Socket.prototype.onClose = function (reason, desc) {
2119  if ('opening' == this.readyState || 'open' == this.readyState) {
2120    debug('socket close with reason: "%s"', reason);
2121    var self = this;
2122
2123    // clear timers
2124    clearTimeout(this.pingIntervalTimer);
2125    clearTimeout(this.pingTimeoutTimer);
2126
2127    // clean buffers in next tick, so developers can still
2128    // grab the buffers on `close` event
2129    setTimeout(function() {
2130      self.writeBuffer = [];
2131      self.callbackBuffer = [];
2132      self.prevBufferLen = 0;
2133    }, 0);
2134
2135    // stop event from firing again for transport
2136    this.transport.removeAllListeners('close');
2137
2138    // ensure transport won't stay open
2139    this.transport.close();
2140
2141    // ignore further transport communication
2142    this.transport.removeAllListeners();
2143
2144    // set ready state
2145    this.readyState = 'closed';
2146
2147    // clear session id
2148    this.id = null;
2149
2150    // emit close event
2151    this.emit('close', reason, desc);
2152  }
2153};
2154
2155/**
2156 * Filters upgrades, returning only those matching client transports.
2157 *
2158 * @param {Array} server upgrades
2159 * @api private
2160 *
2161 */
2162
2163Socket.prototype.filterUpgrades = function (upgrades) {
2164  var filteredUpgrades = [];
2165  for (var i = 0, j = upgrades.length; i<j; i++) {
2166    if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
2167  }
2168  return filteredUpgrades;
2169};
2170
2171},{"./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){
2172/**
2173 * Module dependencies.
2174 */
2175
2176var parser = require('engine.io-parser');
2177var Emitter = require('component-emitter');
2178
2179/**
2180 * Module exports.
2181 */
2182
2183module.exports = Transport;
2184
2185/**
2186 * Transport abstract constructor.
2187 *
2188 * @param {Object} options.
2189 * @api private
2190 */
2191
2192function Transport (opts) {
2193  this.path = opts.path;
2194  this.hostname = opts.hostname;
2195  this.port = opts.port;
2196  this.secure = opts.secure;
2197  this.query = opts.query;
2198  this.timestampParam = opts.timestampParam;
2199  this.timestampRequests = opts.timestampRequests;
2200  this.readyState = '';
2201  this.agent = opts.agent || false;
2202  this.socket = opts.socket;
2203}
2204
2205/**
2206 * Mix in `Emitter`.
2207 */
2208
2209Emitter(Transport.prototype);
2210
2211/**
2212 * A counter used to prevent collisions in the timestamps used
2213 * for cache busting.
2214 */
2215
2216Transport.timestamps = 0;
2217
2218/**
2219 * Emits an error.
2220 *
2221 * @param {String} str
2222 * @return {Transport} for chaining
2223 * @api public
2224 */
2225
2226Transport.prototype.onError = function (msg, desc) {
2227  var err = new Error(msg);
2228  err.type = 'TransportError';
2229  err.description = desc;
2230  this.emit('error', err);
2231  return this;
2232};
2233
2234/**
2235 * Opens the transport.
2236 *
2237 * @api public
2238 */
2239
2240Transport.prototype.open = function () {
2241  if ('closed' == this.readyState || '' == this.readyState) {
2242    this.readyState = 'opening';
2243    this.doOpen();
2244  }
2245
2246  return this;
2247};
2248
2249/**
2250 * Closes the transport.
2251 *
2252 * @api private
2253 */
2254
2255Transport.prototype.close = function () {
2256  if ('opening' == this.readyState || 'open' == this.readyState) {
2257    this.doClose();
2258    this.onClose();
2259  }
2260
2261  return this;
2262};
2263
2264/**
2265 * Sends multiple packets.
2266 *
2267 * @param {Array} packets
2268 * @api private
2269 */
2270
2271Transport.prototype.send = function(packets){
2272  if ('open' == this.readyState) {
2273    this.write(packets);
2274  } else {
2275    throw new Error('Transport not open');
2276  }
2277};
2278
2279/**
2280 * Called upon open
2281 *
2282 * @api private
2283 */
2284
2285Transport.prototype.onOpen = function () {
2286  this.readyState = 'open';
2287  this.writable = true;
2288  this.emit('open');
2289};
2290
2291/**
2292 * Called with data.
2293 *
2294 * @param {String} data
2295 * @api private
2296 */
2297
2298Transport.prototype.onData = function(data){
2299  try {
2300    var packet = parser.decodePacket(data, this.socket.binaryType);
2301    this.onPacket(packet);
2302  } catch(e){
2303    e.data = data;
2304    this.onError('parser decode error', e);
2305  }
2306};
2307
2308/**
2309 * Called with a decoded packet.
2310 */
2311
2312Transport.prototype.onPacket = function (packet) {
2313  this.emit('packet', packet);
2314};
2315
2316/**
2317 * Called upon close.
2318 *
2319 * @api private
2320 */
2321
2322Transport.prototype.onClose = function () {
2323  this.readyState = 'closed';
2324  this.emit('close');
2325};
2326
2327},{"component-emitter":8,"engine.io-parser":22}],15:[function(require,module,exports){
2328var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};/**
2329 * Module dependencies
2330 */
2331
2332var XMLHttpRequest = require('xmlhttprequest');
2333var XHR = require('./polling-xhr');
2334var JSONP = require('./polling-jsonp');
2335var websocket = require('./websocket');
2336
2337/**
2338 * Export transports.
2339 */
2340
2341exports.polling = polling;
2342exports.websocket = websocket;
2343
2344/**
2345 * Polling transport polymorphic constructor.
2346 * Decides on xhr vs jsonp based on feature detection.
2347 *
2348 * @api private
2349 */
2350
2351function polling(opts){
2352  var xhr;
2353  var xd = false;
2354
2355  if (global.location) {
2356    var isSSL = 'https:' == location.protocol;
2357    var port = location.port;
2358
2359    // some user agents have empty `location.port`
2360    if (!port) {
2361      port = isSSL ? 443 : 80;
2362    }
2363
2364    xd = opts.hostname != location.hostname || port != opts.port;
2365  }
2366
2367  opts.xdomain = xd;
2368  xhr = new XMLHttpRequest(opts);
2369
2370  if ('open' in xhr && !opts.forceJSONP) {
2371    return new XHR(opts);
2372  } else {
2373    return new JSONP(opts);
2374  }
2375}
2376
2377},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(require,module,exports){
2378var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
2379/**
2380 * Module requirements.
2381 */
2382
2383var Polling = require('./polling');
2384var inherit = require('component-inherit');
2385
2386/**
2387 * Module exports.
2388 */
2389
2390module.exports = JSONPPolling;
2391
2392/**
2393 * Cached regular expressions.
2394 */
2395
2396var rNewline = /\n/g;
2397var rEscapedNewline = /\\n/g;
2398
2399/**
2400 * Global JSONP callbacks.
2401 */
2402
2403var callbacks;
2404
2405/**
2406 * Callbacks count.
2407 */
2408
2409var index = 0;
2410
2411/**
2412 * N

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