Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / socket.io / lib / namespace.js
1 /**
2  * Module dependencies.
3  */
4
5 var Socket = require('./socket')
6   , EventEmitter = process.EventEmitter
7   , parser = require('./parser')
8   , util = require('./util');
9
10 /**
11  * Exports the constructor.
12  */
13
14 exports = module.exports = SocketNamespace;
15
16 /**
17  * Constructor.
18  *
19  * @api public.
20  */
21
22 function SocketNamespace (mgr, name) {
23   this.manager = mgr;
24   this.name = name || '';
25   this.sockets = {};
26   this.auth = false;
27   this.setFlags();
28 };
29
30 /**
31  * Inherits from EventEmitter.
32  */
33
34 SocketNamespace.prototype.__proto__ = EventEmitter.prototype;
35
36 /**
37  * Copies emit since we override it.
38  *
39  * @api private
40  */
41
42 SocketNamespace.prototype.$emit = EventEmitter.prototype.emit;
43
44 /**
45  * Retrieves all clients as Socket instances as an array.
46  *
47  * @api public
48  */
49
50 SocketNamespace.prototype.clients = function (room) {
51   var room = this.name + (room !== undefined ?
52      '/' + room : '');
53
54   if (!this.manager.rooms[room]) {
55     return [];
56   }
57
58   return this.manager.rooms[room].map(function (id) {
59     return this.socket(id);
60   }, this);
61 };
62
63 /**
64  * Access logger interface.
65  *
66  * @api public
67  */
68
69 SocketNamespace.prototype.__defineGetter__('log', function () {
70   return this.manager.log;
71 });
72
73 /**
74  * Access store.
75  *
76  * @api public
77  */
78
79 SocketNamespace.prototype.__defineGetter__('store', function () {
80   return this.manager.store;
81 });
82
83 /**
84  * JSON message flag.
85  *
86  * @api public
87  */
88
89 SocketNamespace.prototype.__defineGetter__('json', function () {
90   this.flags.json = true;
91   return this;
92 });
93
94 /**
95  * Volatile message flag.
96  *
97  * @api public
98  */
99
100 SocketNamespace.prototype.__defineGetter__('volatile', function () {
101   this.flags.volatile = true;
102   return this;
103 });
104
105 /**
106  * Overrides the room to relay messages to (flag).
107  *
108  * @api public
109  */
110
111 SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) {
112   this.flags.endpoint = this.name + (room ? '/' + room : '');
113   return this;
114 };
115
116 /**
117  * Adds a session id we should prevent relaying messages to (flag).
118  *
119  * @api public
120  */
121
122 SocketNamespace.prototype.except = function (id) {
123   this.flags.exceptions.push(id);
124   return this;
125 };
126
127 /**
128  * Sets the default flags.
129  *
130  * @api private
131  */
132
133 SocketNamespace.prototype.setFlags = function () {
134   this.flags = {
135       endpoint: this.name
136     , exceptions: []
137   };
138   return this;
139 };
140
141 /**
142  * Sends out a packet.
143  *
144  * @api private
145  */
146
147 SocketNamespace.prototype.packet = function (packet) {
148   packet.endpoint = this.name;
149
150   var store = this.store
151     , log = this.log
152     , volatile = this.flags.volatile
153     , exceptions = this.flags.exceptions
154     , packet = parser.encodePacket(packet);
155
156   this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions);
157   this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions);
158
159   this.setFlags();
160
161   return this;
162 };
163
164 /**
165  * Sends to everyone.
166  *
167  * @api public
168  */
169
170 SocketNamespace.prototype.send = function (data) {
171   return this.packet({
172       type: this.flags.json ? 'json' : 'message'
173     , data: data
174   });
175 };
176
177 /**
178  * Emits to everyone (override).
179  *
180  * @api public
181  */
182
183 SocketNamespace.prototype.emit = function (name) {
184   if (name == 'newListener') {
185     return this.$emit.apply(this, arguments);
186   }
187
188   return this.packet({
189       type: 'event'
190     , name: name
191     , args: util.toArray(arguments).slice(1)
192   });
193 };
194
195 /**
196  * Retrieves or creates a write-only socket for a client, unless specified.
197  *
198  * @param {Boolean} whether the socket will be readable when initialized
199  * @api public
200  */
201
202 SocketNamespace.prototype.socket = function (sid, readable) {
203   if (!this.sockets[sid]) {
204     this.sockets[sid] = new Socket(this.manager, sid, this, readable);
205   }
206
207   return this.sockets[sid];
208 };
209
210 /**
211  * Sets authorization for this namespace.
212  *
213  * @api public
214  */
215
216 SocketNamespace.prototype.authorization = function (fn) {
217   this.auth = fn;
218   return this;
219 };
220
221 /**
222  * Called when a socket disconnects entirely.
223  *
224  * @api private
225  */
226
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];
231   }
232 };
233
234 /**
235  * Performs authentication.
236  *
237  * @param Object client request data
238  * @api private
239  */
240
241 SocketNamespace.prototype.authorize = function (data, fn) {
242   if (this.auth) {
243     var self = this;
244
245     this.auth.call(this, data, function (err, authorized) {
246       self.log.debug('client ' +
247         (authorized ? '' : 'un') + 'authorized for ' + self.name);
248       fn(err, authorized);
249     });
250   } else {
251     this.log.debug('client authorized for ' + this.name);
252     fn(null, true);
253   }
254
255   return this;
256 };
257
258 /**
259  * Handles a packet.
260  *
261  * @api private
262  */
263
264 SocketNamespace.prototype.handlePacket = function (sessid, packet) {
265   var socket = this.socket(sessid)
266     , dataAck = packet.ack == 'data'
267     , manager = this.manager
268     , self = this;
269
270   function ack () {
271     self.log.debug('sending data ack packet');
272     socket.packet({
273         type: 'ack'
274       , args: util.toArray(arguments)
275       , ackId: packet.id
276     });
277   };
278
279   function error (err) {
280     self.log.warn('handshake error ' + err + ' for ' + self.name);
281     socket.packet({ type: 'error', reason: err });
282   };
283
284   function connect () {
285     self.manager.onJoin(sessid, self.name);
286     self.store.publish('join', sessid, self.name);
287
288     // packet echo
289     socket.packet({ type: 'connect' });
290
291     // emit connection event
292     self.$emit('connection', socket);
293   };
294
295   switch (packet.type) {
296     case 'connect':
297       if (packet.endpoint == '') {
298         connect();
299       } else {
300         var handshakeData = manager.handshaken[sessid];
301
302         this.authorize(handshakeData, function (err, authorized, newData) {
303           if (err) return error(err);
304
305           if (authorized) {
306             manager.onHandshake(sessid, newData || handshakeData);
307             self.store.publish('handshake', sessid, newData || handshakeData);
308             connect();
309           } else {
310             error('unauthorized');
311           }
312         });
313       }
314       break;
315
316     case 'ack':
317       if (socket.acks[packet.ackId]) {
318         socket.acks[packet.ackId].apply(socket, packet.args);
319       } else {
320         this.log.info('unknown ack packet');
321       }
322       break;
323
324     case 'event':
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 + '`');
328       } else {
329         var params = [packet.name].concat(packet.args);
330
331         if (dataAck) {
332           params.push(ack);
333         }
334
335         socket.$emit.apply(socket, params);
336       }
337       break;
338
339     case 'disconnect':
340       this.manager.onLeave(sessid, this.name);
341       this.store.publish('leave', sessid, this.name);
342
343       socket.$emit('disconnect', packet.reason || 'packet');
344       break;
345
346     case 'json':
347     case 'message':
348       var params = ['message', packet.data];
349
350       if (dataAck)
351         params.push(ack);
352
353       socket.$emit.apply(socket, params);
354   };
355 };