From 0c5ced643160b8fb3752377b3c684c4b27bc8df0 Mon Sep 17 00:00:00 2001 From: Andrey Pechkurov Date: Thu, 22 Oct 2020 12:04:35 +0300 Subject: [PATCH] tls: allow reading data into a static buffer Refs: #25436 PR-URL: https://github.com/nodejs/node/pull/35753 Refs: https://github.com/nodejs/node/pull/25436 Reviewed-By: Matteo Collina Reviewed-By: Minwoo Jung --- .../tls/{throughput.js => throughput-c2s.js} | 0 benchmark/tls/throughput-s2c.js | 104 +++++++++ doc/api/tls.md | 7 + lib/_tls_wrap.js | 2 + lib/net.js | 87 ++++---- .../parallel/test-tls-onread-static-buffer.js | 206 ++++++++++++++++++ 6 files changed, 362 insertions(+), 44 deletions(-) rename benchmark/tls/{throughput.js => throughput-c2s.js} (100%) create mode 100644 benchmark/tls/throughput-s2c.js create mode 100644 test/parallel/test-tls-onread-static-buffer.js diff --git a/benchmark/tls/throughput.js b/benchmark/tls/throughput-c2s.js similarity index 100% rename from benchmark/tls/throughput.js rename to benchmark/tls/throughput-c2s.js diff --git a/benchmark/tls/throughput-s2c.js b/benchmark/tls/throughput-s2c.js new file mode 100644 index 00000000000000..a505a719d30884 --- /dev/null +++ b/benchmark/tls/throughput-s2c.js @@ -0,0 +1,104 @@ +'use strict'; +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + dur: [5], + type: ['buf', 'asc', 'utf'], + sendchunklen: [256, 32 * 1024, 128 * 1024, 16 * 1024 * 1024], + recvbuflen: [0, 64 * 1024, 1024 * 1024], + recvbufgenfn: ['true', 'false'] +}); + +const fixtures = require('../../test/common/fixtures'); +let options; +let recvbuf; +let received = 0; +const tls = require('tls'); + +function main({ dur, type, sendchunklen, recvbuflen, recvbufgenfn }) { + if (isFinite(recvbuflen) && recvbuflen > 0) + recvbuf = Buffer.alloc(recvbuflen); + + let encoding; + let chunk; + switch (type) { + case 'buf': + chunk = Buffer.alloc(sendchunklen, 'b'); + break; + case 'asc': + chunk = 'a'.repeat(sendchunklen); + encoding = 'ascii'; + break; + case 'utf': + chunk = 'ΓΌ'.repeat(sendchunklen / 2); + encoding = 'utf8'; + break; + default: + throw new Error('invalid type'); + } + + options = { + key: fixtures.readKey('rsa_private.pem'), + cert: fixtures.readKey('rsa_cert.crt'), + ca: fixtures.readKey('rsa_ca.crt'), + ciphers: 'AES256-GCM-SHA384' + }; + + let socketOpts; + if (recvbuf === undefined) { + socketOpts = { port: common.PORT, rejectUnauthorized: false }; + } else { + let buffer = recvbuf; + if (recvbufgenfn === 'true') { + let bufidx = -1; + const bufpool = [ + recvbuf, + Buffer.from(recvbuf), + Buffer.from(recvbuf), + ]; + buffer = () => { + bufidx = (bufidx + 1) % bufpool.length; + return bufpool[bufidx]; + }; + } + socketOpts = { + port: common.PORT, + rejectUnauthorized: false, + onread: { + buffer, + callback: function(nread, buf) { + received += nread; + } + } + }; + } + + const server = tls.createServer(options, (socket) => { + socket.on('data', (buf) => { + socket.on('drain', write); + write(); + }); + + function write() { + while (false !== socket.write(chunk, encoding)); + } + }); + + let conn; + server.listen(common.PORT, () => { + conn = tls.connect(socketOpts, () => { + setTimeout(done, dur * 1000); + bench.start(); + conn.write('hello'); + }); + + conn.on('data', (chunk) => { + received += chunk.length; + }); + }); + + function done() { + const mbits = (received * 8) / (1024 * 1024); + bench.end(mbits); + process.exit(0); + } +} diff --git a/doc/api/tls.md b/doc/api/tls.md index 055ba472b5c666..74288e7bb3d2ed 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1357,6 +1357,9 @@ being issued by trusted CA (`options.ca`).