PageRenderTime 699ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 1ms

/htdocs/assets/js/socket.io.js

https://github.com/FreePBX/ucp
JavaScript | 6193 lines | 3499 code | 956 blank | 1738 comment | 992 complexity | a561e9cf505224b56d5495169cbd33ed MD5 | raw file
Possible License(s): AGPL-3.0

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

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