nhttp_listener (nhttp v1.0.0)

View Source

Listener supervisor for nhttp.

A listener is the public supervisor users embed in their own supervision trees. It owns one nhttp_transport_sup per transport it serves (one for a single-transport server) and fans get_port / drain out to them. Connection caps, registry tables and listen sockets live inside each transport supervisor. The listener stays a thin one_for_one parent so a crash in one transport never disturbs another.

Usage

ChildSpec = nhttp_listener:child_spec(my_http_listener, #{
    port => 8080,
    handler => my_handler
}),
{ok, {SupFlags, [ChildSpec | OtherChildren]}}.

Summary

Functions

Generate a child spec for embedding in your supervisor with an auto-generated id.

Generate a child spec for embedding in your supervisor under a caller-supplied name. The supervisor child id is {nhttp_listener, Name}. When the listener starts it also registers itself under Name so it can be looked up later. Accepts the standard gen_server name forms (atom(), {local, atom()}, {global, term()}, {via, module(), term()}).

Drain connections from this listener.

Get the TCP port the listener is bound to. Returns the TCP/TLS transport's port (the historical meaning). For a QUIC-only listener it returns the sole transport's UDP port. Useful when port 0 was specified to get an ephemeral port. Use get_port/2 or get_ports/1 to read a specific transport's port in a mixed listener. With port => 0 the TCP and UDP transports bind different ephemeral ports, never assume they are equal.

Get the bound port for a specific transport (tcp or quic). Returns {error, {server, {no_transport, Kind}}} when the listener does not serve that transport.

Get every bound transport port as a map keyed by transport. A single-transport listener yields a one-entry map. A mixed listener yields #{tcp => P1, quic => P2}. With port => 0 the two ports differ.

Start an unnamed listener supervisor linked to the calling process. The returned pid is the only handle to the listener.

Start a named listener supervisor linked to the calling process. Name is one of atom(), {local, atom()}, {global, term()}, or {via, module(), term()}. The supervisor is registered under that name so it can be looked up later.

Types

name()

-type name() :: atom() | {local, atom()} | {global, term()} | {via, module(), term()}.

Functions

child_spec(Opts)

-spec child_spec(nhttp:opts()) -> supervisor:child_spec().

Generate a child spec for embedding in your supervisor with an auto-generated id.

Use this form when you do not need to reference the listener later by name. The supervisor child id is internally generated and not exposed.

child_spec(Name, Opts)

-spec child_spec(name(), nhttp:opts()) -> supervisor:child_spec().

Generate a child spec for embedding in your supervisor under a caller-supplied name. The supervisor child id is {nhttp_listener, Name}. When the listener starts it also registers itself under Name so it can be looked up later. Accepts the standard gen_server name forms (atom(), {local, atom()}, {global, term()}, {via, module(), term()}).

drain(ListenerPid, Timeout)

-spec drain(pid(), timeout()) -> ok.

Drain connections from this listener.

  1. Stop advertising h3 over Alt-Svc so the TCP path emits Alt-Svc: clear before any GOAWAY (RFC 7838 §2.1: stop advertising before you stop accepting).
  2. Stop the acceptor sub-supervisor so no new connections are accepted.
  3. Signal every live connection to wind down (via the tracker).
  4. Block until the tracker reports every monitored connection has exited, or the timeout elapses (reactive, no polling).
  5. Brutally terminate the conn sub-supervisor to kill any stragglers.

get_port(ListenerPid)

-spec get_port(pid()) -> {ok, inet:port_number()} | {error, term()}.

Get the TCP port the listener is bound to. Returns the TCP/TLS transport's port (the historical meaning). For a QUIC-only listener it returns the sole transport's UDP port. Useful when port 0 was specified to get an ephemeral port. Use get_port/2 or get_ports/1 to read a specific transport's port in a mixed listener. With port => 0 the TCP and UDP transports bind different ephemeral ports, never assume they are equal.

get_port(ListenerPid, Kind)

-spec get_port(pid(), tcp | quic) -> {ok, inet:port_number()} | {error, term()}.

Get the bound port for a specific transport (tcp or quic). Returns {error, {server, {no_transport, Kind}}} when the listener does not serve that transport.

get_ports(ListenerPid)

-spec get_ports(pid()) -> #{tcp | quic => inet:port_number()}.

Get every bound transport port as a map keyed by transport. A single-transport listener yields a one-entry map. A mixed listener yields #{tcp => P1, quic => P2}. With port => 0 the two ports differ.

init/1

-spec init({name() | undefined, nhttp:opts()}) ->
              {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.

start_link(Opts)

-spec start_link(nhttp:opts()) -> {ok, pid()} | ignore | {error, nhttp:start_error()}.

Start an unnamed listener supervisor linked to the calling process. The returned pid is the only handle to the listener.

start_link(Name, Opts)

-spec start_link(name(), nhttp:opts()) -> {ok, pid()} | ignore | {error, nhttp:start_error()}.

Start a named listener supervisor linked to the calling process. Name is one of atom(), {local, atom()}, {global, term()}, or {via, module(), term()}. The supervisor is registered under that name so it can be looked up later.