quic (quic v1.6.4)

View Source

QUIC public API.

This module provides the public interface for QUIC connections. The API is compatible with hackney_quic for drop-in replacement.

Messages

Messages sent to owner process (Conn is the connection pid):

  • {quic, Conn, {connected, Info}} - Connection established
  • {quic, Conn, {stream_opened, StreamId}} - Stream opened
  • {quic, Conn, {closed, Reason}} - Connection closed
  • {quic, Conn, {transport_error, Code, Reason}} - Transport error
  • {quic, Conn, {stream_data, StreamId, Bin, Fin}} - Data received
  • {quic, Conn, {stream_reset, StreamId, ErrorCode}} - Stream reset
  • {quic, Conn, {stop_sending, StreamId, ErrorCode}} - Stop sending
  • {quic, Conn, {goaway, LastStreamId, ErrorCode, Debug}} - GoAway received
  • {quic, Conn, {session_ticket, Ticket}} - Session ticket for 0-RTT
  • {quic, Conn, {send_ready, StreamId}} - Stream ready to write
  • {quic, Conn, {timer, NextTimeoutMs}} - Timer notification
  • {quic, Conn, {datagram, Data}} - Datagram received (RFC 9221)
  • {quic, Conn, {stream_deadline, StreamId}} - Stream deadline expired

Summary

Functions

Cancel a stream deadline. Returns ok if the deadline was cancelled, or {error, not_found} if no deadline exists.

Close a QUIC connection with normal reason.

Close a QUIC connection with the given reason. An integer is treated as an application error code (RFC 9000 §19.19) and sent verbatim in the CONNECTION_CLOSE frame; any other term keeps its historical pass-through behaviour.

Close a QUIC connection with application error code and reason phrase. ErrorCode is a 62-bit unsigned integer (RFC 9000). Reason is the reason phrase sent in the CONNECTION_CLOSE frame.

Connect to a QUIC server. Returns {ok, Conn} on success where Conn is a pid(). Host may be a hostname, an IP-literal string (IPv4 or IPv6, optionally bracketed), or an inet:ip_address() tuple. The owner process will receive {quic, Conn, {connected, Info}} when the connection is established.

Get maximum datagram payload size. Returns 0 if peer doesn't support datagrams (RFC 9221). The returned size is the peer's advertised max_datagram_frame_size.

Get datagram accounting counters. Returns delivered / dropped_recv / sent / dropped_send counters so callers can detect back-pressure when datagram_recv_queue_len has been set to a finite value.

Returns whether the server accepted early data, or unknown if the handshake has not yet completed. Use after the connection enters the connected state to confirm 0-RTT was actually used.

Get the file descriptor from a gen_udp socket. This can be used to pass an existing UDP socket to connect/4 via the socket_fd option.

Get the current MTU for a connection.

Return a snapshot of the connection's path metrics.

Get the peer's transport parameters.

Get send queue information for a connection. This can be used by distribution controllers or other high-level protocols to implement backpressure based on queue state.

Get the list of connection PIDs for a named server.

Get information about a named server.

Get the listening port of a named server.

Get the bound address of a named server.

Get connection statistics for liveness detection.

Get the remaining time for a stream deadline. Returns {ok, {RemainingMs, Action}} where RemainingMs is milliseconds until expiry. Returns {error, no_deadline} if no deadline is set.

Get the priority for a stream. Returns {ok, {Urgency, Incremental}} or {error, not_found}.

Handle connection timeout. Should be called when timer expires. Returns next timeout in ms or 'infinity'.

Returns whether the connection has derived early keys (i.e. a session ticket was provided and 0-RTT is possible). Used by the H3 layer to choose between the fresh-handshake and 0-RTT paths.

Check if QUIC support is available. Always returns true for pure Erlang implementation.

Trigger connection migration to a new local address. This initiates path validation on a new network path. The connection will send PATH_CHALLENGE and wait for PATH_RESPONSE.

Trigger connection migration with options. This initiates path validation on a new network path. The connection will send PATH_CHALLENGE and wait for PATH_RESPONSE.

Open a new bidirectional stream. Returns {ok, StreamId} on success.

