nquic_listener (nquic v1.0.0)

View Source

Public listener API shim.

Forwards user-facing calls to nquic_listener_mgr, the gen_server child of nquic_listener_sup that holds the accept queue and the resolved listen port. The handle returned by start_link/1 (and by nquic:listen/2) is the supervisor pid; the mgr child is resolved on demand via supervisor:which_children/1. Hot-path dispatch helpers (dispatch_lookup/2, dispatch_register/3, dispatch_unregister/2) operate directly on the dispatch handle and never go through the mgr.

Summary

Functions

Accept a new connection, blocking until one is available or timeout expires.

Hand a proactively exported, freshly handshaked connection to the listener manager.

Look up the process for a connection ID, or return undefined.

Register a connection ID to a process in the dispatch table.

Remove a connection ID from the dispatch table.

Return the dispatch table for external use (e.g., library-mode export).

Return the metrics handle for this listener. Cheap snapshot; looks up the dispatch table once and reads the attached nquic_metrics handle.

Return the port number this listener is bound to.

Return a single listener option (e.g. idle_timeout, receivers) as seen at startup.

Start a new connection statem child under the partition supervisor selected by hashing the DCID. Reads the partition pid directly from the dispatch table, no gen_server:call required.

Start a listener supervision tree with the given options. Returns the supervisor pid; that pid is the public listener handle threaded through all nquic:* calls.

Stop a running listener. cascade (the default behind nquic:stop_listener/1) stops accepting, broadcasts {quic_drain, Listener} to every owner-held established connection over the dispatch pid-index, then tears the supervision tree down: the listen sockets are closed, the port is released, and the handshake-phase nquic_conn_statem processes are terminated under the supervisor shutdown budget. Owner-held connections close gracefully in their own loop on the drain signal. No connection of either class survives a cascade. detach stops accepting and frees the port (terminates the receiver sub-tree and the accept manager) but sends no drain signal: owner-held established connections keep running until their own idle timeout, and handshake-phase processes, now packet-starved, idle out. Use it to let in-flight work finish. The listener supervisor is started with supervisor:start_link/2, so it is linked to whoever called nquic:listen/2. The stop is synchronous and exits the supervisor with reason normal, so that link never kills the owner. cascade also unlinks the calling process first, so a caller that itself opened the listener is fully detached once this returns. Timeout bounds the graceful cascade shutdown before the supervisor is brutally killed. Calling stop on an already-stopped listener is a no-op.

Functions

accept(Listener, Timeout)

-spec accept(pid(), timeout()) ->
                {ok, nquic_listener_mgr:accept_entry()} | {error, nquic_error:any_reason()}.

Accept a new connection, blocking until one is available or timeout expires.

connection_established(Listener, Entry)

-spec connection_established(pid(), nquic_listener_mgr:accept_entry()) -> ok.

Hand a proactively exported, freshly handshaked connection to the listener manager.

dispatch_lookup(Dispatch, DCID)

-spec dispatch_lookup(nquic_dispatch:t(), binary()) -> pid() | undefined.

Look up the process for a connection ID, or return undefined.

dispatch_register(Dispatch, DCID, Pid)

-spec dispatch_register(nquic_dispatch:t(), binary(), pid()) -> true.

Register a connection ID to a process in the dispatch table.

dispatch_unregister(Dispatch, DCID)

-spec dispatch_unregister(nquic_dispatch:t(), binary()) -> true.

Remove a connection ID from the dispatch table.

get_dispatch(Listener)

-spec get_dispatch(pid()) -> {ok, nquic_dispatch:t()} | {error, nquic_error:any_reason()}.

Return the dispatch table for external use (e.g., library-mode export).

get_metrics(Listener)

-spec get_metrics(pid()) -> {ok, nquic_metrics:t()} | {error, nquic_error:any_reason()}.

Return the metrics handle for this listener. Cheap snapshot; looks up the dispatch table once and reads the attached nquic_metrics handle.

get_port(Listener)

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

Return the port number this listener is bound to.

opt(Listener, Key)

-spec opt(pid(), atom()) -> {ok, term()} | {error, nquic_error:any_reason()}.

Return a single listener option (e.g. idle_timeout, receivers) as seen at startup.

start_conn_child(Listener, DCID, ChildOpts)

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

Start a new connection statem child under the partition supervisor selected by hashing the DCID. Reads the partition pid directly from the dispatch table, no gen_server:call required.

start_link(Opts)

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

Start a listener supervision tree with the given options. Returns the supervisor pid; that pid is the public listener handle threaded through all nquic:* calls.

stop/3

-spec stop(pid(), cascade | detach, timeout()) -> ok.

Stop a running listener. cascade (the default behind nquic:stop_listener/1) stops accepting, broadcasts {quic_drain, Listener} to every owner-held established connection over the dispatch pid-index, then tears the supervision tree down: the listen sockets are closed, the port is released, and the handshake-phase nquic_conn_statem processes are terminated under the supervisor shutdown budget. Owner-held connections close gracefully in their own loop on the drain signal. No connection of either class survives a cascade. detach stops accepting and frees the port (terminates the receiver sub-tree and the accept manager) but sends no drain signal: owner-held established connections keep running until their own idle timeout, and handshake-phase processes, now packet-starved, idle out. Use it to let in-flight work finish. The listener supervisor is started with supervisor:start_link/2, so it is linked to whoever called nquic:listen/2. The stop is synchronous and exits the supervisor with reason normal, so that link never kills the owner. cascade also unlinks the calling process first, so a caller that itself opened the listener is fully detached once this returns. Timeout bounds the graceful cascade shutdown before the supervisor is brutally killed. Calling stop on an already-stopped listener is a no-op.