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};