Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
22c2e34
meta: add additional gitignore entries
jasnell May 12, 2026
cabae1e
quic: improve backend quic packet processing
jasnell May 12, 2026
5360171
test: fixup quic tests
jasnell May 12, 2026
6011429
quic: improve batching of packet sending
jasnell May 12, 2026
3e09dd6
quic: add support for future ECN marking
jasnell May 12, 2026
8afc8d0
quic: cache the timestamp on send and receive
jasnell May 12, 2026
22fa893
quic: eliminate per-received datagram allocation
jasnell May 12, 2026
af6e9e1
quic: fix crash in early handshake failure
jasnell May 12, 2026
5107283
quic: fixup linting issue after other changes
jasnell May 12, 2026
5a73c7d
quic: implement rate limiting for version nego and immediate close
jasnell May 12, 2026
461fece
quic: add handshake timeout and default connection limits
jasnell May 12, 2026
fea579f
quic: add aliased struct arenas
jasnell May 13, 2026
7b3d437
quic: improve internal structure of QuicStream
jasnell May 13, 2026
4349b5a
quic: improve the quic js structure
jasnell May 14, 2026
19dc615
quic: fix UAF in Application::OnTimeout()
jasnell May 14, 2026
cd5f352
quic: fixup UAFs in bindingdata, streams, and app
jasnell May 14, 2026
159c0bc
quic: fix premature unref of endpoint when listening
jasnell May 14, 2026
6c2ba1d
quic: fixup some v8:: qualifiers
jasnell May 14, 2026
15f22b4
quic: fix tests that are missing serverEndpoint close
jasnell May 14, 2026
c0551c3
quic: apply multiple additional minor improvements
jasnell May 15, 2026
fdef9eb
quic: coalesce received data into fewer buffers
jasnell May 15, 2026
c429d16
quic: add reusePort option to QuicEndpoint
jasnell May 16, 2026
bd2e04d
quic: improve stream header collection performance
jasnell May 16, 2026
46a16bb
quic: enable recvmmsg batching in Endpoint
jasnell May 16, 2026
9651a8f
quic: add initial RTT option to session options
jasnell May 16, 2026
25af788
quic: improve recv coalescing test sizes
jasnell May 16, 2026
1cded9d
quic: add getters for local and remote transport parameters
jasnell May 16, 2026
4981fc5
quic: add applicationOptions to session
jasnell May 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
/tags
/tags.*
/doc/api.xml
/docs/
/node
/node_g
/gon-config.json
Expand Down
231 changes: 208 additions & 23 deletions doc/api/quic.md
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,18 @@ added: v23.8.0

A `QuicSession` represents the local side of a QUIC connection.

### `session.applicationOptions`

<!-- YAML
added: REPLACEME
-->

* Type: {quic.ApplicationOptions}

The current application-level options for this session. These include settings
that are specific to the negotiated application protocol (e.g. HTTP/3) and may
be negotiated separately from the transport parameters. Read only.

### `session.close([options])`

<!-- YAML
Expand Down Expand Up @@ -851,6 +863,17 @@ added: v23.8.0

True if `session.destroy()` has been called. Read only.

### `session.localTransportParams`

<!-- YAML
added: REPLACEME
-->

* Type: {quic.TransportParams|null}

The transport parameters advertised by the local endpoint during the handshake.
Returns `null` if the session has been destroyed. Read only.

### `session.endpoint`

<!-- YAML
Expand Down Expand Up @@ -1144,6 +1167,19 @@ added: v23.8.0

The local and remote socket addresses associated with the session. Read only.

### `session.remoteTransportParams`

<!-- YAML
added: REPLACEME
-->

* Type: {quic.TransportParams|null|undefined}

The transport parameters advertised by the remote peer during the handshake.
Returns `null` if the session has been destroyed, `undefined` if the handshake
has not yet completed and the remote parameters are not yet available. Read
only.

### `session.sendDatagram(datagram[, encoding])`

