Getting Started

View Source

Requirements

  • Erlang/OTP 26.0 or later
  • rebar3
  • OpenSSL (for certificate generation)

Installation

Add to your rebar.config:

{deps, [
    {webtransport, {git, "https://github.com/benoitc/erlang-webtransport.git",
                    {branch, "main"}}}
]}.

Fetch and compile:

rebar3 get-deps
rebar3 compile

TLS Certificates

WebTransport requires TLS. For local development, generate a self-signed certificate:

openssl req -x509 -newkey rsa:2048 \
  -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj '/CN=localhost'

This produces two files:

  • cert.pem -- the X.509 certificate
  • key.pem -- the unencrypted private key

For production, use certificates from a trusted CA (e.g. Let's Encrypt). The certfile and keyfile options accept absolute or relative file paths.

Quick Start

Start a shell with all dependencies loaded:

rebar3 shell

Start the server

{ok, _} = webtransport:start_listener(my_server, #{
    transport => h3,
    port => 4433,
    certfile => "cert.pem",
    keyfile => "key.pem",
    handler => echo_server
}).

Connect a client

{ok, Session} = webtransport:connect("localhost", 4433, <<"/echo">>, #{
    transport => h3,
    verify => verify_none
}).

Send and receive

%% Open a bidirectional stream
{ok, Stream} = webtransport:open_stream(Session, bidi).

%% Send data
ok = webtransport:send(Session, Stream, <<"hello">>).

%% Receive the echo (default client handler forwards to calling process)
receive
    {webtransport, Session, {stream, Stream, bidi, Data}} ->
        io:format("Got: ~s~n", [Data])  %% prints "Got: echo: hello"
after 3000 ->
    io:format("timeout~n")
end.

%% Send an unreliable datagram
ok = webtransport:send_datagram(Session, <<"ping">>).

receive
    {webtransport, Session, {datagram, DgData}} ->
        io:format("Got: ~s~n", [DgData])  %% prints "Got: echo: ping"
after 3000 ->
    io:format("timeout~n")
end.

%% Clean up
webtransport:close_session(Session).
webtransport:stop_listener(my_server).

Default Client Handler

When connecting without a custom handler, webtransport_client_handler is used. It forwards all events to the calling process as Erlang messages:

MessageDescription
{webtransport, Session, {stream, Stream, Type, Data}}Stream data received
{webtransport, Session, {stream_fin, Stream, Type, Data}}Stream data with FIN
{webtransport, Session, {datagram, Data}}Datagram received
{webtransport, Session, {stream_closed, Stream, Reason}}Stream closed
{webtransport, Session, closed}Session terminated

Next Steps