Open a new unidirectional stream. Returns {ok, StreamId} on success. Unidirectional streams are send-only for the initiator.

Get the peer certificate. Returns the DER-encoded certificate of the peer if available.

Get the remote address of the connection.

Process pending QUIC events. This is called automatically by the connection process.

Reset a stream with an error code.

Reset a stream with reliable delivery up to specified size. Data up to ReliableSize will be delivered before the reset takes effect. Requires peer support for the reliable stream reset extension (draft-ietf-quic-reliable-stream-reset-07). ReliableSize must be less than or equal to the amount of data already sent.

Close a connection, ignoring any error if it is already gone. For teardown paths that must not crash when the connection has already closed or the pid is dead.

Like safe_close/1 with a close reason.

Like safe_close/1 with an application error code and reason phrase.

Send data on a stream. Fin indicates if this is the final frame on the stream.

Send data on a stream with a timeout. Fin indicates if this is the final frame on the stream. Timeout is in milliseconds; if the operation takes longer, returns {error, timeout}.

Send data on a stream asynchronously (fire-and-forget). This is faster than send_data/4 because it uses cast instead of call, avoiding the round-trip latency. However, errors are silently dropped. Use this for high-throughput scenarios where occasional dropped data is acceptable.

Send a datagram on the connection. Datagrams are unreliable and may be lost.

Send a PING frame on the connection.

Return a child spec for embedding a QUIC server in your own supervisor.

Set the congestion control algorithm for a connection. This changes the algorithm on a live connection. The new algorithm starts fresh (cwnd, ssthresh reset to defaults). Only works in connected state.

Set the owner process for a connection. Similar to gen_tcp:controlling_process/2.

Set the owner process for a connection (synchronous). Use this when you need to ensure ownership is transferred before continuing.

Set a deadline for a stream. TimeoutMs is the number of milliseconds from now until the deadline expires. When the deadline expires, the stream will be reset and/or the owner will be notified. Default action is 'both' (notify + reset).

Set a deadline for a stream with options. TimeoutMs is the number of milliseconds from now until the deadline expires.

Set the priority for a stream. Urgency: 0-7 (lower = more urgent, default 3) Incremental: boolean (data can be processed incrementally, default false) Per RFC 9218 (Extensible Priorities for HTTP).

Set connection options.

Get the local address of the connection.

Start a named QUIC server on the specified port.

Request peer to stop sending on a stream. Sends a STOP_SENDING frame (RFC 9000 Section 19.5).

Stop a named QUIC server.

List all running server names.

Types

path_stats/0

-type path_stats() ::
          #{srtt := non_neg_integer(),
            latest_rtt := non_neg_integer(),
            min_rtt := non_neg_integer(),
            rtt_var := non_neg_integer(),
            cwnd := non_neg_integer(),
            bytes_in_flight := non_neg_integer(),
            in_recovery := boolean(),
            congested := boolean()}.

send_queue_info/0

-type send_queue_info() ::
          #{bytes := non_neg_integer(),
            cwnd := non_neg_integer(),
            in_flight := non_neg_integer(),
            in_recovery := boolean(),
            congested := boolean()}.

Functions

cancel_stream_deadline(Conn, StreamId)

-spec cancel_stream_deadline(Conn, StreamId) -> ok | {error, term()}
                                when Conn :: pid(), StreamId :: non_neg_integer().

Cancel a stream deadline. Returns ok if the deadline was cancelled, or {error, not_found} if no deadline exists.

close(Conn)

-spec close(Conn) -> ok when Conn :: pid().

Close a QUIC connection with normal reason.

close(Conn, Reason)

-spec close(Conn, Reason) -> ok when Conn :: pid(), Reason :: non_neg_integer() | term().

Close a QUIC connection with the given reason. An integer is treated as an application error code (RFC 9000 §19.19) and sent verbatim in the CONNECTION_CLOSE frame; any other term keeps its historical pass-through behaviour.

close(Conn, ErrorCode, Reason)

-spec close(Conn, ErrorCode, Reason) -> ok
               when Conn :: pid(), ErrorCode :: 0..4611686018427387903, Reason :: binary().

