webtransport (webtransport v0.5.9)
View SourceWebTransport Public API
This module provides the public API for WebTransport over HTTP/2 and HTTP/3.
Server Usage
%% Start a WebTransport listener
{ok, Listener} = webtransport:start_listener(my_listener, #{
transport => h3,
port => 8443,
certfile => "cert.pem",
keyfile => "key.pem",
handler => my_wt_handler
}).
%% Stop the listener
ok = webtransport:stop_listener(my_listener).Client Usage
%% Connect to a WebTransport server
{ok, Session} = webtransport:connect("example.com", 443, "/wt", #{
transport => h3
}).
%% Open a bidirectional stream
{ok, Stream} = webtransport:open_stream(Session, bidi).
%% Send data
ok = webtransport:send(Session, Stream, <<"Hello">>).
%% Send with FIN flag
ok = webtransport:send(Session, Stream, <<"World">>, fin).
%% Send unreliable datagram
ok = webtransport:send_datagram(Session, <<"ping">>).
%% Close stream
ok = webtransport:close_stream(Session, Stream).
%% Close session
ok = webtransport:close_session(Session).Handler Behaviour
See webtransport_handler for the callback behaviour.
Summary
Functions
Accept a WebTransport session on an incoming CONNECT request.
Close the session gracefully.
Close the session with an error code.
Close the session with an error code and reason. http3-17 §6, http2-16 §6.12: the code is 32 bits and the reason is valid UTF-8 of at most 1024 bytes.
Close a stream gracefully (send FIN).
Connect to a WebTransport server.
Connect to a WebTransport server with a custom handler.
Signal that no new streams will be created.
Report whether the session's connection negotiated 0-RTT early data.
Return HTTP/2 settings to merge into an h2 server configuration.
Return HTTP/3 settings to merge into a quic_h3 server configuration.
Get information about a listener.
Get the bound {Ip, Port} of a listener.
List all active listeners.
Open a new stream on the session.
Abruptly terminate a stream with an error code.
Send data on a stream.
Send data on a stream with optional FIN flag.
Send an unreliable datagram.
Get session information.
Start a WebTransport listener.
Stop a WebTransport listener.
Request that the peer stop sending on a stream.
Types
-type connect_opts() :: #{transport => h2 | h3, certfile => file:filename(), keyfile => file:filename(), cacertfile => file:filename(), verify => verify_none | verify_peer, headers => [{binary(), binary()}], timeout => timeout(), family => inet | inet6 | any, happy_eyeballs => boolean(), connection_attempt_delay => non_neg_integer(), session_ticket => term(), socket_opts => [gen_tcp:connect_option()], compat_mode => latest | legacy_browser_compat | draft07}.
-type listener_name() :: atom().
-type listener_opts() :: #{transport := h2 | h3, port := inet:port_number(), certfile := file:filename(), keyfile := file:filename(), handler := module(), handler_opts => term(), max_data => non_neg_integer(), max_streams_bidi => non_neg_integer(), max_streams_uni => non_neg_integer(), max_send_buffer => non_neg_integer(), ip => inet:ip_address(), family => inet | inet6, socket_opts => list(), sni_callback => sni_callback(), compat_mode => latest | legacy_browser_compat | auto}.
-type session() :: pid().
-type stream() :: non_neg_integer().
Functions
-spec accept(pid(), non_neg_integer(), [{binary(), binary()}], map()) -> {ok, session()} | {error, term()}.
Accept a WebTransport session on an incoming CONNECT request.
Call this from your HTTP request handler when you want a particular CONNECT request to become a WebTransport session. The function validates headers, starts the session gen_statem, registers it as the stream handler (like quic_h3:set_stream_handler/3), sends 200, and returns {ok, Session}.
my_handler(Conn, StreamId, <<"CONNECT">>, <<"/wt">>, Headers) ->
webtransport:accept(Conn, StreamId, Headers, #{
transport => h3,
handler => my_wt_handler,
handler_opts => #{owner => self()}
});
my_handler(Conn, StreamId, <<"GET">>, _Path, _Headers) ->
quic_h3:send_response(Conn, StreamId, 200, []),
quic_h3:send_data(Conn, StreamId, <<"hello">>, true).
-spec close_session(session()) -> ok.
Close the session gracefully.
-spec close_session(session(), non_neg_integer()) -> ok.
Close the session with an error code.
-spec close_session(session(), non_neg_integer(), binary()) -> ok | {error, reason_too_long | invalid_reason | invalid_error_code}.
Close the session with an error code and reason. http3-17 §6, http2-16 §6.12: the code is 32 bits and the reason is valid UTF-8 of at most 1024 bytes.
Close a stream gracefully (send FIN).
-spec connect(Host, Port, Path, Opts) -> {ok, session()} | {error, term()} when Host :: string() | binary() | inet:ip_address(), Port :: inet:port_number(), Path :: binary(), Opts :: connect_opts().
Connect to a WebTransport server.
Options: - transport - Optional. Either h2 or h3 (default: h3) - cacertfile - Optional. CA certificate file for verification - verify - Optional. verify_none or verify_peer (default: verify_peer) - headers - Optional. Extra headers to send in CONNECT request - timeout - Optional. Connection timeout in ms (default: 30000) - socket_opts - Optional. gen_tcp/inet options for the client socket, for example [{ip, {192,168,1,10}}, {recbuf, 262144}]. On h3 the options that apply to UDP are used and TCP-only ones (nodelay, keepalive, linger, send_timeout, ...) are ignored. On h2 they are set on the TCP socket and win over the library's defaults. Options the library controls (active, mode, packet, header, inet, inet6) and TLS options are ignored on both.
-spec connect(Host, Port, Path, Opts, Handler) -> {ok, session()} | {error, term()} when Host :: string() | binary() | inet:ip_address(), Port :: inet:port_number(), Path :: binary(), Opts :: connect_opts(), Handler :: module() | undefined.
Connect to a WebTransport server with a custom handler.
-spec drain_session(session()) -> ok.
Signal that no new streams will be created.
Report whether the session's connection negotiated 0-RTT early data.
Returns true, false, or unknown for h3 sessions (RFC 9001 §4.6), and not_supported for h2. This is connection-level: it reflects whether the QUIC connection used 0-RTT, regardless of whether the WebTransport CONNECT itself rode as early data.
-spec h2_settings() -> map().
Return HTTP/2 settings to merge into an h2 server configuration.
Opts = maps:merge(webtransport:h2_settings(), #{
cert => "cert.pem", key => "key.pem",
handler => fun my_handler/5,
enable_connect_protocol => true
}),
h2:start_server(443, Opts).
-spec h3_settings() -> map().
Return HTTP/3 settings to merge into a quic_h3 server configuration.
Use this when embedding WebTransport into an existing HTTP/3 server instead of using start_listener/2. The returned map contains:
- settings -- H3 SETTINGS to advertise (wt_enabled, flow control, etc.) - stream_type_handler -- claims WT extension streams (0x41 bidi, 0x54 uni) - h3_datagram_enabled -- enables QUIC datagrams - quic_opts -- QUIC transport params (max_datagram_frame_size, reset_stream_at) - connection_handler -- per-connection setup (creates the WT stream router)
Merge the result into your quic_h3 server opts:
Opts = maps:merge(webtransport:h3_settings(), #{
cert => CertDer, key => PrivateKey,
handler => fun my_handler/5
}),
quic_h3:start_server(my_server, 443, Opts).
-spec listener_info(listener_name()) -> {ok, map()} | {error, not_found}.
Get information about a listener.
The sockname field is the bound {Ip, Port}. For h3 it is resolved live from the QUIC socket (correct even when bound with port 0 or inet6). For h2 it is best-effort (requested address + bound port), since the h2 library does not expose the bound IP.
-spec listener_sockname(listener_name()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}.
Get the bound {Ip, Port} of a listener.
For h3, resolved live from the QUIC listener socket. For h2 this is best-effort: the requested bind address (defaulting to the family wildcard) paired with the actual bound port, because the h2 library exposes only the port, not the bound IP.
-spec listeners() -> [listener_name()].
List all active listeners.
Open a new stream on the session.
-spec reset_stream(session(), stream(), non_neg_integer()) -> ok | {error, term()}.
Abruptly terminate a stream with an error code.
Send data on a stream.
Send data on a stream with optional FIN flag.
Bytes beyond the peer's flow-control credit wait in the session. When it already holds max_send_buffer bytes (4 MiB by default), a send that cannot go out at once returns {error, send_buffer_full}; try again once the peer has read.
Send an unreliable datagram.
Get session information.
-spec start_listener(listener_name(), listener_opts()) -> {ok, pid()} | {error, term()}.
Start a WebTransport listener.
Options: - transport - Required. Either h2 (HTTP/2) or h3 (HTTP/3) - port - Required. Port to listen on - certfile - Required. Path to TLS certificate - keyfile - Required. Path to TLS private key - handler - Required. Module implementing webtransport_handler behaviour - handler_opts - Optional. Initial options passed to handler:init/2 - max_data - Optional. Initial max session data (default 1MB) - max_streams_bidi - Optional. Initial max bidi streams (default 100) - max_streams_uni - Optional. Initial max uni streams (default 100)
-spec stop_listener(listener_name()) -> ok | {error, term()}.
Stop a WebTransport listener.
-spec stop_sending(session(), stream(), non_neg_integer()) -> ok | {error, term()}.
Request that the peer stop sending on a stream.