11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciconst assert = require('assert'); 41cb0ef41Sopenharmony_ciif (!common.hasCrypto) common.skip('missing crypto'); 51cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 61cb0ef41Sopenharmony_ciconst tls = require('tls'); 71cb0ef41Sopenharmony_ciconst net = require('net'); 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci// Sending tls data on a server TLSSocket with an active write led to a crash: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// node[1296]: ../src/crypto/crypto_tls.cc:963:virtual int node::crypto::TLSWrap::DoWrite(node::WriteWrap*, 121cb0ef41Sopenharmony_ci// uv_buf_t*, size_t, uv_stream_t*): Assertion `!current_write_' failed. 131cb0ef41Sopenharmony_ci// 1: 0xb090e0 node::Abort() [node] 141cb0ef41Sopenharmony_ci// 2: 0xb0915e [node] 151cb0ef41Sopenharmony_ci// 3: 0xca8413 node::crypto::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, unsigned long, uv_stream_s*) [node] 161cb0ef41Sopenharmony_ci// 4: 0xcaa549 node::StreamBase::Write(uv_buf_t*, unsigned long, uv_stream_s*, v8::Local<v8::Object>) [node] 171cb0ef41Sopenharmony_ci// 5: 0xca88d7 node::crypto::TLSWrap::EncOut() [node] 181cb0ef41Sopenharmony_ci// 6: 0xca9ba8 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node] 191cb0ef41Sopenharmony_ci// 7: 0xca8eb0 node::crypto::TLSWrap::ClearOut() [node] 201cb0ef41Sopenharmony_ci// 8: 0xca9ba0 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node] 211cb0ef41Sopenharmony_ci// 9: 0xbe50dd node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) [node] 221cb0ef41Sopenharmony_ci// 10: 0xbe54c4 [node] 231cb0ef41Sopenharmony_ci// 11: 0x15583d7 [node] 241cb0ef41Sopenharmony_ci// 12: 0x1558c00 [node] 251cb0ef41Sopenharmony_ci// 13: 0x155ede4 [node] 261cb0ef41Sopenharmony_ci// 14: 0x154d008 uv_run [node] 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciconst serverReplaySize = 2 * 1024 * 1024; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci(async function() { 311cb0ef41Sopenharmony_ci const tlsClientHello = await getClientHello(); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci const subserver = tls.createServer({ 341cb0ef41Sopenharmony_ci key: fixtures.readKey('agent1-key.pem'), 351cb0ef41Sopenharmony_ci cert: fixtures.readKey('agent1-cert.pem'), 361cb0ef41Sopenharmony_ci }); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci const server = tls.createServer({ 391cb0ef41Sopenharmony_ci key: fixtures.readKey('agent1-key.pem'), 401cb0ef41Sopenharmony_ci cert: fixtures.readKey('agent1-cert.pem'), 411cb0ef41Sopenharmony_ci }) 421cb0ef41Sopenharmony_ci .listen(startClient) 431cb0ef41Sopenharmony_ci .on('secureConnection', (serverTlsSock) => { 441cb0ef41Sopenharmony_ci // Craft writes that are large enough to stuck in sending 451cb0ef41Sopenharmony_ci // In reality this can be a 200 response to the incoming HTTP CONNECT 461cb0ef41Sopenharmony_ci const half = Buffer.alloc(serverReplaySize / 2, 0); 471cb0ef41Sopenharmony_ci serverTlsSock.write(half, common.mustSucceed()); 481cb0ef41Sopenharmony_ci serverTlsSock.write(half, common.mustSucceed()); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci subserver.emit('connection', serverTlsSock); 511cb0ef41Sopenharmony_ci }); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci function startClient() { 551cb0ef41Sopenharmony_ci const clientTlsSock = tls.connect({ 561cb0ef41Sopenharmony_ci host: '127.0.0.1', 571cb0ef41Sopenharmony_ci port: server.address().port, 581cb0ef41Sopenharmony_ci rejectUnauthorized: false, 591cb0ef41Sopenharmony_ci }); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci const recv = []; 621cb0ef41Sopenharmony_ci let revcLen = 0; 631cb0ef41Sopenharmony_ci clientTlsSock.on('data', (chunk) => { 641cb0ef41Sopenharmony_ci revcLen += chunk.length; 651cb0ef41Sopenharmony_ci recv.push(chunk); 661cb0ef41Sopenharmony_ci if (revcLen > serverReplaySize) { 671cb0ef41Sopenharmony_ci // Check the server's replay is followed by the subserver's TLS ServerHello 681cb0ef41Sopenharmony_ci const serverHelloFstByte = Buffer.concat(recv).subarray(serverReplaySize, serverReplaySize + 1); 691cb0ef41Sopenharmony_ci assert.strictEqual(serverHelloFstByte.toString('hex'), '16'); 701cb0ef41Sopenharmony_ci process.exit(0); 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci }); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci // In reality, one may want to send a HTTP CONNECT before starting this double TLS 751cb0ef41Sopenharmony_ci clientTlsSock.write(tlsClientHello); 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci})().then(common.mustCall()); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_cifunction getClientHello() { 801cb0ef41Sopenharmony_ci return new Promise((resolve) => { 811cb0ef41Sopenharmony_ci const server = net.createServer((sock) => { 821cb0ef41Sopenharmony_ci sock.on('data', (chunk) => { 831cb0ef41Sopenharmony_ci resolve(chunk); 841cb0ef41Sopenharmony_ci }); 851cb0ef41Sopenharmony_ci }) 861cb0ef41Sopenharmony_ci .listen(() => { 871cb0ef41Sopenharmony_ci tls.connect({ 881cb0ef41Sopenharmony_ci port: server.address().port, 891cb0ef41Sopenharmony_ci host: '127.0.0.1', 901cb0ef41Sopenharmony_ci ALPNProtocols: ['h2'], 911cb0ef41Sopenharmony_ci }).on('error', () => {}); 921cb0ef41Sopenharmony_ci }); 931cb0ef41Sopenharmony_ci }); 941cb0ef41Sopenharmony_ci} 95