diff --git a/doc/api/cli.md b/doc/api/cli.md index 87eda0deb66b46..4290f5461c6538 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -966,6 +966,14 @@ If the ES module being `require()`'d contains top-level `await`, this flag allows Node.js to evaluate the module, try to locate the top-level awaits, and print their location to help users find them. +### `--experimental-quic` + + + +Enables the experimental `node:quic` built-in module. + ### `--experimental-require-module` + +* `address` {string|net.SocketAddress} +* `options` {quic.SessionOptions} +* Returns: {Promise} a promise for a {quic.QuicSession} + +Initiate a new client-side session. ```mjs -import { QuicEndpoint } from 'node:quic'; +import { connect } from 'node:quic'; +import { Buffer } from 'node:buffer'; + +const enc = new TextEncoder(); +const alpn = 'foo'; +const client = await connect('123.123.123.123:8888', { alpn }); +await client.createUnidirectionalStream({ + body: enc.encode('hello world'), +}); +``` -const endpoint = new QuicEndpoint(); +By default, every call to `connect(...)` will create a new local +`QuicEndpoint` instance bound to a new random local IP port. To +specify the exact local address to use, or to multiplex multiple +QUIC sessions over a single local port, pass the `endpoint` option +with either a `QuicEndpoint` or `EndpointOptions` as the argument. -// Server... -endpoint.listen((session) => { - session.onstream = (stream) => { - // Handle the stream.... - }; +```mjs +import { QuicEndpoint, connect } from 'node:quic'; + +const endpoint = new QuicEndpoint({ + address: '127.0.0.1:1234', }); -// Client... -const client = endpoint.connect('123.123.123.123:8888'); -const stream = client.openBidirectionalStream(); +const client = await connect('123.123.123.123:8888', { endpoint }); ``` +## `quic.listen(onsession,[options])` + + + +* `onsession` {quic.OnSessionCallback} +* `options` {quic.SessionOptions} +* Returns: {Promise} a promise for a {quic.QuicEndpoint} + +Configures the endpoint to listen as a server. When a new session is initiated by +a remote peer, the given `onsession` callback will be invoked with the created +session. + +```mjs +import { listen } from 'node:quic'; + +const endpoint = await listen((session) => { + // ... handle the session +}); + +// Closing the endpoint allows any sessions open when close is called +// to complete naturally while preventing new sessions from being +// initiated. Once all existing sessions have finished, the endpoint +// will be destroyed. The call returns a promise that is resolved once +// the endpoint is destroyed. +await endpoint.close(); +``` + +By default, every call to `listen(...)` will create a new local +`QuicEndpoint` instance bound to a new random local IP port. To +specify the exact local address to use, or to multiplex multiple +QUIC sessions over a single local port, pass the `endpoint` option +with either a `QuicEndpoint` or `EndpointOptions` as the argument. + +At most, any single `QuicEndpoint` can only be configured to listen as +a server once. + +## Class: `QuicEndpoint` + +A `QuicEndpoint` encapsulates the local UDP-port binding for QUIC. It can be +used as both a client and a server. + ### `new QuicEndpoint([options])` -* `address` {string|net.SocketAddress} -* `options` {quic.SessionOptions} -* Returns: {quic.QuicSession} +* {boolean} -Initiate a new client-side session using this endpoint. +True if `endpoint.close()` has been called and closing the endpoint has not yet completed. +Read only. ### `endpoint.destroy([error])` @@ -130,10 +190,9 @@ added: REPLACEME --> * `error` {any} -* Returns: {Promise} Forcefully closes the endpoint by forcing all open sessions to be immediately -closed. Returns `endpoint.closed`. +closed. ### `endpoint.destroyed` @@ -145,56 +204,13 @@ added: REPLACEME True if `endpoint.destroy()` has been called. Read only. -### `endpoint.listen([onsession,][options])` - - - -* `onsession` {quic.OnSessionCallback} -* `options` {quic.SessionOptions} - -Configures the endpoint to listen as a server. When a new session is initiated by -a remote peer, the given `onsession` callback will be invoked with the created -session. - -The `onsession` callback must be specified either here or by setting the `onsession` -property or an error will be thrown. - -### `endpoint.onsession` - -* {quic.OnSessionCallback} - -The callback function that is invoked when a new session is initiated by a remote peer. -Read/write. - -### `endpoint.sessions` - - - -* {Iterator} of {quic.QuicSession}. - -An iterator over all sessions associated with this endpoint. Read only. - -### `endpoint.state` - - - -* {quic.QuicEndpointState} - -The state associated with an active session. Read only. - ### `endpoint.stats` -* {quic.QuicEndpointStats} +* {quic.QuicEndpoint.Stats} The statistics collected for an active session. Read only. @@ -207,64 +223,7 @@ added: REPLACEME Calls `endpoint.close()` and returns a promise that fulfills when the endpoint has closed. -## Class: `QuicEndpointState` - - - -A view of the internal state of an endpoint. - -### `endpointState.isBound` - - - -* {boolean} True if the endpoint is bound to a local UDP port. - -### `endpointState.isReceiving` - - - -* {boolean} True if the endpoint is bound to a local UDP port and actively listening - for packets. - -### `endpointState.isListening` - - - -* {boolean} True if the endpoint is listening as a server. - -### `endpointState.isClosing` - - - -* {boolean} True if the endpoint is in the process of closing down. - -### `endpointState.isBusy` - - - -* {boolean} True if the endpoint has been marked busy. - -### `endpointState.pendingCallbacks` - - - -* {bigint} The total number of pending callbacks the endpoint is waiting on currently. - -## Class: `QuicEndpointStats` +## Class: `QuicEndpoint.Stats` +A `QuicSession` represents the local side of a QUIC connection. + ### `session.close()` * `error` {any} -* Returns: {Promise} + +Immediately destroy the session. All streams will be destroys and the +session will be closed. ### `session.destroyed` @@ -416,6 +386,8 @@ added: REPLACEME * {boolean} +True if `session.destroy()` has been called. Read only. + ### `session.endpoint` * `options` {Object} - * `headers` {Object} -* Returns: {quic.QuicStream} + * `body` {ArrayBuffer | ArrayBufferView | Blob} + * `sendOrder` {number} +* Returns: {Promise} for a {quic.QuicStream} -### `session.openUnidirectionalStream([options])` +Open a new bidirectional stream. If the `body` option is not specified, +the outgoing stream will be half-closed. + +### `session.createUnidirectionalStream([options])` * `options` {Object} - * `headers` {Object -* Returns: {quic.QuicStream} + * `body` {ArrayBuffer | ArrayBufferView | Blob} + * `sendOrder` {number} +* Returns: {Promise} for a {quic.QuicStream} + +Open a new unidirectional stream. If the `body` option is not specified, +the outgoing stream will be closed. ### `session.path` @@ -510,22 +506,20 @@ added: REPLACEME * `local` {net.SocketAddress} * `remote` {net.SocketAddress} +The local and remote socket addresses associated with the session. Read only. + ### `session.sendDatagram(datagram)` -* `datagram` {Uint8Array} +* `datagram` {string|ArrayBufferView} * Returns: {bigint} -### `session.state` - - - -* {quic.QuicSessionState} +Sends an unreliable datagram to the remote peer, returning the datagram ID. +If the datagram payload is specified as an `ArrayBufferView`, then ownership of +that view will be transfered to the underlying stream. ### `session.stats` @@ -533,147 +527,28 @@ added: REPLACEME added: REPLACEME --> -* {quic.QuicSessionStats} - -### `session.updateKey()` - - - -### `session[Symbol.asyncDispose]()` - - - -## Class: `QuicSessionState` - - - -### `sessionState.hasPathValidationListener` - - - -* {boolean} - -### `sessionState.hasVersionNegotiationListener` - - - -* {boolean} - -### `sessionState.hasDatagramListener` - - - -* {boolean} - -### `sessionState.hasSessionTicketListener` - - - -* {boolean} - -### `sessionState.isClosing` - - - -* {boolean} - -### `sessionState.isGracefulClose` - - - -* {boolean} +* {quic.QuicSession.Stats} -### `sessionState.isSilentClose` +Return the current statistics for the session. Read only. - - -* {boolean} - -### `sessionState.isStatelessReset` - - - -* {boolean} - -### `sessionState.isDestroyed` - - - -* {boolean} - -### `sessionState.isHandshakeCompleted` - - - -* {boolean} - -### `sessionState.isHandshakeConfirmed` - - - -* {boolean} - -### `sessionState.isStreamOpenAllowed` - - - -* {boolean} - -### `sessionState.isPrioritySupported` - - - -* {boolean} - -### `sessionState.isWrapped` +### `session.updateKey()` -* {boolean} +Initiate a key update for the session. -### `sessionState.lastDatagramId` +### `session[Symbol.asyncDispose]()` -* {bigint} +Calls `session.close()` and returns a promise that fulfills when the +session has closed. -## Class: `QuicSessionStats` +## Class: `QuicSession.Stats` - -* {bigint} - ### `sessionStats.handshakeCompletedAt` - -* {bigint} - ### `sessionStats.bytesReceived` - -* {bigint} - ### `sessionStats.maxBytesInFlights` * `error` {any} -* Returns: {Promise} + +Immediately and abruptly destroys the stream. ### `stream.destroyed` @@ -918,6 +772,8 @@ added: REPLACEME * {boolean} +True if `stream.destroy()` has been called. + ### `stream.direction` - -* {quic.OnHeadersCallback} +The callback to invoke when the stream is blocked. Read/write. ### `stream.onreset` @@ -956,253 +810,48 @@ added: REPLACEME added: REPLACEME --> -* {quic.OnStreamErrorCallback} - -### `stream.ontrailers` - - - -* {quic.OnTrailersCallback} - -### `stream.pull(callback)` - - - -* `callback` {quic.OnPullCallback} - -### `stream.sendHeaders(headers)` - - - -* `headers` {Object} - -### `stream.session` - - - -* {quic.QuicSession} - -### `stream.state` - - - -* {quic.QuicStreamState} - -### `stream.stats` - - - -* {quic.QuicStreamStats} - -## Class: `QuicStreamState` - - - -### `streamState.destroyed` - - - -* {boolean} - -### `streamState.finReceived` - - - -* {boolean} - -### `streamState.finSent` - - - -* {boolean} - -### `streamState.hasReader` - - - -* {boolean} - -### `streamState.id` - - - -* {bigint} - -### `streamState.paused` - - - -* {boolean} - -### `streamState.pending` - - - -* {boolean} - -### `streamState.readEnded` - - - -* {boolean} - -### `streamState.reset` - - - -* {boolean} - -### `streamState.wantsBlock` - - - -* {boolean} - -### `streamState.wantsHeaders` - - - -* {boolean} - -### `streamState.wantsReset` - - - -* {boolean} - -### `streamState.wantsTrailers` - - - -* {boolean} - -### `streamState.writeEnded` - - - -* {boolean} - -## Class: `QuicStreamStats` - - - -### `streamStats.ackedAt` - - - -* {bigint} - -### `streamStats.bytesReceived` - - - -* {bigint} - -### `streamStats.bytesSent` - - - -* {bigint} - -### `streamStats.createdAt` - - - -* {bigint} - -### `streamStats.destroyedAt` - - - -* {bigint} +* {quic.OnStreamErrorCallback} -### `streamStats.finalSize` +The callback to invoke when the stream is reset. Read/write. + +### `stream.pull(callback)` -* {bigint} +* `callback` {quic.OnPullCallback} -### `streamStats.isConnected` +Read received data from the stream. The callback will be invoked with the +next chunk of received data. + +### `stream.session` -* {bigint} +* {quic.QuicSession} -### `streamStats.maxOffset` +The session that created this stream. Read only. + +### `stream.stats` -* {bigint} +* {quic.QuicStream.Stats} -### `streamStats.maxOffsetAcknowledged` +The current statistics for the stream. Read only. + +## Class: `QuicStream.Stats` -* {bigint} - -### `streamStats.maxOffsetReceived` +### `streamStats.ackedAt` -#### `applicationOptions.maxHeaderPairs` +* {bigint} + +### `streamStats.destroyedAt` -* {bigint|number} The maximum number of header pairs that can be received. +* {bigint} -#### `applicationOptions.maxHeaderLength` +### `streamStats.finalSize` -* {bigint|number} The maximum number of header bytes that can be received. +* {bigint} -#### `applicationOptions.maxFieldSectionSize` +### `streamStats.isConnected` -* {bigint|number} The maximum header field section size. +* {bigint} -#### `applicationOptions.qpackMaxDTableCapacity` +### `streamStats.maxOffset` -* {bigint|number} The QPack maximum dynamic table capacity. +* {bigint} -#### `applicationOptions.qpackEncoderMaxDTableCapacity` +### `streamStats.maxOffsetAcknowledged` -* {bigint|number} The QPack encoder maximum dynamic table capacity. +* {bigint} -#### `applicationOptions.qpackBlockedStreams` +### `streamStats.maxOffsetReceived` -* {bigint|number} The maximum number of QPack blocked streams. +* {bigint} -#### `applicationOptions.enableConnectProtocol` +### `streamStats.openedAt` -* {boolean} - -True to allow use of the `CONNECT` method when using HTTP/3. +* {bigint} -#### `applicationOptions.enableDatagrams` +### `streamStats.receivedAt` -* {boolean} +* {bigint} -True to allow use of unreliable datagrams. +## Types ### Type: `EndpointOptions` @@ -1310,6 +957,8 @@ added: REPLACEME * {Object} +The endpoint configuration options passed when constructing a new `QuicEndpoint` instance. + #### `endpointOptions.address` - -* {string|number} - -Specifies the congestion control algorithm that will be used by all sessions -using this endpoint. Must be set to one of: - -* `QuicEndpoint.CC_ALGO_RENO` -* `QuicEndpoint.CC_ALGP_RENO_STR` -* `QuicEndpoint.CC_ALGO_CUBIC` -* `QuicEndpoint.CC_ALGO_CUBIC_STR` -* `QuicEndpoint.CC_ALGO_BBR` -* `QuicEndpoint.CC_ALGO_BBR_STR` - -This is an advanced option that users typically won't have need to specify -unless. - -#### `endpointOptions.disableActiveMigration` - - - -* {boolean} - -When `true`, this option disables the ability for a session to migrate to a different -socket address. - -\*\* THIS OPTION IS AT RISK OF BEING DROPPED \*\* - -#### `endpointOptions.handshakeTimeout` - - - -* {bigint|number} - -Specifies the maximum number of milliseconds a TLS handshake is permitted to take -to complete before timing out. - #### `endpointOptions.ipv6Only` - -* {bigint|number} - -Specifies the maximum UDP packet payload size. - #### `endpointOptions.maxRetries` - -* {bigint|number} - -Specifies the maximum stream flow-control window size. - -#### `endpointOptions.maxWindow` - - - -* {bigint|number} - -Specifies the maxumum session flow-control window size. - -#### `endpointOptions.noUdpPayloadSizeShaping` - - - -* {boolean} - #### `endpointOptions.retryTokenExpiration` -* {bigint|number} +* {boolean} -Specifies the maximum number of unacknowledged packets a session should allow. +When `true`, requires that the endpoint validate peer addresses using retry packets +while establishing a new connection. -#### `endpointOptions.validateAddress` +### Type: `SessionOptions` -* {boolean} +#### `sessionOptions.alpn` + + -When `true`, requires that the endpoint validate peer addresses while establishing -a connection. +* {string} -### Type: `SessionOptions` +The ALPN protocol identifier. + +#### `sessionOptions.ca` -#### `sessionOptions.application` +* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} + +The CA certificates to use for sessions. + +#### `sessionOptions.cc` -* {quic.ApplicationOptions} +* {string} + +Specifies the congestion control algorithm that will be used +. Must be set to one of either `'reno'`, `'cubic'`, or `'bbr'`. -The application-level options to use for the session. +This is an advanced option that users typically won't have need to specify. -#### `sessionOptions.minVersion` +#### `sessionOptions.certs` -* {number} +* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} -The minimum QUIC version number to allow. This is an advanced option that users -typically won't have need to specify. +The TLS certificates to use for sessions. -#### `sessionOptions.preferredAddressPolicy` +#### `sessionOptions.ciphers` -* {string} One of `'use'`, `'ignore'`, or `'default'`. +* {string} -When the remote peer advertises a preferred address, this option specifies whether -to use it or ignore it. +The list of supported TLS 1.3 cipher algorithms. -#### `sessionOptions.qlog` +#### `sessionOptions.crl` -* {boolean} +* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} -True if qlog output should be enabled. +The CRL to use for sessions. -#### `sessionOptions.sessionTicket` +#### `sessionOptions.groups` -* {ArrayBufferView} A session ticket to use for 0RTT session resumption. +* {string} + +The list of support TLS 1.3 cipher groups. -#### `sessionOptions.tls` +#### `sessionOptions.keylog` -* {quic.TlsOptions} +* {boolean} -The TLS options to use for the session. +True to enable TLS keylogging output. -#### `sessionOptions.transportParams` +#### `sessionOptions.keys` -* {quic.TransportParams} +* {KeyObject|CryptoKey|KeyObject\[]|CryptoKey\[]} -The QUIC transport parameters to use for the session. +The TLS crypto keys to use for sessions. -#### `sessionOptions.version` +#### `sessionOptions.maxPayloadSize` -* {number} +* {bigint|number} -The QUIC version number to use. This is an advanced option that users typically -won't have need to specify. +Specifies the maximum UDP packet payload size. -### Type: `TlsOptions` +#### `sessionOptions.maxStreamWindow` -#### `tlsOptions.sni` +* {bigint|number} + +Specifies the maximum stream flow-control window size. + +#### `sessionOptions.maxWindow` -* {string} +* {bigint|number} -The peer server name to target. +Specifies the maxumum session flow-control window size. -#### `tlsOptions.alpn` +#### `sessionOptions.minVersion` -* {string} +* {number} -The ALPN protocol identifier. +The minimum QUIC version number to allow. This is an advanced option that users +typically won't have need to specify. -#### `tlsOptions.ciphers` +#### `sessionOptions.preferredAddressPolicy` -* {string} +* {string} One of `'use'`, `'ignore'`, or `'default'`. -The list of supported TLS 1.3 cipher algorithms. +When the remote peer advertises a preferred address, this option specifies whether +to use it or ignore it. -#### `tlsOptions.groups` +#### `sessionOptions.qlog` -* {string} +* {boolean} -The list of support TLS 1.3 cipher groups. +True if qlog output should be enabled. -#### `tlsOptions.keylog` +#### `sessionOptions.sessionTicket` -* {boolean} +* {ArrayBufferView} A session ticket to use for 0RTT session resumption. -True to enable TLS keylogging output. +#### `sessionOptions.handshakeTimeout` + + + +* {bigint|number} + +Specifies the maximum number of milliseconds a TLS handshake is permitted to take +to complete before timing out. -#### `tlsOptions.verifyClient` +#### `sessionOptions.sni` -* {boolean} +* {string} -True to require verification of TLS client certificate. +The peer server name to target. -#### `tlsOptions.tlsTrace` +#### `sessionOptions.tlsTrace` -* {boolean} +* {quic.TransportParams} -True to require private key verification. +The QUIC transport parameters to use for the session. -#### `tlsOptions.keys` +#### `sessionOptions.unacknowledgedPacketThreshold` -* {KeyObject|CryptoKey|KeyObject\[]|CryptoKey\[]} +* {bigint|number} -The TLS crypto keys to use for sessions. +Specifies the maximum number of unacknowledged packets a session should allow. -#### `tlsOptions.certs` +#### `sessionOptions.verifyClient` -* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} +* {boolean} -The TLS certificates to use for sessions. +True to require verification of TLS client certificate. -#### `tlsOptions.ca` +#### `sessionOptions.verifyPrivateKey` -* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} +* {boolean} -The CA certificates to use for sessions. +True to require private key verification. -#### `tlsOptions.crl` +#### `sessionOptions.version` -* {ArrayBuffer|ArrayBufferView|ArrayBuffer\[]|ArrayBufferView\[]} +* {number} -The CRL to use for sessions. +The QUIC version number to use. This is an advanced option that users typically +won't have need to specify. ### Type: `TransportParams` @@ -1874,14 +1468,6 @@ added: REPLACEME * {bigint|number} -#### `transportParams.disableActiveMigration` - - - -* {boolean} - ## Callbacks ### Callback: `OnSessionCallback` @@ -1990,24 +1576,6 @@ added: REPLACEME * `this` {quic.QuicStream} * `error` {any} -### Callback: `OnHeadersCallback` - - - -* `this` {quic.QuicStream} -* `headers` {Object} -* `kind` {string} - -### Callback: `OnTrailersCallback` - - - -* `this` {quic.QuicStream} - ### Callback: `OnPullCallback`