Node.js v15.0.0-v8-canary202007012ebe3fc1ae Documentation


Table of Contents

QUIC#

Stability: 1 - Experimental

The net module provides an implementation of the QUIC protocol. To access it, the Node.js binary must be compiled using the --experimental-quic configuration flag.

const { createQuicSocket } = require('net');

Example#

'use strict';

const key = getTLSKeySomehow();
const cert = getTLSCertSomehow();

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!

  session.on('secure', () => {
    // Once the TLS handshake is completed, we can
    // open streams...
    const uni = session.openStream({ halfOpen: true });
    uni.write('hi ');
    uni.end('from the server!');
  });

  // The peer opened a new stream!
  session.on('stream', (stream) => {
    // Let's say hello
    stream.end('Hello World');

    // Let's see what the peer has to say...
    stream.setEncoding('utf8');
    stream.on('data', console.log);
    stream.on('end', () => console.log('stream ended'));
  });
});

socket.on('listening', () => {
  // The socket is listening for sessions!
});

QUIC Basics#

QUIC is a UDP-based network transport protocol that includes built-in security via TLS 1.3, flow control, error correction, connection migration, multiplexing, and more.

Within the Node.js implementation of the QUIC protocol, there are three main components: the QuicSocket, the QuicSession and the QuicStream.

QuicSocket#

A QuicSocket encapsulates a binding to one or more local UDP ports. It is used to send data to, and receive data from, remote endpoints. Once created, a QuicSocket is associated with a local network address and IP port and can act as both a QUIC client and server simultaneously. User code at the JavaScript level interacts with the QuicSocket object to:

  • Query or modified the properties of the local UDP binding;
  • Create client QuicSession instances;
  • Wait for server QuicSession instances; or
  • Query activity statistics

Unlike the net.Socket and tls.TLSSocket, a QuicSocket instance cannot be directly used by user code at the JavaScript level to send or receive data over the network.

Client and Server QuicSessions#

A QuicSession represents a logical connection between two QUIC endpoints (a client and a server). In the JavaScript API, each is represented by the QuicClientSession and QuicServerSession specializations.

At any given time, a QuicSession exists is one of four possible states:

  • Initial - Entered as soon as the QuicSession is created.
  • Handshake - Entered as soon as the TLS 1.3 handshake between the client and server begins. The handshake is always initiated by the client.
  • Ready - Entered as soon as the TLS 1.3 handshake completes. Once the QuicSession enters the Ready state, it may be used to exchange application data using QuicStream instances.
  • Closed - Entere as soon as the QuicSession connection has been terminated.

New instances of QuicClientSession are created using the connect() function on a QuicSocket as in the example below:

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'
});

As soon as the QuicClientSession is created, the address provided in the connect options will be resolved to an IP address (if necessary), and the TLS 1.3 handshake will begin. The QuicClientSession cannot be used to exchange application data until after the 'secure' event has been emitted by the QuicClientSession object, signaling the completion of the TLS 1.3 handshake.

client.on('secure', () => {
  // The QuicClientSession can now be used for application data
});

New instances of QuicServerSession are created internally by the QuicSocket if it has been configured to listen for new connections using the listen() method.

const key = getTLSKeySomehow();
const cert = getTLSCertSomehow();

socket.listen({
  key,
  cert,
  alpn: 'foo'
});

socket.on('session', (session) => {
  session.on('secure', () => {
    // The QuicServerSession can now be used for application data
  });
});

As with client QuicSession instances, the QuicServerSession cannot be used to exhange application data until the 'secure' event has been emitted.

QuicSession and ALPN#

QUIC uses the TLS 1.3 ALPN ("Application-Layer Protocol Negotiation") extension to identify the application level protocol that is using the QUIC connection. Every QuicSession instance has an ALPN identifier that must be specified in either the connect() or listen() options. ALPN identifiers that are known to Node.js (such as the ALPN identifier for HTTP/3) will alter how the QuicSession and QuicStream objects operate internally, but the QUIC implementation for Node.js has been designed to allow any ALPN to be specified and used.

QuicStream#

Once a QuicSession transitions to the Ready state, QuicStream instances may be created and used to exchange application data. On a general level, all QuicStream instances are simply Node.js Duplex Streams that allow bidirectional data flow between the QUIC client and server. However, the application protocol negotiated for the QuicSession may alter the semantics and operation of a QuicStream associated with the session. Specifically, some features of the QuicStream (e.g. headers) are enabled only if the application protocol selected is known by Node.js to support those features.

Once the QuicSession is ready, a QuicStream may be created by either the client or server, and may be unidirectional or bidirectional.

The openStream() method is used to create a new QuicStream:

// Create a new bidirectional stream
const stream1 = session.openStream();

// Create a new unidirectional stream
const stream2 = session.openStream({ halfOpen: true });

As suggested by the names, a bidirectional stream allows data to be sent on a stream in both directions, by both client and server, regardless of which peer opened the stream. A unidirectional stream can be written to only by the QuicSession that opened it.

The 'stream' event is emitted by the QuicSession when a new QuicStream has been initated by the connected peer:

session.on('stream', (stream) => {
  if (stream.bidirectional) {
    stream.write('Hello World');
    stream.end();
  }
  stream.on('data', console.log);
  stream.on('end', () => {});
});

QuicStream Headers#

Some QUIC application protocols (like HTTP/3) make use of headers.

There are four kinds of headers that the Node.js QUIC implementation is capable of handling dependent entirely on known application protocol support:

  • Informational Headers
  • Initial Headers
  • Trailing Headers
  • Push Headers

These categories correlate exactly with the equivalent HTTP concepts:

  • Informational Headers: Any response headers transmitted within a block of headers using a 1xx status code.
  • Initial Headers: HTTP request or response headers
  • Trailing Headers: A block of headers that follow the body of a request or response.
  • Push Promise Headers: A block of headers included in a promised push stream.

