diff --git a/doc/api/tls.md b/doc/api/tls.md index 6239ec6f4174d4..21eec25b337554 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -455,7 +455,10 @@ changes: description: ALPN options are supported now. --> -* `socket` {net.Socket} An instance of [`net.Socket`][] +* `socket` {net.Socket|stream.Duplex} + On the server side, any `Duplex` stream. On the client side, any + instance of [`net.Socket`][] (for generic `Duplex` stream support + on the client side, [`tls.connect()`][] must be used). * `options` {Object} * `isServer`: The SSL/TLS protocol is asymmetrical, TLSSockets must know if they are to behave as a server or a client. If `true` the TLS socket will be @@ -815,10 +818,12 @@ changes: * `port` {number} Port the client should connect to. * `path` {string} Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. - * `socket` {net.Socket} Establish secure connection on a given socket rather - than creating a new socket. If this option is specified, `path`, `host` and - `port` are ignored. Usually, a socket is already connected when passed to - `tls.connect()`, but it can be connected later. Note that + * `socket` {stream.Duplex} Establish secure connection on a given socket + rather than creating a new socket. Typically, this is an instance of + [`net.Socket`][], but any `Duplex` stream is allowed. + If this option is specified, `path`, `host` and `port` are ignored, + except for certificate validation. Usually, a socket is already connected + when passed to `tls.connect()`, but it can be connected later. Note that connection/disconnection/destruction of `socket` is the user's responsibility, calling `tls.connect()` will not cause `net.connect()` to be called. diff --git a/test/parallel/test-tls-generic-stream.js b/test/parallel/test-tls-generic-stream.js new file mode 100644 index 00000000000000..d4e5427acae110 --- /dev/null +++ b/test/parallel/test-tls-generic-stream.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const fixtures = require('../common/fixtures'); +const makeDuplexPair = require('../common/duplexpair'); +const assert = require('assert'); +const { TLSSocket, connect } = require('tls'); + +const key = fixtures.readKey('agent1-key.pem'); +const cert = fixtures.readKey('agent1-cert.pem'); +const ca = fixtures.readKey('ca1-cert.pem'); + +const { clientSide, serverSide } = makeDuplexPair(); + +const clientTLS = connect({ + socket: clientSide, + ca, + host: 'agent1' // Hostname from certificate +}); +const serverTLS = new TLSSocket(serverSide, { + isServer: true, + key, + cert, + ca +}); + +assert.strictEqual(clientTLS.connecting, false); +assert.strictEqual(serverTLS.connecting, false); + +clientTLS.on('secureConnect', common.mustCall(() => { + clientTLS.write('foobar', common.mustCall(() => { + assert.strictEqual(serverTLS.read().toString(), 'foobar'); + assert.strictEqual(clientTLS._handle.writeQueueSize, 0); + })); + assert.ok(clientTLS._handle.writeQueueSize > 0); +})); diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index 43af1cb97819a5..3bcdd817a2f134 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -49,6 +49,7 @@ const typeMap = { 'Stream': 'stream.html#stream_stream', 'stream.Readable': 'stream.html#stream_class_stream_readable', 'stream.Writable': 'stream.html#stream_class_stream_writable', + 'stream.Duplex': 'stream.html#stream_class_stream_duplex', 'tls.TLSSocket': 'tls.html#tls_class_tls_tlssocket',