From 79c0e892dd10bc951220419eff2c2fec786823c9 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 9 Jul 2020 17:33:30 -0700 Subject: [PATCH] quic: implement QuicSocket Promise API, part 1 PR-URL: https://github.com/nodejs/node/pull/34283 Reviewed-By: Anna Henningsen --- doc/api/quic.md | 112 +++-- lib/internal/quic/core.js | 452 ++++++++---------- ...t-quic-client-connect-multiple-parallel.js | 60 +-- ...quic-client-connect-multiple-sequential.js | 61 ++- ...est-quic-client-empty-preferred-address.js | 17 +- test/parallel/test-quic-client-server.js | 359 +++++++------- ...test-quic-errors-quicsession-openstream.js | 21 +- .../test-quic-errors-quicsocket-connect.js | 291 ++++++----- .../test-quic-errors-quicsocket-listen.js | 182 ++++--- .../parallel/test-quic-http3-client-server.js | 130 +++-- test/parallel/test-quic-http3-push.js | 169 ++++--- test/parallel/test-quic-http3-trailers.js | 115 +++-- test/parallel/test-quic-idle-timeout.js | 11 +- test/parallel/test-quic-ipv6only.js | 56 +-- test/parallel/test-quic-keylog.js | 15 +- .../test-quic-maxconnectionsperhost.js | 75 ++- test/parallel/test-quic-process-cleanup.js | 39 +- test/parallel/test-quic-qlog.js | 32 +- ...est-quic-quicsession-openstream-pending.js | 12 +- test/parallel/test-quic-quicsession-resume.js | 36 +- .../parallel/test-quic-quicsession-send-fd.js | 64 +-- ...quicsession-send-file-close-before-open.js | 47 +- ...uicsession-send-file-open-error-handled.js | 62 +-- ...t-quic-quicsession-send-file-open-error.js | 58 +-- ...t-quic-quicsession-server-destroy-early.js | 80 +--- ...-quicsession-server-openstream-pending.js} | 12 +- ...st-quic-quicsocket-packetloss-stream-rx.js | 99 ++-- ...st-quic-quicsocket-packetloss-stream-tx.js | 103 ++-- .../test-quic-quicsocket-serverbusy.js | 46 +- test/parallel/test-quic-quicsocket.js | 12 +- .../test-quic-quicstream-close-early.js | 97 +--- test/parallel/test-quic-quicstream-destroy.js | 71 ++- .../test-quic-quicstream-identifiers.js | 124 +++-- ...quic-server-listening-event-error-async.js | 4 +- .../test-quic-server-listening-event-error.js | 4 +- ...t-quic-server-session-event-error-async.js | 47 +- .../test-quic-server-session-event-error.js | 47 +- .../test-quic-simple-client-migrate.js | 94 ++-- test/parallel/test-quic-statelessreset.js | 63 ++- test/parallel/test-quic-with-fake-udp.js | 49 +- .../test-quic-preferred-address-ipv6.js | 123 ----- .../sequential/test-quic-preferred-address.js | 128 ----- 42 files changed, 1596 insertions(+), 2083 deletions(-) rename test/parallel/{test-quic-quicession-server-openstream-pending.js => test-quic-quicsession-server-openstream-pending.js} (87%) delete mode 100644 test/sequential/test-quic-preferred-address-ipv6.js delete mode 100644 test/sequential/test-quic-preferred-address.js diff --git a/doc/api/quic.md b/doc/api/quic.md index dee7f65f55cd49..318f48cc62094e 100644 --- a/doc/api/quic.md +++ b/doc/api/quic.md @@ -25,11 +25,6 @@ const { createQuicSocket } = require('net'); // Create the QUIC UDP IPv4 socket bound to local IP port 1234 const socket = createQuicSocket({ endpoint: { port: 1234 } }); -// Tell the socket to operate as a server using the given -// key and certificate to secure new connections, using -// the fictional 'hello' application protocol. -socket.listen({ key, cert, alpn: 'hello' }); - socket.on('session', (session) => { // A new server side session has been created! @@ -53,9 +48,14 @@ socket.on('session', (session) => { }); }); -socket.on('listening', () => { - // The socket is listening for sessions! -}); +// Tell the socket to operate as a server using the given +// key and certificate to secure new connections, using +// the fictional 'hello' application protocol. +(async function() { + await socket.listen({ key, cert, alpn: 'hello' }); + console.log('The socket is listening for sessions!'); +})(); + ``` ## QUIC Basics @@ -110,11 +110,13 @@ const { createQuicSocket } = require('net'); // Create a QuicSocket associated with localhost and port 1234 const socket = createQuicSocket({ endpoint: { port: 1234 } }); -const client = socket.connect({ - address: 'example.com', - port: 4567, - alpn: 'foo' -}); +(async function() { + const client = await socket.connect({ + address: 'example.com', + port: 4567, + alpn: 'foo' + }); +})(); ``` As soon as the `QuicClientSession` is created, the `address` provided in @@ -135,20 +137,22 @@ New instances of `QuicServerSession` are created internally by the using the `listen()` method. ```js +const { createQuicSocket } = require('net'); + const key = getTLSKeySomehow(); const cert = getTLSCertSomehow(); -socket.listen({ - key, - cert, - alpn: 'foo' -}); +const socket = createQuicSocket(); socket.on('session', (session) => { session.on('secure', () => { // The QuicServerSession can now be used for application data }); }); + +(async function() { + await socket.listen({ key, cert, alpn: 'foo' }); +})(); ``` As with client `QuicSession` instances, the `QuicServerSession` cannot be @@ -1275,20 +1279,17 @@ added: REPLACEME Set to `true` if the `QuicClientSession` is ready for use. False if the `QuicSocket` has not yet been bound. -#### quicclientsession.setSocket(socket, callback]) +#### quicclientsession.setSocket(socket]) * `socket` {QuicSocket} A `QuicSocket` instance to move this session to. -* `callback` {Function} A callback function that will be invoked once the - migration to the new `QuicSocket` is complete. +* Returns: {Promise} Migrates the `QuicClientSession` to the given `QuicSocket` instance. If the new `QuicSocket` has not yet been bound to a local UDP port, it will be bound prior -to attempting the migration. If the `QuicClientSession` is not yet ready to -migrate, the callback will be invoked with an `Error` using the code -`ERR_OPERATION_FAILED`. +to attempting the migration. ### Class: QuicServerSession extends QuicSession @@ -1877,13 +1882,10 @@ added: REPLACEME [OpenSSL Options][]. * `sessionIdContext` {string} Opaque identifier used by servers to ensure session state is not shared between applications. Unused by clients. +* Returns: {Promise} -* `callback` {Function} - -Listen for new peer-initiated sessions. - -If a `callback` is given, it is registered as a handler for the -`'session'` event. +Listen for new peer-initiated sessions. Returns a `Promise` that is resolved +once the `QuicSocket` is actively listening. #### quicsocket.listenDuration -* Type: {number} - -The number of stateless resets that have been sent. +* Type: {boolean} `true` if stateless reset processing is enabled; `false` + if disabled. -Read-only. +By default, a listening `QuicSocket` will generate stateless reset tokens when +appropriate. The `disableStatelessReset` option may be set when the +`QuicSocket` is created to disable generation of stateless resets. The +`quicsocket.statelessReset` property allows stateless reset to be turned on and +off dynamically through the lifetime of the `QuicSocket`. -#### quicsocket.toggleStatelessReset() +#### quicsocket.statelessResetCount -* Returns {boolean} `true` if stateless reset processing is enabled; `false` - if disabled. +* Type: {number} -By default, a listening `QuicSocket` will generate stateless reset tokens when -appropriate. The `disableStatelessReset` option may be set when the -`QuicSocket` is created to disable generation of stateless resets. The -`toggleStatelessReset()` function allows stateless reset to be turned on and -off dynamically through the lifetime of the `QuicSocket`. +The number of stateless resets that have been sent. + +Read-only. #### quicsocket.unref();