js/net/quic/listener

js/net/quic/listener.ts

fino:net/quic/listener — QUIC listener lifecycle.

A QuicListener is created by QuicEndpoint.listen() and owns the server side of a UDP binding until closed. Accepted connections are still delivered by the endpoint through connection events and accept().

import { QuicEndpoint } from 'fino:net/quic/endpoint';
import type { QuicListener } from 'fino:net/quic/listener';

const endpoint = new QuicEndpoint({ alpnProtocols: ['h3'] });
const listener: QuicListener = await endpoint.listen({
  address: { family: 'ipv4', ip: '127.0.0.1', port: 4433 },
});

await listener.close();
await endpoint.close();

Classes

class QuicListener {

A bound server listener created by QuicEndpoint.listen().

Each listener owns the UDP socket(s) bound for one listen() call — the listen address plus any advertised preferred addresses — and the TLS server context (including per-SNI contexts). It runs the receive loop that feeds incoming packets into the endpoint's connection routing; accepted connections surface on the endpoint, not the listener. Construct one only through endpoint.listen().

close() releases the listener's sockets and TLS contexts and unregisters it from the endpoint. The listener also implements Symbol.asyncDispose. SNI contexts can be swapped at runtime with setSNIContexts().

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',
});
console.log('listening on', listener.address.port);
// ...later
await listener.close();

Readonly Properties

readonly endpoint: QuicEndpoint

The endpoint that owns this listener.

readonly address: QuicAddress

The bound local address, with any ephemeral port resolved.

readonly alpnProtocols: string[]

ALPN protocols this listener accepts.

readonly options: ResolvedQuicOptions

Resolved options this listener was created with.

Constructors

constructor( endpoint: QuicEndpoint, address: QuicAddress, alpnProtocols: string[], transports: QuicDatagramTransport[], ctx: QuicTlsContext, options: ResolvedQuicOptions, sniContexts: Map<string, QuicTlsContext> = new Map( ) )

Constructed internally by QuicEndpoint.listen(); not a public entry point.

Getters

get closed(): boolean

Whether this listener has been closed.

get retryTokenSecret(): Uint8Array

Secret used to mint and verify this listener's Retry tokens.

get resetTokenSecret(): Uint8Array

Secret used to derive this listener's stateless-reset tokens.

Methods

async close(): Promise<void>

Close the listener, releasing its sockets and TLS contexts.

Unregisters the listener from its endpoint, frees the main and per-SNI TLS contexts, and closes every socket bound for it. Idempotent; also invoked by Symbol.asyncDispose. Existing connections accepted through this listener are unaffected.

getSNIContexts(): Record<string, QuicSNIContextOptions>

Return the server names that currently have a dedicated SNI context.

The values are placeholder objects — the certificate and key paths are not echoed back — so this is a listing of configured names, not a way to read secrets.

setSNIContexts(entries: Record<string, QuicSNIContextOptions>): void

Replace this listener's per-server-name TLS contexts.

Builds fresh TLS contexts for the given entries and swaps them in atomically, freeing the previous contexts. If building any entry fails, no change is made and the error propagates. Throws if the listener is closed.

listener.setSNIContexts({
  'api.example.com': {
    certificateFile: '/etc/tls/api-cert.pem',
    privateKeyFile: '/etc/tls/api-key.pem',
  },
});

Interfaces

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.

Types

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.