Close a QUIC connection with application error code and reason phrase. ErrorCode is a 62-bit unsigned integer (RFC 9000). Reason is the reason phrase sent in the CONNECTION_CLOSE frame.

connect(Host, Port, Opts, Owner)

-spec connect(Host, Port, Opts, Owner) -> {ok, pid()} | {error, term()}
                 when
                     Host :: binary() | string() | inet:ip_address(),
                     Port :: inet:port_number(),
                     Opts :: map(),
                     Owner :: pid().

Connect to a QUIC server. Returns {ok, Conn} on success where Conn is a pid(). Host may be a hostname, an IP-literal string (IPv4 or IPv6, optionally bracketed), or an inet:ip_address() tuple. The owner process will receive {quic, Conn, {connected, Info}} when the connection is established.

For a hostname that resolves to both IPv4 and IPv6 addresses, RFC 8305 Happy Eyeballs is used: the addresses are raced IPv6-first and the first to complete its handshake is returned. In that case connect/4 blocks until the first attempt connects (or all fail / time out); a single address, IP literal/tuple, or pre-opened socket keeps the immediate, asynchronous return.

Options:

  • happy_eyeballs - Race IPv6/IPv4 for multi-address hostnames (default: true). false forces the legacy IPv4-first resolver.
  • family - inet | inet6 | any (default any); restricts resolution to one address family.
  • connection_attempt_delay - RFC 8305 stagger between attempts in milliseconds (default: 250).
  • connect_timeout - Overall Happy Eyeballs deadline in milliseconds (default: 5000).
  • socket - Use an existing UDP socket (gen_udp:socket())
  • extra_socket_opts - Options for socket creation (e.g., [{ip, Addr}])
  • socket_backend - gen_udp (default), socket (OTP NIF) or adapter (caller-supplied datagram callbacks)
  • socket_adapter - Required when socket_backend = adapter. Map with send_fun => fun((IP, Port, Packet) -> ok | {error,_}) and optional close_fun, local. Inbound packets must be delivered to the owning connection as {udp, Socket, IP, Port, Data} messages.
  • verify - Validate the server certificate chain, signature and hostname (default: true). Set to false to skip validation (e.g. self-signed test servers).
  • cacerts - Trust anchors as a list of DER-encoded CA certificates. Defaults to the OS trust store.
  • alpn - ALPN protocols (default: [<<"h3">>])
  • server_name - Server Name Indication, also the hostname checked against the certificate (default: Host)
  • external_psk - TLS 1.3 external PSK (RFC 8446 §4.2.11). {Identity, Secret} defaults to modes [psk_dhe_ke]; {Identity, Secret, Modes} takes an explicit non-empty list (psk_dhe_ke | psk_ke). Mutually exclusive with session_ticket. See docs/PSK.md.
  • groups - key-exchange groups in preference order (x25519 | secp256r1 | secp384r1; default [x25519]). The head gets a key_share; the rest are HelloRetryRequest eligible.
  • signature_algs - advertised signature schemes (ecdsa_secp256r1_sha256 | ecdsa_secp384r1_sha384 | rsa_pss_rsae_sha256|384|512 | ed25519 | rsa_pkcs1_sha256). Defaults to the historical wire list.

datagram_max_size(Conn)

-spec datagram_max_size(Conn) -> non_neg_integer() | {error, term()} when Conn :: pid().

Get maximum datagram payload size. Returns 0 if peer doesn't support datagrams (RFC 9221). The returned size is the peer's advertised max_datagram_frame_size.

datagram_stats(Conn)

-spec datagram_stats(Conn) ->
                        #{delivered := non_neg_integer(),
                          dropped_recv := non_neg_integer(),
                          sent := non_neg_integer(),
                          dropped_send := non_neg_integer()}
                        when Conn :: pid().

Get datagram accounting counters. Returns delivered / dropped_recv / sent / dropped_send counters so callers can detect back-pressure when datagram_recv_queue_len has been set to a finite value.

early_data_accepted(Conn)

-spec early_data_accepted(Conn) -> boolean() | unknown when Conn :: pid().