<!-- YAML
Expand Down Expand Up @@ -2094,6 +2130,20 @@ added: v23.8.0

* Type: {bigint}

### `streamStats.bytesAccumulated`

<!-- YAML
added: REPLACEME
-->

* Type: {bigint}

The current number of bytes sitting in the stream's receive accumulation
buffer, awaiting delivery to the application. A value near zero indicates
the reader is keeping up with incoming data. A value near the stream's
flow control window indicates the application is not consuming data fast
enough.

### `streamStats.bytesReceived`

<!-- YAML
Expand Down Expand Up @@ -2142,6 +2192,20 @@ added: v23.8.0

* Type: {bigint}

### `streamStats.maxBytesAccumulated`

<!-- YAML
added: REPLACEME
-->

* Type: {bigint}

The peak number of bytes that were accumulated in the stream's receive
buffer at any point during the stream's lifetime. This value only
increases monotonically. It is useful for diagnosing whether a stream
experienced backpressure episodes and whether the accumulation buffer
sizing is appropriate for the workload.

### `streamStats.maxOffset`

<!-- YAML
Expand Down Expand Up @@ -2184,6 +2248,70 @@ added: v23.8.0

## Types

### type: `ApplicationOptions`

<!-- YAML
added: REPLACEME
-->

* Type: {Object}

The application specific options.

#### `applicationOptions.maxHeaderPairs`

* Type: {bigint|number}

Maximum number of header name-value pairs accepted per header block.
Headers beyond this limit are silently dropped. **Default:** `128`

#### `applicationOptions.maxHeaderLength`

* Type: {bigint|number}

Maximum total byte length of all header names and values combined per header
block. Headers that would push the total over this limit are silently
dropped. **Default:** `8192`

#### `applicationOptions.maxFieldSectionSize`

* Type: {bigint|number}

Maximum size of a compressed header field section (QPACK). `0` means
unlimited. **Default:** `0`

#### `applicationOptions.qpackMaxDTableCapacity`

* Type: {bigint|number}

QPACK dynamic table capacity in bytes. Set to `0` to disable the dynamic
table. **Default:** `4096`

#### `applicationOptions.qpackEncoderMaxDTableCapacity`

* Type: {bigint|number}

QPACK encoder maximum dynamic table capacity. **Default:** `4096`

#### `applicationOptions.qpackBlockedStreams`

* Type: {bigint|number}

Maximum number of streams that can e blocked waiting for QPACK dynamic table
updates. **Default:** `100`

#### `applicationOptions.enableConnectProtocol`

* Type: {boolean}

Enable the extended CONNECT protocol (RFC 9220). **Default:** `false`

#### `applicationOptions.enableDatagrams`

* Type: {boolean}

Enable HTTP/3 datagrams (RFC 9297). **Default:** `false`

### Type: `EndpointOptions`

<!-- YAML
Expand Down Expand Up @@ -2258,6 +2386,23 @@ added: v23.8.0

When `true`, indicates that the endpoint should bind only to IPv6 addresses.

#### `endpointOptions.reusePort`

<!-- YAML
added: REPLACEME
-->

* Type: {boolean}
* Default: `false`

When `true`, allows multiple endpoints (across separate processes) to bind to
the same address and port. The kernel will load-balance incoming UDP datagrams
across all sockets bound with this option. This enables horizontal scaling of
QUIC servers by running multiple Node.js processes on the same port.

Supported on Linux 3.9+ and DragonFlyBSD 3.6+. On unsupported platforms, the
bind will fail with an error.

#### `endpointOptions.maxConnectionsPerHost`

<!-- YAML
Expand Down Expand Up @@ -2423,30 +2568,9 @@ Default: `'h3'`
added: REPLACEME
-->

* Type: {Object}
* Type: {quic.ApplicationOptions}

HTTP/3 application-specific options. These only apply when the negotiated
ALPN selects the HTTP/3 application (`'h3'`).

