5 var Socket = require('./socket')
6 , EventEmitter = process.EventEmitter
7 , parser = require('./parser')
8 , util = require('./util');
11 * Exports the constructor.
14 exports = module.exports = SocketNamespace;
22 function SocketNamespace (mgr, name) {
24 this.name = name || '';
31 * Inherits from EventEmitter.
34 SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
37 * Copies emit since we override it.
42 SocketNamespace.prototype.$emit = EventEmitter.prototype.emit;
45 * Retrieves all clients as Socket instances as an array.
50 SocketNamespace.prototype.clients = function (room) {
51 var room = this.name + (room !== undefined ?
54 if (!this.manager.rooms[room]) {
58 return this.manager.rooms[room].map(function (id) {
59 return this.socket(id);
64 * Access logger interface.
69 SocketNamespace.prototype.__defineGetter__('log', function () {
70 return this.manager.log;
79 SocketNamespace.prototype.__defineGetter__('store', function () {
80 return this.manager.store;
89 SocketNamespace.prototype.__defineGetter__('json', function () {
90 this.flags.json = true;
95 * Volatile message flag.
100 SocketNamespace.prototype.__defineGetter__('volatile', function () {
101 this.flags.volatile = true;
106 * Overrides the room to relay messages to (flag).
111 SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
112 this.flags.endpoint = this.name + (room ? '/' + room : '');
117 * Adds a session id we should prevent relaying messages to (flag).
122 SocketNamespace.prototype.except = function (id) {
123 this.flags.exceptions.push(id);
128 * Sets the default flags.
133 SocketNamespace.prototype.setFlags = function () {
142 * Sends out a packet.
147 SocketNamespace.prototype.packet = function (packet) {
148 packet.endpoint = this.name;
150 var store = this.store
152 , volatile = this.flags.volatile
153 , exceptions = this.flags.exceptions
154 , packet = parser.encodePacket(packet);
156 this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions);
157 this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions);
170 SocketNamespace.prototype.send = function (data) {
172 type: this.flags.json ? 'json' : 'message'
178 * Emits to everyone (override).
183 SocketNamespace.prototype.emit = function (name) {
184 if (name == 'newListener') {
185 return this.$emit.apply(this, arguments);
191 , args: util.toArray(arguments).slice(1)
196 * Retrieves or creates a write-only socket for a client, unless specified.
198 * @param {Boolean} whether the socket will be readable when initialized
202 SocketNamespace.prototype.socket = function (sid, readable) {
203 if (!this.sockets[sid]) {
204 this.sockets[sid] = new Socket(this.manager, sid, this, readable);
207 return this.sockets[sid];
211 * Sets authorization for this namespace.
216 SocketNamespace.prototype.authorization = function (fn) {
222 * Called when a socket disconnects entirely.
227 SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) {
228 if (this.sockets[sid] && this.sockets[sid].readable) {
229 if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason);
230 delete this.sockets[sid];
235 * Performs authentication.
237 * @param Object client request data
241 SocketNamespace.prototype.authorize = function (data, fn) {
245 this.auth.call(this, data, function (err, authorized) {
246 self.log.debug('client ' +
247 (authorized ? '' : 'un') + 'authorized for ' + self.name);
251 this.log.debug('client authorized for ' + this.name);
264 SocketNamespace.prototype.handlePacket = function (sessid, packet) {
265 var socket = this.socket(sessid)
266 , dataAck = packet.ack == 'data'
267 , manager = this.manager
271 self.log.debug('sending data ack packet');
274 , args: util.toArray(arguments)
279 function error (err) {
280 self.log.warn('handshake error ' + err + ' for ' + self.name);
281 socket.packet({ type: 'error', reason: err });
284 function connect () {
285 self.manager.onJoin(sessid, self.name);
286 self.store.publish('join', sessid, self.name);
289 socket.packet({ type: 'connect' });
291 // emit connection event
292 self.$emit('connection', socket);
295 switch (packet.type) {
297 if (packet.endpoint == '') {
300 var handshakeData = manager.handshaken[sessid];
302 this.authorize(handshakeData, function (err, authorized, newData) {
303 if (err) return error(err);
306 manager.onHandshake(sessid, newData || handshakeData);
307 self.store.publish('handshake', sessid, newData || handshakeData);
310 error('unauthorized');
317 if (socket.acks[packet.ackId]) {
318 socket.acks[packet.ackId].apply(socket, packet.args);
320 this.log.info('unknown ack packet');
325 // check if the emitted event is not blacklisted
326 if (-~manager.get('blacklist').indexOf(packet.name)) {
327 this.log.debug('ignoring blacklisted event `' + packet.name + '`');
329 var params = [packet.name].concat(packet.args);
335 socket.$emit.apply(socket, params);
340 this.manager.onLeave(sessid, this.name);
341 this.store.publish('leave', sessid, this.name);
343 socket.$emit('disconnect', packet.reason || 'packet');
348 var params = ['message', packet.data];
353 socket.$emit.apply(socket, params);