comparison node_modules/socket.io/lib/client.js @ 77:cd921abc8887

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