* `maxHeaderPairs` {number} Maximum number of header name-value pairs
accepted per header block. Headers beyond this limit are silently
dropped. **Default:** `128`
* `maxHeaderLength` {number} Maximum total byte length of all header
names and values combined per header block. Headers that would push
the total over this limit are silently dropped. **Default:** `8192`
* `maxFieldSectionSize` {number} Maximum size of a compressed header
field section (QPACK). `0` means unlimited. **Default:** `0`
* `qpackMaxDTableCapacity` {number} QPACK dynamic table capacity in
bytes. Set to `0` to disable the dynamic table. **Default:** `4096`
* `qpackEncoderMaxDTableCapacity` {number} QPACK encoder maximum
dynamic table capacity. **Default:** `4096`
* `qpackBlockedStreams` {number} Maximum number of streams that can
be blocked waiting for QPACK dynamic table updates.
**Default:** `100`
* `enableConnectProtocol` {boolean} Enable the extended CONNECT
protocol (RFC 9220). **Default:** `false`
* `enableDatagrams` {boolean} Enable HTTP/3 datagrams (RFC 9297).
**Default:** `false`
Application-specific options.

```mjs
const { listen } = await import('node:quic');
Expand Down Expand Up @@ -2698,6 +2822,23 @@ added: v23.8.0
Specifies the maximum number of milliseconds a TLS handshake is permitted to take
to complete before timing out.

#### `sessionOptions.initialRtt`

<!-- YAML
added: REPLACEME
-->

* Type: {bigint|number}
* **Default:** `0` (use ngtcp2 default of 333ms)

Specifies the initial round-trip time estimate in milliseconds. This value is
used for probe timeout (PTO) computation, initial pacing, and early loss
detection before the first actual RTT sample is collected from the connection.
The default of 333ms is appropriate for the general internet. For low-latency
environments such as loopback or same-rack deployments, setting a value closer
to the actual RTT (e.g., `1`) avoids unnecessarily conservative initial
behavior.

#### `sessionOptions.keepAlive`

<!-- YAML
Expand Down Expand Up @@ -2885,6 +3026,37 @@ won't have need to specify.
added: v23.8.0
-->

The `TransportParams` type represents the QUIC transport parameters that are
negotiated during session establishment. These parameters are used when
creating a session. The negotiated values can be observed via the
`session.localTransportParams` and `session.remoteTransportParams` properties.

#### `transportParams.initialSCID`

<!-- YAML
added: REPLACEME
-->

* Type: {string}

The initial source connection ID (SCID) specified. This field is ignored on
creation of the session and is provided for informational purposes only when
available in the `session.localTransportParams` and
`session.remoteTransportParams` properties.

#### `transportParams.originalDCID`

<!-- YAML
added: REPLACEME
-->

* Type: {string}

The original destination connection ID (DCID) specified. This field is
ignored on creation of the session and is provided for informational
purposes only when available in the `session.localTransportParams` and
`session.remoteTransportParams` properties.

#### `transportParams.preferredAddressIpv4`

<!-- YAML
Expand Down Expand Up @@ -2998,6 +3170,19 @@ will not send datagrams larger than this value. The actual maximum size of
a datagram that can be _sent_ is determined by the peer's
`maxDatagramFrameSize`, not this endpoint's value.

#### `transportParams.retrySCID`

<!-- YAML
added: REPLACEME
-->

* Type: {string}

The retry connection ID specified. This field is ignored on creation
of the session and is provided for informational purposes only when
available in the `session.localTransportParams` and
`session.remoteTransportParams` properties.

## Callbacks

### Callback error handling
Expand Down
6 changes: 6 additions & 0 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ function handleErrorFromBinding(error) {
}

class FileHandle extends EventEmitter {
#brandCheck = undefined;

static isFileHandle(value) {
return (value != null && typeof value === 'object' && #brandCheck in value);
}

/**
* @param {InternalFSBinding.FileHandle | undefined} filehandle
*/
Expand Down
Loading
Loading