js/net/quic/types

js/net/quic/types.ts

Types

type QuicAddress = { family: 'ipv4' | 'ipv6'; ip: string; port: number; }

A UDP socket address: an IP literal, its port, and its address family.

This is the currency of every QUIC path. Endpoints bind to a QuicAddress, connections carry a local and remote one, and migration and preferred-address handling exchange them. The ip field is an unresolved literal (no DNS is performed here); family must agree with the literal — an IPv4 dotted-quad pairs with 'ipv4' and a bracketless IPv6 literal with 'ipv6'. A port of 0 requests an ephemeral port, and the actual port chosen by the OS is read back from the bound listener or connection address.

const addr: QuicAddress = { family: 'ipv4', ip: '127.0.0.1', port: 4433 };

type QuicCaOptions = { file?: string; directory?: string; pem?: string | Uint8Array | Array<string | Uint8Array>; }

Sources of trusted CA certificates for peer verification.

Any combination may be supplied. file and directory point at PEM bundles on disk (OpenSSL's X509_STORE load paths); pem supplies in-memory certificate material as a PEM string, raw bytes, or an array mixing both. When none are given and verification is enabled, the OpenSSL backend falls back to the system default verify paths.

type QuicConnectionOptions = { handshakeTimeoutMs?: number; initialRttMs?: number; keepAliveTimeoutMs?: number; maxPayloadSize?: number; maxWindow?: number; maxStreamWindow?: number; unacknowledgedPacketThreshold?: number; congestionControl?: 'cubic' | 'reno' | 'bbr'; drainingPeriodMultiplier?: number; streamIdleTimeoutMs?: number; maxIdleTimeoutMs?: number; initialMaxData?: number; initialMaxStreamDataBidiLocal?: number; initialMaxStreamDataBidiRemote?: number; initialMaxStreamDataUni?: number; initialMaxStreamsBidi?: number; initialMaxStreamsUni?: number; activeConnectionIdLimit?: number; maxAckDelayMs?: number; ackDelayExponent?: number; disableActiveMigration?: boolean; cidLength?: number; }

Per-connection QUIC transport tuning.

type QuicConnectionState = 'connecting' | 'connected' | 'closing' | 'closed'

type QuicConnectionStats = { readonly createdAt: number; readonly connectedAt: number | null; readonly handshakeConfirmedAt: number | null; readonly closingAt: number | null; readonly destroyedAt: number | null; readonly bytesReceived: number; readonly bytesSent: number; readonly packetsReceived: number; readonly packetsSent: number; readonly datagramsReceived: number; readonly datagramsSent: number; readonly datagramsAcked: number; readonly datagramsLost: number; readonly datagramsAbandoned: number; readonly streamsOpened: number; readonly streamsReceived: number; readonly bidiIncomingStreams: number; readonly bidiOutgoingStreams: number; readonly uniIncomingStreams: number; readonly uniOutgoingStreams: number; readonly streamsClosed: number; readonly maxBytesInFlight: number; readonly bytesInFlight: number; readonly blockCount: number; readonly congestionWindow: number; readonly latestRttMs: number; readonly minRttMs: number; readonly rttVarianceMs: number; readonly smoothedRttMs: number; readonly slowStartThreshold: number; readonly packetsLost: number; readonly bytesLost: number; readonly pingReceived: number; readonly packetsDiscarded: number; readonly streamsIdleTimedOut: number; readonly pendingWriteBytes: number; readonly outstandingStreamBytes: number; readonly qlogOpenFailed: number; readonly qlogWriteFailed: number; }

Per-connection counters and recovery metrics, read from QuicConnection.stats.

Each read returns a frozen snapshot refreshed from ngtcp2's live connection info, so the RTT, congestion-window, bytes-in-flight, and loss fields track the current recovery state rather than lifetime totals. Timestamps are millisecond epochs and are null until the corresponding milestone occurs (connectedAt on handshake completion, closingAt/destroyedAt on close). Stream and datagram counts are lifetime totals for the connection.

type QuicDatagramOptions = { enabled?: boolean; maxFrameSize?: number; maxPending?: number; dropPolicy?: 'drop-oldest' | 'drop-newest'; maxSendAttempts?: number; }

QUIC DATAGRAM negotiation settings from RFC 9221.

type QuicDatagramStatus = 'ack' | 'lost' | 'abandoned'

Delivery state for a locally sent QUIC DATAGRAM frame.

type QuicEarlyDataPolicy = { replaySafe: true; maxBytes?: number; }

Explicit application policy required before sending replayable 0-RTT data.

type QuicEndpointStats = { createdAt: number; destroyedAt: number | null; packetsReceived: number; packetsSent: number; bytesReceived: number; bytesSent: number; packetsBlocked: number; sourceBlockedPackets: number; serverBusyCount: number; connectionLimitPackets: number; retrySent: number; retryRateLimited: number; retryTokenAccepted: number; retryTokenRejected: number; addressTokenAccepted: number; addressTokenRejected: number; versionNegotiationSent: number; versionNegotiationRateLimited: number; statelessResetSent: number; statelessResetRateLimited: number; immediateCloseSent: number; immediateCloseRateLimited: number; sessionCreationRateLimited: number; serverConnections: number; clientConnections: number; activeServerConnections: number; activeConnections: number; }

Aggregate counters for one QuicEndpoint, read from QuicEndpoint.stats.

Each read returns a frozen snapshot. Alongside packet/byte totals it records how the endpoint's server-side defenses behaved: how many packets were dropped by source-address filtering, rejected while busy or over the connection limit, and how the Retry, Version Negotiation, stateless-reset, immediate-close, and session-creation rate limiters fired. destroyedAt is null until the endpoint is closed. The active* fields are live gauges; the rest are monotonic counters.

type QuicKeylogOptions = false | { path: string; }

TLS keylog diagnostics configuration. Disabled by default.

type QuicMigrationOptions = { enabled?: boolean; preferredAddress?: QuicPreferredAddressOptions; usePreferredAddress?: boolean; }

Connection migration policy. Disabled by default.

type QuicPath = { localAddress: QuicAddress; remoteAddress: QuicAddress; }

Local and remote socket addresses associated with a QUIC network path.

type QuicPathValidationResult = 'success' | 'failure' | 'aborted'

Result of an ngtcp2 path-validation attempt.

type QuicQlogOptions = false | { path?: string; events?: string[]; }

qlog diagnostics configuration. Disabled by default.

type QuicRateLimitOptions = false | { rate?: number; burst?: number; }

Token-bucket rate limit configuration for endpoint packet defenses.

type QuicResolvedConnectionOptions = { readonly handshakeTimeoutMs: number; readonly initialRttMs: number; readonly keepAliveTimeoutMs: number; readonly maxPayloadSize: number; readonly maxWindow: number; readonly maxStreamWindow: number; readonly unacknowledgedPacketThreshold: number; readonly congestionControl: 'cubic' | 'reno' | 'bbr'; readonly drainingPeriodMultiplier: number; readonly streamIdleTimeoutMs: number; readonly cidLength: number; }

Frozen snapshot of an endpoint's resolved per-connection transport tuning.

Returned by QuicEndpoint.connection. It exposes the effective values with timeouts and windows converted back to the millisecond/byte units of QuicConnectionOptions (the internal representation is nanosecond/bigint).

type QuicResolvedRateLimitOptions = { readonly rate: number; readonly burst: number; }

Frozen view of a resolved token-bucket rate limit.

Exposed inside QuicResolvedTransportOptions so callers can inspect the effective packet-defense limits after endpoint defaults have been applied.

type QuicResolvedSourceAddressOptions = { readonly allow: readonly string[] | null; readonly deny: readonly string[]; }

Frozen view of the resolved source-address allow/deny lists.

allow is null when no allow-list was configured (all sources permitted unless denied); otherwise only the listed keys are permitted. deny always takes precedence over allow.

type QuicResolvedTransportOptions = { readonly busy: boolean; readonly maxConnections: number; readonly maxConnectionsPerRemoteAddress: number; readonly sourceAddress: QuicResolvedSourceAddressOptions; readonly retryTokenTimeoutMs: number; readonly addressTokenTimeoutMs: number; readonly addressValidationCacheSize: number; readonly retryRateLimit: QuicResolvedRateLimitOptions; readonly versionNegotiationRateLimit: QuicResolvedRateLimitOptions; readonly statelessResetRateLimit: QuicResolvedRateLimitOptions; readonly immediateCloseRateLimit: QuicResolvedRateLimitOptions; readonly sessionCreationRateLimit: QuicResolvedRateLimitOptions; readonly disableStatelessReset: boolean; readonly ecn: boolean; }

Frozen snapshot of an endpoint's resolved server-transport controls.

Returned by QuicEndpoint.transport. Every field reflects the effective value after endpoint defaults and per-call overrides were merged, with millisecond timeouts denormalized back from ngtcp2's nanosecond internals.

type QuicRetryOptions = false | { enabled: boolean; tokenSecret?: Uint8Array; }

Server Retry and address-validation configuration. Enabled by default.

type QuicSessionState = { ticket?: Uint8Array; addressToken?: Uint8Array; transportParameters?: Uint8Array; earlyDataMax?: number; version?: QuicVersion; expiresAt?: number; }

Persisted TLS session material for future resumption and 0-RTT support.

type QuicSNIContextOptions = { certificateFile: string; privateKeyFile: string; alpnProtocols?: string[]; tlsGroups?: string[]; clientAuth?: 'none' | 'request' | 'require'; verifyClient?: boolean; rejectUnauthorized?: boolean; ca?: QuicCaOptions; }

TLS context for one server name, selected by the client's SNI extension.

Supplied through QuicListenOptions.sni (or QuicListener.setSNIContexts), keyed by the server name it serves. certificateFile and privateKeyFile are required; the remaining fields default to the listener's own values when omitted, so an SNI entry can share the listener's ALPN and client-auth policy while presenting a different certificate.

type QuicSocketOptions = { ipv6Only?: boolean; reusePort?: boolean; receiveBufferSize?: number; sendBufferSize?: number; ttl?: number; }

Low-level UDP socket tuning applied to every socket an endpoint binds.

These map directly onto setsockopt calls made when the endpoint binds a datagram socket. They affect all listeners and the ephemeral client sockets alike, and cannot be changed per connection.

type QuicSourceAddressOptions = { allow?: string[]; deny?: string[]; }

Source-address allow/deny lists for incoming server packets.

type QuicTlsCipherSuite = 'TLS_AES_128_GCM_SHA256' | 'TLS_AES_256_GCM_SHA384' | 'TLS_CHACHA20_POLY1305_SHA256'

TLS 1.3 cipher suites that are compatible with QUIC packet protection.

type QuicTransportOptions = { busy?: boolean; maxConnections?: number; maxConnectionsPerRemoteAddress?: number; sourceAddress?: QuicSourceAddressOptions; retryTokenTimeoutMs?: number; addressTokenTimeoutMs?: number; addressValidationCacheSize?: number; retryRateLimit?: QuicRateLimitOptions; versionNegotiationRateLimit?: QuicRateLimitOptions; statelessResetRateLimit?: QuicRateLimitOptions; immediateCloseRateLimit?: QuicRateLimitOptions; sessionCreationRateLimit?: QuicRateLimitOptions; disableStatelessReset?: boolean; ecn?: boolean; }

Server-side QUIC transport controls and packet-defense tuning.

type QuicTransportParameterSnapshot = { readonly initialMaxStreamDataBidiLocal: number; readonly initialMaxStreamDataBidiRemote: number; readonly initialMaxStreamDataUni: number; readonly initialMaxData: number; readonly initialMaxStreamsBidi: number; readonly initialMaxStreamsUni: number; readonly maxIdleTimeoutMs: number; readonly maxUdpPayloadSize: number; readonly activeConnectionIdLimit: number; readonly ackDelayExponent: number; readonly maxAckDelayMs: number; readonly maxDatagramFrameSize: number; readonly disableActiveMigration: boolean; readonly preferredAddress: QuicAddress | null; readonly originalDestinationConnectionId: Uint8Array | null; readonly initialSourceConnectionId: Uint8Array | null; readonly retrySourceConnectionId: Uint8Array | null; readonly statelessResetToken: Uint8Array | null; }

Decoded QUIC transport parameters for one side of a connection.

Returned by QuicConnection.localTransportParameters and .remoteTransportParameters (both null before the native connection exists). It exposes the negotiated flow-control limits, idle timeout, ACK tuning, migration flag, advertised preferred address, and the connection-ID fields QUIC uses to bind the handshake — including the byte-array CIDs, each null when the peer did not send it.

type QuicVersion = 'v1' | 'v2'

Supported QUIC wire versions accepted by public endpoint options.

Interfaces

interface QuicConnectOptions {

Options for a single QuicEndpoint.connect() call.

address is the only required field — it names the server to dial. When serverName is omitted it defaults to 'localhost'; it is used both for SNI and for certificate verification when verifyPeer is set. Peer verification is opt-in: verifyPeer defaults to false, so callers dialing untrusted or self-signed servers get a working connection, and production clients should set it to true (optionally with ca trust anchors). Every non-address field inherits the endpoint default when omitted.

const conn = await endpoint.connect({
  address: { family: 'ipv4', ip: '203.0.113.10', port: 4433 },
  serverName: 'example.com',
  verifyPeer: true,
  alpnProtocols: ['h3'],
});

Properties

address: QuicAddress

Remote server address to dial. Required.

alpnProtocols?: string[]

ALPN protocols offered to the server; overrides the endpoint default.

serverName?: string

SNI / certificate-verification hostname; defaults to 'localhost'.

verifyPeer?: boolean

Verify the server certificate against the trust store. Defaults to false.

certificateFile?: string

Path to a PEM client certificate chain for mutual TLS.

privateKeyFile?: string

Path to the PEM client private key for mutual TLS.

ca?: QuicCaOptions

Trust anchors used to verify the server certificate.

versions?: QuicVersion[]

QUIC wire versions offered, in preference order.

tlsCipherSuites?: QuicTlsCipherSuite[]

TLS 1.3 cipher suites offered to the server.

tlsGroups?: string[]

Named key-exchange groups offered to the server.

retry?: QuicRetryOptions

Retry-token handling for this connection.

sessionStore?: QuicSessionStore

Session store consulted for resumption/0-RTT state, keyed by server name and ALPN.

earlyData?: false | QuicEarlyDataPolicy

0-RTT early-data policy for this connection.

migration?: QuicMigrationOptions

Migration policy, including whether active migration is permitted.

datagrams?: QuicDatagramOptions

DATAGRAM negotiation settings for this connection.

connection?: QuicConnectionOptions

Per-connection transport tuning.

transport?: QuicTransportOptions

Transport-level controls (mostly server-side; ECN applies to clients too).

qlog?: QuicQlogOptions

qlog diagnostics for this connection.

keylog?: QuicKeylogOptions

TLS keylog diagnostics for this connection.

interface QuicEndpointOptions {

Endpoint-wide defaults inherited by every listen() and connect() call.

These are the baseline for the endpoint. A QuicListenOptions or QuicConnectOptions passed to listen()/connect() is resolved against these defaults, so a value set here applies to every listener and connection on the endpoint unless the per-call options override it. Only socket is endpoint-only (it configures the UDP sockets themselves and cannot be overridden per connection).

import { QuicEndpoint } from 'internal:net/quic/endpoint';

const endpoint = new QuicEndpoint({
  alpnProtocols: ['h3'],
  versions: ['v1', 'v2'],
  datagrams: { enabled: true },
  connection: { maxIdleTimeoutMs: 30_000 },
  socket: { reusePort: true },
});

Properties

alpnProtocols?: string[]

Default ALPN protocol list offered/accepted; defaults to ['h3', 'fino-hq'].

versions?: QuicVersion[]

QUIC wire versions to enable; order expresses preference.

tlsCipherSuites?: QuicTlsCipherSuite[]

Restrict the TLS 1.3 cipher suites offered for QUIC packet protection.

tlsGroups?: string[]

Named key-exchange groups (curves) to offer, in preference order.

retry?: QuicRetryOptions

Server Retry / address-validation policy. Enabled by default.

sessionStore?: QuicSessionStore

Store used to persist and resume TLS session state for 0-RTT/resumption.

earlyData?: false | QuicEarlyDataPolicy

0-RTT early-data policy; false (default) disables early data.

migration?: QuicMigrationOptions

Connection migration and preferred-address policy.

datagrams?: QuicDatagramOptions

RFC 9221 DATAGRAM negotiation and queueing settings.

connection?: QuicConnectionOptions

Per-connection transport tuning (windows, timeouts, congestion control).

transport?: QuicTransportOptions

Server-side packet defenses and connection limits.

qlog?: QuicQlogOptions

qlog diagnostics output. Disabled by default.

keylog?: QuicKeylogOptions

TLS keylog (SSLKEYLOGFILE) diagnostics. Disabled by default.

socket?: QuicSocketOptions

UDP socket tuning applied to every socket this endpoint binds.

interface QuicListenOptions {

Options for a single QuicEndpoint.listen() call.

certificateFile and privateKeyFile are mandatory — listen() throws a TypeError without them. Every other field is optional and, when omitted, inherits the endpoint's QuicEndpointOptions default. The TLS and transport fields shared with the endpoint (versions, retry, datagrams, and so on) override the endpoint default for connections accepted by this listener only.

const listener = await endpoint.listen({
  address: { family: 'ipv4', ip: '0.0.0.0', port: 4433 },
  certificateFile: '/etc/tls/cert.pem',
  privateKeyFile: '/etc/tls/key.pem',
  alpnProtocols: ['h3'],
  clientAuth: 'request',
  sni: {
    'api.example.com': {
      certificateFile: '/etc/tls/api-cert.pem',
      privateKeyFile: '/etc/tls/api-key.pem',
    },
  },
});

Properties

address?: QuicAddress

Local address to bind; a port of 0 requests an ephemeral port.

alpnProtocols?: string[]

ALPN protocols this listener accepts; overrides the endpoint default.

certificateFile?: string

Path to the PEM server certificate chain. Required.

privateKeyFile?: string

Path to the PEM server private key. Required.

clientAuth?: 'none' | 'request' | 'require'

Whether client certificates are requested or required during the handshake.

verifyClient?: boolean

Request a client certificate; shorthand that maps onto clientAuth.

rejectUnauthorized?: boolean

Fail the handshake when a presented client certificate does not verify.

ca?: QuicCaOptions

Trust anchors used to verify client certificates.

sni?: Record<string, QuicSNIContextOptions>

Per-server-name TLS contexts selected by the client's SNI value.

versions?: QuicVersion[]

QUIC wire versions this listener accepts.

tlsCipherSuites?: QuicTlsCipherSuite[]

TLS 1.3 cipher suites offered by this listener.

tlsGroups?: string[]

Named key-exchange groups offered by this listener.

retry?: QuicRetryOptions

Retry / address-validation policy for this listener.

sessionStore?: QuicSessionStore

Session store used for this listener's resumption state.

earlyData?: false | QuicEarlyDataPolicy

0-RTT early-data policy for connections accepted by this listener.

migration?: QuicMigrationOptions

Migration / preferred-address policy advertised to accepted clients.

datagrams?: QuicDatagramOptions

DATAGRAM negotiation settings for this listener.

connection?: QuicConnectionOptions

Per-connection transport tuning for accepted connections.

transport?: QuicTransportOptions

Server packet defenses and connection limits for this listener.

qlog?: QuicQlogOptions

qlog diagnostics for connections accepted by this listener.

keylog?: QuicKeylogOptions

TLS keylog diagnostics for connections accepted by this listener.

interface QuicSessionStore {

Storage interface used by resumption and replay-checked 0-RTT policies.

Supplied as sessionStore in endpoint/connect options. On connect() the client loads any state keyed by server name and ALPN; when the server issues a session ticket or address-validation token it is saved back. Every method may be synchronous or async — the driver awaits the result — so a store can be an in-memory Map or a shared cache.

import type { QuicSessionStore, QuicSessionState } from 'internal:net/quic/endpoint';

const map = new Map<string, QuicSessionState>();
const store: QuicSessionStore = {
  load: (key) => map.get(key) ?? null,
  save: (key, state) => { map.set(key, state); },
  delete: (key) => { map.delete(key); },
};

const conn = await endpoint.connect({ address, sessionStore: store });

Methods

load(key: string): QuicSessionState | null | Promise<QuicSessionState | null>

Load a session by lookup key, or return null when no valid state exists.

save(key: string, state: QuicSessionState): void | Promise<void>

Persist session state for a future connection attempt.

delete(key: string): void | Promise<void>

Delete a session after expiry, incompatibility, or application policy change.