If headers are supported by the application protocol in use for a given QuicSession, the 'initialHeaders', 'informationalHeaders', and 'trailingHeaders' events will be emitted by the QuicStream object when headers are received; and the submitInformationalHeaders(), submitInitialHeaders(), and submitTrailingHeaders() methods can be used to send headers.

QUIC and HTTP/3#

HTTP/3 is an application layer protocol that uses QUIC as the transport.

TBD

QUIC JavaScript API#

net.createQuicSocket([options])#

  • options <Object>

    • client <Object> A default configuration for QUIC client sessions created using quicsocket.connect().
    • endpoint <Object> An object describing the local address to bind to.

      • address <string> The local address to bind to. This may be an IPv4 or IPv6 address or a host name. If a host name is given, it will be resolved to an IP address.
      • port <number> The local port to bind to.
      • type <string> Either 'udp4' or 'upd6' to use either IPv4 or IPv6, respectively. Default: 'udp4'.
      • ipv6Only <boolean> If type is 'udp6', then setting ipv6Only to true will disable dual-stack support on the UDP binding -- that is, binding to address '::' will not make '0.0.0.0' be bound. The option is ignored if type is 'udp4'. Default: false.
    • lookup <Function> A custom DNS lookup function. Default dns.lookup().
    • maxConnections <number> The maximum number of total active inbound connections.
    • maxConnectionsPerHost <number> The maximum number of inbound connections allowed per remote host. Default: 100.
    • maxStatelessResetsPerHost <number> The maximum number of stateless resets that the QuicSocket is permitted to send per remote host. Default: 10.
    • qlog <boolean> Whether to emit 'qlog' events for incoming sessions. (For outgoing client sessions, set client.qlog.) Default: false.
    • retryTokenTimeout <number> The maximum number of seconds for retry token validation. Default: 10 seconds.
    • server <Object> A default configuration for QUIC server sessions.
    • validateAddress <boolean> When true, the QuicSocket will use explicit address validation using a QUIC RETRY frame when listening for new server sessions. Default: false.
    • validateAddressLRU <boolean> When true, validation will be skipped if the address has been recently validated. Currently, only the 10 most recently validated addresses are remembered. Setting validateAddressLRU to true, will enable the validateAddress option as well. Default: false.

The net.createQuicSocket() function is used to create new QuicSocket instances associated with a local UDP address.

Class: QuicEndpoint#

The QuicEndpoint wraps a local UDP binding used by a QuicSocket to send and receive data. A single QuicSocket may be bound to multiple QuicEndpoint instances at any given time.

Users will not create instances of QuicEndpoint directly.

quicendpoint.addMembership(address, iface)#

Tells the kernel to join a multicast group at the given multicastAddress and multicastInterface using the IP_ADD_MEMBERSHIP socket option. If the multicastInterface argument is not specified, the operating system will choose one interface and will add membership to it. To add membership to every available interface, call addMembership() multiple times, once per interface.

quicendpoint.address#

  • Type: Address

An object containing the address information for a bound QuicEndpoint.

The object will contain the properties:

  • address <string> The local IPv4 or IPv6 address to which the QuicEndpoint is bound.
  • family <string> Either 'IPv4' or 'IPv6'.
  • port <number> The local IP port to which the QuicEndpoint is bound.

If the QuicEndpoint is not bound, quicendpoint.address is an empty object.

quicendpoint.bound#

Set to true if the QuicEndpoint is bound to the local UDP port.

quicendpoint.closing#

Set to true if the QuicEndpoint is in the process of closing.

quicendpoint.destroy([error])#

Closes and destroys the QuicEndpoint instance making it usuable.

quicendpoint.destroyed#

Set to true if the QuicEndpoint has been destroyed.

quicendpoint.dropMembership(address, iface)#

Instructs the kernel to leave a multicast group at multicastAddress using the IP_DROP_MEMBERSHIP socket option. This method is automatically called by the kernel when the socket is closed or the process terminates, so most apps will never have reason to call this.

If multicastInterface is not specified, the operating system will attempt to drop membership on all valid interfaces.

quicendpoint.fd#

The system file descriptor the QuicEndpoint is bound to. This property is not set on Windows.

quicendpoint.pending#

Set to true if the QuicEndpoint is in the process of binding to the local UDP port.

quicendpoint.ref()#

quicendpoint.setBroadcast([on])#

Sets or clears the SO_BROADCAST socket option. When set to true, UDP packets may be sent to a local interface's broadcast address.

quicendpoint.setMulticastInterface(iface)#

All references to scope in this section are referring to IPv6 Zone Indices, which are defined by RFC 4007. In string form, an IP with a scope index is written as 'IP%scope' where scope is an interface name or interface number.

Sets the default outgoing multicast interface of the socket to a chosen interface or back to system interface selection. The multicastInterface must be a valid string representation of an IP from the socket's family.

For IPv4 sockets, this should be the IP configured for the desired physical interface. All packets sent to multicast on the socket will be sent on the interface determined by the most recent successful use of this call.

For IPv6 sockets, multicastInterface should include a scope to indicate the interface as in the examples that follow. In IPv6, individual send calls can also use explicit scope in addresses, so only packets sent to a multicast address without specifying an explicit scope are affected by the most recent successful use of this call.

Examples: IPv6 Outgoing Multicast Interface#

On most systems, where scope format uses the interface name:

const { createQuicSocket } = require('net');
const socket = createQuicSocket({ endpoint: { type: 'udp6', port: 1234 } });

socket.on('ready', () => {
  socket.endpoints[0].setMulticastInterface('::%eth1');
});

On Windows, where scope format uses an interface number:

const { createQuicSocket } = require('net');
const socket = createQuicSocket({ endpoint: { type: 'udp6', port: 1234 } });

socket.on('ready', () => {
  socket.endpoints[0].setMulticastInterface('::%2');
});
Example: IPv4 Outgoing Multicast Interface#

All systems use an IP of the host on the desired physical interface:

const { createQuicSocket } = require('net');
const socket = createQuicSocket({ endpoint: { type: 'udp4', port: 1234 } });

socket.on('ready', () => {
  socket.endpoints[0].setMulticastInterface('10.0.0.2');
});
Call Results#