Returns whether the server accepted early data, or unknown if the handshake has not yet completed. Use after the connection enters the connected state to confirm 0-RTT was actually used.

get_fd(Socket)

-spec get_fd(gen_udp:socket()) -> {ok, integer()} | {error, term()}.

Get the file descriptor from a gen_udp socket. This can be used to pass an existing UDP socket to connect/4 via the socket_fd option.

get_mtu(Conn)

-spec get_mtu(Conn) -> {ok, pos_integer()} | {error, term()} when Conn :: pid().

Get the current MTU for a connection.

Returns the effective MTU discovered via DPLPMTUD (RFC 8899). The MTU starts at 1200 bytes (QUIC minimum) and is probed up to the peer's max_udp_payload_size or local configuration.

Returns {ok, MTU} where MTU is the current maximum packet size, or {error, not_found} if the connection doesn't exist.

get_path_stats(Conn)

-spec get_path_stats(Conn) -> {ok, path_stats()} | {error, term()} when Conn :: pid().

Return a snapshot of the connection's path metrics.

The map combines RTT estimates from quic_loss with congestion control state from quic_cc. Intended for routing layers that need per-connection path quality without poking at internal records via sys:get_state/1.

Returns {error, not_connected} if the connection has not yet completed the handshake.

get_peer_transport_params(Conn)

-spec get_peer_transport_params(Conn) -> {ok, map()} | {error, term()} when Conn :: pid().

Get the peer's transport parameters.

Returns the transport parameters received from the peer during handshake. Useful for verifying peer capabilities such as WebTransport support (e.g., checking for reset_stream_at transport parameter).

Returns {ok, TransportParams} where TransportParams is a map of the peer's advertised transport parameters.

get_send_queue_info(Conn)

-spec get_send_queue_info(Conn) -> {ok, send_queue_info()} | {error, term()} when Conn :: pid().

Get send queue information for a connection. This can be used by distribution controllers or other high-level protocols to implement backpressure based on queue state.

Returns a map with: - bytes: Current bytes in send queue - cwnd: Congestion window size - in_flight: Bytes sent but not acknowledged - in_recovery: Whether in congestion recovery - congested: Whether backpressure should be applied

See quic_dist_controller for usage example.

get_server_connections(Name)

-spec get_server_connections(Name) -> {ok, [pid()]} | {error, not_found} when Name :: atom().

Get the list of connection PIDs for a named server.

get_server_info(Name)

-spec get_server_info(Name) -> {ok, map()} | {error, not_found} when Name :: atom().

Get information about a named server.

Returns a map containing:

  • pid - Server supervisor PID
  • port - Listening port
  • opts - Server options
  • started_at - Start timestamp in milliseconds

get_server_port(Name)

-spec get_server_port(Name) -> {ok, inet:port_number()} | {error, not_found} when Name :: atom().

Get the listening port of a named server.

Useful when the server was started with port 0 (ephemeral port).

get_server_sockname(Name)

-spec get_server_sockname(Name) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}
                             when Name :: atom().

Get the bound address of a named server.

Returns the listener's actual {IP, Port}, resolved from the socket, so it is correct even when the server was started with port 0, inet6, {ip, _} or {ifaddr, _}.

get_stats(Conn)

-spec get_stats(Conn) -> {ok, map()} | {error, term()} when Conn :: pid().

Get connection statistics for liveness detection.

Returns packet counts that can be used by net_kernel for tick checking. Any QUIC packet (ACK, PING, data) counts as proof of peer liveness.

Returns a map with: - packets_received: Total QUIC packets successfully received - packets_sent: Total QUIC packets sent - data_received: Total bytes of application data received - data_sent: Total bytes of application data sent

See quic_dist_controller for usage in distribution tick checking.

get_stream_deadline(Conn, StreamId)

-spec get_stream_deadline(Conn, StreamId) ->
                             {ok, {non_neg_integer() | infinity, reset | notify | both}} |
                             {error, term()}
                             when Conn :: pid(), StreamId :: non_neg_integer().

