node/test/sequential/test-dtls-interop-openssl-server.mjs
James M Snell f835cc42da src,lib: add dtls interop tests
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>
2026-05-21 14:13:07 -07:00

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');