A call on a socket that is not ready to send or no longer open may throw a Not running Error.

If multicastInterface can not be parsed into an IP then an EINVAL System Error is thrown.

On IPv4, if multicastInterface is a valid address but does not match any interface, or if the address does not match the family then a System Error such as EADDRNOTAVAIL or EPROTONOSUP is thrown.

On IPv6, most errors with specifying or omitting scope will result in the socket continuing to use (or returning to) the system's default interface selection.

A socket's address family's ANY address (IPv4 '0.0.0.0' or IPv6 '::') can be used to return control of the sockets default outgoing interface to the system for future multicast packets.

quicendpoint.setMulticastLoopback([on])#

Sets or clears the IP_MULTICAST_LOOP socket option. When set to true, multicast packets will also be received on the local interface.

quicendpoint.setMulticastTTL(ttl)#

Sets the IP_MULTICAST_TTL socket option. While TTL generally stands for "Time to Live", in this context it specifies the number of IP hops that a packet is allowed to travel through, specifically for multicast traffic. Each router or gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.

The argument passed to setMulticastTTL() is a number of hops between 0 and 255. The default on most systems is 1 but can vary.

quicendpoint.setTTL(ttl)#

Sets the IP_TTL socket option. While TTL generally stands for "Time to Live", in this context it specifies the number of IP hops that a packet is allowed to travel through. Each router or gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded. Changing TTL values is typically done for network probes or when multicasting.

The argument to setTTL() is a number of hops between 1 and 255. The default on most systems is 64 but can vary.

quicendpoint.unref()#

Class: QuicSession extends EventEmitter#

The QuicSession is an abstract base class that defines events, methods, and properties that are shared by both QuicClientSession and QuicServerSession.

Users will not create instances of QuicSession directly.

Event: 'close'#

Emitted after the QuicSession has been destroyed and is no longer usable.

The 'close' event will not be emitted more than once.

Event: 'error'#

Emitted immediately before the 'close' event if the QuicSession was destroyed with an error.

The callback will be invoked with a single argument:

The 'error' event will not be emitted more than once.

Event: 'keylog'#

Emitted when key material is generated or received by a QuicSession (typically during or immediately following the handshake process). This keying material can be stored for debugging, as it allows captured TLS traffic to be decrypted. It may be emitted multiple times per QuicSession instance.

The callback will be invoked with a single argument:

  • line Line of ASCII text, in NSS SSLKEYLOGFILE format.

A typical use case is to append received lines to a common text file, which is later used by software (such as Wireshark) to decrypt the traffic:

const log = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
// ...
session.on('keylog', (line) => log.write(line));

The 'keylog' event will be emitted multiple times.

Event: 'pathValidation'#

Emitted when a path validation result has been determined. This event is strictly informational. When path validation is successful, the QuicSession will automatically update to use the new validated path.

The callback will be invoked with three arguments:

  • result <string> Either 'failure' or 'success', denoting the status of the path challenge.
  • local <Object> The local address component of the tested path.
  • remote <Object> The remote address component of the tested path.

The 'pathValidation' event will be emitted multiple times.

Event: 'qlog'#

Emitted if the qlog: true option was passed to quicsocket.connect() or net.createQuicSocket() functions.

The argument is a JSON fragment according to the qlog standard.

The 'qlog' event will be emitted multiple times.

Event: 'secure'#

Emitted after the TLS handshake has been completed.

The callback will be invoked with two arguments:

  • servername <string> The SNI servername requested by the client.
  • alpnProtocol <string> The negotiated ALPN protocol.
  • cipher <Object> Information about the selected cipher algorithm.

    • name <string> The cipher algorithm name.
    • version <string> The TLS version (currently always 'TLSv1.3').

These will also be available using the quicsession.servername, quicsession.alpnProtocol, and quicsession.cipher properties.

The 'secure' event will not be emitted more than once.

Event: 'stream'#

Emitted when a new QuicStream has been initiated by the connected peer.

The 'stream' event may be emitted multiple times.

quicsession.ackDelayRetransmitCount#

A BigInt representing the number of retransmissions caused by delayed acknowledgements.

quicsession.address#

  • Type: <Object>

    • address <string> The local IPv4 or IPv6 address to which the QuicSession is bound.
    • family <string> Either 'IPv4' or 'IPv6'.
    • port <number> The local IP port to which the QuicSocket is bound.

An object containing the local address information for the QuicSocket to which the QuicSession is currently associated.

quicsession.alpnProtocol#

The ALPN protocol identifier negotiated for this session.

quicsession.authenticated#

True if the certificate provided by the peer during the TLS 1.3 handshake has been verified.

quicsession.authenticationError#

If quicsession.authenticated is false, returns an Error object representing the reason the peer certificate verification failed.

quicsession.bidiStreamCount#

A BigInt representing the total number of bidirectional streams created for this QuicSession.

quicsession.blockCount#

A BigInt representing the total number of times the QuicSession has been blocked from sending stream data due to flow control.

Such blocks indicate that transmitted stream data is not being consumed quickly enough by the connected peer.

quicsession.bytesInFlight#

The total number of unacknowledged bytes this QUIC endpoint has transmitted to the connected peer.

quicsession.bytesReceived#

A BigInt representing the total number of bytes received from the peer.

quicsession.bytesSent#

A BigInt representing the total number of bytes sent to the peer.

quicsession.cipher#

Information about the cipher algorithm selected for the session.

quicsession.close([callback])#

  • callback <Function> Callback invoked when the close operation is completed

Begins a graceful close of the QuicSession. Existing QuicStream instances will be permitted to close naturally. New QuicStream instances will not be permitted. Once all QuicStream instances have closed, the QuicSession instance will be destroyed.

quicsession.closeCode#

  • Type: <Object>

    • code <number> The error code reported when the QuicSession closed.
    • family <number> The type of error code reported (0 indicates a QUIC protocol level error, 1 indicates a TLS error, 2 represents an application level error.)

quicsession.closing#

