node/test/parallel/test-http2-socket-close.js
Tim Perry 048e0bec51
tls: ensure TLS Sockets are closed if the underlying wrap closes
This fixes a potential segfault, among various other likely-related
issues, which all occur because TLSSockets were not informed if their
underlying stream was closed in many cases.

This also significantly modifies an existing TLS test. With this change
in place, that test no longer works, as it tries to mess with internals
to trigger a race, and those internals are now cleaned up earlier. This
test has been simplified to a more general TLS shutdown test.

PR-URL: https://github.com/nodejs/node/pull/49327
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Debadree Chatterjee <debadree333@gmail.com>
2023-09-01 07:00:05 +00:00

68 lines
1.8 KiB
JavaScript

'use strict';
const common = require('../common');
const fixtures = require('../common/fixtures');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const net = require('net');
const h2 = require('http2');
const tlsOptions = {
key: fixtures.readKey('agent1-key.pem'),
cert: fixtures.readKey('agent1-cert.pem'),
ALPNProtocols: ['h2']
};
// Create a net server that upgrades sockets to HTTP/2 manually, handles the
// request, and then shuts down via a short socket timeout and a longer H2 session
// timeout. This is an unconventional way to shut down a session (the underlying
// socket closing first) but it should work - critically, it shouldn't segfault
// (as it did until Node v20.5.1).
let serverRawSocket;
let serverH2Session;
const netServer = net.createServer((socket) => {
serverRawSocket = socket;
h2Server.emit('connection', socket);
});
const h2Server = h2.createSecureServer(tlsOptions, (req, res) => {
res.writeHead(200);
res.end();
});
h2Server.on('session', (session) => {
serverH2Session = session;
});
netServer.listen(0, common.mustCall(() => {
const proxyClient = h2.connect(`https://localhost:${netServer.address().port}`, {
rejectUnauthorized: false
});
proxyClient.on('close', common.mustCall(() => {
netServer.close();
}));
const req = proxyClient.request({
':method': 'GET',
':path': '/'
});
req.on('response', common.mustCall((response) => {
assert.strictEqual(response[':status'], 200);
// Asynchronously shut down the server's connections after the response,
// but not in the order it typically expects:
setTimeout(() => {
serverRawSocket.destroy();
setTimeout(() => {
serverH2Session.close();
}, 10);
}, 10);
}));
}));