arnaucube
arnaucube/comunicationLeapPublic Self-hosted repository
comunicationLeap/node_modules/socket.io/lib/client.js
node_modules/socket.io/lib/client.jsRaw
  1
  2/**
  3 * Module dependencies.
  4 */
  5
  6var parser = require('socket.io-parser');
  7var debug = require('debug')('socket.io:client');
  8
  9/**
 10 * Module exports.
 11 */
 12
 13module.exports = Client;
 14
 15/**
 16 * Client constructor.
 17 *
 18 * @param {Server} server instance
 19 * @param {Socket} connection
 20 * @api private
 21 */
 22
 23function Client(server, conn){
 24  this.server = server;
 25  this.conn = conn;
 26  this.encoder = new parser.Encoder();
 27  this.decoder = new parser.Decoder();
 28  this.id = conn.id;
 29  this.request = conn.request;
 30  this.setup();
 31  this.sockets = [];
 32  this.nsps = {};
 33  this.connectBuffer = [];
 34}
 35
 36/**
 37 * Sets up event listeners.
 38 *
 39 * @api private
 40 */
 41
 42Client.prototype.setup = function(){
 43  this.onclose = this.onclose.bind(this);
 44  this.ondata = this.ondata.bind(this);
 45  this.ondecoded = this.ondecoded.bind(this);
 46  this.decoder.on('decoded', this.ondecoded);
 47  this.conn.on('data', this.ondata);
 48  this.conn.on('close', this.onclose);
 49};
 50
 51/**
 52 * Connects a client to a namespace.
 53 *
 54 * @param {String} namespace name
 55 * @api private
 56 */
 57
 58Client.prototype.connect = function(name){
 59  debug('connecting to namespace %s', name);
 60  if (!this.server.nsps[name]) {
 61    this.packet({ type: parser.ERROR, nsp: name, data : 'Invalid namespace'});
 62    return;
 63  }
 64  var nsp = this.server.of(name);
 65  if ('/' != name && !this.nsps['/']) {
 66    this.connectBuffer.push(name);
 67    return;
 68  }
 69
 70  var self = this;
 71  var socket = nsp.add(this, function(){
 72    self.sockets.push(socket);
 73    self.nsps[nsp.name] = socket;
 74
 75    if ('/' == nsp.name && self.connectBuffer.length > 0) {
 76      self.connectBuffer.forEach(self.connect, self);
 77      self.connectBuffer = [];
 78    }
 79  });
 80};
 81
 82/**
 83 * Disconnects from all namespaces and closes transport.
 84 *
 85 * @api private
 86 */
 87
 88Client.prototype.disconnect = function(){
 89  var socket;
 90  // we don't use a for loop because the length of
 91  // `sockets` changes upon each iteration
 92  while (socket = this.sockets.shift()) {
 93    socket.disconnect();
 94  }
 95  this.close();
 96};
 97
 98/**
 99 * Removes a socket. Called by each `Socket`.
100 *
101 * @api private
102 */
103
104Client.prototype.remove = function(socket){
105  var i = this.sockets.indexOf(socket);
106  if (~i) {
107    var nsp = this.sockets[i].nsp.name;
108    this.sockets.splice(i, 1);
109    delete this.nsps[nsp];
110  } else {
111    debug('ignoring remove for %s', socket.id);
112  }
113};
114
115/**
116 * Closes the underlying connection.
117 *
118 * @api private
119 */
120
121Client.prototype.close = function(){
122  if ('open' == this.conn.readyState) {
123    debug('forcing transport close');
124    this.conn.close();
125    this.onclose('forced server close');
126  }
127};
128
129/**
130 * Writes a packet to the transport.
131 *
132 * @param {Object} packet object
133 * @param {Boolean} whether packet is already encoded
134 * @param {Boolean} whether packet is volatile
135 * @api private
136 */
137
138Client.prototype.packet = function(packet, preEncoded, volatile){
139  var self = this;
140
141  // this writes to the actual connection
142  function writeToEngine(encodedPackets) {
143    if (volatile && !self.conn.transport.writable) return;
144    for (var i = 0; i < encodedPackets.length; i++) {
145      self.conn.write(encodedPackets[i]);
146    }
147  }
148
149  if ('open' == this.conn.readyState) {
150    debug('writing packet %j', packet);
151    if(!preEncoded) { // not broadcasting, need to encode
152      this.encoder.encode(packet, function (encodedPackets) { // encode, then write results to engine
153        writeToEngine(encodedPackets);
154      });
155    } else { // a broadcast pre-encodes a packet
156      writeToEngine(packet);
157    }
158  } else {
159    debug('ignoring packet write %j', packet);
160  }
161};
162
163/**
164 * Called with incoming transport data.
165 *
166 * @api private
167 */
168
169Client.prototype.ondata = function(data){
170  this.decoder.add(data);
171};
172
173/**
174 * Called when parser fully decodes a packet.
175 *
176 * @api private
177 */
178
179Client.prototype.ondecoded = function(packet) {
180  if (parser.CONNECT == packet.type) {
181    this.connect(packet.nsp);
182  } else {
183    var socket = this.nsps[packet.nsp];
184    if (socket) {
185      socket.onpacket(packet);
186    } else {
187      debug('no socket for namespace %s', packet.nsp);
188    }
189  }
190};
191
192/**
193 * Called upon transport close.
194 *
195 * @param {String} reason
196 * @api private
197 */
198
199Client.prototype.onclose = function(reason){
200  debug('client close with reason %s', reason);
201
202  // ignore a potential subsequent `close` event
203  this.destroy();
204
205  // `nsps` and `sockets` are cleaned up seamlessly
206  var socket;
207  while (socket = this.sockets.shift()) {
208    socket.onclose(reason);
209  }
210
211  this.decoder.destroy(); // clean up decoder
212};
213
214/**
215 * Cleans up event listeners.
216 *
217 * @api private
218 */
219
220Client.prototype.destroy = function(){
221  this.conn.removeListener('data', this.ondata);
222  this.conn.removeListener('close', this.onclose);
223  this.decoder.removeListener('decoded', this.ondecoded);
224};