Get the remaining time for a stream deadline. Returns {ok, {RemainingMs, Action}} where RemainingMs is milliseconds until expiry. Returns {error, no_deadline} if no deadline is set.

get_stream_priority(Conn, StreamId)

-spec get_stream_priority(Conn, StreamId) -> {ok, {0..7, boolean()}} | {error, term()}
                             when Conn :: pid(), StreamId :: non_neg_integer().

Get the priority for a stream. Returns {ok, {Urgency, Incremental}} or {error, not_found}.

handle_timeout(Conn, NowMs)

-spec handle_timeout(Conn, NowMs) -> non_neg_integer() | infinity
                        when Conn :: pid(), NowMs :: non_neg_integer().

Handle connection timeout. Should be called when timer expires. Returns next timeout in ms or 'infinity'.

has_early_keys(Conn)

-spec has_early_keys(Conn) -> boolean() when Conn :: pid().

Returns whether the connection has derived early keys (i.e. a session ticket was provided and 0-RTT is possible). Used by the H3 layer to choose between the fresh-handshake and 0-RTT paths.

is_available()

-spec is_available() -> boolean().

Check if QUIC support is available. Always returns true for pure Erlang implementation.

migrate(Conn)

-spec migrate(Conn) -> ok | {error, term()} when Conn :: pid().

Trigger connection migration to a new local address. This initiates path validation on a new network path. The connection will send PATH_CHALLENGE and wait for PATH_RESPONSE.

migrate(Conn, Opts)

-spec migrate(Conn, Opts) -> ok | {error, term()}
                 when Conn :: pid(), Opts :: #{timeout => pos_integer()}.

Trigger connection migration with options. This initiates path validation on a new network path. The connection will send PATH_CHALLENGE and wait for PATH_RESPONSE.

Options:

  • timeout - Timeout in milliseconds for the gen_statem call (default: 5000)

open_stream(Conn)

-spec open_stream(Conn) -> {ok, non_neg_integer()} | {error, term()} when Conn :: pid().

Open a new bidirectional stream. Returns {ok, StreamId} on success.

open_unidirectional_stream(Conn)

-spec open_unidirectional_stream(Conn) -> {ok, non_neg_integer()} | {error, term()} when Conn :: pid().

Open a new unidirectional stream. Returns {ok, StreamId} on success. Unidirectional streams are send-only for the initiator.

peercert(Conn)

-spec peercert(Conn) -> {ok, binary()} | {error, term()} when Conn :: pid().

Get the peer certificate. Returns the DER-encoded certificate of the peer if available.

peername(Conn)

-spec peername(Conn) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}
                  when Conn :: pid().

Get the remote address of the connection.

process(Conn)

-spec process(Conn) -> ok when Conn :: pid().

Process pending QUIC events. This is called automatically by the connection process.

reset_stream(Conn, StreamId, ErrorCode)

-spec reset_stream(Conn, StreamId, ErrorCode) -> ok | {error, term()}
                      when Conn :: pid(), StreamId :: non_neg_integer(), ErrorCode :: non_neg_integer().

Reset a stream with an error code.

reset_stream_at(Conn, StreamId, ErrorCode, ReliableSize)

-spec reset_stream_at(Conn, StreamId, ErrorCode, ReliableSize) -> ok | {error, term()}
                         when
                             Conn :: pid(),
                             StreamId :: non_neg_integer(),
                             ErrorCode :: non_neg_integer(),
                             ReliableSize :: non_neg_integer().

Reset a stream with reliable delivery up to specified size. Data up to ReliableSize will be delivered before the reset takes effect. Requires peer support for the reliable stream reset extension (draft-ietf-quic-reliable-stream-reset-07). ReliableSize must be less than or equal to the amount of data already sent.

safe_close(Conn)

-spec safe_close(Conn) -> ok when Conn :: pid().

Close a connection, ignoring any error if it is already gone. For teardown paths that must not crash when the connection has already closed or the pid is dead.

safe_close(Conn, Reason)

-spec safe_close(Conn, Reason) -> ok when Conn :: pid(), Reason :: non_neg_integer() | term().

Like safe_close/1 with a close reason.

safe_close(Conn, ErrorCode, Reason)

