PR-URL: https://github.com/nodejs/node/pull/63182 Fixes: https://github.com/nodejs/node/issues/61630 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
95 lines
2.7 KiB
JavaScript
95 lines
2.7 KiB
JavaScript
// Flags: --experimental-dtls --no-warnings
|
|
|
|
// Test: DTLS interop -- OpenSSL s_server with Node.js DTLS client.
|
|
// Verifies that Node's DTLS client can complete a handshake with an
|
|
// external DTLS server (OpenSSL CLI) and exchange application data.
|
|
|
|
import { hasCrypto, skip, mustCall, mustNotCall } from '../common/index.mjs';
|
|
import { createRequire } from 'module';
|
|
import assert from 'node:assert';
|
|
import { spawn } from 'node:child_process';
|
|
import * as fixtures from '../common/fixtures.mjs';
|
|
|
|
if (!hasCrypto) {
|
|
skip('missing crypto');
|
|
}
|
|
|
|
if (!process.features.dtls) {
|
|
skip('DTLS is not enabled');
|
|
}
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const common = require('../common');
|
|
const { opensslCli } = require('../common/crypto');
|
|
|
|
if (!opensslCli) {
|
|
skip('missing openssl-cli');
|
|
}
|
|
|
|
const { connect } = await import('node:dtls');
|
|
|
|
const reply = 'I AM THE WALRUS'; // Something recognizable
|
|
|
|
// Start OpenSSL DTLS server.
|
|
const server = spawn(opensslCli, [
|
|
's_server',
|
|
'-dtls1_2',
|
|
'-accept', String(common.PORT),
|
|
'-cert', fixtures.path('keys/agent1-cert.pem'),
|
|
'-key', fixtures.path('keys/agent1-key.pem'),
|
|
'-listen',
|
|
], { stdio: 'pipe' });
|
|
|
|
let serverOut = '';
|
|
server.stdout.on('data', (data) => { serverOut += data; });
|
|
let serverErr = '';
|
|
server.stderr.on('data', (data) => { serverErr += data; });
|
|
server.on('error', mustNotCall());
|
|
|
|
const timeout = setTimeout(() => {
|
|
server.kill();
|
|
assert.fail(`Test timed out\nstdout: ${serverOut}\nstderr: ${serverErr}`);
|
|
}, 10000);
|
|
|
|
// Wait for "ACCEPT" on stdout -- this means s_server is ready.
|
|
await new Promise((resolve) => {
|
|
server.stdout.on('data', function onReady() {
|
|
if (!serverOut.includes('ACCEPT')) return;
|
|
server.stdout.removeListener('data', onReady);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
// Connect Node.js DTLS client.
|
|
const session = connect('127.0.0.1', common.PORT, {
|
|
ca: [fixtures.readKey('ca1-cert.pem').toString()],
|
|
rejectUnauthorized: false,
|
|
});
|
|
|
|
const { protocol } = await session.opened;
|
|
assert.match(protocol, /DTLS/i);
|
|
|
|
// Send data from Node to OpenSSL server.
|
|
session.send('hello from node');
|
|
|
|
// Send data from OpenSSL server to Node client via s_server stdin.
|
|
// s_server forwards its stdin to the connected client.
|
|
server.stdin.write(reply + '\n');
|
|
|
|
// Wait for Node client to receive the message.
|
|
const data = await new Promise((resolve) => {
|
|
session.onmessage = mustCall(resolve);
|
|
});
|
|
assert.strictEqual(data.toString().trim(), reply);
|
|
|
|
// Clean up.
|
|
await session.close();
|
|
await session.endpoint.close();
|
|
clearTimeout(timeout);
|
|
server.kill();
|
|
|
|
// Wait for server to exit.
|
|
const [, signal] = await new Promise((resolve) => {
|
|
server.on('exit', mustCall((...args) => resolve(args)));
|
|
});
|
|
assert.strictEqual(signal, 'SIGTERM');
|