Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ee15142

Browse filesBrowse files
puzpuzpuztargos
authored andcommitted
tls: allow reading data into a static buffer
Refs: #25436 PR-URL: #35753 Refs: #25436 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
1 parent 4e76a3c commit ee15142
Copy full SHA for ee15142

File tree

Expand file treeCollapse file tree

6 files changed

+362
-44
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+362
-44
lines changed
Open diff view settings
Collapse file

‎benchmark/tls/throughput-s2c.js‎

Copy file name to clipboard
+104Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
const bench = common.createBenchmark(main, {
4+
dur: [5],
5+
type: ['buf', 'asc', 'utf'],
6+
sendchunklen: [256, 32 * 1024, 128 * 1024, 16 * 1024 * 1024],
7+
recvbuflen: [0, 64 * 1024, 1024 * 1024],
8+
recvbufgenfn: ['true', 'false']
9+
});
10+
11+
const fixtures = require('../../test/common/fixtures');
12+
let options;
13+
let recvbuf;
14+
let received = 0;
15+
const tls = require('tls');
16+
17+
function main({ dur, type, sendchunklen, recvbuflen, recvbufgenfn }) {
18+
if (isFinite(recvbuflen) && recvbuflen > 0)
19+
recvbuf = Buffer.alloc(recvbuflen);
20+
21+
let encoding;
22+
let chunk;
23+
switch (type) {
24+
case 'buf':
25+
chunk = Buffer.alloc(sendchunklen, 'b');
26+
break;
27+
case 'asc':
28+
chunk = 'a'.repeat(sendchunklen);
29+
encoding = 'ascii';
30+
break;
31+
case 'utf':
32+
chunk = 'ü'.repeat(sendchunklen / 2);
33+
encoding = 'utf8';
34+
break;
35+
default:
36+
throw new Error('invalid type');
37+
}
38+
39+
options = {
40+
key: fixtures.readKey('rsa_private.pem'),
41+
cert: fixtures.readKey('rsa_cert.crt'),
42+
ca: fixtures.readKey('rsa_ca.crt'),
43+
ciphers: 'AES256-GCM-SHA384'
44+
};
45+
46+
let socketOpts;
47+
if (recvbuf === undefined) {
48+
socketOpts = { port: common.PORT, rejectUnauthorized: false };
49+
} else {
50+
let buffer = recvbuf;
51+
if (recvbufgenfn === 'true') {
52+
let bufidx = -1;
53+
const bufpool = [
54+
recvbuf,
55+
Buffer.from(recvbuf),
56+
Buffer.from(recvbuf),
57+
];
58+
buffer = () => {
59+
bufidx = (bufidx + 1) % bufpool.length;
60+
return bufpool[bufidx];
61+
};
62+
}
63+
socketOpts = {
64+
port: common.PORT,
65+
rejectUnauthorized: false,
66+
onread: {
67+
buffer,
68+
callback: function(nread, buf) {
69+
received += nread;
70+
}
71+
}
72+
};
73+
}
74+
75+
const server = tls.createServer(options, (socket) => {
76+
socket.on('data', (buf) => {
77+
socket.on('drain', write);
78+
write();
79+
});
80+
81+
function write() {
82+
while (false !== socket.write(chunk, encoding));
83+
}
84+
});
85+
86+
let conn;
87+
server.listen(common.PORT, () => {
88+
conn = tls.connect(socketOpts, () => {
89+
setTimeout(done, dur * 1000);
90+
bench.start();
91+
conn.write('hello');
92+
});
93+
94+
conn.on('data', (chunk) => {
95+
received += chunk.length;
96+
});
97+
});
98+
99+
function done() {
100+
const mbits = (received * 8) / (1024 * 1024);
101+
bench.end(mbits);
102+
process.exit(0);
103+
}
104+
}
Collapse file

‎doc/api/tls.md‎

Copy file name to clipboardExpand all lines: doc/api/tls.md
+7Lines changed: 7 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,9 @@ being issued by trusted CA (`options.ca`).
13431343
<!-- YAML
13441344
added: v0.11.3
13451345
changes:
1346+
- version: REPLACEME
1347+
pr-url: https://github.com/nodejs/node/pull/35753
1348+
description: Added `onread` option.
13461349
- version:
13471350
- v14.1.0
13481351
- v13.14.0
@@ -1456,6 +1459,10 @@ changes:
14561459
[`tls.createSecureContext()`][]. If a `secureContext` is _not_ provided, one
14571460
will be created by passing the entire `options` object to
14581461
`tls.createSecureContext()`.
1462+
* `onread` {Object} If the `socket` option is missing, incoming data is
1463+
stored in a single `buffer` and passed to the supplied `callback` when
1464+
data arrives on the socket, otherwise the option is ignored. See the
1465+
`onread` option of [`net.Socket`][] for details.
14591466
* ...: [`tls.createSecureContext()`][] options that are used if the
14601467
`secureContext` option is missing, otherwise they are ignored.
14611468
* ...: Any [`socket.connect()`][] option not already listed.
Collapse file