Set to true if the QuicSession is in the process of a graceful shutdown.

quicsession.destroy([error])#

Destroys the QuicSession immediately causing the close event to be emitted. If error is not undefined, the error event will be emitted immediately before the close event.

Any QuicStream instances that are still opened will be abruptly closed.

quicsession.destroyed#

Set to true if the QuicSession has been destroyed.

quicsession.duration#

A BigInt representing the length of time the QuicSession was active.

quicsession.getCertificate()#

Returns an object representing the local certificate. The returned object has some properties corresponding to the fields of the certificate.

If there is no local certificate, or if the QuicSession has been destroyed, an empty object will be returned.

quicsession.getPeerCertificate([detailed])#

Returns an object representing the peer's certificate. If the peer does not provide a certificate, or if the QuicSession has been destroyed, an empty object will be returned.

If the full certificate chain was requested (details equals true), each certificate will include an issuerCertificate property containing an object representing the issuer's certificate.

quicsession.handshakeAckHistogram#

TBD

quicsession.handshakeContinuationHistogram#

TBD

quicsession.handshakeComplete#

Set to true if the TLS handshake has completed.

quicsession.handshakeConfirmed#

Set to true when the TLS handshake completion has been confirmed.

quicsession.handshakeDuration#

A BigInt representing the length of time taken to complete the TLS handshake.

quicsession.idleTimeout#

Set to true if the QuicSession was closed due to an idle timeout.

quicsession.keyUpdateCount#

A BigInt representing the number of key update operations that have occured.

quicsession.latestRTT#

The most recently recorded RTT for this QuicSession.

quicsession.lossRetransmitCount#

A BigInt representing the number of lost-packet retransmissions that have been performed on this QuicSession.

quicsession.maxDataLeft#

The total number of bytes the QuicSession is currently allowed to send to the connected peer.

quicsession.maxInFlightBytes#

A BigInt representing the maximum number of in-flight bytes recorded for this QuicSession.

quicsession.maxStreams#

  • Type: <Object>

    • uni <number> The maximum number of unidirectional streams.
    • bidi <number> The maximum number of bidirectional streams.

The highest cumulative number of bidirectional and unidirectional streams that can currently be opened. The values are set initially by configuration parameters when the QuicSession is created, then updated over the lifespan of the QuicSession as the connected peer allows new streams to be created.

quicsession.minRTT#

The minimum RTT recorded so far for this QuicSession.

quicsession.openStream([options])#

  • options <Object>

    • halfOpen <boolean> Set to true to open a unidirectional stream, false to open a bidirectional stream. Default: true.
    • highWaterMark <number> Total number of bytes that the QuicStream may buffer internally before the quicstream.write() function starts returning false. Default: 16384.
    • defaultEncoding <string> The default encoding that is used when no encoding is specified as an argument to quicstream.write(). Default: 'utf8'.
  • Returns: <QuicStream>

Returns a new QuicStream.

An error will be thrown if the QuicSession has been destroyed or is in the process of a graceful shutdown.

quicsession.ping()#

The ping() method will trigger the underlying QUIC connection to serialize any frames currently pending in the outbound queue if it is able to do so. This has the effect of keeping the connection with the peer active and resets the idle and retransmission timers. The ping() method is a best-effort that ignores any errors that may occur during the serialization and send operations. There is no return value and there is no way to monitor the status of the ping() operation.

quicsession.peerInitiatedStreamCount#

A BigInt representing the total number of QuicStreams initiated by the connected peer.

quicsession.remoteAddress#

  • Type: <Object>

    • address <string> The local IPv4 or IPv6 address to which the QuicSession is connected.
    • family <string> Either 'IPv4' or 'IPv6'.
    • port <number> The local IP port to which the QuicSocket is bound.

An object containing the remote address information for the connected peer.

quicsession.selfInitiatedStreamCount#

A BigInt representing the total number of QuicStream instances initiated by this QuicSession.

quicsession.servername#

The SNI servername requested for this session by the client.

quicsession.smoothedRTT#

The modified RTT calculated for this QuicSession.

quicsession.socket#

The QuicSocket the QuicSession is associated with.

quicsession.statelessReset#

True if the QuicSession was closed due to QUIC stateless reset.

quicsession.uniStreamCount#

A BigInt representing the total number of unidirectional streams created on this QuicSession.

quicsession.updateKey()#

  • Returns: <boolean> true if the key update operation is successfully initiated.

Initiates QuicSession key update.

An error will be thrown if called before quicsession.handshakeConfirmed is equal to true.

quicsession.usingEarlyData#

On server QuicSession instances, set to true on completion of the TLS handshake if early data is enabled. On client QuicSession instances, set to true on handshake completion if early data is enabled and was accepted by the server.

Class: QuicClientSession extends QuicSession#

The QuicClientSession class implements the client side of a QUIC connection. Instances are created using the quicsocket.connect() method.

Event: 'OCSPResponse'#

Emitted when the QuicClientSession receives a requested OCSP certificate status response from the QUIC server peer.

The callback is invoked with a single argument:

Node.js does not perform any automatic validation or processing of the response.

The 'OCSPResponse' event will not be emitted more than once.

Event: 'sessionTicket'#

The 'sessionTicket' event is emitted when a new TLS session ticket has been generated for the current QuicClientSession. The callback is invoked with two arguments:

  • sessionTicket <Buffer> The serialized session ticket.
  • remoteTransportParams <Buffer> The serialized remote transport parameters provided by the QUIC server.

The sessionTicket and remoteTransportParams are useful when creating a new QuicClientSession to more quickly resume an existing session.

The 'sessionTicket' event may be emitted multiple times.

Event: 'usePreferredAddress'#

The 'usePreferredAddress' event is emitted when the client QuicSession is updated to use the server-advertised preferred address. The callback is invoked with a single address argument:

This event is purely informational and will be emitted only when preferredAddressPolicy is set to 'accept'.

The 'usePreferredAddress' event will not be emitted more than once.

quicclientsession.ephemeralKeyInfo#

