6 var Socket = require('./socket');
7 var Emitter = require('events').EventEmitter;
8 var parser = require('socket.io-parser');
9 var hasBin = require('has-binary2');
10 var debug = require('debug')('socket.io:namespace');
16 module.exports = exports = Namespace;
23 'connect', // for symmetry with client
39 * `EventEmitter#emit` reference.
42 var emit = Emitter.prototype.emit;
45 * Namespace constructor.
47 * @param {Server} server instance
48 * @param {Socket} name
52 function Namespace(server, name){
65 * Inherits from `EventEmitter`.
68 Namespace.prototype.__proto__ = Emitter.prototype;
71 * Apply flags from `Socket`.
74 exports.flags.forEach(function(flag){
75 Object.defineProperty(Namespace.prototype, flag, {
77 this.flags[flag] = true;
84 * Initializes the `Adapter` for this nsp.
85 * Run upon changing adapter by `Server#adapter`
86 * in addition to the constructor.
91 Namespace.prototype.initAdapter = function(){
92 this.adapter = new (this.server.adapter())(this);
96 * Sets up namespace middleware.
98 * @return {Namespace} self
102 Namespace.prototype.use = function(fn){
103 if (this.server.eio && this.name === '/') {
104 debug('removing initial packet');
105 delete this.server.eio.initialPacket;
112 * Executes the middleware for an incoming client.
114 * @param {Socket} socket that will get added
115 * @param {Function} fn last fn call in the middleware
119 Namespace.prototype.run = function(socket, fn){
120 var fns = this.fns.slice(0);
121 if (!fns.length) return fn(null);
124 fns[i](socket, function(err){
125 // upon error, short-circuit
126 if (err) return fn(err);
128 // if no middleware left, summon callback
129 if (!fns[i + 1]) return fn(null);
140 * Targets a room when emitting.
142 * @param {String} name
143 * @return {Namespace} self
147 Namespace.prototype.to =
148 Namespace.prototype.in = function(name){
149 if (!~this.rooms.indexOf(name)) this.rooms.push(name);
160 Namespace.prototype.add = function(client, query, fn){
161 debug('adding socket to nsp %s', this.name);
162 var socket = new Socket(this, client, query);
164 this.run(socket, function(err){
165 process.nextTick(function(){
166 if ('open' == client.conn.readyState) {
167 if (err) return socket.error(err.data || err.message);
170 self.sockets[socket.id] = socket;
172 // it's paramount that the internal `onconnect` logic
173 // fires before user-set events to prevent state order
174 // violations (such as a disconnection before the connection
175 // logic is complete)
179 // fire user-set events
180 self.emit('connect', socket);
181 self.emit('connection', socket);
183 debug('next called after client was closed - ignoring socket');
191 * Removes a client. Called by each `Socket`.
196 Namespace.prototype.remove = function(socket){
197 if (this.sockets.hasOwnProperty(socket.id)) {
198 delete this.sockets[socket.id];
200 debug('ignoring remove for %s', socket.id);
205 * Emits to all clients.
207 * @return {Namespace} self
211 Namespace.prototype.emit = function(ev){
212 if (~exports.events.indexOf(ev)) {
213 emit.apply(this, arguments);
216 // set up packet object
217 var args = Array.prototype.slice.call(arguments);
219 type: (this.flags.binary !== undefined ? this.flags.binary : hasBin(args)) ? parser.BINARY_EVENT : parser.EVENT,
223 if ('function' == typeof args[args.length - 1]) {
224 throw new Error('Callbacks are not supported when broadcasting');
227 var rooms = this.rooms.slice(0);
228 var flags = Object.assign({}, this.flags);
234 this.adapter.broadcast(packet, {
243 * Sends a `message` event to all clients.
245 * @return {Namespace} self
249 Namespace.prototype.send =
250 Namespace.prototype.write = function(){
251 var args = Array.prototype.slice.call(arguments);
252 args.unshift('message');
253 this.emit.apply(this, args);
258 * Gets a list of clients.
260 * @return {Namespace} self
264 Namespace.prototype.clients = function(fn){
266 throw new Error('No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?')
268 this.adapter.clients(this.rooms, fn);
269 // reset rooms for scenario:
270 // .in('room').clients() (GH-1978)
276 * Sets the compress flag.
278 * @param {Boolean} compress if `true`, compresses the sending data
279 * @return {Socket} self
283 Namespace.prototype.compress = function(compress){
284 this.flags.compress = compress;
289 * Sets the binary flag
291 * @param {Boolean} Encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false`
292 * @return {Socket} self
296 Namespace.prototype.binary = function (binary) {
297 this.flags.binary = binary;