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