An object representing the type, name, and size of parameter of an ephemeral key exchange in Perfect Forward Secrecy on a client connection. It is an empty object when the key exchange is not ephemeral. The supported types are 'DH' and 'ECDH'. The name property is available only when type is 'ECDH'.

For example: { type: 'ECDH', name: 'prime256v1', size: 256 }.

quicclientsession.ready#

Set to true if the QuicClientSession is ready for use. False if the QuicSocket has not yet been bound.

quicclientsession.setSocket(socket, callback])#

  • 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.

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_QUICCLIENTSESSION_FAILED_SETSOCKET.

Class: QuicServerSession extends QuicSession#

The QuicServerSession class implements the server side of a QUIC connection. Instances are created internally and are emitted using the QuicSocket 'session' event.

Event: 'clientHello'#

Emitted at the start of the TLS handshake when the QuicServerSession receives the initial TLS Client Hello.

The event handler is given a callback function that must be invoked for the handshake to continue.

The callback is invoked with four arguments:

  • alpn <string> The ALPN protocol identifier requested by the client.
  • servername <string> The SNI servername requested by the client.
  • ciphers <string[]> The list of TLS cipher algorithms requested by the client.
  • callback <Function> A callback function that must be called in order for the TLS handshake to continue.

The 'clientHello' event will not be emitted more than once.

Event: 'OCSPRequest'#

Emitted when the QuicServerSession has received a OCSP certificate status request as part of the TLS handshake.

The callback is invoked with three arguments:

The callback must be invoked in order for the TLS handshake to continue.

The 'OCSPRequest' event will not be emitted more than once.

quicserversession.addContext(servername[, context])#

  • servername <string> A DNS name to associate with the given context.
  • context <tls.SecureContext> A TLS SecureContext to associate with the servername.

TBD

Class: QuicSocket#

New instances of QuicSocket are created using the net.createQuicSocket() method.

Once created, a QuicSocket can be configured to work as both a client and a server.

Event: 'busy'#

Emitted when the server busy state has been toggled using quicSocket.setServerBusy(). The callback is invoked with a single boolean argument indicating true if busy status is enabled, false otherwise. This event is strictly informational.

const { createQuicSocket } = require('net');

const socket = createQuicSocket();

socket.on('busy', (busy) => {
  if (busy)
    console.log('Server is busy');
  else
    console.log('Server is not busy');
});

socket.setServerBusy(true);
socket.setServerBusy(false);

This 'busy' event may be emitted multiple times.

Event: 'close'#

Emitted after the QuicSocket has been destroyed and is no longer usable.

The 'close' event will not be emitted multiple times.

Event: 'error'#

Emitted before the 'close' event if the QuicSocket was destroyed with an error.

The 'error' event will not be emitted multiple times.

Event: 'ready'#

Emitted once the QuicSocket has been bound to a local UDP port.

The 'ready' event will not be emitted multiple times.

Event: 'session'#

Emitted when a new QuicServerSession has been created.

The 'session' event will be emitted multiple times.

quicsocket.addEndpoint(options)#

  • options: <Object> An object describing the local address to bind to.

    • address <string> The local address to bind to. This may be an IPv4 or IPv6 address or a host name. If a host name is given, it will be resolved to an IP address.
    • port <number> The local port to bind to.
    • type <string> Either 'udp4' or 'upd6' to use either IPv4 or IPv6, respectively. Default: 'udp4'.
    • ipv6Only <boolean> If type is 'udp6', then setting ipv6Only to true will disable dual-stack support on the UDP binding -- that is, binding to address '::' will not make '0.0.0.0' be bound. The option is ignored if type is 'udp4'. Default: false.
  • Returns: <QuicEndpoint>

Creates and adds a new QuicEndpoint to the QuicSocket instance.

quicsocket.bound#

Will be true if the QuicSocket has been successfully bound to the local UDP port.

quicsocket.boundDuration#

A BigInt representing the length of time this QuicSocket has been bound to a local port.

quicsocket.bytesReceived#

A BigInt representing the number of bytes received by this QuicSocket.

quicsocket.bytesSent#

A BigInt representing the number of bytes sent by this QuicSocket.

quicsocket.clientSessions#

A BigInt representing the number of client QuicSession instances that have been associated with this QuicSocket.

quicsocket.close([callback])#

Gracefully closes the QuicSocket. Existing QuicSession instances will be permitted to close naturally. New QuicClientSession and QuicServerSession instances will not be allowed.

