arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/server/node_modules/socket.io/lib/namespace.js
server/node_modules/socket.io/lib/namespace.jsRaw
  1
  2/**
  3 * Module dependencies.
  4 */
  5
  6var Socket = require('./socket');
  7var Emitter = require('events').EventEmitter;
  8var parser = require('socket.io-parser');
  9var debug = require('debug')('socket.io:namespace');
 10var hasBin = require('has-binary');
 11
 12/**
 13 * Module exports.
 14 */
 15
 16module.exports = exports = Namespace;
 17
 18/**
 19 * Blacklisted events.
 20 */
 21
 22exports.events = [
 23  'connect',    // for symmetry with client
 24  'connection',
 25  'newListener'
 26];
 27
 28/**
 29 * Flags.
 30 */
 31
 32exports.flags = [
 33  'json',
 34  'volatile',
 35  'local'
 36];
 37
 38/**
 39 * `EventEmitter#emit` reference.
 40 */
 41
 42var emit = Emitter.prototype.emit;
 43
 44/**
 45 * Namespace constructor.
 46 *
 47 * @param {Server} server instance
 48 * @param {Socket} name
 49 * @api private
 50 */
 51
 52function Namespace(server, name){
 53  this.name = name;
 54  this.server = server;
 55  this.sockets = {};
 56  this.connected = {};
 57  this.fns = [];
 58  this.ids = 0;
 59  this.initAdapter();
 60}
 61
 62/**
 63 * Inherits from `EventEmitter`.
 64 */
 65
 66Namespace.prototype.__proto__ = Emitter.prototype;
 67
 68/**
 69 * Apply flags from `Socket`.
 70 */
 71
 72exports.flags.forEach(function(flag){
 73  Object.defineProperty(Namespace.prototype, flag, {
 74    get: function() {
 75      this.flags = this.flags || {};
 76      this.flags[flag] = true;
 77      return this;
 78    }
 79  });
 80});
 81
 82/**
 83 * Initializes the `Adapter` for this nsp.
 84 * Run upon changing adapter by `Server#adapter`
 85 * in addition to the constructor.
 86 *
 87 * @api private
 88 */
 89
 90Namespace.prototype.initAdapter = function(){
 91  this.adapter = new (this.server.adapter())(this);
 92};
 93
 94/**
 95 * Sets up namespace middleware.
 96 *
 97 * @return {Namespace} self
 98 * @api public
 99 */
100
101Namespace.prototype.use = function(fn){
102  this.fns.push(fn);
103  return this;
104};
105
106/**
107 * Executes the middleware for an incoming client.
108 *
109 * @param {Socket} socket that will get added
110 * @param {Function} fn last fn call in the middleware
111 * @api private
112 */
113
114Namespace.prototype.run = function(socket, fn){
115  var fns = this.fns.slice(0);
116  if (!fns.length) return fn(null);
117
118  function run(i){
119    fns[i](socket, function(err){
120      // upon error, short-circuit
121      if (err) return fn(err);
122
123      // if no middleware left, summon callback
124      if (!fns[i + 1]) return fn(null);
125
126      // go on to next
127      run(i + 1);
128    });
129  }
130
131  run(0);
132};
133
134/**
135 * Targets a room when emitting.
136 *
137 * @param {String} name
138 * @return {Namespace} self
139 * @api public
140 */
141
142Namespace.prototype.to =
143Namespace.prototype.in = function(name){
144  this.rooms = this.rooms || [];
145  if (!~this.rooms.indexOf(name)) this.rooms.push(name);
146  return this;
147};
148
149/**
150 * Adds a new client.
151 *
152 * @return {Socket}
153 * @api private
154 */
155
156Namespace.prototype.add = function(client, query, fn){
157  debug('adding socket to nsp %s', this.name);
158  var socket = new Socket(this, client, query);
159  var self = this;
160  this.run(socket, function(err){
161    process.nextTick(function(){
162      if ('open' == client.conn.readyState) {
163        if (err) return socket.error(err.data || err.message);
164
165        // track socket
166        self.sockets[socket.id] = socket;
167
168        // it's paramount that the internal `onconnect` logic
169        // fires before user-set events to prevent state order
170        // violations (such as a disconnection before the connection
171        // logic is complete)
172        socket.onconnect();
173        if (fn) fn();
174
175        // fire user-set events
176        self.emit('connect', socket);
177        self.emit('connection', socket);
178      } else {
179        debug('next called after client was closed - ignoring socket');
180      }
181    });
182  });
183  return socket;
184};
185
186/**
187 * Removes a client. Called by each `Socket`.
188 *
189 * @api private
190 */
191
192Namespace.prototype.remove = function(socket){
193  if (this.sockets.hasOwnProperty(socket.id)) {
194    delete this.sockets[socket.id];
195  } else {
196    debug('ignoring remove for %s', socket.id);
197  }
198};
199
200/**
201 * Emits to all clients.
202 *
203 * @return {Namespace} self
204 * @api public
205 */
206
207Namespace.prototype.emit = function(ev){
208  if (~exports.events.indexOf(ev)) {
209    emit.apply(this, arguments);
210  } else {
211    // set up packet object
212    var args = Array.prototype.slice.call(arguments);
213    var parserType = parser.EVENT; // default
214    if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
215
216    var packet = { type: parserType, data: args };
217
218    if ('function' == typeof args[args.length - 1]) {
219      throw new Error('Callbacks are not supported when broadcasting');
220    }
221
222    this.adapter.broadcast(packet, {
223      rooms: this.rooms,
224      flags: this.flags
225    });
226
227    delete this.rooms;
228    delete this.flags;
229  }
230  return this;
231};
232
233/**
234 * Sends a `message` event to all clients.
235 *
236 * @return {Namespace} self
237 * @api public
238 */
239
240Namespace.prototype.send =
241Namespace.prototype.write = function(){
242  var args = Array.prototype.slice.call(arguments);
243  args.unshift('message');
244  this.emit.apply(this, args);
245  return this;
246};
247
248/**
249 * Gets a list of clients.
250 *
251 * @return {Namespace} self
252 * @api public
253 */
254
255Namespace.prototype.clients = function(fn){
256  this.adapter.clients(this.rooms, fn);
257  // delete rooms flag for scenario:
258  // .in('room').clients() (GH-1978)
259  delete this.rooms;
260  return this;
261};
262
263/**
264 * Sets the compress flag.
265 *
266 * @param {Boolean} compress if `true`, compresses the sending data
267 * @return {Socket} self
268 * @api public
269 */
270
271Namespace.prototype.compress = function(compress){
272  this.flags = this.flags || {};
273  this.flags.compress = compress;
274  return this;
275};