[SignalingServer] Optimize dependent modules
[platform/framework/web/wrtjs.git] / signaling_server / service / node_modules / socket.io / lib / client.js
1
2 /**
3  * Module dependencies.
4  */
5
6 var parser = require('socket.io-parser');
7 var debug = require('debug')('socket.io:client');
8 var url = require('url');
9
10 /**
11  * Module exports.
12  */
13
14 module.exports = Client;
15
16 /**
17  * Client constructor.
18  *
19  * @param {Server} server instance
20  * @param {Socket} conn
21  * @api private
22  */
23
24 function Client(server, conn){
25   this.server = server;
26   this.conn = conn;
27   this.encoder = server.encoder;
28   this.decoder = new server.parser.Decoder();
29   this.id = conn.id;
30   this.request = conn.request;
31   this.setup();
32   this.sockets = {};
33   this.nsps = {};
34   this.connectBuffer = [];
35 }
36
37 /**
38  * Sets up event listeners.
39  *
40  * @api private
41  */
42
43 Client.prototype.setup = function(){
44   this.onclose = this.onclose.bind(this);
45   this.ondata = this.ondata.bind(this);
46   this.onerror = this.onerror.bind(this);
47   this.ondecoded = this.ondecoded.bind(this);
48
49   this.decoder.on('decoded', this.ondecoded);
50   this.conn.on('data', this.ondata);
51   this.conn.on('error', this.onerror);
52   this.conn.on('close', this.onclose);
53 };
54
55 /**
56  * Connects a client to a namespace.
57  *
58  * @param {String} name namespace
59  * @param {Object} query the query parameters
60  * @api private
61  */
62
63 Client.prototype.connect = function(name, query){
64   if (this.server.nsps[name]) {
65     debug('connecting to namespace %s', name);
66     return this.doConnect(name, query);
67   }
68
69   this.server.checkNamespace(name, query, (dynamicNsp) => {
70     if (dynamicNsp) {
71       debug('dynamic namespace %s was created', dynamicNsp.name);
72       this.doConnect(name, query);
73     } else {
74       debug('creation of namespace %s was denied', name);
75       this.packet({ type: parser.ERROR, nsp: name, data: 'Invalid namespace' });
76     }
77   });
78 };
79
80 /**
81  * Connects a client to a namespace.
82  *
83  * @param {String} name namespace
84  * @param {String} query the query parameters
85  * @api private
86  */
87
88 Client.prototype.doConnect = function(name, query){
89   var nsp = this.server.of(name);
90
91   if ('/' != name && !this.nsps['/']) {
92     this.connectBuffer.push(name);
93     return;
94   }
95
96   var self = this;
97   var socket = nsp.add(this, query, function(){
98     self.sockets[socket.id] = socket;
99     self.nsps[nsp.name] = socket;
100
101     if ('/' == nsp.name && self.connectBuffer.length > 0) {
102       self.connectBuffer.forEach(self.connect, self);
103       self.connectBuffer = [];
104     }
105   });
106 };
107
108 /**
109  * Disconnects from all namespaces and closes transport.
110  *
111  * @api private
112  */
113
114 Client.prototype.disconnect = function(){
115   for (var id in this.sockets) {
116     if (this.sockets.hasOwnProperty(id)) {
117       this.sockets[id].disconnect();
118     }
119   }
120   this.sockets = {};
121   this.close();
122 };
123
124 /**
125  * Removes a socket. Called by each `Socket`.
126  *
127  * @api private
128  */
129
130 Client.prototype.remove = function(socket){
131   if (this.sockets.hasOwnProperty(socket.id)) {
132     var nsp = this.sockets[socket.id].nsp.name;
133     delete this.sockets[socket.id];
134     delete this.nsps[nsp];
135   } else {
136     debug('ignoring remove for %s', socket.id);
137   }
138 };
139
140 /**
141  * Closes the underlying connection.
142  *
143  * @api private
144  */
145
146 Client.prototype.close = function(){
147   if ('open' == this.conn.readyState) {
148     debug('forcing transport close');
149     this.conn.close();
150     this.onclose('forced server close');
151   }
152 };
153
154 /**
155  * Writes a packet to the transport.
156  *
157  * @param {Object} packet object
158  * @param {Object} opts
159  * @api private
160  */
161
162 Client.prototype.packet = function(packet, opts){
163   opts = opts || {};
164   var self = this;
165
166   // this writes to the actual connection
167   function writeToEngine(encodedPackets) {
168     if (opts.volatile && !self.conn.transport.writable) return;
169     for (var i = 0; i < encodedPackets.length; i++) {
170       self.conn.write(encodedPackets[i], { compress: opts.compress });
171     }
172   }
173
174   if ('open' == this.conn.readyState) {
175     debug('writing packet %j', packet);
176     if (!opts.preEncoded) { // not broadcasting, need to encode
177       this.encoder.encode(packet, writeToEngine); // encode, then write results to engine
178     } else { // a broadcast pre-encodes a packet
179       writeToEngine(packet);
180     }
181   } else {
182     debug('ignoring packet write %j', packet);
183   }
184 };
185
186 /**
187  * Called with incoming transport data.
188  *
189  * @api private
190  */
191
192 Client.prototype.ondata = function(data){
193   // try/catch is needed for protocol violations (GH-1880)
194   try {
195     this.decoder.add(data);
196   } catch(e) {
197     this.onerror(e);
198   }
199 };
200
201 /**
202  * Called when parser fully decodes a packet.
203  *
204  * @api private
205  */
206
207 Client.prototype.ondecoded = function(packet) {
208   if (parser.CONNECT == packet.type) {
209     this.connect(url.parse(packet.nsp).pathname, url.parse(packet.nsp, true).query);
210   } else {
211     var socket = this.nsps[packet.nsp];
212     if (socket) {
213       process.nextTick(function() {
214         socket.onpacket(packet);
215       });
216     } else {
217       debug('no socket for namespace %s', packet.nsp);
218     }
219   }
220 };
221
222 /**
223  * Handles an error.
224  *
225  * @param {Object} err object
226  * @api private
227  */
228
229 Client.prototype.onerror = function(err){
230   for (var id in this.sockets) {
231     if (this.sockets.hasOwnProperty(id)) {
232       this.sockets[id].onerror(err);
233     }
234   }
235   this.conn.close();
236 };
237
238 /**
239  * Called upon transport close.
240  *
241  * @param {String} reason
242  * @api private
243  */
244
245 Client.prototype.onclose = function(reason){
246   debug('client close with reason %s', reason);
247
248   // ignore a potential subsequent `close` event
249   this.destroy();
250
251   // `nsps` and `sockets` are cleaned up seamlessly
252   for (var id in this.sockets) {
253     if (this.sockets.hasOwnProperty(id)) {
254       this.sockets[id].onclose(reason);
255     }
256   }
257   this.sockets = {};
258
259   this.decoder.destroy(); // clean up decoder
260 };
261
262 /**
263  * Cleans up event listeners.
264  *
265  * @api private
266  */
267
268 Client.prototype.destroy = function(){
269   this.conn.removeListener('data', this.ondata);
270   this.conn.removeListener('error', this.onerror);
271   this.conn.removeListener('close', this.onclose);
272   this.decoder.removeListener('decoded', this.ondecoded);
273 };