quicsocket.connect([options])#

  • options <Object>

    • address <string> The domain name or IP address of the QUIC server endpoint.
    • alpn <string> An ALPN protocol identifier.
    • ca <string> | <string[]> | <Buffer> | <Buffer[]> Optionally override the trusted CA certificates. Default is to trust the well-known CAs curated by Mozilla. Mozilla's CAs are completely replaced when CAs are explicitly specified using this option. The value can be a string or Buffer, or an Array of strings and/or Buffers. Any string or Buffer can contain multiple PEM CAs concatenated together. The peer's certificate must be chainable to a CA trusted by the server for the connection to be authenticated. When using certificates that are not chainable to a well-known CA, the certificate's CA must be explicitly specified as a trusted or the connection will fail to authenticate. If the peer uses a certificate that doesn't match or chain to one of the default CAs, use the ca option to provide a CA certificate that the peer's certificate can match or chain to. For self-signed certificates, the certificate is its own CA, and must be provided. For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE", "X509 CERTIFICATE", and "CERTIFICATE".
    • cert <string> | <string[]> | <Buffer> | <Buffer[]> Cert chains in PEM format. One cert chain should be provided per private key. Each cert chain should consist of the PEM formatted certificate for a provided private key, followed by the PEM formatted intermediate certificates (if any), in order, and not including the root CA (the root CA must be pre-known to the peer, see ca). When providing multiple cert chains, they do not have to be in the same order as their private keys in key. If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail.
    • ciphers <string> Cipher suite specification, replacing the default. For more information, see modifying the default cipher suite. Permitted ciphers can be obtained via tls.getCiphers(). Cipher names must be uppercased in order for OpenSSL to accept them.
    • clientCertEngine <string> Name of an OpenSSL engine which can provide the client certificate.
    • crl <string> | <string[]> | <Buffer> | <Buffer[]> PEM formatted CRLs (Certificate Revocation Lists).
    • defaultEncoding <string> The default encoding that is used when no encoding is specified as an argument to quicstream.write(). Default: 'utf8'.
    • dhparam <string> | <Buffer> Diffie Hellman parameters, required for Perfect Forward Secrecy. Use openssl dhparam to create the parameters. The key length must be greater than or equal to 1024 bits, otherwise an error will be thrown. It is strongly recommended to use 2048 bits or larger for stronger security. If omitted or invalid, the parameters are silently discarded and DHE ciphers will not be available.
    • ecdhCurve <string> A string describing a named curve or a colon separated list of curve NIDs or names, for example P-521:P-384:P-256, to use for ECDH key agreement. Set to auto to select the curve automatically. Use crypto.getCurves() to obtain a list of available curve names. On recent releases, openssl ecparam -list_curves will also display the name and description of each available elliptic curve. Default: tls.DEFAULT_ECDH_CURVE.
    • highWaterMark <number> Total number of bytes that the QuicStream may buffer internally before the quicstream.write() function starts returning false. Default: 16384.
    • honorCipherOrder <boolean> Attempt to use the server's cipher suite preferences instead of the client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be set in secureOptions, see OpenSSL Options for more information.
    • idleTimeout <number>
    • ipv6Only <boolean> If type is 'udp6', then setting ipv6Only to true will disable dual-stack support on the UDP binding -- that is, binding to address '::' will not make '0.0.0.0' be bound. The option is ignored if type is 'udp4'. Default: false.
    • key <string> | <string[]> | <Buffer> | <Buffer[]> | <Object[]> Private keys in PEM format. PEM allows the option of private keys being encrypted. Encrypted keys will be decrypted with options.passphrase. Multiple keys using different algorithms can be provided either as an array of unencrypted key strings or buffers, or an array of objects in the form {pem: <string|buffer>[, passphrase: <string>]}. The object form can only occur in an array. object.passphrase is optional. Encrypted keys will be decrypted with object.passphrase if provided, or options.passphrase if it is not.
    • activeConnectionIdLimit <number> Must be a value between 2 and 8 (inclusive). Default: 2.
    • congestionAlgorithm <string> Must be either 'reno' or 'cubic'. Default: 'reno'.
    • maxAckDelay <number>
    • maxData <number>
    • maxUdpPayloadSize <number>
    • maxStreamDataBidiLocal <number>
    • maxStreamDataBidiRemote <number>
    • maxStreamDataUni <number>
    • maxStreamsBidi <number>
    • maxStreamsUni <number>
    • h3 <Object> HTTP/3 Specific Configuration Options

    • passphrase <string> Shared passphrase used for a single private key and/or a PFX.
    • pfx <string> | <string[]> | <Buffer> | <Buffer[]> | <Object[]> PFX or PKCS12 encoded private key and certificate chain. pfx is an alternative to providing key and cert individually. PFX is usually encrypted, if it is, passphrase will be used to decrypt it. Multiple PFX can be provided either as an array of unencrypted PFX buffers, or an array of objects in the form {buf: <string|buffer>[, passphrase: <string>]}. The object form can only occur in an array. object.passphrase is optional. Encrypted PFX will be decrypted with object.passphrase if provided, or options.passphrase if it is not.
    • port <number> The IP port of the remote QUIC server.
    • preferredAddressPolicy <string> 'accept' or 'reject'. When 'accept', indicates that the client will automatically use the preferred address advertised by the server.
    • remoteTransportParams <Buffer> | <TypedArray> | <DataView> The serialized remote transport parameters from a previously established session. These would have been provided as part of the 'sessionTicket' event on a previous QuicClientSession object.
    • qlog <boolean> Whether to emit 'qlog' events for this session. Default: false.
    • requestOCSP <boolean> If true, specifies that the OCSP status request extension will be added to the client hello and an 'OCSPResponse' event will be emitted before establishing a secure communication.
    • secureOptions <number> Optionally affect the OpenSSL protocol behavior, which is not usually necessary. This should be used carefully if at all! Value is a numeric bitmask of the SSL_OP_* options from OpenSSL Options.
    • servername <string> The SNI servername.
    • sessionTicket: <Buffer> | <TypedArray> | <DataView> The serialized TLS Session Ticket from a previously established session. These would have been provided as part of the 'sessionTicket' event on a previous QuicClientSession object.
    • type: <string> Identifies the type of UDP socket. The value must either be 'udp4', indicating UDP over IPv4, or 'udp6', indicating UDP over IPv6. Default: 'udp4'.

Create a new QuicClientSession. This function can be called multiple times to create sessions associated with different endpoints on the same client endpoint.

quicsocket.destroy([error])#

Destroys the QuicSocket then emits the 'close' event when done. The 'error' event will be emitted after 'close' if the error is not undefined.

quicsocket.destroyed#

Will be true if the QuicSocket has been destroyed.

quicsocket.duration#

A BigInt representing the length of time this QuicSocket has been active,

quicsocket.endpoints#

An array of QuicEndpoint instances associated with the QuicSocket.

