comunicationLeap/node_modules/socket.io/lib/namespace.js
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-data');
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 = ['json'];
33
34/**
35 * `EventEmitter#emit` reference.
36 */
37
38var emit = Emitter.prototype.emit;
39
40/**
41 * Namespace constructor.
42 *
43 * @param {Server} server instance
44 * @param {Socket} name
45 * @api private
46 */
47
48function Namespace(server, name){
49 this.name = name;
50 this.server = server;
51 this.sockets = [];
52 this.connected = {};
53 this.fns = [];
54 this.ids = 0;
55 this.acks = {};
56 this.initAdapter();
57}
58
59/**
60 * Inherits from `EventEmitter`.
61 */
62
63Namespace.prototype.__proto__ = Emitter.prototype;
64
65/**
66 * Apply flags from `Socket`.
67 */
68
69exports.flags.forEach(function(flag){
70 Namespace.prototype.__defineGetter__(flag, function(){
71 this.flags = this.flags || {};
72 this.flags[flag] = true;
73 return this;
74 });
75});
76
77/**
78 * Initializes the `Adapter` for this nsp.
79 * Run upon changing adapter by `Server#adapter`
80 * in addition to the constructor.
81 *
82 * @api private
83 */
84
85Namespace.prototype.initAdapter = function(){
86 this.adapter = new (this.server.adapter())(this);
87};
88
89/**
90 * Sets up namespace middleware.
91 *
92 * @return {Namespace} self
93 * @api public
94 */
95
96Namespace.prototype.use = function(fn){
97 this.fns.push(fn);
98 return this;
99};
100
101/**
102 * Executes the middleware for an incoming client.
103 *
104 * @param {Socket} socket that will get added
105 * @param {Function} last fn call in the middleware
106 * @api private
107 */
108
109Namespace.prototype.run = function(socket, fn){
110 var fns = this.fns.slice(0);
111 if (!fns.length) return fn(null);
112
113 function run(i){
114 fns[i](socket, function(err){
115 // upon error, short-circuit
116 if (err) return fn(err);
117
118 // if no middleware left, summon callback
119 if (!fns[i + 1]) return fn(null);
120
121 // go on to next
122 run(i + 1);
123 });
124 }
125
126 run(0);
127};
128
129/**
130 * Targets a room when emitting.
131 *
132 * @param {String} name
133 * @return {Namespace} self
134 * @api public
135 */
136
137Namespace.prototype.to =
138Namespace.prototype['in'] = function(name){
139 this.rooms = this.rooms || [];
140 if (!~this.rooms.indexOf(name)) this.rooms.push(name);
141 return this;
142};
143
144/**
145 * Adds a new client.
146 *
147 * @return {Socket}
148 * @api private
149 */
150
151Namespace.prototype.add = function(client, fn){
152 debug('adding socket to nsp %s', this.name);
153 var socket = new Socket(this, client);
154 var self = this;
155 this.run(socket, function(err){
156 process.nextTick(function(){
157 if ('open' == client.conn.readyState) {
158 if (err) return socket.error(err.data || err.message);
159
160 // track socket
161 self.sockets.push(socket);
162
163 // it's paramount that the internal `onconnect` logic
164 // fires before user-set events to prevent state order
165 // violations (such as a disconnection before the connection
166 // logic is complete)
167 socket.onconnect();
168 if (fn) fn();
169
170 // fire user-set events
171 self.emit('connect', socket);
172 self.emit('connection', socket);
173 } else {
174 debug('next called after client was closed - ignoring socket');
175 }
176 });
177 });
178 return socket;
179};
180
181/**
182 * Removes a client. Called by each `Socket`.
183 *
184 * @api private
185 */
186
187Namespace.prototype.remove = function(socket){
188 var i = this.sockets.indexOf(socket);
189 if (~i) {
190 this.sockets.splice(i, 1);
191 } else {
192 debug('ignoring remove for %s', socket.id);
193 }
194};
195
196/**
197 * Emits to all clients.
198 *
199 * @return {Namespace} self
200 * @api public
201 */
202
203Namespace.prototype.emit = function(ev){
204 if (~exports.events.indexOf(ev)) {
205 emit.apply(this, arguments);
206 } else {
207 // set up packet object
208 var args = Array.prototype.slice.call(arguments);
209 var parserType = parser.EVENT; // default
210 if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
211
212 var packet = { type: parserType, data: args };
213
214 if ('function' == typeof args[args.length - 1]) {
215 throw new Error('Callbacks are not supported when broadcasting');
216 }
217
218 this.adapter.broadcast(packet, {
219 rooms: this.rooms,
220 flags: this.flags
221 });
222
223 delete this.rooms;
224 delete this.flags;
225 }
226 return this;
227};
228
229/**
230 * Sends a `message` event to all clients.
231 *
232 * @return {Namespace} self
233 * @api public
234 */
235
236Namespace.prototype.send =
237Namespace.prototype.write = function(){
238 var args = Array.prototype.slice.call(arguments);
239 args.unshift('message');
240 this.emit.apply(this, args);
241 return this;
242};