Skip to content

Commit 869c989

Browse files
committedAug 28, 2021
[fix] Resume the socket in the next tick
Ensure that `socket.resume()` is called after `socket.pause()`. Fixes #1940
1 parent ea6c054 commit 869c989

File tree

2 files changed

+75
-3
lines changed

2 files changed

+75
-3
lines changed
 

‎lib/websocket.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Readable$" }] */
2+
13
'use strict';
24

35
const EventEmitter = require('events');
@@ -6,6 +8,7 @@ const http = require('http');
68
const net = require('net');
79
const tls = require('tls');
810
const { randomBytes, createHash } = require('crypto');
11+
const { Readable } = require('stream');
912
const { URL } = require('url');
1013

1114
const PerMessageDeflate = require('./permessage-deflate');
@@ -954,7 +957,7 @@ function receiverOnConclude(code, reason) {
954957
const websocket = this[kWebSocket];
955958

956959
websocket._socket.removeListener('data', socketOnData);
957-
websocket._socket.resume();
960+
process.nextTick(resume, websocket._socket);
958961

959962
websocket._closeFrameReceived = true;
960963
websocket._closeMessage = reason;
@@ -983,7 +986,12 @@ function receiverOnError(err) {
983986
const websocket = this[kWebSocket];
984987

985988
websocket._socket.removeListener('data', socketOnData);
986-
websocket._socket.resume();
989+
990+
//
991+
// On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See
992+
// https://github.com/websockets/ws/issues/1940.
993+
//
994+
process.nextTick(resume, websocket._socket);
987995

988996
websocket.close(err[kStatusCode]);
989997
websocket.emit('error', err);
@@ -1032,6 +1040,16 @@ function receiverOnPong(data) {
10321040
this[kWebSocket].emit('pong', data);
10331041
}
10341042

1043+
/**
1044+
* Resume a readable stream
1045+
*
1046+
* @param {Readable} stream The readable stream
1047+
* @private
1048+
*/
1049+
function resume(stream) {
1050+
stream.resume();
1051+
}
1052+
10351053
/**
10361054
* The listener of the `net.Socket` `'close'` event.
10371055
*

‎test/websocket.test.js

+55-1
Original file line numberDiff line numberDiff line change
@@ -3308,7 +3308,7 @@ describe('WebSocket', () => {
33083308
});
33093309
});
33103310

3311-
describe('Connection close edge cases', () => {
3311+
describe('Connection close', () => {
33123312
it('closes cleanly after simultaneous errors (1/2)', (done) => {
33133313
let clientCloseEventEmitted = false;
33143314
let serverClientCloseEventEmitted = false;
@@ -3420,5 +3420,59 @@ describe('WebSocket', () => {
34203420
});
34213421
});
34223422
});
3423+
3424+
it('resumes the socket when an error occurs', (done) => {
3425+
const maxPayload = 16 * 1024;
3426+
const wss = new WebSocket.Server({ maxPayload, port: 0 }, () => {
3427+
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
3428+
});
3429+
3430+
wss.on('connection', (ws) => {
3431+
const list = [
3432+
...Sender.frame(Buffer.alloc(maxPayload + 1), {
3433+
fin: true,
3434+
opcode: 0x02,
3435+
mask: true,
3436+
readOnly: false
3437+
})
3438+
];
3439+
3440+
ws.on('error', (err) => {
3441+
assert.ok(err instanceof RangeError);
3442+
assert.strictEqual(err.code, 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH');
3443+
assert.strictEqual(err.message, 'Max payload size exceeded');
3444+
3445+
ws.on('close', (code, reason) => {
3446+
assert.strictEqual(code, 1006);
3447+
assert.strictEqual(reason, EMPTY_BUFFER);
3448+
wss.close(done);
3449+
});
3450+
});
3451+
3452+
ws._socket.push(Buffer.concat(list));
3453+
});
3454+
});
3455+
3456+
it('resumes the socket when the close frame is received', (done) => {
3457+
const wss = new WebSocket.Server({ port: 0 }, () => {
3458+
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
3459+
});
3460+
3461+
wss.on('connection', (ws) => {
3462+
const opts = { fin: true, mask: true, readOnly: false };
3463+
const list = [
3464+
...Sender.frame(Buffer.alloc(16 * 1024), { opcode: 0x02, ...opts }),
3465+
...Sender.frame(EMPTY_BUFFER, { opcode: 0x08, ...opts })
3466+
];
3467+
3468+
ws.on('close', (code, reason) => {
3469+
assert.strictEqual(code, 1005);
3470+
assert.strictEqual(reason, EMPTY_BUFFER);
3471+
wss.close(done);
3472+
});
3473+
3474+
ws._socket.push(Buffer.concat(list));
3475+
});
3476+
});
34233477
});
34243478
});

0 commit comments

Comments
 (0)
Please sign in to comment.