quicsocket.listen([options][, callback])#

  • options <Object>

    • alpn <string> A required ALPN protocol identifier.
    • ca <string> | <string[]> | <Buffer> | <Buffer[]> Optionally override the trusted CA certificates. Default is to trust the well-known CAs curated by Mozilla. Mozilla's CAs are completely replaced when CAs are explicitly specified using this option. The value can be a string or Buffer, or an Array of strings and/or Buffers. Any string or Buffer can contain multiple PEM CAs concatenated together. The peer's certificate must be chainable to a CA trusted by the server for the connection to be authenticated. When using certificates that are not chainable to a well-known CA, the certificate's CA must be explicitly specified as a trusted or the connection will fail to authenticate. If the peer uses a certificate that doesn't match or chain to one of the default CAs, use the ca option to provide a CA certificate that the peer's certificate can match or chain to. For self-signed certificates, the certificate is its own CA, and must be provided. For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE", "X509 CERTIFICATE", and "CERTIFICATE".
    • cert <string> | <string[]> | <Buffer> | <Buffer[]> Cert chains in PEM format. One cert chain should be provided per private key. Each cert chain should consist of the PEM formatted certificate for a provided private key, followed by the PEM formatted intermediate certificates (if any), in order, and not including the root CA (the root CA must be pre-known to the peer, see ca). When providing multiple cert chains, they do not have to be in the same order as their private keys in key. If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail.
    • ciphers <string> Cipher suite specification, replacing the default. For more information, see modifying the default cipher suite. Permitted ciphers can be obtained via tls.getCiphers(). Cipher names must be uppercased in order for OpenSSL to accept them.
    • clientCertEngine <string> Name of an OpenSSL engine which can provide the client certificate.
    • crl <string> | <string[]> | <Buffer> | <Buffer[]> PEM formatted CRLs (Certificate Revocation Lists).
    • defaultEncoding <string> The default encoding that is used when no encoding is specified as an argument to quicstream.write(). Default: 'utf8'.
    • dhparam <string> | <Buffer> Diffie Hellman parameters, required for Perfect Forward Secrecy. Use openssl dhparam to create the parameters. The key length must be greater than or equal to 1024 bits, otherwise an error will be thrown. It is strongly recommended to use 2048 bits or larger for stronger security. If omitted or invalid, the parameters are silently discarded and DHE ciphers will not be available.
    • earlyData <boolean> Set to false to disable 0RTT early data. Default: true.
    • ecdhCurve <string> A string describing a named curve or a colon separated list of curve NIDs or names, for example P-521:P-384:P-256, to use for ECDH key agreement. Set to auto to select the curve automatically. Use crypto.getCurves() to obtain a list of available curve names. On recent releases, openssl ecparam -list_curves will also display the name and description of each available elliptic curve. Default: tls.DEFAULT_ECDH_CURVE.
    • highWaterMark <number> Total number of bytes that QuicStream instances may buffer internally before the quicstream.write() function starts returning false. Default: 16384.
    • honorCipherOrder <boolean> Attempt to use the server's cipher suite references instead of the client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be set in secureOptions, see OpenSSL Options for more information.
    • idleTimeout <number>
    • key <string> | <string[]> | <Buffer> | <Buffer[]> | <Object[]> Private keys in PEM format. PEM allows the option of private keys being encrypted. Encrypted keys will be decrypted with options.passphrase. Multiple keys using different algorithms can be provided either as an array of unencrypted key strings or buffers, or an array of objects in the form {pem: <string|buffer>[, passphrase: <string>]}. The object form can only occur in an array. object.passphrase is optional. Encrypted keys will be decrypted with object.passphrase if provided, or options.passphrase if it is not.
    • activeConnectionIdLimit <number>
    • congestionAlgorithm <string> Must be either 'reno' or 'cubic'. Default: 'reno'.
    • maxAckDelay <number>
    • maxData <number>
    • maxUdpPayloadSize <number>
    • maxStreamsBidi <number>
    • maxStreamsUni <number>
    • maxStreamDataBidiLocal <number>
    • maxStreamDataBidiRemote <number>
    • maxStreamDataUni <number>
    • passphrase <string> Shared passphrase used for a single private key and/or a PFX.
    • pfx <string> | <string[]> | <Buffer> | <Buffer[]> | <Object[]> PFX or PKCS12 encoded private key and certificate chain. pfx is an alternative to providing key and cert individually. PFX is usually encrypted, if it is, passphrase will be used to decrypt it. Multiple PFX can be provided either as an array of unencrypted PFX buffers, or an array of objects in the form {buf: <string|buffer>[, passphrase: <string>]}. The object form can only occur in an array. object.passphrase is optional. Encrypted PFX will be decrypted with object.passphrase if provided, or options.passphrase if it is not.
    • preferredAddress <Object>

    • requestCert <boolean> Request a certificate used to authenticate the client.
    • rejectUnauthorized <boolean> If not false the server will reject any connection which is not authorized with the list of supplied CAs. This option only has an effect if requestCert is true. Default: true.
    • secureOptions <number> Optionally affect the OpenSSL protocol behavior, which is not usually necessary. This should be used carefully if at all! Value is a numeric bitmask of the SSL_OP_* options from OpenSSL Options.
    • sessionIdContext <string> Opaque identifier used by servers to ensure session state is not shared between applications. Unused by clients.
  • callback <Function>

Listen for new peer-initiated sessions.

If a callback is given, it is registered as a handler for the 'session' event.

quicsocket.listenDuration#

A BigInt representing the length of time this QuicSocket has been listening for connections.

quicsocket.listening#

Set to true if the QuicSocket is listening for new connections.

quicsocket.packetsIgnored#

A BigInt representing the number of packets received by this QuicSocket that have been ignored.

quicsocket.packetsReceived#

A BigInt representing the number of packets successfully received by this QuicSocket.

quicsocket.packetsSent#

A BigInt representing the number of packets sent by this QuicSocket.

quicsocket.pending#

Set to true if the socket is not yet bound to the local UDP port.

quicsocket.ref()#

quicsocket.serverBusyCount#

A BigInt representing the number of QuicSession instances rejected due to server busy status.

quicsocket.serverSessions#

A BigInt representing the number of server QuicSession instances that have been associated with this QuicSocket.

quicsocket.setDiagnosticPacketLoss(options)#

  • options <Object>

    • rx <number> A value in the range 0.0 to 1.0 that specifies the probability of received packet loss.
    • tx <number> A value in the range 0.0 to 1.0 that specifies the probability of transmitted packet loss.

The quicsocket.setDiagnosticPacketLoss() method is a diagnostic only tool that can be used to simulate packet loss conditions for this QuicSocket by artificially dropping received or transmitted packets.

This method is not to be used in production applications.

