hackney_wt (hackney v4.2.2)

View Source

gen_statem process for WebTransport client connections.

This module mirrors hackney_ws so an application can move from WebSocket to WebTransport by swapping the ws_ API prefix for wt_. It wraps an erlang-webtransport client session (HTTP/3 by default, HTTP/2 optional) and owns that session process.

Connection reuse and multiplexing

A WebTransport session is the analog of an HTTP/2 connection: one hackney_wt process owns a single session and many streams are multiplexed over it. open_stream/2 opens as many bidirectional or unidirectional streams as the peer's flow control allows; each stream has its own send (stream_send/3,4) and receive (stream_recv/2,3) channel, keyed by stream id, exactly like the h2_streams map in hackney_conn.

Default message channel

WebTransport has no message framing of its own, so to stay interoperable with any server we do NOT invent a wire format. The send/2 / recv/1 convenience channel maps onto a single persistent bidirectional stream opened at connect time: send/2 writes bytes to it and recv/1 returns the next chunk received on it as {binary, Data}. Datagrams and data from server-opened streams are also surfaced on this channel as {datagram, Data} and {stream, Id, Data}. Because there is no framing, chunks are not guaranteed to align with send boundaries; an application that needs message boundaries must self-delimit.

Delivery modes

In passive mode (the default) data is buffered per channel and read with recv/stream_recv. In active mode every event is forwarded to the owner uniformly tagged with its stream id: {hackney_wt, Conn, {binary, Data}}, {hackney_wt, Conn, {datagram, Data}}, {hackney_wt, Conn, {stream, Id, Data}}, {hackney_wt, Conn, {stream_fin, Id, Data}}, {hackney_wt, Conn, {stream_closed, Id, Reason}} and {hackney_wt, Conn, closed}.

States:

  • idle: process started, session not yet established
  • connected: session established, ready for I/O
  • closed: session terminated (buffered data still drainable)

Summary

Functions

Close the session gracefully (error code 0, no reason).

Close a stream gracefully (send FIN).

Establish the WebTransport session. Blocks until the CONNECT completes or fails.

Assign a new controlling process.

Open a new stream multiplexed over the session. Returns its id.

Receive the next message on the primary channel (passive mode only).

Abruptly terminate a stream with an error code.

Send on the connection. Frame forms

Send an unreliable datagram.

Return session information (transport, stream count, flow control).

Set options. Supported: [{active, true|false|once}]

Start a WebTransport connection process. Options

Ask the peer to stop sending on a stream.

Receive the next chunk on a client-opened stream (passive mode). Returns {ok, Data}, {ok, {fin, Data}} when the peer ends the stream, or {error, Reason}.

Write to a stream (no FIN).

Write to a stream, optionally closing the write side (FIN).

Types

stream_msg/0

-type stream_msg() :: {ok, binary()} | {ok, {fin, binary()}} | {error, term()}.

wt_frame/0

-type wt_frame() ::
          {text, iodata()} |
          {binary, iodata()} |
          iodata() |
          {datagram, iodata()} |
          {stream, non_neg_integer(), iodata()} |
          {stream, non_neg_integer(), iodata(), fin | nofin}.

wt_msg/0

-type wt_msg() ::
          {binary, binary()} |
          {datagram, binary()} |
          {stream, non_neg_integer(), binary()} |
          {stream_fin, non_neg_integer(), binary()} |
          {stream_closed, non_neg_integer(), term()}.

Functions

close(Pid)

-spec close(pid()) -> ok.

Close the session gracefully (error code 0, no reason).

close(Pid, _)

-spec close(pid(), {non_neg_integer(), binary()}) -> ok.

close_stream(Pid, StreamId)

-spec close_stream(pid(), non_neg_integer()) -> ok | {error, term()}.

Close a stream gracefully (send FIN).

closed(_, OldState, Data)

connect(Pid)

-spec connect(pid()) -> ok | {error, term()}.

Establish the WebTransport session. Blocks until the CONNECT completes or fails.

connect(Pid, Timeout)

-spec connect(pid(), timeout()) -> ok | {error, term()}.

connected(_, OldState, Data)

controlling_process(Pid, NewOwner)

-spec controlling_process(pid(), pid()) -> ok | {error, term()}.

Assign a new controlling process.

idle(_, OldState, Data)

open_stream(Pid, Type)

-spec open_stream(pid(), bidi | uni) -> {ok, non_neg_integer()} | {error, term()}.

Open a new stream multiplexed over the session. Returns its id.

recv(Pid)

-spec recv(pid()) -> {ok, wt_msg()} | {error, term()}.

Receive the next message on the primary channel (passive mode only).

recv(Pid, Timeout)

-spec recv(pid(), timeout()) -> {ok, wt_msg()} | {error, term()}.

reset_stream(Pid, StreamId, ErrorCode)

-spec reset_stream(pid(), non_neg_integer(), non_neg_integer()) -> ok | {error, term()}.

Abruptly terminate a stream with an error code.

send(Pid, Frame)

-spec send(pid(), wt_frame()) -> ok | {error, term()}.

Send on the connection. Frame forms:

  • {text, Data} | {binary, Data} | Data (binary/iodata): write to the persistent default stream
  • {datagram, Data}: send an unreliable datagram
  • {stream, StreamId, Data} | {stream, StreamId, Data, fin|nofin}: write to a specific stream

send_datagram(Pid, Data)

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

Send an unreliable datagram.

session_info(Pid)

-spec session_info(pid()) -> {ok, map()} | {error, term()}.

Return session information (transport, stream count, flow control).

setopts(Pid, Opts)

-spec setopts(pid(), list()) -> ok | {error, term()}.

Set options. Supported: [{active, true|false|once}]

start_link(Opts)

-spec start_link(map()) -> {ok, pid()} | {error, term()}.

Start a WebTransport connection process. Options:

  • host: Target host (string or binary)
  • port: Target port (integer)
  • transport: h3 (default) or h2
  • path: WebTransport path (binary, default "/")
  • connect_opts: webtransport:connect/4 options map
  • connect_timeout: Connection timeout (default 8000ms)
  • recv_timeout: Default receive timeout (default infinity)
  • active: false | true | once (default false)
  • max_recv_buffer: passive buffer cap in bytes (default 64 MiB)

stop_sending(Pid, StreamId, ErrorCode)

-spec stop_sending(pid(), non_neg_integer(), non_neg_integer()) -> ok | {error, term()}.

Ask the peer to stop sending on a stream.

stream_recv(Pid, StreamId)

-spec stream_recv(pid(), non_neg_integer()) -> stream_msg().

Receive the next chunk on a client-opened stream (passive mode). Returns {ok, Data}, {ok, {fin, Data}} when the peer ends the stream, or {error, Reason}.

stream_recv(Pid, StreamId, Timeout)

-spec stream_recv(pid(), non_neg_integer(), timeout()) -> stream_msg().

stream_send(Pid, StreamId, Data)

-spec stream_send(pid(), non_neg_integer(), iodata()) -> ok | {error, term()}.

Write to a stream (no FIN).

stream_send(Pid, StreamId, Data, Fin)

-spec stream_send(pid(), non_neg_integer(), iodata(), fin | nofin) -> ok | {error, term()}.

Write to a stream, optionally closing the write side (FIN).