1'use strict'; 2const common = require('../common'); 3const assert = require('assert'); 4if (!common.hasCrypto) common.skip('missing crypto'); 5const fixtures = require('../common/fixtures'); 6const tls = require('tls'); 7const net = require('net'); 8 9// Sending tls data on a server TLSSocket with an active write led to a crash: 10// 11// node[1296]: ../src/crypto/crypto_tls.cc:963:virtual int node::crypto::TLSWrap::DoWrite(node::WriteWrap*, 12// uv_buf_t*, size_t, uv_stream_t*): Assertion `!current_write_' failed. 13// 1: 0xb090e0 node::Abort() [node] 14// 2: 0xb0915e [node] 15// 3: 0xca8413 node::crypto::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, unsigned long, uv_stream_s*) [node] 16// 4: 0xcaa549 node::StreamBase::Write(uv_buf_t*, unsigned long, uv_stream_s*, v8::Local<v8::Object>) [node] 17// 5: 0xca88d7 node::crypto::TLSWrap::EncOut() [node] 18// 6: 0xca9ba8 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node] 19// 7: 0xca8eb0 node::crypto::TLSWrap::ClearOut() [node] 20// 8: 0xca9ba0 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node] 21// 9: 0xbe50dd node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) [node] 22// 10: 0xbe54c4 [node] 23// 11: 0x15583d7 [node] 24// 12: 0x1558c00 [node] 25// 13: 0x155ede4 [node] 26// 14: 0x154d008 uv_run [node] 27 28const serverReplaySize = 2 * 1024 * 1024; 29 30(async function() { 31 const tlsClientHello = await getClientHello(); 32 33 const subserver = tls.createServer({ 34 key: fixtures.readKey('agent1-key.pem'), 35 cert: fixtures.readKey('agent1-cert.pem'), 36 }); 37 38 const server = tls.createServer({ 39 key: fixtures.readKey('agent1-key.pem'), 40 cert: fixtures.readKey('agent1-cert.pem'), 41 }) 42 .listen(startClient) 43 .on('secureConnection', (serverTlsSock) => { 44 // Craft writes that are large enough to stuck in sending 45 // In reality this can be a 200 response to the incoming HTTP CONNECT 46 const half = Buffer.alloc(serverReplaySize / 2, 0); 47 serverTlsSock.write(half, common.mustSucceed()); 48 serverTlsSock.write(half, common.mustSucceed()); 49 50 subserver.emit('connection', serverTlsSock); 51 }); 52 53 54 function startClient() { 55 const clientTlsSock = tls.connect({ 56 host: '127.0.0.1', 57 port: server.address().port, 58 rejectUnauthorized: false, 59 }); 60 61 const recv = []; 62 let revcLen = 0; 63 clientTlsSock.on('data', (chunk) => { 64 revcLen += chunk.length; 65 recv.push(chunk); 66 if (revcLen > serverReplaySize) { 67 // Check the server's replay is followed by the subserver's TLS ServerHello 68 const serverHelloFstByte = Buffer.concat(recv).subarray(serverReplaySize, serverReplaySize + 1); 69 assert.strictEqual(serverHelloFstByte.toString('hex'), '16'); 70 process.exit(0); 71 } 72 }); 73 74 // In reality, one may want to send a HTTP CONNECT before starting this double TLS 75 clientTlsSock.write(tlsClientHello); 76 } 77})().then(common.mustCall()); 78 79function getClientHello() { 80 return new Promise((resolve) => { 81 const server = net.createServer((sock) => { 82 sock.on('data', (chunk) => { 83 resolve(chunk); 84 }); 85 }) 86 .listen(() => { 87 tls.connect({ 88 port: server.address().port, 89 host: '127.0.0.1', 90 ALPNProtocols: ['h2'], 91 }).on('error', () => {}); 92 }); 93 }); 94} 95