quicsocket.setServerBusy([on])#

  • on <boolean> When true, the QuicSocket will reject new connections. Defaults: true.

Calling setServerBusy() or setServerBusy(true) will tell the QuicSocket to reject all new incoming connection requests using the SERVER_BUSY QUIC error code. To begin receiving connections again, disable busy mode by calling setServerBusy(false).

quicsocket.statelessResetCount#

A BigInt that represents the number of stateless resets that have been sent.

quicsocket.toggleStatelessReset()#

  • Returns <boolean> true if stateless reset processing is enabled; false if disabled.

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.

quicsocket.unref();#

Class: QuicStream extends stream.Duplex#

Event: 'blocked'#

Emitted when the QuicStream has been prevented from sending queued data for the QuicStream due to congestion control.

Event: 'close'#

Emitted when the QuicStream has is completely closed and the underlying resources have been freed.

Event: 'data'#

Event: 'end'#

Event: 'error'#

Event: 'informationalHeaders'#

Emitted when the QuicStream has received a block of informational headers.

Support for headers depends entirely on the QUIC Application used as identified by the alpn configuration option. In QUIC Applications that support headers, informational header blocks typically come before initial headers.

The event handler is invoked with a single argument representing the block of Headers as an object.

stream('informationalHeaders', (headers) => {
  // Use headers
});

Event: 'initialHeaders'#

Emitted when the QuicStream has received a block of initial headers.

Support for headers depends entirely on the QUIC Application used as identified by the alpn configuration option. HTTP/3, for instance, supports two kinds of initial headers: request headers for HTTP request messages and response headers for HTTP response messages. For HTTP/3 QUIC streams, request and response headers are each emitted using the 'initialHeaders' event.

The event handler is invoked with a single argument representing the block of Headers as an object.

stream('initialHeaders', (headers) => {
  // Use headers
});

Event: 'ready'#

Emitted when the underlying QuicSession has emitted its secure event this stream has received its id, which is accessible as stream.id once this event is emitted.

Event: 'trailingHeaders'#

Emitted when the QuicStream has received a block of trailing headers.

Support for headers depends entirely on the QUIC Application used as identified by the alpn configuration option. Trailing headers typically follow any data transmitted on the QuicStream, and therefore typically emit sometime after the last 'data' event but before the 'close' event. The precise timing may vary from one QUIC application to another.

The event handler is invoked with a single argument representing the block of Headers as an object.

stream('trailingHeaders', (headers) => {
  // Use headers
});

Event: 'readable'#

quicstream.aborted#

True if dataflow on the QuicStream was prematurely terminated.

quicstream.bidirectional#

Set to true if the QuicStream is bidirectional.

quicstream.bytesReceived#

A BigInt representing the total number of bytes received for this QuicStream.

quicstream.bytesSent#

A BigInt representing the total number of bytes sent by this QuicStream.

quicstream.clientInitiated#

Set to true if the QuicStream was initiated by a QuicClientSession instance.

quicstream.close(code)#

Closes the QuicStream.

quicstream.dataAckHistogram#

TBD

quicstream.dataRateHistogram#

TBD

quicstream.dataSizeHistogram#

TBD

quicstream.duration#

A BigInt representing the length of time the QuicStream has been active.

quicstream.finalSize#

A BigInt specifying the total number of bytes successfully received by the QuicStream.

quicstream.id#

The numeric identifier of the QuicStream.

quicstream.maxAcknowledgedOffset#

A BigInt representing the highest acknowledged data offset received for this QuicStream.

quicstream.maxExtendedOffset#

A BigInt representing the maximum extended data offset that has been reported to the connected peer.

quicstream.maxReceivedOffset#

A BigInt representing the maximum received offset for this QuicStream.

quicstream.pending#

This property is true if the underlying session is not finished yet, i.e. before the 'ready' event is emitted.

quicstream.pushStream(headers[, options])#

  • headers <Object> An object representing a block of headers to be transmitted with the push promise.

  • options <Object>

    • highWaterMark <number> Total number of bytes that the QuicStream may buffer internally before the quicstream.write() function starts returning false. Default: 16384.
    • defaultEncoding <string> The default encoding that is used when no encoding is specified as an argument to quicstream.write(). Default: 'utf8'.
  • Returns: <QuicStream>

If the selected QUIC application protocol supports push streams, then the pushStream() method will initiate a new push promise and create a new unidirectional QuicStream object used to fulfill that push.

Currently only HTTP/3 supports the use of pushStream().

If the selected QUIC application protocol does not support push streams, an error will be thrown.

quicstream.serverInitiated#

Set to true if the QuicStream was initiated by a QuicServerSession instance.

quicstream.session#

The QuicServerSession or QuicClientSession.

quicstream.sendFD(fd[, options])#

Instead of using a Quicstream as a writable stream, send data from a given file descriptor.

If offset is set to a non-negative number, reading starts from that position and the file offset will not be advanced. If length is set to a non-negative number, it gives the maximum number of bytes that are read from the file.

The file descriptor or FileHandle is not closed when the stream is closed, so it will need to be closed manually once it is no longer needed. Using the same file descriptor concurrently for multiple streams is not supported and may result in data loss. Re-using a file descriptor after a stream has finished is supported.

quicstream.sendFile(path[, options])#

  • path <string> | <Buffer> | <URL>
  • options <Object>

    • onError <Function> Callback function invoked in the case of an error before send.
    • offset <number> The offset position at which to begin reading. Default: -1.
    • length <number> The amount of data from the fd to send. Default: -1.

Instead of using a QuicStream as a writable stream, send data from a given file path.

The options.onError callback will be called if the file could not be opened. If offset is set to a non-negative number, reading starts from that position. If length is set to a non-negative number, it gives the maximum number of bytes that are read from the file.

quicstream.submitInformationalHeaders(headers)#

TBD

quicstream.submitInitialHeaders(headers)#

TBD

quicstream.submitTrailingHeaders(headers)#

TBD

quicstream.unidirectional#

Set to true if the QuicStream is unidirectional.