11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciif (!common.hasCrypto) 51cb0ef41Sopenharmony_ci common.skip('missing crypto'); 61cb0ef41Sopenharmony_ciif (!common.opensslCli) 71cb0ef41Sopenharmony_ci common.skip('missing openssl cli'); 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst assert = require('assert'); 101cb0ef41Sopenharmony_ciconst tls = require('tls'); 111cb0ef41Sopenharmony_ciconst net = require('net'); 121cb0ef41Sopenharmony_ciconst { spawn } = require('child_process'); 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst CIPHERS = 'PSK+HIGH'; 151cb0ef41Sopenharmony_ciconst KEY = 'd731ef57be09e5204f0b205b60627028'; 161cb0ef41Sopenharmony_ciconst IDENTITY = 'Client_identity'; // Hardcoded by `openssl s_server` 171cb0ef41Sopenharmony_ciconst useIPv4 = !common.hasIPv6; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciconst server = spawn(common.opensslCli, [ 201cb0ef41Sopenharmony_ci 's_server', 211cb0ef41Sopenharmony_ci '-accept', common.PORT, 221cb0ef41Sopenharmony_ci '-cipher', CIPHERS, 231cb0ef41Sopenharmony_ci '-psk', KEY, 241cb0ef41Sopenharmony_ci '-psk_hint', IDENTITY, 251cb0ef41Sopenharmony_ci '-nocert', 261cb0ef41Sopenharmony_ci '-rev', 271cb0ef41Sopenharmony_ci ...(useIPv4 ? ['-4'] : []), 281cb0ef41Sopenharmony_ci], { encoding: 'utf8' }); 291cb0ef41Sopenharmony_cilet serverErr = ''; 301cb0ef41Sopenharmony_cilet serverOut = ''; 311cb0ef41Sopenharmony_ciserver.stderr.on('data', (data) => serverErr += data); 321cb0ef41Sopenharmony_ciserver.stdout.on('data', (data) => serverOut += data); 331cb0ef41Sopenharmony_ciserver.on('error', common.mustNotCall()); 341cb0ef41Sopenharmony_ciserver.on('exit', (code, signal) => { 351cb0ef41Sopenharmony_ci // Server is expected to be terminated by cleanUp(). 361cb0ef41Sopenharmony_ci assert.strictEqual(code, null, 371cb0ef41Sopenharmony_ci `'${server.spawnfile} ${server.spawnargs.join(' ')}' unexpected exited with output:\n${serverOut}\n${serverErr}`); 381cb0ef41Sopenharmony_ci assert.strictEqual(signal, 'SIGTERM'); 391cb0ef41Sopenharmony_ci}); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciconst cleanUp = (err) => { 421cb0ef41Sopenharmony_ci clearTimeout(timeout); 431cb0ef41Sopenharmony_ci if (err) 441cb0ef41Sopenharmony_ci console.log('Failed:', err); 451cb0ef41Sopenharmony_ci server.kill(); 461cb0ef41Sopenharmony_ci process.exitCode = err ? 1 : 0; 471cb0ef41Sopenharmony_ci}; 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciconst timeout = setTimeout(() => cleanUp('Timed out'), 5000); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_cifunction waitForPort(port, cb) { 521cb0ef41Sopenharmony_ci const socket = net.connect(common.PORT, () => { 531cb0ef41Sopenharmony_ci socket.on('data', () => {}); 541cb0ef41Sopenharmony_ci socket.end(); 551cb0ef41Sopenharmony_ci socket.on('end', cb); 561cb0ef41Sopenharmony_ci }); 571cb0ef41Sopenharmony_ci socket.on('error', (e) => { 581cb0ef41Sopenharmony_ci if (e.code === 'ENOENT' || e.code === 'ECONNREFUSED') { 591cb0ef41Sopenharmony_ci setTimeout(() => waitForPort(port, cb), 1000); 601cb0ef41Sopenharmony_ci } else { 611cb0ef41Sopenharmony_ci cb(e); 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci }); 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciwaitForPort(common.PORT, common.mustCall((err) => { 671cb0ef41Sopenharmony_ci if (err) { 681cb0ef41Sopenharmony_ci cleanUp(err); 691cb0ef41Sopenharmony_ci return; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci const message = 'hello'; 731cb0ef41Sopenharmony_ci const reverse = message.split('').reverse().join(''); 741cb0ef41Sopenharmony_ci runClient(message, common.mustCall((err, data) => { 751cb0ef41Sopenharmony_ci try { 761cb0ef41Sopenharmony_ci if (!err) assert.strictEqual(data.trim(), reverse); 771cb0ef41Sopenharmony_ci } finally { 781cb0ef41Sopenharmony_ci cleanUp(err); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci })); 811cb0ef41Sopenharmony_ci})); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cifunction runClient(message, cb) { 841cb0ef41Sopenharmony_ci const s = tls.connect(common.PORT, { 851cb0ef41Sopenharmony_ci ciphers: CIPHERS, 861cb0ef41Sopenharmony_ci checkServerIdentity: () => {}, 871cb0ef41Sopenharmony_ci pskCallback(hint) { 881cb0ef41Sopenharmony_ci // 'hint' will be null in TLS1.3. 891cb0ef41Sopenharmony_ci if (hint === null || hint === IDENTITY) { 901cb0ef41Sopenharmony_ci return { 911cb0ef41Sopenharmony_ci identity: IDENTITY, 921cb0ef41Sopenharmony_ci psk: Buffer.from(KEY, 'hex') 931cb0ef41Sopenharmony_ci }; 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci }); 971cb0ef41Sopenharmony_ci s.on('secureConnect', common.mustCall(() => { 981cb0ef41Sopenharmony_ci let data = ''; 991cb0ef41Sopenharmony_ci s.on('data', common.mustCallAtLeast((d) => { 1001cb0ef41Sopenharmony_ci data += d; 1011cb0ef41Sopenharmony_ci })); 1021cb0ef41Sopenharmony_ci s.on('end', common.mustCall(() => { 1031cb0ef41Sopenharmony_ci cb(null, data); 1041cb0ef41Sopenharmony_ci })); 1051cb0ef41Sopenharmony_ci s.end(message); 1061cb0ef41Sopenharmony_ci })); 1071cb0ef41Sopenharmony_ci s.on('error', (e) => { 1081cb0ef41Sopenharmony_ci cb(e); 1091cb0ef41Sopenharmony_ci }); 1101cb0ef41Sopenharmony_ci} 111