arnaucube
arnaucube/raspberryGPIOhtmlserverPublic Self-hosted repository
raspberryGPIOhtmlserver/node_modules/socket.io-client/lib/socket.js
node_modules/socket.io-client/lib/socket.jsRaw
  1
  2/**
  3 * Module dependencies.
  4 */
  5
  6var parser = require('socket.io-parser');
  7var Emitter = require('component-emitter');
  8var toArray = require('to-array');
  9var on = require('./on');
 10var bind = require('component-bind');
 11var debug = require('debug')('socket.io-client:socket');
 12var hasBin = require('has-binary');
 13
 14/**
 15 * Module exports.
 16 */
 17
 18module.exports = exports = Socket;
 19
 20/**
 21 * Internal events (blacklisted).
 22 * These events can't be emitted by the user.
 23 *
 24 * @api private
 25 */
 26
 27var events = {
 28  connect: 1,
 29  connect_error: 1,
 30  connect_timeout: 1,
 31  disconnect: 1,
 32  error: 1,
 33  reconnect: 1,
 34  reconnect_attempt: 1,
 35  reconnect_failed: 1,
 36  reconnect_error: 1,
 37  reconnecting: 1
 38};
 39
 40/**
 41 * Shortcut to `Emitter#emit`.
 42 */
 43
 44var emit = Emitter.prototype.emit;
 45
 46/**
 47 * `Socket` constructor.
 48 *
 49 * @api public
 50 */
 51
 52function Socket(io, nsp){
 53  this.io = io;
 54  this.nsp = nsp;
 55  this.json = this; // compat
 56  this.ids = 0;
 57  this.acks = {};
 58  if (this.io.autoConnect) this.open();
 59  this.receiveBuffer = [];
 60  this.sendBuffer = [];
 61  this.connected = false;
 62  this.disconnected = true;
 63}
 64
 65/**
 66 * Mix in `Emitter`.
 67 */
 68
 69Emitter(Socket.prototype);
 70
 71/**
 72 * Subscribe to open, close and packet events
 73 *
 74 * @api private
 75 */
 76
 77Socket.prototype.subEvents = function() {
 78  if (this.subs) return;
 79
 80  var io = this.io;
 81  this.subs = [
 82    on(io, 'open', bind(this, 'onopen')),
 83    on(io, 'packet', bind(this, 'onpacket')),
 84    on(io, 'close', bind(this, 'onclose'))
 85  ];
 86};
 87
 88/**
 89 * "Opens" the socket.
 90 *
 91 * @api public
 92 */
 93
 94Socket.prototype.open =
 95Socket.prototype.connect = function(){
 96  if (this.connected) return this;
 97
 98  this.subEvents();
 99  this.io.open(); // ensure open
100  if ('open' == this.io.readyState) this.onopen();
101  return this;
102};
103
104/**
105 * Sends a `message` event.
106 *
107 * @return {Socket} self
108 * @api public
109 */
110
111Socket.prototype.send = function(){
112  var args = toArray(arguments);
113  args.unshift('message');
114  this.emit.apply(this, args);
115  return this;
116};
117
118/**
119 * Override `emit`.
120 * If the event is in `events`, it's emitted normally.
121 *
122 * @param {String} event name
123 * @return {Socket} self
124 * @api public
125 */
126
127Socket.prototype.emit = function(ev){
128  if (events.hasOwnProperty(ev)) {
129    emit.apply(this, arguments);
130    return this;
131  }
132
133  var args = toArray(arguments);
134  var parserType = parser.EVENT; // default
135  if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
136  var packet = { type: parserType, data: args };
137
138  // event ack callback
139  if ('function' == typeof args[args.length - 1]) {
140    debug('emitting packet with ack id %d', this.ids);
141    this.acks[this.ids] = args.pop();
142    packet.id = this.ids++;
143  }
144
145  if (this.connected) {
146    this.packet(packet);
147  } else {
148    this.sendBuffer.push(packet);
149  }
150
151  return this;
152};
153
154/**
155 * Sends a packet.
156 *
157 * @param {Object} packet
158 * @api private
159 */
160
161Socket.prototype.packet = function(packet){
162  packet.nsp = this.nsp;
163  this.io.packet(packet);
164};
165
166/**
167 * Called upon engine `open`.
168 *
169 * @api private
170 */
171
172Socket.prototype.onopen = function(){
173  debug('transport is open - connecting');
174
175  // write connect packet if necessary
176  if ('/' != this.nsp) {
177    this.packet({ type: parser.CONNECT });
178  }
179};
180
181/**
182 * Called upon engine `close`.
183 *
184 * @param {String} reason
185 * @api private
186 */
187
188Socket.prototype.onclose = function(reason){
189  debug('close (%s)', reason);
190  this.connected = false;
191  this.disconnected = true;
192  this.emit('disconnect', reason);
193};
194
195/**
196 * Called with socket packet.
197 *
198 * @param {Object} packet
199 * @api private
200 */
201
202Socket.prototype.onpacket = function(packet){
203  if (packet.nsp != this.nsp) return;
204
205  switch (packet.type) {
206    case parser.CONNECT:
207      this.onconnect();
208      break;
209
210    case parser.EVENT:
211      this.onevent(packet);
212      break;
213
214    case parser.BINARY_EVENT:
215      this.onevent(packet);
216      break;
217
218    case parser.ACK:
219      this.onack(packet);
220      break;
221
222    case parser.BINARY_ACK:
223      this.onack(packet);
224      break;
225
226    case parser.DISCONNECT:
227      this.ondisconnect();
228      break;
229
230    case parser.ERROR:
231      this.emit('error', packet.data);
232      break;
233  }
234};
235
236/**
237 * Called upon a server event.
238 *
239 * @param {Object} packet
240 * @api private
241 */
242
243Socket.prototype.onevent = function(packet){
244  var args = packet.data || [];
245  debug('emitting event %j', args);
246
247  if (null != packet.id) {
248    debug('attaching ack callback to event');
249    args.push(this.ack(packet.id));
250  }
251
252  if (this.connected) {
253    emit.apply(this, args);
254  } else {
255    this.receiveBuffer.push(args);
256  }
257};
258
259/**
260 * Produces an ack callback to emit with an event.
261 *
262 * @api private
263 */
264
265Socket.prototype.ack = function(id){
266  var self = this;
267  var sent = false;
268  return function(){
269    // prevent double callbacks
270    if (sent) return;
271    sent = true;
272    var args = toArray(arguments);
273    debug('sending ack %j', args);
274
275    var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
276    self.packet({
277      type: type,
278      id: id,
279      data: args
280    });
281  };
282};
283
284/**
285 * Called upon a server acknowlegement.
286 *
287 * @param {Object} packet
288 * @api private
289 */
290
291Socket.prototype.onack = function(packet){
292  debug('calling ack %s with %j', packet.id, packet.data);
293  var fn = this.acks[packet.id];
294  fn.apply(this, packet.data);
295  delete this.acks[packet.id];
296};
297
298/**
299 * Called upon server connect.
300 *
301 * @api private
302 */
303
304Socket.prototype.onconnect = function(){
305  this.connected = true;
306  this.disconnected = false;
307  this.emit('connect');
308  this.emitBuffered();
309};
310
311/**
312 * Emit buffered events (received and emitted).
313 *
314 * @api private
315 */
316
317Socket.prototype.emitBuffered = function(){
318  var i;
319  for (i = 0; i < this.receiveBuffer.length; i++) {
320    emit.apply(this, this.receiveBuffer[i]);
321  }
322  this.receiveBuffer = [];
323
324  for (i = 0; i < this.sendBuffer.length; i++) {
325    this.packet(this.sendBuffer[i]);
326  }
327  this.sendBuffer = [];
328};
329
330/**
331 * Called upon server disconnect.
332 *
333 * @api private
334 */
335
336Socket.prototype.ondisconnect = function(){
337  debug('server disconnect (%s)', this.nsp);
338  this.destroy();
339  this.onclose('io server disconnect');
340};
341
342/**
343 * Called upon forced client/server side disconnections,
344 * this method ensures the manager stops tracking us and
345 * that reconnections don't get triggered for this.
346 *
347 * @api private.
348 */
349
350Socket.prototype.destroy = function(){
351  if (this.subs) {
352    // clean subscriptions to avoid reconnections
353    for (var i = 0; i < this.subs.length; i++) {
354      this.subs[i].destroy();
355    }
356    this.subs = null;
357  }
358
359  this.io.destroy(this);
360};
361
362/**
363 * Disconnects the socket manually.
364 *
365 * @return {Socket} self
366 * @api public
367 */
368
369Socket.prototype.close =
370Socket.prototype.disconnect = function(){
371  if (this.connected) {
372    debug('performing disconnect (%s)', this.nsp);
373    this.packet({ type: parser.DISCONNECT });
374  }
375
376  // remove socket from pool
377  this.destroy();
378
379  if (this.connected) {
380    // fire events
381    this.onclose('io client disconnect');
382  }
383  return this;
384};