rc-web@69
|
1
|
rc-web@69
|
2 /*!
|
rc-web@69
|
3 * socket.io-node
|
rc-web@69
|
4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
rc-web@69
|
5 * MIT Licensed
|
rc-web@69
|
6 */
|
rc-web@69
|
7
|
rc-web@69
|
8 /**
|
rc-web@69
|
9 * Module dependencies.
|
rc-web@69
|
10 */
|
rc-web@69
|
11
|
rc-web@69
|
12 var parser = require('./parser');
|
rc-web@69
|
13
|
rc-web@69
|
14 /**
|
rc-web@69
|
15 * Expose the constructor.
|
rc-web@69
|
16 */
|
rc-web@69
|
17
|
rc-web@69
|
18 exports = module.exports = Transport;
|
rc-web@69
|
19
|
rc-web@69
|
20 /**
|
rc-web@69
|
21 * Transport constructor.
|
rc-web@69
|
22 *
|
rc-web@69
|
23 * @api public
|
rc-web@69
|
24 */
|
rc-web@69
|
25
|
rc-web@69
|
26 function Transport (mng, data, req) {
|
rc-web@69
|
27 this.manager = mng;
|
rc-web@69
|
28 this.id = data.id;
|
rc-web@69
|
29 this.disconnected = false;
|
rc-web@69
|
30 this.drained = true;
|
rc-web@69
|
31 this.handleRequest(req);
|
rc-web@69
|
32 };
|
rc-web@69
|
33
|
rc-web@69
|
34 /**
|
rc-web@69
|
35 * Access the logger.
|
rc-web@69
|
36 *
|
rc-web@69
|
37 * @api public
|
rc-web@69
|
38 */
|
rc-web@69
|
39
|
rc-web@69
|
40 Transport.prototype.__defineGetter__('log', function () {
|
rc-web@69
|
41 return this.manager.log;
|
rc-web@69
|
42 });
|
rc-web@69
|
43
|
rc-web@69
|
44 /**
|
rc-web@69
|
45 * Access the store.
|
rc-web@69
|
46 *
|
rc-web@69
|
47 * @api public
|
rc-web@69
|
48 */
|
rc-web@69
|
49
|
rc-web@69
|
50 Transport.prototype.__defineGetter__('store', function () {
|
rc-web@69
|
51 return this.manager.store;
|
rc-web@69
|
52 });
|
rc-web@69
|
53
|
rc-web@69
|
54 /**
|
rc-web@69
|
55 * Handles a request when it's set.
|
rc-web@69
|
56 *
|
rc-web@69
|
57 * @api private
|
rc-web@69
|
58 */
|
rc-web@69
|
59
|
rc-web@69
|
60 Transport.prototype.handleRequest = function (req) {
|
rc-web@69
|
61 this.log.debug('setting request', req.method, req.url);
|
rc-web@69
|
62 this.req = req;
|
rc-web@69
|
63
|
rc-web@69
|
64 if (req.method == 'GET') {
|
rc-web@69
|
65 this.socket = req.socket;
|
rc-web@69
|
66 this.open = true;
|
rc-web@69
|
67 this.drained = true;
|
rc-web@69
|
68 this.setHeartbeatInterval();
|
rc-web@69
|
69
|
rc-web@69
|
70 this.setHandlers();
|
rc-web@69
|
71 this.onSocketConnect();
|
rc-web@69
|
72 }
|
rc-web@69
|
73 };
|
rc-web@69
|
74
|
rc-web@69
|
75 /**
|
rc-web@69
|
76 * Called when a connection is first set.
|
rc-web@69
|
77 *
|
rc-web@69
|
78 * @api private
|
rc-web@69
|
79 */
|
rc-web@69
|
80
|
rc-web@69
|
81 Transport.prototype.onSocketConnect = function () { };
|
rc-web@69
|
82
|
rc-web@69
|
83 /**
|
rc-web@69
|
84 * Sets transport handlers
|
rc-web@69
|
85 *
|
rc-web@69
|
86 * @api private
|
rc-web@69
|
87 */
|
rc-web@69
|
88
|
rc-web@69
|
89 Transport.prototype.setHandlers = function () {
|
rc-web@69
|
90 var self = this;
|
rc-web@69
|
91
|
rc-web@69
|
92 // we need to do this in a pub/sub way since the client can POST the message
|
rc-web@69
|
93 // over a different socket (ie: different Transport instance)
|
rc-web@69
|
94 this.store.subscribe('heartbeat-clear:' + this.id, function () {
|
rc-web@69
|
95 self.onHeartbeatClear();
|
rc-web@69
|
96 });
|
rc-web@69
|
97
|
rc-web@69
|
98 this.store.subscribe('disconnect-force:' + this.id, function () {
|
rc-web@69
|
99 self.onForcedDisconnect();
|
rc-web@69
|
100 });
|
rc-web@69
|
101
|
rc-web@69
|
102 this.store.subscribe('dispatch:' + this.id, function (packet, volatile) {
|
rc-web@69
|
103 self.onDispatch(packet, volatile);
|
rc-web@69
|
104 });
|
rc-web@69
|
105
|
rc-web@69
|
106 this.bound = {
|
rc-web@69
|
107 end: this.onSocketEnd.bind(this)
|
rc-web@69
|
108 , close: this.onSocketClose.bind(this)
|
rc-web@69
|
109 , error: this.onSocketError.bind(this)
|
rc-web@69
|
110 , drain: this.onSocketDrain.bind(this)
|
rc-web@69
|
111 };
|
rc-web@69
|
112
|
rc-web@69
|
113 this.socket.on('end', this.bound.end);
|
rc-web@69
|
114 this.socket.on('close', this.bound.close);
|
rc-web@69
|
115 this.socket.on('error', this.bound.error);
|
rc-web@69
|
116 this.socket.on('drain', this.bound.drain);
|
rc-web@69
|
117
|
rc-web@69
|
118 this.handlersSet = true;
|
rc-web@69
|
119 };
|
rc-web@69
|
120
|
rc-web@69
|
121 /**
|
rc-web@69
|
122 * Removes transport handlers
|
rc-web@69
|
123 *
|
rc-web@69
|
124 * @api private
|
rc-web@69
|
125 */
|
rc-web@69
|
126
|
rc-web@69
|
127 Transport.prototype.clearHandlers = function () {
|
rc-web@69
|
128 if (this.handlersSet) {
|
rc-web@69
|
129 this.store.unsubscribe('disconnect-force:' + this.id);
|
rc-web@69
|
130 this.store.unsubscribe('heartbeat-clear:' + this.id);
|
rc-web@69
|
131 this.store.unsubscribe('dispatch:' + this.id);
|
rc-web@69
|
132
|
rc-web@69
|
133 this.socket.removeListener('end', this.bound.end);
|
rc-web@69
|
134 this.socket.removeListener('close', this.bound.close);
|
rc-web@69
|
135 this.socket.removeListener('error', this.bound.error);
|
rc-web@69
|
136 this.socket.removeListener('drain', this.bound.drain);
|
rc-web@69
|
137 }
|
rc-web@69
|
138 };
|
rc-web@69
|
139
|
rc-web@69
|
140 /**
|
rc-web@69
|
141 * Called when the connection dies
|
rc-web@69
|
142 *
|
rc-web@69
|
143 * @api private
|
rc-web@69
|
144 */
|
rc-web@69
|
145
|
rc-web@69
|
146 Transport.prototype.onSocketEnd = function () {
|
rc-web@69
|
147 this.end('socket end');
|
rc-web@69
|
148 };
|
rc-web@69
|
149
|
rc-web@69
|
150 /**
|
rc-web@69
|
151 * Called when the connection dies
|
rc-web@69
|
152 *
|
rc-web@69
|
153 * @api private
|
rc-web@69
|
154 */
|
rc-web@69
|
155
|
rc-web@69
|
156 Transport.prototype.onSocketClose = function (error) {
|
rc-web@69
|
157 this.end(error ? 'socket error' : 'socket close');
|
rc-web@69
|
158 };
|
rc-web@69
|
159
|
rc-web@69
|
160 /**
|
rc-web@69
|
161 * Called when the connection has an error.
|
rc-web@69
|
162 *
|
rc-web@69
|
163 * @api private
|
rc-web@69
|
164 */
|
rc-web@69
|
165
|
rc-web@69
|
166 Transport.prototype.onSocketError = function (err) {
|
rc-web@69
|
167 if (this.open) {
|
rc-web@69
|
168 this.socket.destroy();
|
rc-web@69
|
169 this.onClose();
|
rc-web@69
|
170 }
|
rc-web@69
|
171
|
rc-web@69
|
172 this.log.info('socket error ' + err.stack);
|
rc-web@69
|
173 };
|
rc-web@69
|
174
|
rc-web@69
|
175 /**
|
rc-web@69
|
176 * Called when the connection is drained.
|
rc-web@69
|
177 *
|
rc-web@69
|
178 * @api private
|
rc-web@69
|
179 */
|
rc-web@69
|
180
|
rc-web@69
|
181 Transport.prototype.onSocketDrain = function () {
|
rc-web@69
|
182 this.drained = true;
|
rc-web@69
|
183 };
|
rc-web@69
|
184
|
rc-web@69
|
185 /**
|
rc-web@69
|
186 * Called upon receiving a heartbeat packet.
|
rc-web@69
|
187 *
|
rc-web@69
|
188 * @api private
|
rc-web@69
|
189 */
|
rc-web@69
|
190
|
rc-web@69
|
191 Transport.prototype.onHeartbeatClear = function () {
|
rc-web@69
|
192 this.clearHeartbeatTimeout();
|
rc-web@69
|
193 this.setHeartbeatInterval();
|
rc-web@69
|
194 };
|
rc-web@69
|
195
|
rc-web@69
|
196 /**
|
rc-web@69
|
197 * Called upon a forced disconnection.
|
rc-web@69
|
198 *
|
rc-web@69
|
199 * @api private
|
rc-web@69
|
200 */
|
rc-web@69
|
201
|
rc-web@69
|
202 Transport.prototype.onForcedDisconnect = function () {
|
rc-web@69
|
203 if (!this.disconnected) {
|
rc-web@69
|
204 this.log.info('transport end by forced client disconnection');
|
rc-web@69
|
205 if (this.open) {
|
rc-web@69
|
206 this.packet({ type: 'disconnect' });
|
rc-web@69
|
207 }
|
rc-web@69
|
208 this.end('booted');
|
rc-web@69
|
209 }
|
rc-web@69
|
210 };
|
rc-web@69
|
211
|
rc-web@69
|
212 /**
|
rc-web@69
|
213 * Dispatches a packet.
|
rc-web@69
|
214 *
|
rc-web@69
|
215 * @api private
|
rc-web@69
|
216 */
|
rc-web@69
|
217
|
rc-web@69
|
218 Transport.prototype.onDispatch = function (packet, volatile) {
|
rc-web@69
|
219 if (volatile) {
|
rc-web@69
|
220 this.writeVolatile(packet);
|
rc-web@69
|
221 } else {
|
rc-web@69
|
222 this.write(packet);
|
rc-web@69
|
223 }
|
rc-web@69
|
224 };
|
rc-web@69
|
225
|
rc-web@69
|
226 /**
|
rc-web@69
|
227 * Sets the close timeout.
|
rc-web@69
|
228 */
|
rc-web@69
|
229
|
rc-web@69
|
230 Transport.prototype.setCloseTimeout = function () {
|
rc-web@69
|
231 if (!this.closeTimeout) {
|
rc-web@69
|
232 var self = this;
|
rc-web@69
|
233
|
rc-web@69
|
234 this.closeTimeout = setTimeout(function () {
|
rc-web@69
|
235 self.log.debug('fired close timeout for client', self.id);
|
rc-web@69
|
236 self.closeTimeout = null;
|
rc-web@69
|
237 self.end('close timeout');
|
rc-web@69
|
238 }, this.manager.get('close timeout') * 1000);
|
rc-web@69
|
239
|
rc-web@69
|
240 this.log.debug('set close timeout for client', this.id);
|
rc-web@69
|
241 }
|
rc-web@69
|
242 };
|
rc-web@69
|
243
|
rc-web@69
|
244 /**
|
rc-web@69
|
245 * Clears the close timeout.
|
rc-web@69
|
246 */
|
rc-web@69
|
247
|
rc-web@69
|
248 Transport.prototype.clearCloseTimeout = function () {
|
rc-web@69
|
249 if (this.closeTimeout) {
|
rc-web@69
|
250 clearTimeout(this.closeTimeout);
|
rc-web@69
|
251 this.closeTimeout = null;
|
rc-web@69
|
252
|
rc-web@69
|
253 this.log.debug('cleared close timeout for client', this.id);
|
rc-web@69
|
254 }
|
rc-web@69
|
255 };
|
rc-web@69
|
256
|
rc-web@69
|
257 /**
|
rc-web@69
|
258 * Sets the heartbeat timeout
|
rc-web@69
|
259 */
|
rc-web@69
|
260
|
rc-web@69
|
261 Transport.prototype.setHeartbeatTimeout = function () {
|
rc-web@69
|
262 if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
rc-web@69
|
263 var self = this;
|
rc-web@69
|
264
|
rc-web@69
|
265 this.heartbeatTimeout = setTimeout(function () {
|
rc-web@69
|
266 self.log.debug('fired heartbeat timeout for client', self.id);
|
rc-web@69
|
267 self.heartbeatTimeout = null;
|
rc-web@69
|
268 self.end('heartbeat timeout');
|
rc-web@69
|
269 }, this.manager.get('heartbeat timeout') * 1000);
|
rc-web@69
|
270
|
rc-web@69
|
271 this.log.debug('set heartbeat timeout for client', this.id);
|
rc-web@69
|
272 }
|
rc-web@69
|
273 };
|
rc-web@69
|
274
|
rc-web@69
|
275 /**
|
rc-web@69
|
276 * Clears the heartbeat timeout
|
rc-web@69
|
277 *
|
rc-web@69
|
278 * @param text
|
rc-web@69
|
279 */
|
rc-web@69
|
280
|
rc-web@69
|
281 Transport.prototype.clearHeartbeatTimeout = function () {
|
rc-web@69
|
282 if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) {
|
rc-web@69
|
283 clearTimeout(this.heartbeatTimeout);
|
rc-web@69
|
284 this.heartbeatTimeout = null;
|
rc-web@69
|
285 this.log.debug('cleared heartbeat timeout for client', this.id);
|
rc-web@69
|
286 }
|
rc-web@69
|
287 };
|
rc-web@69
|
288
|
rc-web@69
|
289 /**
|
rc-web@69
|
290 * Sets the heartbeat interval. To be called when a connection opens and when
|
rc-web@69
|
291 * a heartbeat is received.
|
rc-web@69
|
292 *
|
rc-web@69
|
293 * @api private
|
rc-web@69
|
294 */
|
rc-web@69
|
295
|
rc-web@69
|
296 Transport.prototype.setHeartbeatInterval = function () {
|
rc-web@69
|
297 if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
rc-web@69
|
298 var self = this;
|
rc-web@69
|
299
|
rc-web@69
|
300 this.heartbeatInterval = setTimeout(function () {
|
rc-web@69
|
301 self.heartbeat();
|
rc-web@69
|
302 self.heartbeatInterval = null;
|
rc-web@69
|
303 }, this.manager.get('heartbeat interval') * 1000);
|
rc-web@69
|
304
|
rc-web@69
|
305 this.log.debug('set heartbeat interval for client', this.id);
|
rc-web@69
|
306 }
|
rc-web@69
|
307 };
|
rc-web@69
|
308
|
rc-web@69
|
309 /**
|
rc-web@69
|
310 * Clears all timeouts.
|
rc-web@69
|
311 *
|
rc-web@69
|
312 * @api private
|
rc-web@69
|
313 */
|
rc-web@69
|
314
|
rc-web@69
|
315 Transport.prototype.clearTimeouts = function () {
|
rc-web@69
|
316 this.clearCloseTimeout();
|
rc-web@69
|
317 this.clearHeartbeatTimeout();
|
rc-web@69
|
318 this.clearHeartbeatInterval();
|
rc-web@69
|
319 };
|
rc-web@69
|
320
|
rc-web@69
|
321 /**
|
rc-web@69
|
322 * Sends a heartbeat
|
rc-web@69
|
323 *
|
rc-web@69
|
324 * @api private
|
rc-web@69
|
325 */
|
rc-web@69
|
326
|
rc-web@69
|
327 Transport.prototype.heartbeat = function () {
|
rc-web@69
|
328 if (this.open) {
|
rc-web@69
|
329 this.log.debug('emitting heartbeat for client', this.id);
|
rc-web@69
|
330 this.packet({ type: 'heartbeat' });
|
rc-web@69
|
331 this.setHeartbeatTimeout();
|
rc-web@69
|
332 }
|
rc-web@69
|
333
|
rc-web@69
|
334 return this;
|
rc-web@69
|
335 };
|
rc-web@69
|
336
|
rc-web@69
|
337 /**
|
rc-web@69
|
338 * Handles a message.
|
rc-web@69
|
339 *
|
rc-web@69
|
340 * @param {Object} packet object
|
rc-web@69
|
341 * @api private
|
rc-web@69
|
342 */
|
rc-web@69
|
343
|
rc-web@69
|
344 Transport.prototype.onMessage = function (packet) {
|
rc-web@69
|
345 var current = this.manager.transports[this.id];
|
rc-web@69
|
346
|
rc-web@69
|
347 if ('heartbeat' == packet.type) {
|
rc-web@69
|
348 this.log.debug('got heartbeat packet');
|
rc-web@69
|
349
|
rc-web@69
|
350 if (current && current.open) {
|
rc-web@69
|
351 current.onHeartbeatClear();
|
rc-web@69
|
352 } else {
|
rc-web@69
|
353 this.store.publish('heartbeat-clear:' + this.id);
|
rc-web@69
|
354 }
|
rc-web@69
|
355 } else {
|
rc-web@69
|
356 if ('disconnect' == packet.type && packet.endpoint == '') {
|
rc-web@69
|
357 this.log.debug('got disconnection packet');
|
rc-web@69
|
358
|
rc-web@69
|
359 if (current) {
|
rc-web@69
|
360 current.onForcedDisconnect();
|
rc-web@69
|
361 } else {
|
rc-web@69
|
362 this.store.publish('disconnect-force:' + this.id);
|
rc-web@69
|
363 }
|
rc-web@69
|
364
|
rc-web@69
|
365 return;
|
rc-web@69
|
366 }
|
rc-web@69
|
367
|
rc-web@69
|
368 if (packet.id && packet.ack != 'data') {
|
rc-web@69
|
369 this.log.debug('acknowledging packet automatically');
|
rc-web@69
|
370
|
rc-web@69
|
371 var ack = parser.encodePacket({
|
rc-web@69
|
372 type: 'ack'
|
rc-web@69
|
373 , ackId: packet.id
|
rc-web@69
|
374 , endpoint: packet.endpoint || ''
|
rc-web@69
|
375 });
|
rc-web@69
|
376
|
rc-web@69
|
377 if (current && current.open) {
|
rc-web@69
|
378 current.onDispatch(ack);
|
rc-web@69
|
379 } else {
|
rc-web@69
|
380 this.manager.onClientDispatch(this.id, ack);
|
rc-web@69
|
381 this.store.publish('dispatch:' + this.id, ack);
|
rc-web@69
|
382 }
|
rc-web@69
|
383 }
|
rc-web@69
|
384
|
rc-web@69
|
385 // handle packet locally or publish it
|
rc-web@69
|
386 if (current) {
|
rc-web@69
|
387 this.manager.onClientMessage(this.id, packet);
|
rc-web@69
|
388 } else {
|
rc-web@69
|
389 this.store.publish('message:' + this.id, packet);
|
rc-web@69
|
390 }
|
rc-web@69
|
391 }
|
rc-web@69
|
392 };
|
rc-web@69
|
393
|
rc-web@69
|
394 /**
|
rc-web@69
|
395 * Clears the heartbeat interval
|
rc-web@69
|
396 *
|
rc-web@69
|
397 * @api private
|
rc-web@69
|
398 */
|
rc-web@69
|
399
|
rc-web@69
|
400 Transport.prototype.clearHeartbeatInterval = function () {
|
rc-web@69
|
401 if (this.heartbeatInterval && this.manager.enabled('heartbeats')) {
|
rc-web@69
|
402 clearTimeout(this.heartbeatInterval);
|
rc-web@69
|
403 this.heartbeatInterval = null;
|
rc-web@69
|
404 this.log.debug('cleared heartbeat interval for client', this.id);
|
rc-web@69
|
405 }
|
rc-web@69
|
406 };
|
rc-web@69
|
407
|
rc-web@69
|
408 /**
|
rc-web@69
|
409 * Finishes the connection and makes sure client doesn't reopen
|
rc-web@69
|
410 *
|
rc-web@69
|
411 * @api private
|
rc-web@69
|
412 */
|
rc-web@69
|
413
|
rc-web@69
|
414 Transport.prototype.disconnect = function (reason) {
|
rc-web@69
|
415 this.packet({ type: 'disconnect' });
|
rc-web@69
|
416 this.end(reason);
|
rc-web@69
|
417
|
rc-web@69
|
418 return this;
|
rc-web@69
|
419 };
|
rc-web@69
|
420
|
rc-web@69
|
421 /**
|
rc-web@69
|
422 * Closes the connection.
|
rc-web@69
|
423 *
|
rc-web@69
|
424 * @api private
|
rc-web@69
|
425 */
|
rc-web@69
|
426
|
rc-web@69
|
427 Transport.prototype.close = function () {
|
rc-web@69
|
428 if (this.open) {
|
rc-web@69
|
429 this.doClose();
|
rc-web@69
|
430 this.onClose();
|
rc-web@69
|
431 }
|
rc-web@69
|
432 };
|
rc-web@69
|
433
|
rc-web@69
|
434 /**
|
rc-web@69
|
435 * Called upon a connection close.
|
rc-web@69
|
436 *
|
rc-web@69
|
437 * @api private
|
rc-web@69
|
438 */
|
rc-web@69
|
439
|
rc-web@69
|
440 Transport.prototype.onClose = function () {
|
rc-web@69
|
441 if (this.open) {
|
rc-web@69
|
442 this.setCloseTimeout();
|
rc-web@69
|
443 this.clearHandlers();
|
rc-web@69
|
444 this.open = false;
|
rc-web@69
|
445 this.manager.onClose(this.id);
|
rc-web@69
|
446 this.store.publish('close', this.id);
|
rc-web@69
|
447 }
|
rc-web@69
|
448 };
|
rc-web@69
|
449
|
rc-web@69
|
450 /**
|
rc-web@69
|
451 * Cleans up the connection, considers the client disconnected.
|
rc-web@69
|
452 *
|
rc-web@69
|
453 * @api private
|
rc-web@69
|
454 */
|
rc-web@69
|
455
|
rc-web@69
|
456 Transport.prototype.end = function (reason) {
|
rc-web@69
|
457 if (!this.disconnected) {
|
rc-web@69
|
458 this.log.info('transport end (' + reason + ')');
|
rc-web@69
|
459
|
rc-web@69
|
460 var local = this.manager.transports[this.id];
|
rc-web@69
|
461
|
rc-web@69
|
462 this.close();
|
rc-web@69
|
463 this.clearTimeouts();
|
rc-web@69
|
464 this.disconnected = true;
|
rc-web@69
|
465
|
rc-web@69
|
466 if (local) {
|
rc-web@69
|
467 this.manager.onClientDisconnect(this.id, reason, true);
|
rc-web@69
|
468 } else {
|
rc-web@69
|
469 this.store.publish('disconnect:' + this.id, reason);
|
rc-web@69
|
470 }
|
rc-web@69
|
471 }
|
rc-web@69
|
472 };
|
rc-web@69
|
473
|
rc-web@69
|
474 /**
|
rc-web@69
|
475 * Signals that the transport should pause and buffer data.
|
rc-web@69
|
476 *
|
rc-web@69
|
477 * @api public
|
rc-web@69
|
478 */
|
rc-web@69
|
479
|
rc-web@69
|
480 Transport.prototype.discard = function () {
|
rc-web@69
|
481 this.log.debug('discarding transport');
|
rc-web@69
|
482 this.discarded = true;
|
rc-web@69
|
483 this.clearTimeouts();
|
rc-web@69
|
484 this.clearHandlers();
|
rc-web@69
|
485
|
rc-web@69
|
486 return this;
|
rc-web@69
|
487 };
|
rc-web@69
|
488
|
rc-web@69
|
489 /**
|
rc-web@69
|
490 * Writes an error packet with the specified reason and advice.
|
rc-web@69
|
491 *
|
rc-web@69
|
492 * @param {Number} advice
|
rc-web@69
|
493 * @param {Number} reason
|
rc-web@69
|
494 * @api public
|
rc-web@69
|
495 */
|
rc-web@69
|
496
|
rc-web@69
|
497 Transport.prototype.error = function (reason, advice) {
|
rc-web@69
|
498 this.packet({
|
rc-web@69
|
499 type: 'error'
|
rc-web@69
|
500 , reason: reason
|
rc-web@69
|
501 , advice: advice
|
rc-web@69
|
502 });
|
rc-web@69
|
503
|
rc-web@69
|
504 this.log.warn(reason, advice ? ('client should ' + advice) : '');
|
rc-web@69
|
505 this.end('error');
|
rc-web@69
|
506 };
|
rc-web@69
|
507
|
rc-web@69
|
508 /**
|
rc-web@69
|
509 * Write a packet.
|
rc-web@69
|
510 *
|
rc-web@69
|
511 * @api public
|
rc-web@69
|
512 */
|
rc-web@69
|
513
|
rc-web@69
|
514 Transport.prototype.packet = function (obj) {
|
rc-web@69
|
515 return this.write(parser.encodePacket(obj));
|
rc-web@69
|
516 };
|
rc-web@69
|
517
|
rc-web@69
|
518 /**
|
rc-web@69
|
519 * Writes a volatile message.
|
rc-web@69
|
520 *
|
rc-web@69
|
521 * @api private
|
rc-web@69
|
522 */
|
rc-web@69
|
523
|
rc-web@69
|
524 Transport.prototype.writeVolatile = function (msg) {
|
rc-web@69
|
525 if (this.open) {
|
rc-web@69
|
526 if (this.drained) {
|
rc-web@69
|
527 this.write(msg);
|
rc-web@69
|
528 } else {
|
rc-web@69
|
529 this.log.debug('ignoring volatile packet, buffer not drained');
|
rc-web@69
|
530 }
|
rc-web@69
|
531 } else {
|
rc-web@69
|
532 this.log.debug('ignoring volatile packet, transport not open');
|
rc-web@69
|
533 }
|
rc-web@69
|
534 };
|