livery_adapter behaviour (livery v0.7.0)

View Source

Internal behaviour implemented by livery_h1, livery_h2, livery_h3, and livery_test_adapter.

Adapters translate engine events into #livery_req{} values and drive the response back onto the wire. They own no state machines; framing, header compression, flow control, and TLS belong upstream in h1, h2, quic, and ws.

Each adapter spawns a livery_req_proc for every incoming request and routes body/trailers/eof messages to that pid. Once the handler returns a #livery_resp{}, the core walks the body variant and calls back into the adapter via the callbacks defined here.

Callbacks

  • start(Name, ListenSpec, Opts) -> {ok, Listener} | {error, _} — start a listener for this adapter.

  • stop(Listener) -> ok — stop a listener cleanly.
  • send_headers(Stream, Status, Headers, SendOpts) -> SendResult — emit response headers. SendOpts may carry end_stream => true when the response has no body.
  • send_data(Stream, IoData, SendOpts) -> SendResult — emit body bytes. end_stream => true closes the send half; flush => true hints the adapter to push immediately rather than batch.
  • send_trailers(Stream, Trailers) -> SendResult — emit trailers (and implicitly close the send half).
  • send_informational(Stream, Status, Headers) -> SendResult — optional: emit an interim (1xx) response, e.g. 103 Early Hints, ahead of the final response. May be called several times per stream. Adapters that cannot (or do not) implement it are reported as informational => false in capabilities/1, and livery_req:inform/3 returns {error, unsupported}.
  • reset(Stream, Reason) -> ok — reset a stream with a protocol-specific reason.
  • peer_info(Stream) -> peer_info() — return peer/TLS info for a stream.
  • capabilities(Listener) -> capabilities() — return the capability bitmap of a listener.

Summary

Types

capabilities()

-type capabilities() ::
          #{trailers => boolean(),
            extended_connect => boolean(),
            datagrams => boolean(),
            capsules => boolean(),
            informational => boolean()}.

listen_spec()

-type listen_spec() :: term().

listener()

-type listener() :: term().

opts()

-type opts() :: map().

peer_info()

-type peer_info() ::
          #{peer => {inet:ip_address(), inet:port_number()} | undefined,
            tls => undefined | map(),
            alpn => binary() | undefined}.

reset_reason()

-type reset_reason() :: term().

send_opts()

-type send_opts() ::
          #{end_stream => boolean(), flush => boolean(), early_response_drain => livery_resp:drain()}.

send_result()

-type send_result() :: ok | {error, closed | flow | term()}.

stream()

-type stream() :: term().

Callbacks

capabilities/1

-callback capabilities(listener()) -> capabilities().

peer_info/1

-callback peer_info(stream()) -> peer_info().

reset/2

-callback reset(stream(), reset_reason()) -> ok.

send_data/3

-callback send_data(stream(), iodata(), send_opts()) -> send_result().

send_full/5

(optional)
-callback send_full(stream(), 100..599, [{binary(), binary()}], iodata(), send_opts()) -> send_result().

send_headers/4

-callback send_headers(stream(), 100..599, [{binary(), binary()}], send_opts()) -> send_result().

send_informational/3

(optional)
-callback send_informational(stream(), 100..199, [{binary(), binary()}]) -> send_result().

send_trailers/2

-callback send_trailers(stream(), [{binary(), binary()}]) -> send_result().

start/3

-callback start(Name :: atom(), listen_spec(), opts()) -> {ok, listener()} | {error, term()}.

stop/1

-callback stop(listener()) -> ok.