Skip to content

Commit ed2b803

Browse files
committedNov 23, 2021
[fix] Resume the socket in the CLOSING state
When the value of the `readyState` attribute is `CLOSING`, the internal socket might still be open. Resume it to read any remaining data and to allow the connection to be closed cleanly.
1 parent b8186dd commit ed2b803

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed
 

‎lib/stream.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ function createWebSocketStream(ws, options) {
155155
};
156156

157157
duplex._read = function () {
158-
if (ws.readyState === ws.OPEN && !resumeOnReceiverDrain) {
158+
if (
159+
(ws.readyState === ws.OPEN || ws.readyState === ws.CLOSING) &&
160+
!resumeOnReceiverDrain
161+
) {
159162
resumeOnReceiverDrain = true;
160163
if (!ws._receiver._writableState.needDrain) ws._socket.resume();
161164
}

‎test/create-websocket-stream.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -568,5 +568,31 @@ describe('createWebSocketStream', () => {
568568
ws.close();
569569
});
570570
});
571+
572+
it('resumes the socket if `readyState` is `CLOSING`', (done) => {
573+
const wss = new WebSocket.Server({ port: 0 }, () => {
574+
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
575+
const duplex = createWebSocketStream(ws);
576+
577+
ws.on('message', () => {
578+
assert.ok(ws._socket.isPaused());
579+
580+
duplex.on('close', () => {
581+
wss.close(done);
582+
});
583+
584+
duplex.end();
585+
586+
process.nextTick(() => {
587+
assert.strictEqual(ws.readyState, WebSocket.CLOSING);
588+
duplex.resume();
589+
});
590+
});
591+
});
592+
593+
wss.on('connection', (ws) => {
594+
ws.send(randomBytes(16 * 1024));
595+
});
596+
});
571597
});
572598
});

0 commit comments

Comments
 (0)
Please sign in to comment.