Skip to content

Commit 5d8ab0e

Browse files
committed
[minor] Discard any data received after the close frame
Remove the `'data'` listener when the close frame is received.
1 parent b890078 commit 5d8ab0e

File tree

3 files changed

+34
-56
lines changed

3 files changed

+34
-56
lines changed

lib/receiver.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ class Receiver {
4848
this._fragments = [];
4949

5050
this._cleanupCallback = null;
51+
this._isCleaningUp = false;
5152
this._hadError = false;
52-
this._dead = false;
5353
this._loop = false;
5454

55+
this.add = this.add.bind(this);
5556
this.onmessage = null;
5657
this.onclose = null;
5758
this.onerror = null;
@@ -72,7 +73,7 @@ class Receiver {
7273
consume (n) {
7374
if (this._bufferedBytes < n) {
7475
this._loop = false;
75-
if (this._dead) this.cleanup(this._cleanupCallback);
76+
if (this._isCleaningUp) this.cleanup(this._cleanupCallback);
7677
return null;
7778
}
7879

@@ -107,14 +108,12 @@ class Receiver {
107108
/**
108109
* Adds new data to the parser.
109110
*
110-
* @param {Buffer} data A chunk of data
111+
* @param {Buffer} chunk A chunk of data
111112
* @public
112113
*/
113-
add (data) {
114-
if (this._dead) return;
115-
116-
this._bufferedBytes += data.length;
117-
this._buffers.push(data);
114+
add (chunk) {
115+
this._bufferedBytes += chunk.length;
116+
this._buffers.push(chunk);
118117
this.startLoop();
119118
}
120119

@@ -532,10 +531,9 @@ class Receiver {
532531
* @public
533532
*/
534533
cleanup (cb) {
535-
this._dead = true;
536-
537534
if (!this._hadError && (this._loop || this._state === INFLATING)) {
538535
this._cleanupCallback = cb;
536+
this._isCleaningUp = true;
539537
} else {
540538
this._extensions = null;
541539
this._fragments = null;

lib/websocket.js

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const EventEmitter = require('events');
44
const crypto = require('crypto');
5-
const Ultron = require('ultron');
65
const https = require('https');
76
const http = require('http');
87
const url = require('url');
@@ -50,7 +49,6 @@ class WebSocket extends EventEmitter {
5049
this._receiver = null;
5150
this._sender = null;
5251
this._socket = null;
53-
this._ultron = null;
5452

5553
if (address !== null) {
5654
if (!protocols) {
@@ -123,18 +121,17 @@ class WebSocket extends EventEmitter {
123121
socket.setTimeout(0);
124122
socket.setNoDelay();
125123

124+
socket.on('close', this._finalize);
125+
socket.on('error', this._finalize);
126+
socket.on('end', this._finalize);
127+
126128
this._receiver = new Receiver(this._extensions, maxPayload, this.binaryType);
127129
this._sender = new Sender(socket, this._extensions);
128-
this._ultron = new Ultron(socket);
129130
this._socket = socket;
130131

131-
this._ultron.on('close', this._finalize);
132-
this._ultron.on('error', this._finalize);
133-
this._ultron.on('end', this._finalize);
134-
135132
if (head.length > 0) socket.unshift(head);
136133

137-
this._ultron.on('data', (data) => this._receiver.add(data));
134+
socket.on('data', this._receiver.add);
138135

139136
this._receiver.onmessage = (data) => this.emit('message', data);
140137
this._receiver.onping = (data) => {
@@ -143,6 +140,11 @@ class WebSocket extends EventEmitter {
143140
};
144141
this._receiver.onpong = (data) => this.emit('pong', data);
145142
this._receiver.onclose = (code, reason) => {
143+
//
144+
// Discard any additional data that is received on the socket.
145+
//
146+
this._socket.removeListener('data', this._receiver.add);
147+
146148
this._closeFrameReceived = true;
147149
this._closeMessage = reason;
148150
this._closeCode = code;
@@ -182,41 +184,32 @@ class WebSocket extends EventEmitter {
182184
this._finalized = true;
183185

184186
if (typeof error === 'object') this.emit('error', error);
185-
if (!this._socket) return this.emitClose();
187+
if (!this._socket) {
188+
this.readyState = WebSocket.CLOSED;
189+
this.emit('close', this._closeCode, this._closeMessage);
190+
return;
191+
}
186192

187193
clearTimeout(this._closeTimer);
188-
this._closeTimer = null;
189-
190-
this._ultron.destroy();
191-
this._ultron = null;
192194

195+
this._socket.removeListener('data', this._receiver.add);
196+
this._socket.removeListener('close', this._finalize);
197+
this._socket.removeListener('error', this._finalize);
198+
this._socket.removeListener('end', this._finalize);
193199
this._socket.on('error', constants.NOOP);
194200

195201
if (!error) this._socket.end();
196202
else this._socket.destroy();
197203

198-
this._socket = null;
199-
this._sender = null;
204+
this._receiver.cleanup(() => {
205+
this.readyState = WebSocket.CLOSED;
200206

201-
this._receiver.cleanup(() => this.emitClose());
202-
this._receiver = null;
203-
}
204-
205-
/**
206-
* Emit the `close` event.
207-
*
208-
* @private
209-
*/
210-
emitClose () {
211-
this.readyState = WebSocket.CLOSED;
212-
213-
this.emit('close', this._closeCode, this._closeMessage);
214-
215-
if (this._extensions[PerMessageDeflate.extensionName]) {
216-
this._extensions[PerMessageDeflate.extensionName].cleanup();
217-
}
207+
if (this._extensions[PerMessageDeflate.extensionName]) {
208+
this._extensions[PerMessageDeflate.extensionName].cleanup();
209+
}
218210

219-
this.removeAllListeners();
211+
this.emit('close', this._closeCode, this._closeMessage);
212+
});
220213
}
221214

222215
/**

test/receiver.test.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -443,19 +443,6 @@ describe('Receiver', function () {
443443
assert.deepStrictEqual(data, ['', 'Hello']);
444444
});
445445

446-
it('ignores data received after a close frame', function () {
447-
const results = [];
448-
const push = results.push.bind(results);
449-
const p = new Receiver();
450-
451-
p.onclose = p.onmessage = push;
452-
453-
p.add(Buffer.from('8800', 'hex'));
454-
p.add(Buffer.from('8100', 'hex'));
455-
456-
assert.deepStrictEqual(results, [1005, '']);
457-
});
458-
459446
it('raises an error when RSV1 is on and permessage-deflate is disabled', function (done) {
460447
const p = new Receiver();
461448

0 commit comments

Comments
 (0)