PageRenderTime 180ms CodeModel.GetById 81ms app.highlight 75ms RepoModel.GetById 1ms app.codeStats 2ms

/js/skynet.bundle.js

https://github.com/SYCCON/skynet
JavaScript | 8844 lines | 5505 code | 1357 blank | 1982 comment | 1405 complexity | a72b3b54dea417156436f69a63e3f0ce MD5 | raw file

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

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

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