-spec safe_close(Conn, ErrorCode, Reason) -> ok
                    when Conn :: pid(), ErrorCode :: 0..4611686018427387903, Reason :: binary().

Like safe_close/1 with an application error code and reason phrase.

send_data(Conn, StreamId, Data, Fin)

-spec send_data(Conn, StreamId, Data, Fin) -> ok | {error, term()}
                   when Conn :: pid(), StreamId :: non_neg_integer(), Data :: iodata(), Fin :: boolean().

Send data on a stream. Fin indicates if this is the final frame on the stream.

send_data(Conn, StreamId, Data, Fin, Timeout)

-spec send_data(Conn, StreamId, Data, Fin, Timeout) -> ok | {error, term()}
                   when
                       Conn :: pid(),
                       StreamId :: non_neg_integer(),
                       Data :: iodata(),
                       Fin :: boolean(),
                       Timeout :: timeout().

Send data on a stream with a timeout. Fin indicates if this is the final frame on the stream. Timeout is in milliseconds; if the operation takes longer, returns {error, timeout}.

send_data_async(Conn, StreamId, Data, Fin)

-spec send_data_async(Conn, StreamId, Data, Fin) -> ok
                         when
                             Conn :: pid(),
                             StreamId :: non_neg_integer(),
                             Data :: iodata(),
                             Fin :: boolean().

Send data on a stream asynchronously (fire-and-forget). This is faster than send_data/4 because it uses cast instead of call, avoiding the round-trip latency. However, errors are silently dropped. Use this for high-throughput scenarios where occasional dropped data is acceptable.

send_datagram(Conn, Data)

-spec send_datagram(Conn, Data) -> ok | {error, term()} when Conn :: pid(), Data :: iodata().

Send a datagram on the connection. Datagrams are unreliable and may be lost.

send_ping(Conn)

-spec send_ping(Conn) -> ok | {error, term()} when Conn :: pid().

Send a PING frame on the connection.

PING frames are transport-level frames that bypass congestion control. They elicit an ACK from the peer and can be used for liveness checking. This is useful for distribution tick messages that must get through even when the connection is congested.

Returns ok if the PING was sent, or {error, Reason} if it failed.

server_spec(Name, Port, Opts)

-spec server_spec(Name, Port, Opts) -> supervisor:child_spec()
                     when Name :: atom(), Port :: inet:port_number(), Opts :: map().

Return a child spec for embedding a QUIC server in your own supervisor.

This allows you to supervise QUIC servers within your application's supervision tree instead of using the built-in server management.

