masque_upstream_pool (masque v0.7.0)

View Source

Registry for pooled upstream MASQUE connections.

Callers ask for an owner that can open a MASQUE tunnel against the configured upstream proxy. The registry either returns a cached masque_upstream_owner pid that has spare stream capacity, or spawns a fresh one that self-dials and notifies the registry when it is ready. Single-flight: multiple callers for the same fingerprint while a dial is in progress all block on the same result.

Fingerprints encode host + port + transport + a hash of connection-affecting opts (verify, cacerts, ssl_opts, alpn). Two callers with different trust or ALPN settings get different owners even if they target the same host:port.

The registry itself never blocks on a handshake; the async spawn of the owner process handles that. A slow upstream only stalls callers on its own key.

h1 is not handled here - the pool is opt-in for h2 / h3 only. Callers that want to pool an h1 upstream receive {error, pool_unsupported_for_transport} and should fall back to the direct per-tunnel path.

Summary

Functions

Get an owner for the given fingerprint. Opens a new one on cache miss, blocks briefly on a concurrent dial for the same fingerprint, returns {error, _} on dial failure.

Tear down every pooled owner. Used on application shutdown and in tests. Safe to call while callers are in flight - they receive {error, shutdown}.

Build a fingerprint from the host / port / transport and the connection-affecting subset of Opts. Stable under re-ordering of list-valued opts so two callers that pass ssl_opts in different order still hash to the same key.

Types

fingerprint/0

-type fingerprint() ::
          {Host :: binary() | string(),
           Port :: inet:port_number(),
           Transport :: h2 | quic_h3,
           OptsHash :: binary()}.

Functions

checkout(FP, Opts)

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

Get an owner for the given fingerprint. Opens a new one on cache miss, blocks briefly on a concurrent dial for the same fingerprint, returns {error, _} on dial failure.

Opts carries everything the owner needs to dial: host, port, connect_opts, optional transport_mod (for tests), plus any owner-level tuning (idle_timeout_ms, max_streams).

close_all()

-spec close_all() -> ok.

Tear down every pooled owner. Used on application shutdown and in tests. Safe to call while callers are in flight - they receive {error, shutdown}.

code_change(_, S, _)

fingerprint(Host, Port, Transport, Opts)

-spec fingerprint(binary() | string(), inet:port_number(), h2 | quic_h3, map()) -> fingerprint().

Build a fingerprint from the host / port / transport and the connection-affecting subset of Opts. Stable under re-ordering of list-valued opts so two callers that pass ssl_opts in different order still hash to the same key.

handle_call(Req, From, S)

handle_cast(_, S)

handle_info(_, S)

init(_)

start_link()

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

terminate(Reason, S)