aboutsummaryrefslogtreecommitdiffhomepage
path: root/node_modules/socket.io-client/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/socket.io-client/lib')
-rw-r--r--node_modules/socket.io-client/lib/index.js94
-rw-r--r--node_modules/socket.io-client/lib/manager.js573
-rw-r--r--node_modules/socket.io-client/lib/on.js24
-rw-r--r--node_modules/socket.io-client/lib/socket.js418
-rw-r--r--node_modules/socket.io-client/lib/url.js75
5 files changed, 1184 insertions, 0 deletions
diff --git a/node_modules/socket.io-client/lib/index.js b/node_modules/socket.io-client/lib/index.js
new file mode 100644
index 0000000..6bc993c
--- /dev/null
+++ b/node_modules/socket.io-client/lib/index.js
@@ -0,0 +1,94 @@
+
+/**
+ * Module dependencies.
+ */
+
+var url = require('./url');
+var parser = require('socket.io-parser');
+var Manager = require('./manager');
+var debug = require('debug')('socket.io-client');
+
+/**
+ * Module exports.
+ */
+
+module.exports = exports = lookup;
+
+/**
+ * Managers cache.
+ */
+
+var cache = exports.managers = {};
+
+/**
+ * Looks up an existing `Manager` for multiplexing.
+ * If the user summons:
+ *
+ * `io('http://localhost/a');`
+ * `io('http://localhost/b');`
+ *
+ * We reuse the existing instance based on same scheme/port/host,
+ * and we initialize sockets for each namespace.
+ *
+ * @api public
+ */
+
+function lookup (uri, opts) {
+ if (typeof uri === 'object') {
+ opts = uri;
+ uri = undefined;
+ }
+
+ opts = opts || {};
+
+ var parsed = url(uri);
+ var source = parsed.source;
+ var id = parsed.id;
+ var path = parsed.path;
+ var sameNamespace = cache[id] && path in cache[id].nsps;
+ var newConnection = opts.forceNew || opts['force new connection'] ||
+ false === opts.multiplex || sameNamespace;
+
+ var io;
+
+ if (newConnection) {
+ debug('ignoring socket cache for %s', source);
+ io = Manager(source, opts);
+ } else {
+ if (!cache[id]) {
+ debug('new io instance for %s', source);
+ cache[id] = Manager(source, opts);
+ }
+ io = cache[id];
+ }
+ if (parsed.query && !opts.query) {
+ opts.query = parsed.query;
+ }
+ return io.socket(parsed.path, opts);
+}
+
+/**
+ * Protocol version.
+ *
+ * @api public
+ */
+
+exports.protocol = parser.protocol;
+
+/**
+ * `connect`.
+ *
+ * @param {String} uri
+ * @api public
+ */
+
+exports.connect = lookup;
+
+/**
+ * Expose constructors for standalone build.
+ *
+ * @api public
+ */
+
+exports.Manager = require('./manager');
+exports.Socket = require('./socket');
diff --git a/node_modules/socket.io-client/lib/manager.js b/node_modules/socket.io-client/lib/manager.js
new file mode 100644
index 0000000..e44bd6c
--- /dev/null
+++ b/node_modules/socket.io-client/lib/manager.js
@@ -0,0 +1,573 @@
+
+/**
+ * Module dependencies.
+ */
+
+var eio = require('engine.io-client');
+var Socket = require('./socket');
+var Emitter = require('component-emitter');
+var parser = require('socket.io-parser');
+var on = require('./on');
+var bind = require('component-bind');
+var debug = require('debug')('socket.io-client:manager');
+var indexOf = require('indexof');
+var Backoff = require('backo2');
+
+/**
+ * IE6+ hasOwnProperty
+ */
+
+var has = Object.prototype.hasOwnProperty;
+
+/**
+ * Module exports
+ */
+
+module.exports = Manager;
+
+/**
+ * `Manager` constructor.
+ *
+ * @param {String} engine instance or engine uri/opts
+ * @param {Object} options
+ * @api public
+ */
+
+function Manager (uri, opts) {
+ if (!(this instanceof Manager)) return new Manager(uri, opts);
+ if (uri && ('object' === typeof uri)) {
+ opts = uri;
+ uri = undefined;
+ }
+ opts = opts || {};
+
+ opts.path = opts.path || '/socket.io';
+ this.nsps = {};
+ this.subs = [];
+ this.opts = opts;
+ this.reconnection(opts.reconnection !== false);
+ this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
+ this.reconnectionDelay(opts.reconnectionDelay || 1000);
+ this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
+ this.randomizationFactor(opts.randomizationFactor || 0.5);
+ this.backoff = new Backoff({
+ min: this.reconnectionDelay(),
+ max: this.reconnectionDelayMax(),
+ jitter: this.randomizationFactor()
+ });
+ this.timeout(null == opts.timeout ? 20000 : opts.timeout);
+ this.readyState = 'closed';
+ this.uri = uri;
+ this.connecting = [];
+ this.lastPing = null;
+ this.encoding = false;
+ this.packetBuffer = [];
+ var _parser = opts.parser || parser;
+ this.encoder = new _parser.Encoder();
+ this.decoder = new _parser.Decoder();
+ this.autoConnect = opts.autoConnect !== false;
+ if (this.autoConnect) this.open();
+}
+
+/**
+ * Propagate given event to sockets and emit on `this`
+ *
+ * @api private
+ */
+
+Manager.prototype.emitAll = function () {
+ this.emit.apply(this, arguments);
+ for (var nsp in this.nsps) {
+ if (has.call(this.nsps, nsp)) {
+ this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
+ }
+ }
+};
+
+/**
+ * Update `socket.id` of all sockets
+ *
+ * @api private
+ */
+
+Manager.prototype.updateSocketIds = function () {
+ for (var nsp in this.nsps) {
+ if (has.call(this.nsps, nsp)) {
+ this.nsps[nsp].id = this.generateId(nsp);
+ }
+ }
+};
+
+/**
+ * generate `socket.id` for the given `nsp`
+ *
+ * @param {String} nsp
+ * @return {String}
+ * @api private
+ */
+
+Manager.prototype.generateId = function (nsp) {
+ return (nsp === '/' ? '' : (nsp + '#')) + this.engine.id;
+};
+
+/**
+ * Mix in `Emitter`.
+ */
+
+Emitter(Manager.prototype);
+
+/**
+ * Sets the `reconnection` config.
+ *
+ * @param {Boolean} true/false if it should automatically reconnect
+ * @return {Manager} self or value
+ * @api public
+ */
+
+Manager.prototype.reconnection = function (v) {
+ if (!arguments.length) return this._reconnection;
+ this._reconnection = !!v;
+ return this;
+};
+
+/**
+ * Sets the reconnection attempts config.
+ *
+ * @param {Number} max reconnection attempts before giving up
+ * @return {Manager} self or value
+ * @api public
+ */
+
+Manager.prototype.reconnectionAttempts = function (v) {
+ if (!arguments.length) return this._reconnectionAttempts;
+ this._reconnectionAttempts = v;
+ return this;
+};
+
+/**
+ * Sets the delay between reconnections.
+ *
+ * @param {Number} delay
+ * @return {Manager} self or value
+ * @api public
+ */
+
+Manager.prototype.reconnectionDelay = function (v) {
+ if (!arguments.length) return this._reconnectionDelay;
+ this._reconnectionDelay = v;
+ this.backoff && this.backoff.setMin(v);
+ return this;
+};
+
+Manager.prototype.randomizationFactor = function (v) {
+ if (!arguments.length) return this._randomizationFactor;
+ this._randomizationFactor = v;
+ this.backoff && this.backoff.setJitter(v);
+ return this;
+};
+
+/**
+ * Sets the maximum delay between reconnections.
+ *
+ * @param {Number} delay
+ * @return {Manager} self or value
+ * @api public
+ */
+
+Manager.prototype.reconnectionDelayMax = function (v) {
+ if (!arguments.length) return this._reconnectionDelayMax;
+ this._reconnectionDelayMax = v;
+ this.backoff && this.backoff.setMax(v);
+ return this;
+};
+
+/**
+ * Sets the connection timeout. `false` to disable
+ *
+ * @return {Manager} self or value
+ * @api public
+ */
+
+Manager.prototype.timeout = function (v) {
+ if (!arguments.length) return this._timeout;
+ this._timeout = v;
+ return this;
+};
+
+/**
+ * Starts trying to reconnect if reconnection is enabled and we have not
+ * started reconnecting yet
+ *
+ * @api private
+ */
+
+Manager.prototype.maybeReconnectOnOpen = function () {
+ // Only try to reconnect if it's the first time we're connecting
+ if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
+ // keeps reconnection from firing twice for the same reconnection loop
+ this.reconnect();
+ }
+};
+
+/**
+ * Sets the current transport `socket`.
+ *
+ * @param {Function} optional, callback
+ * @return {Manager} self
+ * @api public
+ */
+
+Manager.prototype.open =
+Manager.prototype.connect = function (fn, opts) {
+ debug('readyState %s', this.readyState);
+ if (~this.readyState.indexOf('open')) return this;
+
+ debug('opening %s', this.uri);
+ this.engine = eio(this.uri, this.opts);
+ var socket = this.engine;
+ var self = this;
+ this.readyState = 'opening';
+ this.skipReconnect = false;
+
+ // emit `open`
+ var openSub = on(socket, 'open', function () {
+ self.onopen();
+ fn && fn();
+ });
+
+ // emit `connect_error`
+ var errorSub = on(socket, 'error', function (data) {
+ debug('connect_error');
+ self.cleanup();
+ self.readyState = 'closed';
+ self.emitAll('connect_error', data);
+ if (fn) {
+ var err = new Error('Connection error');
+ err.data = data;
+ fn(err);
+ } else {
+ // Only do this if there is no fn to handle the error
+ self.maybeReconnectOnOpen();
+ }
+ });
+
+ // emit `connect_timeout`
+ if (false !== this._timeout) {
+ var timeout = this._timeout;
+ debug('connect attempt will timeout after %d', timeout);
+
+ // set timer
+ var timer = setTimeout(function () {
+ debug('connect attempt timed out after %d', timeout);
+ openSub.destroy();
+ socket.close();
+ socket.emit('error', 'timeout');
+ self.emitAll('connect_timeout', timeout);
+ }, timeout);
+
+ this.subs.push({
+ destroy: function () {
+ clearTimeout(timer);
+ }
+ });
+ }
+
+ this.subs.push(openSub);
+ this.subs.push(errorSub);
+
+ return this;
+};
+
+/**
+ * Called upon transport open.
+ *
+ * @api private
+ */
+
+Manager.prototype.onopen = function () {
+ debug('open');
+
+ // clear old subs
+ this.cleanup();
+
+ // mark as open
+ this.readyState = 'open';
+ this.emit('open');
+
+ // add new subs
+ var socket = this.engine;
+ this.subs.push(on(socket, 'data', bind(this, 'ondata')));
+ this.subs.push(on(socket, 'ping', bind(this, 'onping')));
+ this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
+ this.subs.push(on(socket, 'error', bind(this, 'onerror')));
+ this.subs.push(on(socket, 'close', bind(this, 'onclose')));
+ this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
+};
+
+/**
+ * Called upon a ping.
+ *
+ * @api private
+ */
+
+Manager.prototype.onping = function () {
+ this.lastPing = new Date();
+ this.emitAll('ping');
+};
+
+/**
+ * Called upon a packet.
+ *
+ * @api private
+ */
+
+Manager.prototype.onpong = function () {
+ this.emitAll('pong', new Date() - this.lastPing);
+};
+
+/**
+ * Called with data.
+ *
+ * @api private
+ */
+
+Manager.prototype.ondata = function (data) {
+ this.decoder.add(data);
+};
+
+/**
+ * Called when parser fully decodes a packet.
+ *
+ * @api private
+ */
+
+Manager.prototype.ondecoded = function (packet) {
+ this.emit('packet', packet);
+};
+
+/**
+ * Called upon socket error.
+ *
+ * @api private
+ */
+
+Manager.prototype.onerror = function (err) {
+ debug('error', err);
+ this.emitAll('error', err);
+};
+
+/**
+ * Creates a new socket for the given `nsp`.
+ *
+ * @return {Socket}
+ * @api public
+ */
+
+Manager.prototype.socket = function (nsp, opts) {
+ var socket = this.nsps[nsp];
+ if (!socket) {
+ socket = new Socket(this, nsp, opts);
+ this.nsps[nsp] = socket;
+ var self = this;
+ socket.on('connecting', onConnecting);
+ socket.on('connect', function () {
+ socket.id = self.generateId(nsp);
+ });
+
+ if (this.autoConnect) {
+ // manually call here since connecting event is fired before listening
+ onConnecting();
+ }
+ }
+
+ function onConnecting () {
+ if (!~indexOf(self.connecting, socket)) {
+ self.connecting.push(socket);
+ }
+ }
+
+ return socket;
+};
+
+/**
+ * Called upon a socket close.
+ *
+ * @param {Socket} socket
+ */
+
+Manager.prototype.destroy = function (socket) {
+ var index = indexOf(this.connecting, socket);
+ if (~index) this.connecting.splice(index, 1);
+ if (this.connecting.length) return;
+
+ this.close();
+};
+
+/**
+ * Writes a packet.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+Manager.prototype.packet = function (packet) {
+ debug('writing packet %j', packet);
+ var self = this;
+ if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query;
+
+ if (!self.encoding) {
+ // encode, then write to engine with result
+ self.encoding = true;
+ this.encoder.encode(packet, function (encodedPackets) {
+ for (var i = 0; i < encodedPackets.length; i++) {
+ self.engine.write(encodedPackets[i], packet.options);
+ }
+ self.encoding = false;
+ self.processPacketQueue();
+ });
+ } else { // add packet to the queue
+ self.packetBuffer.push(packet);
+ }
+};
+
+/**
+ * If packet buffer is non-empty, begins encoding the
+ * next packet in line.
+ *
+ * @api private
+ */
+
+Manager.prototype.processPacketQueue = function () {
+ if (this.packetBuffer.length > 0 && !this.encoding) {
+ var pack = this.packetBuffer.shift();
+ this.packet(pack);
+ }
+};
+
+/**
+ * Clean up transport subscriptions and packet buffer.
+ *
+ * @api private
+ */
+
+Manager.prototype.cleanup = function () {
+ debug('cleanup');
+
+ var subsLength = this.subs.length;
+ for (var i = 0; i < subsLength; i++) {
+ var sub = this.subs.shift();
+ sub.destroy();
+ }
+
+ this.packetBuffer = [];
+ this.encoding = false;
+ this.lastPing = null;
+
+ this.decoder.destroy();
+};
+
+/**
+ * Close the current socket.
+ *
+ * @api private
+ */
+
+Manager.prototype.close =
+Manager.prototype.disconnect = function () {
+ debug('disconnect');
+ this.skipReconnect = true;
+ this.reconnecting = false;
+ if ('opening' === this.readyState) {
+ // `onclose` will not fire because
+ // an open event never happened
+ this.cleanup();
+ }
+ this.backoff.reset();
+ this.readyState = 'closed';
+ if (this.engine) this.engine.close();
+};
+
+/**
+ * Called upon engine close.
+ *
+ * @api private
+ */
+
+Manager.prototype.onclose = function (reason) {
+ debug('onclose');
+
+ this.cleanup();
+ this.backoff.reset();
+ this.readyState = 'closed';
+ this.emit('close', reason);
+
+ if (this._reconnection && !this.skipReconnect) {
+ this.reconnect();
+ }
+};
+
+/**
+ * Attempt a reconnection.
+ *
+ * @api private
+ */
+
+Manager.prototype.reconnect = function () {
+ if (this.reconnecting || this.skipReconnect) return this;
+
+ var self = this;
+
+ if (this.backoff.attempts >= this._reconnectionAttempts) {
+ debug('reconnect failed');
+ this.backoff.reset();
+ this.emitAll('reconnect_failed');
+ this.reconnecting = false;
+ } else {
+ var delay = this.backoff.duration();
+ debug('will wait %dms before reconnect attempt', delay);
+
+ this.reconnecting = true;
+ var timer = setTimeout(function () {
+ if (self.skipReconnect) return;
+
+ debug('attempting reconnect');
+ self.emitAll('reconnect_attempt', self.backoff.attempts);
+ self.emitAll('reconnecting', self.backoff.attempts);
+
+ // check again for the case socket closed in above events
+ if (self.skipReconnect) return;
+
+ self.open(function (err) {
+ if (err) {
+ debug('reconnect attempt error');
+ self.reconnecting = false;
+ self.reconnect();
+ self.emitAll('reconnect_error', err.data);
+ } else {
+ debug('reconnect success');
+ self.onreconnect();
+ }
+ });
+ }, delay);
+
+ this.subs.push({
+ destroy: function () {
+ clearTimeout(timer);
+ }
+ });
+ }
+};
+
+/**
+ * Called upon successful reconnect.
+ *
+ * @api private
+ */
+
+Manager.prototype.onreconnect = function () {
+ var attempt = this.backoff.attempts;
+ this.reconnecting = false;
+ this.backoff.reset();
+ this.updateSocketIds();
+ this.emitAll('reconnect', attempt);
+};
diff --git a/node_modules/socket.io-client/lib/on.js b/node_modules/socket.io-client/lib/on.js
new file mode 100644
index 0000000..fad9264
--- /dev/null
+++ b/node_modules/socket.io-client/lib/on.js
@@ -0,0 +1,24 @@
+
+/**
+ * Module exports.
+ */
+
+module.exports = on;
+
+/**
+ * Helper for subscriptions.
+ *
+ * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
+ * @param {String} event name
+ * @param {Function} callback
+ * @api public
+ */
+
+function on (obj, ev, fn) {
+ obj.on(ev, fn);
+ return {
+ destroy: function () {
+ obj.removeListener(ev, fn);
+ }
+ };
+}
diff --git a/node_modules/socket.io-client/lib/socket.js b/node_modules/socket.io-client/lib/socket.js
new file mode 100644
index 0000000..702c602
--- /dev/null
+++ b/node_modules/socket.io-client/lib/socket.js
@@ -0,0 +1,418 @@
+
+/**
+ * Module dependencies.
+ */
+
+var parser = require('socket.io-parser');
+var Emitter = require('component-emitter');
+var toArray = require('to-array');
+var on = require('./on');
+var bind = require('component-bind');
+var debug = require('debug')('socket.io-client:socket');
+var parseqs = require('parseqs');
+
+/**
+ * Module exports.
+ */
+
+module.exports = exports = Socket;
+
+/**
+ * Internal events (blacklisted).
+ * These events can't be emitted by the user.
+ *
+ * @api private
+ */
+
+var events = {
+ connect: 1,
+ connect_error: 1,
+ connect_timeout: 1,
+ connecting: 1,
+ disconnect: 1,
+ error: 1,
+ reconnect: 1,
+ reconnect_attempt: 1,
+ reconnect_failed: 1,
+ reconnect_error: 1,
+ reconnecting: 1,
+ ping: 1,
+ pong: 1
+};
+
+/**
+ * Shortcut to `Emitter#emit`.
+ */
+
+var emit = Emitter.prototype.emit;
+
+/**
+ * `Socket` constructor.
+ *
+ * @api public
+ */
+
+function Socket (io, nsp, opts) {
+ this.io = io;
+ this.nsp = nsp;
+ this.json = this; // compat
+ this.ids = 0;
+ this.acks = {};
+ this.receiveBuffer = [];
+ this.sendBuffer = [];
+ this.connected = false;
+ this.disconnected = true;
+ if (opts && opts.query) {
+ this.query = opts.query;
+ }
+ if (this.io.autoConnect) this.open();
+}
+
+/**
+ * Mix in `Emitter`.
+ */
+
+Emitter(Socket.prototype);
+
+/**
+ * Subscribe to open, close and packet events
+ *
+ * @api private
+ */
+
+Socket.prototype.subEvents = function () {
+ if (this.subs) return;
+
+ var io = this.io;
+ this.subs = [
+ on(io, 'open', bind(this, 'onopen')),
+ on(io, 'packet', bind(this, 'onpacket')),
+ on(io, 'close', bind(this, 'onclose'))
+ ];
+};
+
+/**
+ * "Opens" the socket.
+ *
+ * @api public
+ */
+
+Socket.prototype.open =
+Socket.prototype.connect = function () {
+ if (this.connected) return this;
+
+ this.subEvents();
+ this.io.open(); // ensure open
+ if ('open' === this.io.readyState) this.onopen();
+ this.emit('connecting');
+ return this;
+};
+
+/**
+ * Sends a `message` event.
+ *
+ * @return {Socket} self
+ * @api public
+ */
+
+Socket.prototype.send = function () {
+ var args = toArray(arguments);
+ args.unshift('message');
+ this.emit.apply(this, args);
+ return this;
+};
+
+/**
+ * Override `emit`.
+ * If the event is in `events`, it's emitted normally.
+ *
+ * @param {String} event name
+ * @return {Socket} self
+ * @api public
+ */
+
+Socket.prototype.emit = function (ev) {
+ if (events.hasOwnProperty(ev)) {
+ emit.apply(this, arguments);
+ return this;
+ }
+
+ var args = toArray(arguments);
+ var packet = { type: parser.EVENT, data: args };
+
+ packet.options = {};
+ packet.options.compress = !this.flags || false !== this.flags.compress;
+
+ // event ack callback
+ if ('function' === typeof args[args.length - 1]) {
+ debug('emitting packet with ack id %d', this.ids);
+ this.acks[this.ids] = args.pop();
+ packet.id = this.ids++;
+ }
+
+ if (this.connected) {
+ this.packet(packet);
+ } else {
+ this.sendBuffer.push(packet);
+ }
+
+ delete this.flags;
+
+ return this;
+};
+
+/**
+ * Sends a packet.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+Socket.prototype.packet = function (packet) {
+ packet.nsp = this.nsp;
+ this.io.packet(packet);
+};
+
+/**
+ * Called upon engine `open`.
+ *
+ * @api private
+ */
+
+Socket.prototype.onopen = function () {
+ debug('transport is open - connecting');
+
+ // write connect packet if necessary
+ if ('/' !== this.nsp) {
+ if (this.query) {
+ var query = typeof this.query === 'object' ? parseqs.encode(this.query) : this.query;
+ debug('sending connect packet with query %s', query);
+ this.packet({type: parser.CONNECT, query: query});
+ } else {
+ this.packet({type: parser.CONNECT});
+ }
+ }
+};
+
+/**
+ * Called upon engine `close`.
+ *
+ * @param {String} reason
+ * @api private
+ */
+
+Socket.prototype.onclose = function (reason) {
+ debug('close (%s)', reason);
+ this.connected = false;
+ this.disconnected = true;
+ delete this.id;
+ this.emit('disconnect', reason);
+};
+
+/**
+ * Called with socket packet.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+Socket.prototype.onpacket = function (packet) {
+ if (packet.nsp !== this.nsp) return;
+
+ switch (packet.type) {
+ case parser.CONNECT:
+ this.onconnect();
+ break;
+
+ case parser.EVENT:
+ this.onevent(packet);
+ break;
+
+ case parser.BINARY_EVENT:
+ this.onevent(packet);
+ break;
+
+ case parser.ACK:
+ this.onack(packet);
+ break;
+
+ case parser.BINARY_ACK:
+ this.onack(packet);
+ break;
+
+ case parser.DISCONNECT:
+ this.ondisconnect();
+ break;
+
+ case parser.ERROR:
+ this.emit('error', packet.data);
+ break;
+ }
+};
+
+/**
+ * Called upon a server event.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+Socket.prototype.onevent = function (packet) {
+ var args = packet.data || [];
+ debug('emitting event %j', args);
+
+ if (null != packet.id) {
+ debug('attaching ack callback to event');
+ args.push(this.ack(packet.id));
+ }
+
+ if (this.connected) {
+ emit.apply(this, args);
+ } else {
+ this.receiveBuffer.push(args);
+ }
+};
+
+/**
+ * Produces an ack callback to emit with an event.
+ *
+ * @api private
+ */
+
+Socket.prototype.ack = function (id) {
+ var self = this;
+ var sent = false;
+ return function () {
+ // prevent double callbacks
+ if (sent) return;
+ sent = true;
+ var args = toArray(arguments);
+ debug('sending ack %j', args);
+
+ self.packet({
+ type: parser.ACK,
+ id: id,
+ data: args
+ });
+ };
+};
+
+/**
+ * Called upon a server acknowlegement.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+Socket.prototype.onack = function (packet) {
+ var ack = this.acks[packet.id];
+ if ('function' === typeof ack) {
+ debug('calling ack %s with %j', packet.id, packet.data);
+ ack.apply(this, packet.data);
+ delete this.acks[packet.id];
+ } else {
+ debug('bad ack %s', packet.id);
+ }
+};
+
+/**
+ * Called upon server connect.
+ *
+ * @api private
+ */
+
+Socket.prototype.onconnect = function () {
+ this.connected = true;
+ this.disconnected = false;
+ this.emit('connect');
+ this.emitBuffered();
+};
+
+/**
+ * Emit buffered events (received and emitted).
+ *
+ * @api private
+ */
+
+Socket.prototype.emitBuffered = function () {
+ var i;
+ for (i = 0; i < this.receiveBuffer.length; i++) {
+ emit.apply(this, this.receiveBuffer[i]);
+ }
+ this.receiveBuffer = [];
+
+ for (i = 0; i < this.sendBuffer.length; i++) {
+ this.packet(this.sendBuffer[i]);
+ }
+ this.sendBuffer = [];
+};
+
+/**
+ * Called upon server disconnect.
+ *
+ * @api private
+ */
+
+Socket.prototype.ondisconnect = function () {
+ debug('server disconnect (%s)', this.nsp);
+ this.destroy();
+ this.onclose('io server disconnect');
+};
+
+/**
+ * Called upon forced client/server side disconnections,
+ * this method ensures the manager stops tracking us and
+ * that reconnections don't get triggered for this.
+ *
+ * @api private.
+ */
+
+Socket.prototype.destroy = function () {
+ if (this.subs) {
+ // clean subscriptions to avoid reconnections
+ for (var i = 0; i < this.subs.length; i++) {
+ this.subs[i].destroy();
+ }
+ this.subs = null;
+ }
+
+ this.io.destroy(this);
+};
+
+/**
+ * Disconnects the socket manually.
+ *
+ * @return {Socket} self
+ * @api public
+ */
+
+Socket.prototype.close =
+Socket.prototype.disconnect = function () {
+ if (this.connected) {
+ debug('performing disconnect (%s)', this.nsp);
+ this.packet({ type: parser.DISCONNECT });
+ }
+
+ // remove socket from pool
+ this.destroy();
+
+ if (this.connected) {
+ // fire events
+ this.onclose('io client disconnect');
+ }
+ return this;
+};
+
+/**
+ * Sets the compress flag.
+ *
+ * @param {Boolean} if `true`, compresses the sending data
+ * @return {Socket} self
+ * @api public
+ */
+
+Socket.prototype.compress = function (compress) {
+ this.flags = this.flags || {};
+ this.flags.compress = compress;
+ return this;
+};
diff --git a/node_modules/socket.io-client/lib/url.js b/node_modules/socket.io-client/lib/url.js
new file mode 100644
index 0000000..8bac542
--- /dev/null
+++ b/node_modules/socket.io-client/lib/url.js
@@ -0,0 +1,75 @@
+
+/**
+ * Module dependencies.
+ */
+
+var parseuri = require('parseuri');
+var debug = require('debug')('socket.io-client:url');
+
+/**
+ * Module exports.
+ */
+
+module.exports = url;
+
+/**
+ * URL parser.
+ *
+ * @param {String} url
+ * @param {Object} An object meant to mimic window.location.
+ * Defaults to window.location.
+ * @api public
+ */
+
+function url (uri, loc) {
+ var obj = uri;
+
+ // default to window.location
+ loc = loc || global.location;
+ if (null == uri) uri = loc.protocol + '//' + loc.host;
+
+ // relative path support
+ if ('string' === typeof uri) {
+ if ('/' === uri.charAt(0)) {
+ if ('/' === uri.charAt(1)) {
+ uri = loc.protocol + uri;
+ } else {
+ uri = loc.host + uri;
+ }
+ }
+
+ if (!/^(https?|wss?):\/\//.test(uri)) {
+ debug('protocol-less url %s', uri);
+ if ('undefined' !== typeof loc) {
+ uri = loc.protocol + '//' + uri;
+ } else {
+ uri = 'https://' + uri;
+ }
+ }
+
+ // parse
+ debug('parse %s', uri);
+ obj = parseuri(uri);
+ }
+
+ // make sure we treat `localhost:80` and `localhost` equally
+ if (!obj.port) {
+ if (/^(http|ws)$/.test(obj.protocol)) {
+ obj.port = '80';
+ } else if (/^(http|ws)s$/.test(obj.protocol)) {
+ obj.port = '443';
+ }
+ }
+
+ obj.path = obj.path || '/';
+
+ var ipv6 = obj.host.indexOf(':') !== -1;
+ var host = ipv6 ? '[' + obj.host + ']' : obj.host;
+
+ // define unique id
+ obj.id = obj.protocol + '://' + host + ':' + obj.port;
+ // define href
+ obj.href = obj.protocol + '://' + host + (loc && loc.port === obj.port ? '' : (':' + obj.port));
+
+ return obj;
+}