### Example Server Setup Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/configuration-reference.md Demonstrates how to start a QUIC server with common configuration options including TLS, ALPN, key exchange groups, connection pooling, address validation, socket backend, and buffer sizes. ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, alpn => [<<"h3">>, <<"h3-29">>] , groups => [x25519], pool_size => 4, address_validation => always, address_token_max_age_ms => 600000, socket_backend => socket, % GRO on Linux recbuf => 7340032, sndbuf => 7340032 }) ``` -------------------------------- ### HTTP/3 Server Start Example Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/configuration-reference.md Start an HTTP/3 server with specified options. Use this for setting up a server to handle H3 requests. ```erlang {ok, _} = quic_h3:start_server(my_h3, 4433, #{ cert => CertDer, key => KeyTerm, handler => fun handle_request/5, settings => #{ qpack_max_table_size => 4096, max_header_list_size => 16384 } }) ``` -------------------------------- ### HTTP/3 Server and Client Example Source: https://github.com/benoitc/erlang_quic/blob/main/README.md Demonstrates how to start an HTTP/3 server and establish a client connection to send a request and receive a response. ```erlang %% Server {ok, _} = quic_h3:start_server(my_h3, 4433, #{ cert => CertDer, key => KeyDer, handler => fun(Conn, StreamId, <<"GET">>, Path, _Headers) -> Body = <<"hello from ", Path/binary>>, quic_h3:send_response(Conn, StreamId, 200, [{<<"content-type">>, <<"text/plain">>}]) , quic_h3:send_data(Conn, StreamId, Body, true) end }). %% Client {ok, H3} = quic_h3:connect("example.com", 4433, #{verify => false, sync => true}), {ok, StreamId} = quic_h3:request(H3, [ {<<":method">>, <<"GET">>}, {<<":scheme">>, <<"https">>}, {<<":path">>, <<"/hi">>}, {<<":authority">>, <<"example.com">>} ]), receive {quic_h3, H3, {response, StreamId, 200, _Headers}} -> ok end, receive {quic_h3, H3, {data, StreamId, Body, true}} -> io:format("got ~p~n", [Body]) end, quic_h3:close(H3). ``` -------------------------------- ### Example: Accessing HTTP/3 Settings Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md Demonstrates how to get HTTP/3 settings and retrieve a specific setting like max_header_list_size. ```erlang Settings = quic_h3:get_settings(H3), MaxFieldSize = maps:get(max_header_list_size, Settings, unlimited) ``` -------------------------------- ### Multi-Server QUIC Load Balancer Setup Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-lb-api.md Example demonstrating how to set up multiple QUIC servers behind a load balancer. It configures each server with a unique server ID but shares a common encryption key, ensuring consistent load balancing. ```erlang setup_quic_lb() -> % Shared key for the load balancer cluster Key = crypto:strong_rand_bytes(16), % Server 1 configuration {ok, Config1} = quic_lb:new_config(#{ algorithm => stream_cipher, server_id => <<"server1">>, key => Key, config_rotation => 0 }), {ok, CIDConfig1} = quic_lb:new_cid_config(#{ lb_config => Config1, cid_len => quic_lb:expected_cid_len(Config1), reset_secret => crypto:strong_rand_bytes(32) }), {ok, _} = quic:start_server(server1, 4433, #{ cert => cert1(), key => key1(), cid_config => CIDConfig1 }), % Server 2 configuration (same key, different server_id) {ok, Config2} = quic_lb:new_config(#{ algorithm => stream_cipher, server_id => <<"server2">>, key => Key, config_rotation => 0 }), {ok, CIDConfig2} = quic_lb:new_cid_config(#{ lb_config => Config2, cid_len => quic_lb:expected_cid_len(Config2), reset_secret => crypto:strong_rand_bytes(32) }), {ok, _} = quic:start_server(server2, 4434, #{ cert => cert2(), key => key2(), cid_config => CIDConfig2 }). ``` -------------------------------- ### Start QUIC Server and Get Port Source: https://github.com/benoitc/erlang_quic/blob/main/docs/SERVER_GUIDE.md Starts the QUIC application and then a server with TLS certificates. Retrieves the listening port. ```erlang %% Start the QUIC application application:ensure_all_started(quic). %% Start a server with TLS certificates {ok, _Pid} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => PrivateKey, alpn => [<<"h3">>, <<"myproto">>] }). %% Get the listening port (useful when using port 0) {ok, Port} = quic:get_server_port(my_server). ``` -------------------------------- ### Example: Accessing QUIC Connection Details Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md Shows how to get the QUIC connection PID and use it to retrieve the peer's network address. ```erlang H3Conn = quic_h3:get_quic_conn(H3), {ok, {IP, Port}} = quic:peername(H3Conn) ``` -------------------------------- ### Build and Start 5-Node Cluster Source: https://github.com/benoitc/erlang_quic/blob/main/test/docker/README.md Build the Docker images and start a 5-node cluster for QUIC distribution testing. Use the '-d' flag to run in detached mode. ```bash docker-compose up --build ``` ```bash docker-compose up -d --build ``` -------------------------------- ### QUIC Client Example Source: https://github.com/benoitc/erlang_quic/blob/main/docs/GETTING_STARTED.md A basic Erlang client that connects to a QUIC server, sends a message, and receives a response. Ensure the 'quic' application is started. ```erlang -module(hello_client). -export([run/2]). run(Host, Port) -> %% Start the quic application application:ensure_all_started(quic), %% Connect to server Opts = #{ alpn => [<<"example">>], verify => verify_none }, {ok, Conn} = quic:connect(Host, Port, Opts, self()), %% Wait for connection receive {quic, Conn, {connected, Info}} -> io:format("Connected to ~s:~p~n", [Host, Port]), io:format("ALPN: ~p~n", [maps:get(alpn, Info, undefined)]) after 5000 -> error(connection_timeout) end, %% Open a stream and send data {ok, StreamId} = quic:open_stream(Conn), ok = quic:send_data(Conn, StreamId, <<"Hello, QUIC!">>, true), %% Wait for response receive {quic, Conn, {stream_data, StreamId, Response, _Fin}} -> io:format("Response: ~s~n", [Response]) after 5000 -> io:format("No response received~n") end, %% Close connection quic:close(Conn), ok. ``` -------------------------------- ### Start Server with QLOG Tracing Source: https://github.com/benoitc/erlang_quic/blob/main/examples/README.md Starts the server with QLOG tracing enabled. QLOG files will be generated in the specified directory for debugging and analysis. ```erlang qlog_example:start_server(4433). %% Output: %% QLOG server started on port 4433 %% QLOG files will be written to: /tmp/qlog ``` -------------------------------- ### Start CONNECT-UDP Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md This snippet shows how to start a CONNECT-UDP server using quic_h3. It configures the server with necessary certificates, enables extended CONNECT protocol, and sets up a custom connection handler for UDP proxying. ```erlang {ok, _} = quic_h3:start_server(udp_proxy, 443, #{ cert => C, key => K, settings => #{enable_connect_protocol => 1}, h3_datagram_enabled => true, connection_handler => fun(_) -> #{owner => spawn(fun udp_proxy_conn:loop/0)} end, handler => fun handle_connect_udp_request/5 }). ``` -------------------------------- ### Simple HTTP/3 Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Start a basic HTTP/3 server that handles GET requests to the root path and returns a 404 for other paths. Requires certificate and key to be provided. ```erlang Handler = fun(Conn, StreamId, Method, Path, Headers) -> case {Method, Path} of {<< ``` ```erlang GET">>, <<"/">>} -> quic_h3:send_response(Conn, StreamId, 200, [ {<< ``` ```erlang content-type">>, << ``` ```erlang text/plain">>} ]), quic_h3:send_data(Conn, StreamId, << ``` ```erlang Hello, HTTP/3!" , true); _ -> quic_h3:send_response(Conn, StreamId, 404, []), quic_h3:send_data(Conn, StreamId, << ``` ```erlang Not Found">>, true) end end, {ok, _} = quic_h3:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, handler => Handler }). ``` -------------------------------- ### Start NAT Simulation and Run Tests Source: https://github.com/benoitc/erlang_quic/blob/main/test/docker/README.md Start the Docker Compose environment configured for NAT simulation and then execute the NAT traversal tests. ```bash cd test/docker # Start NAT simulation docker-compose -f docker-compose.nat.yml up --build # Run NAT tests docker-compose -f docker-compose.nat.yml run --rm nat_test_runner ``` -------------------------------- ### Start QUIC Listener Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC listener on a specified port with given options. Use this to initiate a server that accepts QUIC connections. Options include certificate, key, and ALPN protocols. ```erlang quic_listener:start_link(Port, Opts) -> {ok, pid()} | {error, term()} ``` ```erlang {ok, Listener} = quic_listener:start_link(4433, #{ cert => CertDer, key => KeyTerm, alpn => [<<"h3">>] }), Port = quic_listener:get_port(Listener) ``` -------------------------------- ### Start QUIC listener directly Source: https://github.com/benoitc/erlang_quic/blob/main/README.md Uses the low-level listener API to start a QUIC listener with specified certificate, key, and ALPN settings. ```erlang %% Load certificate and key {ok, CertDer} = file:read_file("server.crt"), {ok, KeyDer} = file:read_file("server.key"), {ok, Listener} = quic_listener:start_link(4433, #{ cert => CertDer, key => KeyDer, alpn => [<<"h3">>] }), Port = quic_listener:get_port(Listener). ``` -------------------------------- ### Start Echo Server with Options Source: https://github.com/benoitc/erlang_quic/blob/main/examples/README.md Starts the echo server with a comprehensive set of configuration options, including flow control limits, timeouts, datagram settings, QLOG tracing, and pool size. ```erlang %% Start server with all options echo_server:start(4433, #{ %% Flow control max_data => 10 * 1024 * 1024, % 10 MB max_stream_data => 1 * 1024 * 1024, % 1 MB max_streams_bidi => 100, max_streams_uni => 100, %% Timeouts idle_timeout => 30000, % 30 seconds keep_alive_interval => 15000, % 15 seconds %% Datagrams (RFC 9221) max_datagram_frame_size => 65535, %% QLOG tracing qlog => #{ enabled => true, dir => "/tmp/qlog", events => all }, %% Server pool pool_size => 4 }). ``` -------------------------------- ### Start Docker H3 Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Command to start the H3 server in a Docker container for client testing. ```bash docker compose -f docker/docker-compose.yml up h3-server -d ``` -------------------------------- ### Start QUIC Server with X.509 Certificate Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC server using X.509 certificate and key for authentication. Ensure 'server.crt' and 'server.key' exist and are readable. ```erlang {ok, CertDer} = file:read_file("server.crt"), {ok, KeyDer} = file:read_file("server.key"), {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyDer }) ``` -------------------------------- ### Start HTTP/3 Server Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md Starts an HTTP/3 server with a given name, port, and options. Requires certificate and key for TLS. ```erlang start_server(Name, Port, Opts) -> {ok, pid()} | {error, term()} ``` -------------------------------- ### start_server/3 Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Starts an HTTP/3 server with a given name, port, and options. Options include certificate, key, and request handler. ```APIDOC ## start_server/3 ### Description Start an HTTP/3 server. ### Method N/A (Erlang function) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Arguments - `Name` (atom) - Server name. - `Port` (integer) - Listen port. - `Opts` (map) - Server options map. ### Options | Option | Type | Required | Description | |---|---|---|---| | `cert` | binary | Yes | DER-encoded certificate | | `key` | term | Yes | Private key | | `handler` | fun/5 or module | No | Request handler | | `settings` | map | No | HTTP/3 settings | | `quic_opts` | map | No | Additional QUIC options | ### Request Example ```erlang {ok, _} = quic_h3:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, handler => fun(Conn, StreamId, << ``` -------------------------------- ### Start QUIC Server with Static PSK Authentication Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC server configured with a static Pre-Shared Key (PSK) table for authentication. This method is suitable for known clients with pre-shared secrets. ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, psks => #{ <<"client1">> => <<"secret1">>, <<"client2">> => <<"secret2">> } }) ``` -------------------------------- ### Start Docker Push-Enabled H3 Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Command to start a push-enabled H3 server in a Docker container. ```bash docker compose -f docker/docker-compose.yml up h3-push-server -d ``` -------------------------------- ### Start QUIC Server with Dynamic PSK Callback Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC server that uses a callback function to dynamically look up Pre-Shared Keys (PSKs) based on the client's identity. This allows for on-the-fly PSK retrieval from a database or other secure storage. ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, psk_callback => fun(Identity) -> case database:lookup_psk(Identity) of {ok, Secret} -> {ok, Secret}; not_found -> not_found end end }) ``` -------------------------------- ### start_server/3 Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a named QUIC server on a specified port with given options. It returns the PID of the server supervisor or an error tuple. ```APIDOC ## start_server/3 ### Description Start a named QUIC server on the specified port. ### Function Signature ```erlang start_server(Name, Port, Opts) -> {ok, pid()} | {error, term()} ``` ### Parameters #### Path Parameters - **Name** (atom()) - Required - Unique server name - **Port** (inet:port_number()) - Required - Listening port (0 for ephemeral) - **Opts** (map()) - Required - Server options #### Options - **cert** (binary()) - Conditional - DER-encoded X.509 certificate - **key** (term()) - Conditional - Private key (from `public_key:pem_entry_decode/2`) - **psks** (#{binary() => binary()}) - Conditional - Static PSK table for external PSK auth - **psk_callback** (fun((binary()) -> {ok, Secret} | not_found)) - Conditional - Dynamic PSK lookup (takes precedence over `psks`) - **alpn** ([binary()]) - Optional - ALPN protocols (default: `[<<"h3">>]`) - **groups** ([atom()]) - Optional - Accepted key-exchange groups (x25519, secp256r1, secp384r1) (default: `[x25519]`) - **signature_algs** ([atom()]) - Optional - Accepted/advertised signature schemes - **pool_size** (pos_integer()) - Optional - Number of listener processes (default: 1) - **connection_handler** (fun((pid()) -> {ok, pid()})) - Optional - Custom connection handler callback ### Authentication Methods At least one must be provided: - X.509: `cert` + `key` - TLS 1.3 External PSK (RFC 8446 §4.2.11): `psks` or `psk_callback` - Both may coexist; per-handshake selection happens automatically ### Return Value - `{ok, Pid}`: On successful server start, where `Pid` is the server supervisor PID. - `{error, Reason}`: If the server fails to start. ### Request Example ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, alpn => [<<"h3">>], pool_size => 4 }) ``` ``` -------------------------------- ### Define and Start Server with Connection Handler Source: https://github.com/benoitc/erlang_quic/blob/main/docs/SERVER_GUIDE.md Defines a function to handle new incoming connections and starts the QUIC server with this handler. The handler receives connection details and spawns a process to manage the connection. ```erlang %% Define a connection handler handle_connection(ConnPid, Info) -> %% Info contains: peer_address, alpn_protocol, etc. io:format("New connection from ~p~n", [maps:get(peer_address, Info)]), %% Spawn a process to handle this connection spawn(fun() -> connection_loop(ConnPid) end). %% Start server with handler quic:start_server(my_server, 4433, #{ cert => Cert, key => Key, connection_handler => fun handle_connection/2 }). ``` -------------------------------- ### Start a named QUIC server Source: https://github.com/benoitc/erlang_quic/blob/main/README.md Loads TLS certificate and key, then starts a named QUIC server. Incoming connections are handled automatically by spawned processes. ```erlang %% Load certificate and key {ok, CertDer} = file:read_file("server.crt"), {ok, KeyDer} = file:read_file("server.key"), %% Start a named server (recommended) {ok, _Pid} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyDer, alpn => [<<"h3">>] }), %% Get the port (useful if 0 was specified for ephemeral port) {ok, Port} = quic:get_server_port(my_server), io:format("Listening on port ~p~n", [Port]), %% Incoming connections are handled automatically %% The server spawns quic_connection processes for each client %% Stop the server when done quic:stop_server(my_server). ``` -------------------------------- ### Start Echo Server Source: https://github.com/benoitc/erlang_quic/blob/main/examples/README.md Starts the echo server on a specified port. Use port 0 to let the system choose a random available port. ```erlang %% Start on port 4433 echo_server:start(4433). %% Output: Echo server started on port 4433 %% Or use port 0 for random port echo_server:start(0). ``` -------------------------------- ### Complete QUIC Distribution Configuration Example Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-dist-api.md A comprehensive example of the QUIC distribution configuration in sys.config, including TLS, node discovery, session tickets, EPMD registration, authentication, and transport options. ```erlang {quic, [ {dist, [ %% TLS Configuration (required) {cert_file, "/path/to/cert.pem"}, {key_file, "/path/to/key.pem"}, {cacert_file, "/path/to/ca.pem"}, {verify, verify_peer}, % or verify_none %% Node Discovery (required) {discovery, quic_discovery_static}, % or quic_discovery_dns {discovery_config, #{ <<"node1@host1">> => {{192, 168, 1, 1}, 9999}, <<"node2@host2">> => {{192, 168, 1, 2}, 9999} }}, %% Optional: Session Tickets for 0-RTT {tickets_dir, "/var/lib/quic/tickets"}, {tickets_ttl_ms, 3600000}, % 1 hour %% Optional: EPMD Registration {register_with_epmd, false}, %% Optional: Custom Authentication {auth_callback, fun my_auth:check/2}, %% Optional: QUIC Transport Options {groups, [x25519]}, {congestion_control, newreno} % newreno | cubic | bbr ]} ]} ``` -------------------------------- ### Start HTTP/3 Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Starts an HTTP/3 server with a specified name, port, and options. The handler can be a function or a module implementing handle_request/5. ```erlang -spec start_server(Name, Port, Opts) -> {ok, pid()} | {error, term()}. ``` ```erlang {ok, _} = quic_h3:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, handler => fun(Conn, StreamId, <<"GET">>, Path, _) -> Body = <<"Hello from ", Path/binary>>, quic_h3:send_response(Conn, StreamId, 200, []), quic_h3:send_data(Conn, StreamId, Body, true) end }). ``` -------------------------------- ### Start QUIC Server Source: https://github.com/benoitc/erlang_quic/blob/main/docs/announcement-1.3.0.linkedin-article.md Initiates a QUIC server with specified port and TLS options. Requires Cert, Key, and ALPN list. ```erlang {ok, _} = quic:start_server(my_server, 4433, #{cert => Cert, key => Key, alpn => [<<"h3">>]}). ``` -------------------------------- ### Start Erlang Node with QUIC Distribution Source: https://github.com/benoitc/erlang_quic/blob/main/docs/QUIC_DIST.md Starts an Erlang node using QUIC as the distribution protocol. Requires specifying the protocol, EPMD module, distribution port, configuration file, and code path. ```bash erl -name node1@host1 \ -proto_dist quic \ -epmd_module quic_epmd \ -start_epmd false \ -quic_dist_port 4433 \ -config sys.config \ -pa _build/default/lib/quic/ebin ``` -------------------------------- ### Request/Response Example Source: https://github.com/benoitc/erlang_quic/blob/main/docs/QUIC_DIST.md Demonstrates a simple request/response pattern between two nodes using QUIC distribution streams. ```erlang %% Node A: Send request {ok, Stream} = quic_dist:open_stream('nodeB@host'), ok = quic_dist:send(Stream, <<"GET /data">>, true), receive {quic_dist_stream, Stream, {data, Response, true}} -> io:format("Response: ~p~n", [Response]) end. %% Node B: Accept and respond ok = quic_dist:accept_streams('nodeA@host'), receive {quic_dist_stream, Stream, {data, Request, true}} -> Response = handle_request(Request), quic_dist:send(Stream, Response, true) end. ``` -------------------------------- ### Start QUIC Listener (Unlinked) Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC listener without linking it to the caller's process. This is an alternative to `start_link/2` when process linking is not desired. ```erlang quic_listener:start(Port, Opts) -> {ok, pid()} | {error, term()} ``` -------------------------------- ### Start High-Performance QUIC Server Pool Source: https://github.com/benoitc/erlang_quic/blob/main/docs/SERVER_GUIDE.md Configures and starts a QUIC server with a pool of listener processes, one for each scheduler, to handle high concurrency. Supports HTTP/3 via ALPN. ```erlang %% Start a server pool with multiple listener processes {ok, _} = quic:start_server(high_perf_server, 4433, #{ cert => Cert, key => Key, pool_size => erlang:system_info(schedulers), % One per scheduler alpn => [<< ``` -------------------------------- ### Erlang HTTP/3-style Client Example Source: https://github.com/benoitc/erlang_quic/blob/main/docs/CLIENT_GUIDE.md An example of an Erlang client making an HTTP/3-style request over QUIC. It handles connection, stream opening, data sending, and response reception. ```erlang -module(h3_client). -export([request/3]). request(Host, Port, Path) -> %% Connect {ok, Conn} = quic:connect(Host, Port, #{ alpn => [<<"h3">>], verify => false }, self()), receive {quic, Conn, {connected, _}} -> ok after 5000 -> quic:close(Conn, timeout), exit(connection_timeout) end, %% Open request stream {ok, StreamId} = quic:open_stream(Conn), %% Send request (simplified, not real H3) Request = <<"GET ", Path/binary, " HTTP/3\r\n\r\n">>, ok = quic:send_data(Conn, StreamId, Request, true), %% Receive response Response = receive_response(Conn, StreamId, <<>>), quic:close(Conn, normal), Response. receive_response(Conn, StreamId, Acc) -> receive {quic, Conn, {stream_data, StreamId, Data, false}} -> receive_response(Conn, StreamId, <>); {quic, Conn, {stream_data, StreamId, Data, true}} -> <>; {quic, Conn, {closed, _}} -> Acc after 10000 -> Acc end. ``` -------------------------------- ### quic_listener:start_link/2 Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC listener process, linking it to the caller. It binds to a specified port and accepts various configuration options for the listener. ```APIDOC ## quic_listener:start_link/2 ### Description Start a QUIC listener on a given port. ### Function Signature ```erlang quic_listener:start_link(Port, Opts) -> {ok, pid()} | {error, term()} ``` ### Parameters #### Path Parameters * **Port** (`inet:port_number()`) - Listening port * **Opts** (`map()`) - Listener options #### Options: * **`cert`** (`binary()`) - DER-encoded certificate * **`cert_chain`** (`[binary()]`) - Certificate chain * **`key`** (`term()`) - Private key * **`alpn`** (`[binary()]`) - ALPN protocols * **`active_n`** (`pos_integer()`) - Packets before socket goes passive * **`reuseport`** (`boolean()`) - Enable SO_REUSEPORT (multiple listeners) * **`connections_table`** (`ets:tid()`) - Shared ETS table (pool mode) * **`preferred_ipv4`** (`{inet:ip_address(), inet:port_number()}`) - Preferred IPv4 (RFC 9000 Section 9.6) * **`preferred_ipv6`** (`{inet:ip_address(), inet:port_number()}`) - Preferred IPv6 (RFC 9000 Section 9.6) * **`socket_backend`** (`gen_udp | socket`) - Socket implementation * **`address_validation`** (`never | always`) - Address validation policy (RFC 9000 §8.1) * **`address_token_max_age_ms`** (`non_neg_integer()`) - Token freshness bound (ms) * **`reset_secret`** (`binary()`) - Stateless reset secret * **`connection_handler`** (`fun((pid()) -> {ok, pid()})`) - Custom connection handler * **`cid_config`** (`#cid_config{}`) - QUIC-LB CID configuration ### Return Value `{ok, ListenerPid}` or error ### Example ```erlang {ok, Listener} = quic_listener:start_link(4433, #{ cert => CertDer, key => KeyTerm, alpn => [<<"h3">>] }), Port = quic_listener:get_port(Listener) ``` ``` -------------------------------- ### Start QUIC Server with Listener Pool Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC server with a listener pool, utilizing SO_REUSEPORT to distribute load across multiple cores for high-throughput scenarios. The 'pool_size' option specifies the number of listener processes. ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, pool_size => 4 % 4 listeners on the same port }) ``` -------------------------------- ### X.509 Certificate Authentication Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Starts a QUIC server using X.509 certificates for authentication. Requires both certificate and key files. ```APIDOC ## quic:start_server/3 with X.509 Certificate Authentication ### Description Starts a QUIC server using X.509 certificates for authentication. This method requires the server to have both a certificate and a private key. ### Method `quic:start_server/3` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body This function does not take a request body in the traditional HTTP sense. Instead, it takes a server name, port, and a keyword list of options. - **my_server** (atom) - The name of the server. - **4433** (integer) - The port number to listen on. - **Options** (keyword list) - **cert** (binary) - The server's X.509 certificate in DER format. - **key** (binary) - The server's private key in DER format. ### Request Example ```erlang {ok, CertDer} = file:read_file("server.crt"), {ok, KeyDer} = file:read_file("server.key"), {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyDer }) ``` ### Response #### Success Response (ok) - **_** (atom) - An atom indicating success, typically `ok`. #### Response Example ```erlang {ok, ServerPid} ``` ``` -------------------------------- ### Acceptor Pool Example Source: https://github.com/benoitc/erlang_quic/blob/main/docs/QUIC_DIST.md Sets up multiple acceptor processes for a node to distribute the load of handling incoming streams. ```erlang %% Start multiple acceptors for load distribution start_acceptor_pool(Node, N) -> [spawn(fun() -> acceptor_loop(Node) end) || _ <- lists:seq(1, N)]. acceptor_loop(Node) -> ok = quic_dist:accept_streams(Node), receive {quic_dist_stream, Stream, {data, Data, Fin}} -> handle_request(Stream, Data, Fin), acceptor_loop(Node) end. ``` -------------------------------- ### HTTP/3 Client Connection Example Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/configuration-reference.md Connect to an HTTP/3 server with specified options. Use this for establishing client-side H3 connections. ```erlang {ok, H3} = quic_h3:connect("example.com", 443, #{ sync => true, connect_timeout => 5000, verify => true, settings => #{ qpack_max_table_size => 4096, max_header_list_size => 8192 } }) ``` -------------------------------- ### Example HTTP/3 Server Handler Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md An example of a request handler function for an HTTP/3 server. It sends a 200 OK response for GET requests and a 405 Method Not Allowed for others. ```erlang {ok, _} = quic_h3:start_server(my_h3, 4433, #{ cert => CertDer, key => KeyTerm, handler => fun handle_request/5 }). handle_request(Conn, StreamId, << ``` ```erlang GET/binary>>, Path, _Headers) -> quic_h3:send_response(Conn, StreamId, 200, [ {<< ``` ```erlang content-type/binary>>, << ``` ```erlang text/plain/binary>> ]), quic_h3:send_data(Conn, StreamId, << ``` ```erlang Hello from ", Path/binary>>, true); handle_request(Conn, StreamId, _Method, _Path, _Headers) -> quic_h3:send_response(Conn, StreamId, 405, []), quic_h3:send_data(Conn, StreamId, << ``` ```erlang Method not allowed/binary>>, true) ``` -------------------------------- ### Quick Start: Connect, Send, and Receive Source: https://github.com/benoitc/erlang_quic/blob/main/docs/CLIENT_GUIDE.md Demonstrates the basic steps to connect to a QUIC server, send data, receive a response, and close the connection. ```erlang %% Start the QUIC application application:ensure_all_started(quic). %% Connect to a server {ok, Conn} = quic:connect("example.com", 443, #{ alpn => [<<"h3">>], verify => false % For testing only! }, self()). %% Wait for connection receive {quic, Conn, {connected, Info}} -> io:format("Connected! ALPN: ~p~n", [maps:get(alpn_protocol, Info)]) end. %% Open a stream and send data {ok, StreamId} = quic:open_stream(Conn), ok = quic:send_data(Conn, StreamId, <<"Hello, QUIC!">>, true). %% Receive response receive {quic, Conn, {stream_data, StreamId, Data, _Fin}} -> io:format("Received: ~p~n", [Data]) end. %% Close connection quic:close(Conn, normal). ``` -------------------------------- ### Run Interop Tests Against aioquic Source: https://github.com/benoitc/erlang_quic/blob/main/interop/README.md Starts the aioquic server using Docker Compose and then runs interop tests against it using rebar3. ```bash # Start aioquic server docker compose -f docker/docker-compose.yml up -d # Run tests rebar3 ct --suite=quic_interop_SUITE ``` -------------------------------- ### QUIC Distribution setup/5 Callback Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-dist-api.md The setup/5 callback establishes an outgoing distribution connection to a specified node. It returns a process ID or an error reason. ```erlang setup(Node, Type, MyNode, LongOrShortNames, SetupTime) -> pid() | {error, Reason} ``` -------------------------------- ### Start a Named QUIC Server Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Use `start_server/3` to initiate a named QUIC server on a specific port with given options. Ensure you provide a unique server name, a listening port, and a map of server options including certificate and key for authentication. ```erlang start_server(Name, Port, Opts) -> {ok, pid()} | {error, term()} ``` ```erlang {ok, _} = quic:start_server(my_server, 4433, #{ cert => CertDer, key => KeyTerm, alpn => [<<"h3">>], pool_size => 4 }) ``` -------------------------------- ### Get QUIC MTU Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-client-api.md Retrieves the current Maximum Transmission Unit (MTU) discovered via DPLPMTUD. The MTU starts at 1200 bytes and is probed up to the peer's max_udp_payload_size. ```erlang get_mtu(Conn) -> {ok, pos_integer()} | {error, term()} ``` -------------------------------- ### Example QUIC Client Connection Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/configuration-reference.md Demonstrates how to establish a QUIC client connection with various configuration options, including ALPN, certificate verification, key exchange groups, CA certificates, happy eyeballs, and connection timeout. ```erlang {ok, Conn} = quic:connect(<<"example.com">>, 443, #{ alpn => [<<"h3">>], verify => true, groups => [x25519, secp256r1], cacerts => [CACertDer], happy_eyeballs => true, connect_timeout => 5000 }, self()) ``` -------------------------------- ### Get QUIC Server Listening Port Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-server-api.md Use `get_server_port/1` to obtain the listening port number of a named QUIC server. This is particularly useful when the server was initially started with an ephemeral port (port 0). ```erlang get_server_port(Name) -> {ok, inet:port_number()} | {error, not_found} ``` -------------------------------- ### Example QLOG File Format (JSON-SEQ) Source: https://github.com/benoitc/erlang_quic/blob/main/docs/QLOG_GUIDE.md Illustrates the JSON-SEQ format used for QLOG files, showing the header and subsequent event objects. ```json {"qlog_format":"JSON-SEQ","qlog_version":"0.4",...} {"time":0,"name":"quic:connection_started",...} {"time":15,"name":"quic:packet_sent",...} {"time":23,"name":"quic:packet_received",...} ``` -------------------------------- ### Start Echo Server in Erlang Shell Source: https://github.com/benoitc/erlang_quic/blob/main/docs/GETTING_STARTED.md Compile and start the echo server in the Erlang shell, listening on port 4433. ```erlang 1> c(echo_server). {ok,echo_server} 2> echo_server:start(4433). {ok,<0.123.0>} ``` -------------------------------- ### Create QUIC-LB Configuration Examples Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-lb-api.md Demonstrates creating configurations for both plaintext and stream cipher algorithms, including specifying a nonce length for the stream cipher configuration. ```erlang {ok, PlaintextConfig} = quic_lb:new_config( #{algorithm => plaintext, server_id => <<"server1">>, config_rotation => 0 }), {ok, CipherConfig} = quic_lb:new_config( #{algorithm => stream_cipher, server_id => <<"server2">>, key => crypto:strong_rand_bytes(16), nonce_len => 8, config_rotation => 1 }) ``` -------------------------------- ### Integrate QUIC-LB with QUIC Server Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-lb-api.md Demonstrates how to set up a QUIC server with QUIC-LB configuration. This involves creating LB and CID generation configurations and passing them to the QUIC server start function. ```erlang % Create LB config {ok, LBConfig} = quic_lb:new_config(#{ algorithm => stream_cipher, server_id => << ``` -------------------------------- ### Build and Development Commands Source: https://github.com/benoitc/erlang_quic/blob/main/AGENTS.md Common commands for building, testing, linting, and generating documentation for the project. ```bash rebar3 compile # Build rebar3 eunit # Run all EUnit tests rebar3 eunit --module=quic_varint_tests # Run specific test module rebar3 eunit --module=quic_varint_tests --test=encode_0_test # Run single test rebar3 proper # Run PropEr property-based tests rebar3 ct --suite=quic_e2e_SUITE # Run specific Common Test suite rebar3 lint # Elvis linter rebar3 fmt --check # Check formatting (erlfmt) rebar3 fmt # Auto-format code rebar3 dialyzer # Type checking rebar3 xref # Cross-reference analysis rebar3 ex_doc # Generate docs ``` -------------------------------- ### Get Maximum Datagram Size Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md Get the maximum datagram payload size for a stream. Returns 0 if datagrams are not supported or the stream doesn't exist. ```erlang max_datagram_size(Conn, StreamId) ``` -------------------------------- ### Example Owner Process Message Loop Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/http3-api.md An example of an Erlang process loop that handles incoming HTTP/3 events such as responses, data, and connection closures. ```erlang loop(H3) -> receive {quic_h3, H3, {response, StreamId, 200, Headers}} -> io:format("Got 200 response~n"), loop(H3); {quic_h3, H3, {data, StreamId, Data, true}} -> io:format("Got final data: ~p~n", [Data]), loop(H3); {quic_h3, H3, {closed, normal}} -> io:format("Connection closed~n"); Other -> io:format("Unexpected message: ~p~n", [Other]), loop(H3) end ``` -------------------------------- ### Basic erlang_quic Server Implementation Source: https://github.com/benoitc/erlang_quic/blob/main/docs/DEVELOPER_GUIDE.md Sets up a basic QUIC server using gen_server. It handles new connections, stream openings, stream data, and connection closures. ```erlang -module(my_server). -behaviour(gen_server). -export([start_link/2, init/1, handle_info/2]). start_link(Port, CertKey) -> gen_server:start_link(?MODULE, {Port, CertKey}, []). init({Port, {Cert, Key}}) -> Opts = #{ cert => Cert, key => Key, alpn => [<<"h3">>] }, {ok, _} = quic:start_server(my_quic_server, Port, Opts), {ok, #{}}. handle_info({quic, Conn, {connected, Info}}, State) -> io:format("New connection from ~p~n", [maps:get(peer, Info)]), {noreply, State}; handle_info({quic, Conn, {stream_opened, StreamId}}, State) -> io:format("Stream ~p opened~n", [StreamId]), {noreply, State}; handle_info({quic, Conn, {stream_data, StreamId, Data, Fin}}, State) -> %% Process request Response = process_request(Data), %% Send response quic:send_data(Conn, StreamId, Response, true), {noreply, State}; handle_info({quic, Conn, {closed, Reason}}, State) -> io:format("Connection closed: ~p~n", [Reason]), {noreply, State}. ``` -------------------------------- ### Simple HTTP/3 GET Request Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Connect to an HTTP/3 server, make a GET request, and receive the response status, headers, and body. Ensure the server is accessible and configured. ```erlang %% Connect and make a request {ok, Conn} = quic_h3:connect("example.com", 443, #{sync => true}), Headers = [ {<<":method">>, << ``` ```erlang GET">>}}, {<<":scheme">>, << ``` ```erlang https">>}}, {<<":path">>, <<"/">>}, {<<":authority">>, << ``` ```erlang example.com">>} ], {ok, StreamId} = quic_h3:request(Conn, Headers), %% Receive response receive {quic_h3, Conn, {response, StreamId, Status, RespHeaders}} -> io:format("Status: ~p~nHeaders: ~p~n", [Status, RespHeaders]) end, %% Receive body receive {quic_h3, Conn, {data, StreamId, Body, true}} -> io:format("Body: ~s~n", [Body]) end, quic_h3:close(Conn). ``` -------------------------------- ### Get Maximum QUIC Datagram Size Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-client-api.md Use datagram_max_size/1 to get the maximum payload size for datagrams. Returns 0 if the peer does not support datagrams as per RFC 9221. ```erlang datagram_max_size(Conn) -> non_neg_integer() | {error, term()} ``` -------------------------------- ### Start HTTP/3 Server with Datagram Support Source: https://github.com/benoitc/erlang_quic/blob/main/docs/HTTP3.md Enables HTTP datagram support when starting an HTTP/3 server. The H3 layer advertises SETTINGS_H3_DATAGRAM and automatically enables RFC 9221 datagram support. ```erlang ok = quic_h3:start_server(my_server, 4433, #{ cert => Cert, key => Key, handler => fun my_http_handler/5, h3_datagram_enabled => true }). ``` -------------------------------- ### Run Client with QLOG Tracing Source: https://github.com/benoitc/erlang_quic/blob/main/examples/README.md Connects to the server with QLOG tracing enabled. The client will also generate a QLOG file upon connection closure. ```erlang qlog_example:run_client("localhost", 4433). %% Output: %% Connecting to localhost:4433 with QLOG enabled %% Connected! %% Sent: <<"QLOG test data - Hello World!">> %% Received: <<"QLOG test data - Hello World!">> %% Connection closed. QLOG file written to: /tmp/qlog ``` -------------------------------- ### QUIC Distribution listen/1, listen/2 Callbacks Source: https://github.com/benoitc/erlang_quic/blob/main/_autodocs/quic-dist-api.md The listen/1 and listen/2 callbacks are used to start listening for incoming distribution connections on node startup. They return the listening socket and associated information. ```erlang listen(Name) -> {ok, {LSocket, TcpAddress, Creation}} | {error, Reason} listen(Name, ExtraOpts) -> {ok, {LSocket, TcpAddress, Creation}} | {error, Reason} ```