123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*!
- * 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;
- /**
- * Default error event listener to prevent uncaught exceptions.
- */
- var defaultError = function () {};
- /**
- * 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.disconnected = false;
- this.ackPackets = 0;
- this.acks = {};
- this.setFlags();
- this.readable = readable;
- this.store = this.manager.store.client(this.id);
- this.on('error', defaultError);
- };
- /**
- * Inherits from EventEmitter.
- */
- Socket.prototype.__proto__ = EventEmitter.prototype;
- /**
- * Accessor shortcut for the handshake data
- *
- * @api private
- */
- Socket.prototype.__defineGetter__('handshake', function () {
- return this.manager.handshaken[this.id];
- });
- /**
- * Accessor shortcut for the transport type
- *
- * @api private
- */
- Socket.prototype.__defineGetter__('transport', function () {
- return this.manager.transports[this.id].name;
- });
- /**
- * 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;
- });
- /**
- * Broadcast message flag.
- *
- * @api public
- */
- Socket.prototype.__defineGetter__('broadcast', function () {
- this.flags.broadcast = true;
- return this;
- });
- /**
- * Overrides the room to broadcast messages to (flag)
- *
- * @api public
- */
- Socket.prototype.to = Socket.prototype.in = function (room) {
- this.flags.room = room;
- return this;
- };
- /**
- * Resets flags
- *
- * @api private
- */
- Socket.prototype.setFlags = function () {
- this.flags = {
- endpoint: this.namespace.name
- , room: ''
- };
- 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) {
- var nsp = this.namespace.name
- , name = (nsp + '/') + name;
- this.manager.onJoin(this.id, name);
- this.manager.store.publish('join', this.id, name);
- if (fn) {
- this.log.warn('Client#join callback is deprecated');
- fn();
- }
- return this;
- };
- /**
- * Un-joins a user from a room.
- *
- * @api public
- */
- Socket.prototype.leave = function (name, fn) {
- var nsp = this.namespace.name
- , name = (nsp + '/') + name;
- this.manager.onLeave(this.id, name);
- this.manager.store.publish('leave', this.id, name);
- if (fn) {
- this.log.warn('Client#leave callback is deprecated');
- fn();
- }
- return this;
- };
- /**
- * Transmits a packet.
- *
- * @api private
- */
- Socket.prototype.packet = function (packet) {
- if (this.flags.broadcast) {
- this.log.debug('broadcasting packet');
- this.namespace.in(this.flags.room).except(this.id).packet(packet);
- } else {
- packet.endpoint = this.flags.endpoint;
- packet = parser.encodePacket(packet);
- this.dispatch(packet, this.flags.volatile);
- }
- this.setFlags();
- return this;
- };
- /**
- * Dispatches a packet
- *
- * @api private
- */
- Socket.prototype.dispatch = function (packet, volatile) {
- if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
- this.manager.transports[this.id].onDispatch(packet, volatile);
- } else {
- if (!volatile) {
- this.manager.onClientDispatch(this.id, packet, volatile);
- }
- this.manager.store.publish('dispatch:' + this.id, packet, volatile);
- }
- };
- /**
- * Stores data for the client.
- *
- * @api public
- */
- Socket.prototype.set = function (key, value, fn) {
- this.store.set(key, value, fn);
- return this;
- };
- /**
- * Retrieves data for the client
- *
- * @api public
- */
- Socket.prototype.get = function (key, fn) {
- this.store.get(key, fn);
- return this;
- };
- /**
- * Checks data for the client
- *
- * @api public
- */
- Socket.prototype.has = function (key, fn) {
- this.store.has(key, fn);
- return this;
- };
- /**
- * Deletes data for the client
- *
- * @api public
- */
- Socket.prototype.del = function (key, fn) {
- this.store.del(key, fn);
- return this;
- };
- /**
- * Kicks client
- *
- * @api public
- */
- Socket.prototype.disconnect = function () {
- if (!this.disconnected) {
- this.log.info('booting client');
- if ('' === this.namespace.name) {
- if (this.manager.transports[this.id] && this.manager.transports[this.id].open) {
- this.manager.transports[this.id].onForcedDisconnect();
- } else {
- this.manager.onClientDisconnect(this.id);
- this.manager.store.publish('disconnect:' + this.id);
- }
- } else {
- this.packet({type: 'disconnect'});
- this.manager.onLeave(this.id, this.namespace.name);
- this.$emit('disconnect', 'booted');
- }
- }
- 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 = 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 (ev == 'newListener') {
- return this.$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.ackPackets;
- packet.ack = lastArg.length ? 'data' : true;
- this.acks[packet.id] = lastArg;
- args = args.slice(0, args.length - 1);
- }
- packet.args = args;
- return this.packet(packet);
- };
|