[SignalingServer] Optimize dependent modules
[platform/framework/web/wrtjs.git] / signaling_server / service / node_modules / socket.io / lib / namespace.js
1
2 /**
3  * Module dependencies.
4  */
5
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');
11
12 /**
13  * Module exports.
14  */
15
16 module.exports = exports = Namespace;
17
18 /**
19  * Blacklisted events.
20  */
21
22 exports.events = [
23   'connect',    // for symmetry with client
24   'connection',
25   'newListener'
26 ];
27
28 /**
29  * Flags.
30  */
31
32 exports.flags = [
33   'json',
34   'volatile',
35   'local'
36 ];
37
38 /**
39  * `EventEmitter#emit` reference.
40  */
41
42 var emit = Emitter.prototype.emit;
43
44 /**
45  * Namespace constructor.
46  *
47  * @param {Server} server instance
48  * @param {Socket} name
49  * @api private
50  */
51
52 function 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.rooms = [];
60   this.flags = {};
61   this.initAdapter();
62 }
63
64 /**
65  * Inherits from `EventEmitter`.
66  */
67
68 Namespace.prototype.__proto__ = Emitter.prototype;
69
70 /**
71  * Apply flags from `Socket`.
72  */
73
74 exports.flags.forEach(function(flag){
75   Object.defineProperty(Namespace.prototype, flag, {
76     get: function() {
77       this.flags[flag] = true;
78       return this;
79     }
80   });
81 });
82
83 /**
84  * Initializes the `Adapter` for this nsp.
85  * Run upon changing adapter by `Server#adapter`
86  * in addition to the constructor.
87  *
88  * @api private
89  */
90
91 Namespace.prototype.initAdapter = function(){
92   this.adapter = new (this.server.adapter())(this);
93 };
94
95 /**
96  * Sets up namespace middleware.
97  *
98  * @return {Namespace} self
99  * @api public
100  */
101
102 Namespace.prototype.use = function(fn){
103   if (this.server.eio && this.name === '/') {
104     debug('removing initial packet');
105     delete this.server.eio.initialPacket;
106   }
107   this.fns.push(fn);
108   return this;
109 };
110
111 /**
112  * Executes the middleware for an incoming client.
113  *
114  * @param {Socket} socket that will get added
115  * @param {Function} fn last fn call in the middleware
116  * @api private
117  */
118
119 Namespace.prototype.run = function(socket, fn){
120   var fns = this.fns.slice(0);
121   if (!fns.length) return fn(null);
122
123   function run(i){
124     fns[i](socket, function(err){
125       // upon error, short-circuit
126       if (err) return fn(err);
127
128       // if no middleware left, summon callback
129       if (!fns[i + 1]) return fn(null);
130
131       // go on to next
132       run(i + 1);
133     });
134   }
135
136   run(0);
137 };
138
139 /**
140  * Targets a room when emitting.
141  *
142  * @param {String} name
143  * @return {Namespace} self
144  * @api public
145  */
146
147 Namespace.prototype.to =
148 Namespace.prototype.in = function(name){
149   if (!~this.rooms.indexOf(name)) this.rooms.push(name);
150   return this;
151 };
152
153 /**
154  * Adds a new client.
155  *
156  * @return {Socket}
157  * @api private
158  */
159
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);
163   var self = this;
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);
168
169         // track socket
170         self.sockets[socket.id] = socket;
171
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)
176         socket.onconnect();
177         if (fn) fn();
178
179         // fire user-set events
180         self.emit('connect', socket);
181         self.emit('connection', socket);
182       } else {
183         debug('next called after client was closed - ignoring socket');
184       }
185     });
186   });
187   return socket;
188 };
189
190 /**
191  * Removes a client. Called by each `Socket`.
192  *
193  * @api private
194  */
195
196 Namespace.prototype.remove = function(socket){
197   if (this.sockets.hasOwnProperty(socket.id)) {
198     delete this.sockets[socket.id];
199   } else {
200     debug('ignoring remove for %s', socket.id);
201   }
202 };
203
204 /**
205  * Emits to all clients.
206  *
207  * @return {Namespace} self
208  * @api public
209  */
210
211 Namespace.prototype.emit = function(ev){
212   if (~exports.events.indexOf(ev)) {
213     emit.apply(this, arguments);
214     return this;
215   }
216   // set up packet object
217   var args = Array.prototype.slice.call(arguments);
218   var packet = {
219     type: (this.flags.binary !== undefined ? this.flags.binary : hasBin(args)) ? parser.BINARY_EVENT : parser.EVENT,
220     data: args
221   };
222
223   if ('function' == typeof args[args.length - 1]) {
224     throw new Error('Callbacks are not supported when broadcasting');
225   }
226
227   var rooms = this.rooms.slice(0);
228   var flags = Object.assign({}, this.flags);
229
230   // reset flags
231   this.rooms = [];
232   this.flags = {};
233
234   this.adapter.broadcast(packet, {
235     rooms: rooms,
236     flags: flags
237   });
238
239   return this;
240 };
241
242 /**
243  * Sends a `message` event to all clients.
244  *
245  * @return {Namespace} self
246  * @api public
247  */
248
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);
254   return this;
255 };
256
257 /**
258  * Gets a list of clients.
259  *
260  * @return {Namespace} self
261  * @api public
262  */
263
264 Namespace.prototype.clients = function(fn){
265   if(!this.adapter){
266     throw new Error('No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?')
267   }
268   this.adapter.clients(this.rooms, fn);
269   // reset rooms for scenario:
270   // .in('room').clients() (GH-1978)
271   this.rooms = [];
272   return this;
273 };
274
275 /**
276  * Sets the compress flag.
277  *
278  * @param {Boolean} compress if `true`, compresses the sending data
279  * @return {Socket} self
280  * @api public
281  */
282
283 Namespace.prototype.compress = function(compress){
284   this.flags.compress = compress;
285   return this;
286 };
287
288 /**
289  * Sets the binary flag
290  *
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
293  * @api public
294  */
295
296  Namespace.prototype.binary = function (binary) {
297    this.flags.binary = binary;
298    return this;
299  };