masque_racer (masque v0.7.0)
View SourceTransport race for MASQUE client connects.
Apple's MASQUE clients (Private Relay, Network.framework) prefer HTTP/3 but fall back to HTTP/2 on networks that block QUIC. They don't wait for an h3 timeout - they give h3 a short head start and then race h2 in parallel, using whichever handshake finishes first. HTTP/1.1 over classic HTTPS follows the same idea as a tertiary rung for networks where h2 is also refused or ALPN is stripped.
This module implements that logic for a single masque:connect/3 call. It runs in the caller's process; no extra supervision.
Flow for [T1, T2, T3] (T3 optional):
- Start
T1immediately with a shadow owner. - After
prefer_timeout_msms, startT2in parallel. - After another
h1_prefer_timeout_msms (only ifT3is present), startT3in parallel. - First attempt to report
okon itshandshake_awaitcall wins. Shadow owner is flipped to the real owner viagen_statem:call(Pid, {set_owner, RealOwner}), losers are killed.
Note: the session modules already deliver to the owner set on start. To avoid a racey burst of messages going to the caller from losing attempts, each session is started with the racer as owner; on win we transfer owner via a session call. Since the race completes before any datagrams are sent (sessions only reach open on 2xx / 101), the owner swap happens on a quiet mailbox.
Summary
Functions
Race the listed transports and return the winning session.
Functions
-spec checkout_pool(masque:transport(), map()) -> {ok, map()} | {error, term()}.
-spec race([masque:transport()], masque:target(), map(), pid()) -> {ok, masque:session()} | {error, term()}.
Race the listed transports and return the winning session.