1'use strict'; 2const common = require('../common'); 3 4if (!common.hasCrypto) 5 common.skip('missing crypto'); 6if (!common.opensslCli) 7 common.skip('missing openssl cli'); 8 9const assert = require('assert'); 10const tls = require('tls'); 11const net = require('net'); 12const { spawn } = require('child_process'); 13 14const CIPHERS = 'PSK+HIGH'; 15const KEY = 'd731ef57be09e5204f0b205b60627028'; 16const IDENTITY = 'Client_identity'; // Hardcoded by `openssl s_server` 17const useIPv4 = !common.hasIPv6; 18 19const server = spawn(common.opensslCli, [ 20 's_server', 21 '-accept', common.PORT, 22 '-cipher', CIPHERS, 23 '-psk', KEY, 24 '-psk_hint', IDENTITY, 25 '-nocert', 26 '-rev', 27 ...(useIPv4 ? ['-4'] : []), 28], { encoding: 'utf8' }); 29let serverErr = ''; 30let serverOut = ''; 31server.stderr.on('data', (data) => serverErr += data); 32server.stdout.on('data', (data) => serverOut += data); 33server.on('error', common.mustNotCall()); 34server.on('exit', (code, signal) => { 35 // Server is expected to be terminated by cleanUp(). 36 assert.strictEqual(code, null, 37 `'${server.spawnfile} ${server.spawnargs.join(' ')}' unexpected exited with output:\n${serverOut}\n${serverErr}`); 38 assert.strictEqual(signal, 'SIGTERM'); 39}); 40 41const cleanUp = (err) => { 42 clearTimeout(timeout); 43 if (err) 44 console.log('Failed:', err); 45 server.kill(); 46 process.exitCode = err ? 1 : 0; 47}; 48 49const timeout = setTimeout(() => cleanUp('Timed out'), 5000); 50 51function waitForPort(port, cb) { 52 const socket = net.connect(common.PORT, () => { 53 socket.on('data', () => {}); 54 socket.end(); 55 socket.on('end', cb); 56 }); 57 socket.on('error', (e) => { 58 if (e.code === 'ENOENT' || e.code === 'ECONNREFUSED') { 59 setTimeout(() => waitForPort(port, cb), 1000); 60 } else { 61 cb(e); 62 } 63 }); 64} 65 66waitForPort(common.PORT, common.mustCall((err) => { 67 if (err) { 68 cleanUp(err); 69 return; 70 } 71 72 const message = 'hello'; 73 const reverse = message.split('').reverse().join(''); 74 runClient(message, common.mustCall((err, data) => { 75 try { 76 if (!err) assert.strictEqual(data.trim(), reverse); 77 } finally { 78 cleanUp(err); 79 } 80 })); 81})); 82 83function runClient(message, cb) { 84 const s = tls.connect(common.PORT, { 85 ciphers: CIPHERS, 86 checkServerIdentity: () => {}, 87 pskCallback(hint) { 88 // 'hint' will be null in TLS1.3. 89 if (hint === null || hint === IDENTITY) { 90 return { 91 identity: IDENTITY, 92 psk: Buffer.from(KEY, 'hex') 93 }; 94 } 95 } 96 }); 97 s.on('secureConnect', common.mustCall(() => { 98 let data = ''; 99 s.on('data', common.mustCallAtLeast((d) => { 100 data += d; 101 })); 102 s.on('end', common.mustCall(() => { 103 cb(null, data); 104 })); 105 s.end(message); 106 })); 107 s.on('error', (e) => { 108 cb(e); 109 }); 110} 111