Skip to content

Commit 7c152da

Browse files
committed
does not matter if TCP FIN or TCP RST
1 parent 9f96023 commit 7c152da

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

lib/internal/http2/core.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,11 +3020,12 @@ ObjectDefineProperty(Http2Session.prototype, 'setTimeout', setTimeoutValue);
30203020
function socketOnError(error) {
30213021
const session = this[kBoundSession];
30223022
if (session !== undefined) {
3023-
// We can ignore ECONNRESET after GOAWAY was received as there's nothing
3024-
// we can do and the other side is fully within its rights to do so.
3025-
if (error.code === 'ECONNRESET' && session[kState].goawayCode !== null)
3026-
return session.destroy();
3027-
debugSessionObj(this, 'socket error [%s]', error.message);
3023+
if (error.code === 'ECONNRESET') {
3024+
// Handled by socketOnClose, it does not matter if the endpoint
3025+
// sends TCP FIN prematurely or TCP RST.
3026+
return;
3027+
}
3028+
debugSessionObj(session, 'socket error [%s]', error.message);
30283029
session.destroy(error);
30293030
}
30303031
}
@@ -3305,15 +3306,28 @@ function socketOnClose() {
33053306
const err = session.connecting ? new ERR_SOCKET_CLOSED() : null;
33063307
const state = session[kState];
33073308

3309+
// Code for premature close
33083310
let code = state.goawayCode ?? state.destroyCode;
3309-
if (code === NGHTTP2_NO_ERROR || code === null) {
3310-
code = session[kType] === NGHTTP2_SESSION_SERVER ?
3311+
if (code === NGHTTP2_NO_ERROR) {
3312+
// Got NO_ERROR but still closed prematurely
3313+
code = null;
3314+
}
3315+
3316+
const defaultCode = session[kType] === NGHTTP2_SESSION_SERVER ?
33113317
NGHTTP2_CANCEL :
33123318
NGHTTP2_INTERNAL_ERROR;
3313-
}
33143319

3315-
state.streams.forEach((stream) => stream.close(code));
3316-
state.pendingStreams.forEach((stream) => stream.close(code));
3320+
const closeStream = (stream) => {
3321+
if (code === null) {
3322+
const connect = stream[kSentHeaders]?.[HTTP2_HEADER_METHOD] === HTTP2_METHOD_CONNECT;
3323+
stream.close(connect ? NGHTTP2_CONNECT_ERROR : defaultCode);
3324+
} else {
3325+
stream.close(code ?? defaultCode);
3326+
}
3327+
};
3328+
3329+
state.streams.forEach(closeStream);
3330+
state.pendingStreams.forEach(closeStream);
33173331
session.close();
33183332
session[kMaybeDestroy](err);
33193333
}

test/parallel/test-http2-client-connection-tunnel-reset.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,14 @@ h2Server.on('connect', (req, res) => {
2020

2121
h2Server.listen(0, common.mustCall(() => {
2222
const proxyClient = h2.connect(`http://localhost:${h2Server.address().port}`);
23-
proxyClient.once('error', common.expectsError({
24-
name: 'Error',
25-
code: 'ECONNRESET',
26-
message: 'read ECONNRESET'
27-
}));
23+
proxyClient.once('error', common.mustNotCall());
2824
const proxyReq = proxyClient.request({
2925
':method': 'CONNECT',
3026
':authority': 'example.com:443'
3127
});
3228
proxyReq.once('error', common.expectsError({
3329
name: 'Error',
34-
code: 'ECONNRESET',
35-
message: 'read ECONNRESET'
30+
code: 'ERR_HTTP2_STREAM_ERROR',
31+
message: 'Stream closed with error code NGHTTP2_CONNECT_ERROR'
3632
}));
3733
}));

test/parallel/test-http2-respond-with-file-connection-abort.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ const {
1313

1414
const server = http2.createServer();
1515
server.on('stream', common.mustCall((stream) => {
16-
stream.on('error', (err) => assert.strictEqual(err.code, 'ECONNRESET'));
16+
stream.on('error', common.expectsError({
17+
code: 'ERR_HTTP2_STREAM_ERROR',
18+
name: 'Error',
19+
message: 'Stream closed with error code NGHTTP2_CANCEL'
20+
}));
1721
stream.respondWithFile(process.execPath, {
1822
[HTTP2_HEADER_CONTENT_TYPE]: 'application/octet-stream'
1923
});

test/parallel/test-http2-server-socket-destroy.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ function onStream(stream) {
3939
message: 'Stream closed with error code NGHTTP2_CANCEL'
4040
}));
4141

42-
// Do not use destroy() as it sends FIN on Linux.
43-
// On macOS, it sends RST.
44-
4542
// Always send RST.
4643
socket.resetAndDestroy();
4744
}
@@ -50,18 +47,14 @@ server.listen(0);
5047

5148
server.on('listening', common.mustCall(async () => {
5249
const client = h2.connect(`http://localhost:${server.address().port}`);
53-
client.on('error', common.expectsError({
54-
name: 'Error',
55-
code: 'ECONNRESET',
56-
message: 'read ECONNRESET'
57-
}));
50+
client.on('error', common.mustNotCall());
5851
client.on('close', common.mustCall());
5952

6053
const req = client.request({ ':method': 'POST' });
6154
req.on('error', common.expectsError({
6255
name: 'Error',
63-
code: 'ECONNRESET',
64-
message: 'read ECONNRESET'
56+
code: 'ERR_HTTP2_STREAM_ERROR',
57+
message: 'Stream closed with error code NGHTTP2_INTERNAL_ERROR'
6558
}));
6659

6760
req.on('aborted', common.mustCall());

0 commit comments

Comments
 (0)