mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
263 lines
4.2 KiB
JavaScript
263 lines
4.2 KiB
JavaScript
|
|
/*!
|
|
* socket.io-node
|
|
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
* MIT Licensed
|
|
*/
|
|
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
|
|
var parser = require('./parser')
|
|
, util = require('./util')
|
|
, EventEmitter = process.EventEmitter;
|
|
|
|
/**
|
|
* Export the constructor.
|
|
*/
|
|
|
|
exports = module.exports = Socket;
|
|
|
|
/**
|
|
* Reserved event names.
|
|
*/
|
|
|
|
var events = {
|
|
message: 1
|
|
, connect: 1
|
|
, disconnect: 1
|
|
, open: 1
|
|
, close: 1
|
|
, error: 1
|
|
, retry: 1
|
|
, reconnect: 1
|
|
, newListener: 1
|
|
};
|
|
|
|
/**
|
|
* Socket constructor.
|
|
*
|
|
* @param {Manager} manager instance
|
|
* @param {String} session id
|
|
* @param {Namespace} namespace the socket belongs to
|
|
* @param {Boolean} whether the
|
|
* @api public
|
|
*/
|
|
|
|
function Socket (manager, id, nsp, readable) {
|
|
this.id = id;
|
|
this.namespace = nsp;
|
|
this.manager = manager;
|
|
this.flags = {};
|
|
this.disconnected = false;
|
|
this.ackPackets = 0;
|
|
this.acks = {};
|
|
|
|
if (readable) {
|
|
var self = this;
|
|
|
|
this.store.once('disconnect:' + id, function (reason) {
|
|
self.onDisconnect(reason);
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Inherits from EventEmitter.
|
|
*/
|
|
|
|
Socket.prototype.__proto__ = EventEmitter.prototype;
|
|
|
|
/**
|
|
* Accessor shortcut for the store.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
Socket.prototype.__defineGetter__('store', function () {
|
|
return this.manager.store;
|
|
});
|
|
|
|
/**
|
|
* Accessor shortcut for the logger.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
Socket.prototype.__defineGetter__('log', function () {
|
|
return this.manager.log;
|
|
});
|
|
|
|
/**
|
|
* JSON message flag.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.__defineGetter__('json', function () {
|
|
this.flags.json = true;
|
|
return this;
|
|
});
|
|
|
|
/**
|
|
* Volatile message flag.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.__defineGetter__('volatile', function () {
|
|
this.flags.volatile = true;
|
|
return this;
|
|
});
|
|
|
|
/**
|
|
* Triggered on disconnect
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
Socket.prototype.onDisconnect = function (reason) {
|
|
if (!this.disconnected) {
|
|
this.emit('disconnect', reason);
|
|
this.disconnected = true;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Joins a user to a room.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.join = function (name, fn) {
|
|
this.store.join(this.nsp.name + '/' + name, fn);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Joins a user to a room.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.leave = function (name, fn) {
|
|
this.store.leave(this.nsp.name + '/' + name, fn);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Transmits a packet.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
Socket.prototype.packet = function (packet) {
|
|
packet.endpoint = this.namespace.name;
|
|
packet = parser.encodePacket(packet);
|
|
|
|
if (this.flags.volatile) {
|
|
this.store.publish('volatile:' + this.id, packet);
|
|
} else {
|
|
this.store.client(this.id).publish(packet);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Stores data for the client.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.set = function (key, value, fn) {
|
|
this.store.client(this.id).set(key, value, fn);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Retrieves data for the client
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.get = function (key, fn) {
|
|
this.store.client(this.id).get(key, fn);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Kicks client
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.disconnect = function () {
|
|
if (!this.disconnected) {
|
|
this.log.info('booting client');
|
|
this.store.disconnect(this.id, true);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Send a message.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.send = function (data, fn) {
|
|
var packet = {
|
|
type: this.flags.json ? 'json' : 'message'
|
|
, data: data
|
|
};
|
|
|
|
if (fn) {
|
|
packet.id = ++this.ackPackets;
|
|
packet.ack = fn.length ? 'data' : true;
|
|
this.acks[packet.id] = fn;
|
|
}
|
|
|
|
return this.packet(packet);
|
|
};
|
|
|
|
/**
|
|
* Original emit function.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
Socket.prototype.$emit = EventEmitter.prototype.emit;
|
|
|
|
/**
|
|
* Emit override for custom events.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Socket.prototype.emit = function (ev) {
|
|
if (events[ev]) {
|
|
return EventEmitter.prototype.emit.apply(this, arguments);
|
|
}
|
|
|
|
var args = util.toArray(arguments).slice(1)
|
|
, lastArg = args[args.length - 1]
|
|
, packet = {
|
|
type: 'event'
|
|
, name: ev
|
|
};
|
|
|
|
if ('function' == typeof lastArg) {
|
|
packet.id = ++this.packets;
|
|
packet.ack = lastArg.length ? 'data' : true;
|
|
this.acks[packet.id] = fn;
|
|
args = args.slice(0, args.length - 1);
|
|
}
|
|
|
|
packet.args = args;
|
|
|
|
return this.packet(packet);
|
|
};
|