‎lib/_tls_wrap.js‎

Copy file name to clipboardExpand all lines: lib/_tls_wrap.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ function TLSSocket(socket, opts) {
502502
pauseOnCreate: tlsOptions.pauseOnConnect,
503503
manualStart: true,
504504
highWaterMark: tlsOptions.highWaterMark,
505+
onread: !socket ? tlsOptions.onread : null,
505506
});
506507

507508
// Proxy for API compatibility
@@ -1592,6 +1593,7 @@ exports.connect = function connect(...args) {
15921593
enableTrace: options.enableTrace,
15931594
pskCallback: options.pskCallback,
15941595
highWaterMark: options.highWaterMark,
1596+
onread: options.onread,
15951597
});
15961598

15971599
tlssock[kConnectOptions] = options;
Collapse file

‎lib/net.js‎

Copy file name to clipboardExpand all lines: lib/net.js
+43-44Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -304,55 +304,54 @@ function Socket(options) {
304304
if (options.handle) {
305305
this._handle = options.handle; // private
306306
this[async_id_symbol] = getNewAsyncId(this._handle);
307-
} else {
308-
const onread = options.onread;
309-
if (onread !== null && typeof onread === 'object' &&
310-
(isUint8Array(onread.buffer) || typeof onread.buffer === 'function') &&
311-
typeof onread.callback === 'function') {
312-
if (typeof onread.buffer === 'function') {
313-
this[kBuffer] = true;
314-
this[kBufferGen] = onread.buffer;
315-
} else {
316-
this[kBuffer] = onread.buffer;
317-
}
318-
this[kBufferCb] = onread.callback;
319-
}
320-
if (options.fd !== undefined) {
321-
const { fd } = options;
322-
let err;
307+
} else if (options.fd !== undefined) {
308+
const { fd } = options;
309+
let err;
323310

324-
// createHandle will throw ERR_INVALID_FD_TYPE if `fd` is not
325-
// a valid `PIPE` or `TCP` descriptor
326-
this._handle = createHandle(fd, false);
311+
// createHandle will throw ERR_INVALID_FD_TYPE if `fd` is not
312+
// a valid `PIPE` or `TCP` descriptor
313+
this._handle = createHandle(fd, false);
314+
315+
err = this._handle.open(fd);
316+
317+
// While difficult to fabricate, in some architectures
318+
// `open` may return an error code for valid file descriptors
319+
// which cannot be opened. This is difficult to test as most
320+
// un-openable fds will throw on `createHandle`
321+
if (err)
322+
throw errnoException(err, 'open');
327323

328-
err = this._handle.open(fd);
324+
this[async_id_symbol] = this._handle.getAsyncId();
329325

330-
// While difficult to fabricate, in some architectures
331-
// `open` may return an error code for valid file descriptors
332-
// which cannot be opened. This is difficult to test as most
333-
// un-openable fds will throw on `createHandle`
326+
if ((fd === 1 || fd === 2) &&
327+
(this._handle instanceof Pipe) && isWindows) {
328+
// Make stdout and stderr blocking on Windows
329+
err = this._handle.setBlocking(true);
334330
if (err)
335-
throw errnoException(err, 'open');
336-
337-
this[async_id_symbol] = this._handle.getAsyncId();
338-
339-
if ((fd === 1 || fd === 2) &&
340-
(this._handle instanceof Pipe) && isWindows) {
341-
// Make stdout and stderr blocking on Windows
342-
err = this._handle.setBlocking(true);
343-
if (err)
344-
throw errnoException(err, 'setBlocking');
345-
346-
this._writev = null;
347-
this._write = makeSyncWrite(fd);
348-
// makeSyncWrite adjusts this value like the original handle would, so
349-
// we need to let it do that by turning it into a writable, own
350-
// property.
351-
ObjectDefineProperty(this._handle, 'bytesWritten', {
352-
value: 0, writable: true
353-
});
354-
}
331+
throw errnoException(err, 'setBlocking');
332+
333+
this._writev = null;
334+
this._write = makeSyncWrite(fd);
335+
// makeSyncWrite adjusts this value like the original handle would, so
336+
// we need to let it do that by turning it into a writable, own
337+
// property.
338+
ObjectDefineProperty(this._handle, 'bytesWritten', {
339+
value: 0, writable: true
340+
});
341+
}
342+
}
343+
344+
const onread = options.onread;
345+
if (onread !== null && typeof onread === 'object' &&
346+
(isUint8Array(onread.buffer) || typeof onread.buffer === 'function') &&
347+
typeof onread.callback === 'function') {
348+
if (typeof onread.buffer === 'function') {
349+
this[kBuffer] = true;
350+
this[kBufferGen] = onread.buffer;
351+
} else {
352+
this[kBuffer] = onread.buffer;
355353
}
354+
this[kBufferCb] = onread.callback;
356355
}
357356

358357
// Shut down the socket when we're finished with it.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.