Example:

  init([]) ->
      Spec = quic:server_spec(my_quic, 4433, #{
          cert => CertDer,
          key => KeyTerm,
          alpn => [<<"h3">>]
      }),
      {ok, {#{strategy => one_for_one}, [Spec]}}.

set_congestion_control(Conn, Algorithm)

-spec set_congestion_control(Conn, Algorithm) -> ok | {error, term()}
                                when Conn :: pid(), Algorithm :: newreno | bbr | cubic.

Set the congestion control algorithm for a connection. This changes the algorithm on a live connection. The new algorithm starts fresh (cwnd, ssthresh reset to defaults). Only works in connected state.

Algorithm: newreno | bbr | cubic

set_owner(Conn, NewOwner)

-spec set_owner(Conn, NewOwner) -> ok | {error, term()} when Conn :: pid(), NewOwner :: pid().

Set the owner process for a connection. Similar to gen_tcp:controlling_process/2.

set_owner_sync(Conn, NewOwner)

-spec set_owner_sync(Conn, NewOwner) -> ok | {error, term()} when Conn :: pid(), NewOwner :: pid().

Set the owner process for a connection (synchronous). Use this when you need to ensure ownership is transferred before continuing.

set_stream_deadline(Conn, StreamId, TimeoutMs)

-spec set_stream_deadline(Conn, StreamId, TimeoutMs) -> ok | {error, term()}
                             when
                                 Conn :: pid(),
                                 StreamId :: non_neg_integer(),
                                 TimeoutMs :: pos_integer().

Set a deadline for a stream. TimeoutMs is the number of milliseconds from now until the deadline expires. When the deadline expires, the stream will be reset and/or the owner will be notified. Default action is 'both' (notify + reset).

set_stream_deadline(Conn, StreamId, TimeoutMs, Opts)

-spec set_stream_deadline(Conn, StreamId, TimeoutMs, Opts) -> ok | {error, term()}
                             when
                                 Conn :: pid(),
                                 StreamId :: non_neg_integer(),
                                 TimeoutMs :: pos_integer(),
                                 Opts ::
                                     #{action => reset | notify | both, error_code => non_neg_integer()}.

Set a deadline for a stream with options. TimeoutMs is the number of milliseconds from now until the deadline expires.

Options: - action: What to do when deadline expires: - notify: Send {quic, Conn, {stream_deadline, StreamId}} to owner - reset: Send RESET_STREAM and clean up - both (default): Notify AND reset - error_code: Error code for RESET_STREAM (default: 16#FF)

set_stream_priority(Conn, StreamId, Urgency, Incremental)

-spec set_stream_priority(Conn, StreamId, Urgency, Incremental) -> ok | {error, term()}
                             when
                                 Conn :: pid(),
                                 StreamId :: non_neg_integer(),
                                 Urgency :: 0..7,
                                 Incremental :: boolean().

Set the priority for a stream. Urgency: 0-7 (lower = more urgent, default 3) Incremental: boolean (data can be processed incrementally, default false) Per RFC 9218 (Extensible Priorities for HTTP).

setopts(Conn, Opts)

-spec setopts(Conn, Opts) -> ok | {error, term()} when Conn :: pid(), Opts :: [{atom(), term()}].

Set connection options.

sockname(Conn)

-spec sockname(Conn) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}
                  when Conn :: pid().

Get the local address of the connection.

start_server(Name, Port, Opts)

-spec start_server(Name, Port, Opts) -> {ok, pid()} | {error, term()}
                      when Name :: atom(), Port :: inet:port_number(), Opts :: map().

Start a named QUIC server on the specified port.

Creates a listener pool that accepts incoming QUIC connections. Multiple named servers can run on different ports.

At least one authentication method must be configured: either a cert + key pair for X.509 auth, or psks / psk_callback for TLS 1.3 external PSK (RFC 8446 §4.2.11). Both may coexist; the per-handshake selection rules are documented in docs/PSK.md.

Options:

  • cert - DER-encoded certificate
  • key - Private key term
  • psks - #{Identity :: binary() => Secret :: binary()} static PSK table
  • psk_callback - fun((Identity :: binary()) -> {ok, Secret} | not_found); takes precedence over psks
  • alpn - List of ALPN protocols (default: [<<"h3">>])
  • groups - accepted key-exchange groups in preference order (x25519 | secp256r1 | secp384r1; default [x25519]). When the client's key_share matches none of these but a supported_groups entry does, the server sends a HelloRetryRequest.
  • signature_algs - accepted/advertised signature schemes; the CertificateVerify scheme is the server's first choice the client also offered. rsa_pkcs1_* is never selected for CertificateVerify (RFC 8446 §4.4.3).
  • pool_size - Number of listener processes (default: 1)
  • connection_handler - Fun(Conn) -> {ok, HandlerPid} where Conn is the pid

Example:

  {ok, _} = quic:start_server(my_server, 4433, #{
      cert => CertDer,
      key => KeyTerm,
      alpn => [<<"h3">>],
      pool_size => 4
  }).

stop_sending(Conn, StreamId, ErrorCode)

-spec stop_sending(Conn, StreamId, ErrorCode) -> ok | {error, term()}
                      when Conn :: pid(), StreamId :: non_neg_integer(), ErrorCode :: non_neg_integer().

Request peer to stop sending on a stream. Sends a STOP_SENDING frame (RFC 9000 Section 19.5).

stop_server(Name)

-spec stop_server(Name) -> ok | {error, term()} when Name :: atom().

Stop a named QUIC server.

Stops the server and all its connections. The port will be freed for reuse.

which_servers()

-spec which_servers() -> [atom()].

List all running server names.