Skip to content

Commit

Permalink
[fix] Close the connection cleanly when an error occurs
Browse files Browse the repository at this point in the history
Instead of destroying the socket, try to close the connection cleanly
if an error (such as a data framing error) occurs after the opening
handshake has completed.

Also, to comply with the specification, use the 1006 status code if no
close frame is received, even if the connection is closed due to an
error.

Fixes #1898
  • Loading branch information
lpinca committed Jun 9, 2021
1 parent 05b8ccd commit 8806aa9
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
5 changes: 2 additions & 3 deletions lib/websocket.js
Expand Up @@ -808,11 +808,10 @@ function receiverOnError(err) {
const websocket = this[kWebSocket];

websocket._socket.removeListener('data', socketOnData);
websocket._socket.resume();

websocket._readyState = WebSocket.CLOSING;
websocket._closeCode = err[kStatusCode];
websocket.close(err[kStatusCode]);
websocket.emit('error', err);
websocket._socket.destroy();
}

/**
Expand Down
23 changes: 19 additions & 4 deletions test/websocket.test.js
Expand Up @@ -429,6 +429,7 @@ describe('WebSocket', () => {

describe('Events', () => {
it("emits an 'error' event if an error occurs", (done) => {
let clientCloseEventEmitted = false;
const wss = new WebSocket.Server({ port: 0 }, () => {
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

Expand All @@ -440,14 +441,21 @@ describe('WebSocket', () => {
);

ws.on('close', (code, reason) => {
assert.strictEqual(code, 1002);
clientCloseEventEmitted = true;
assert.strictEqual(code, 1006);
assert.strictEqual(reason, '');
wss.close(done);
});
});
});

wss.on('connection', (ws) => {
ws.on('close', (code, reason) => {
assert.ok(clientCloseEventEmitted);
assert.strictEqual(code, 1002);
assert.strictEqual(reason, '');
wss.close(done);
});

ws._socket.write(Buffer.from([0x85, 0x00]));
});
});
Expand Down Expand Up @@ -1410,10 +1418,17 @@ describe('WebSocket', () => {
});

it('honors the `mask` option', (done) => {
let serverClientCloseEventEmitted = false;
const wss = new WebSocket.Server({ port: 0 }, () => {
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);

ws.on('open', () => ws.send('hi', { mask: false }));
ws.on('close', (code, reason) => {
assert.ok(serverClientCloseEventEmitted);
assert.strictEqual(code, 1002);
assert.strictEqual(reason, '');
wss.close(done);
});
});

wss.on('connection', (ws) => {
Expand All @@ -1434,9 +1449,9 @@ describe('WebSocket', () => {
);

ws.on('close', (code, reason) => {
assert.strictEqual(code, 1002);
serverClientCloseEventEmitted = true;
assert.strictEqual(code, 1006);
assert.strictEqual(reason, '');
wss.close(done);
});
});
});
Expand Down

0 comments on commit 8806aa9

Please sign in to comment.