Skip to content

h3: advertise and accept RFC-track SETTINGS_WT_MAX_SESSIONS (0xc671706a) - #363

Open
dgarnier wants to merge 1 commit into
hyperium:masterfrom
openstarnz:wt-modern-settings-pr
Open

h3: advertise and accept RFC-track SETTINGS_WT_MAX_SESSIONS (0xc671706a)#363
dgarnier wants to merge 1 commit into
hyperium:masterfrom
openstarnz:wt-modern-settings-pr

Conversation

@dgarnier

Copy link
Copy Markdown

Problem

Safari cannot establish WebTransport sessions against h3-webtransport servers. Its extended CONNECTs arrive and are then cancelled by the browser itself (H3_REQUEST_CANCELLED), while Chrome succeeds against the same server.

The cause is settings-dialect negotiation. h3 currently advertises and recognizes only the legacy draft-02 experiment codepoints:

  • SETTINGS_ENABLE_WEBTRANSPORT = 0x2b603742
  • WEBTRANSPORT_MAX_SESSIONS = 0x2b603743

The RFC-track spec (draft-ietf-webtrans-http3, draft-07 and later) negotiates via a different codepoint, SETTINGS_WT_MAX_SESSIONS = 0xc671706a, and deprecates the legacy pair. WebKit implements only the RFC-track dialect: when the server's SETTINGS lack 0xc671706a, Safari concludes the server does not support WebTransport and abandons the CONNECT. Chrome still accepts either dialect for compatibility.

Change

17 insertions across h3/src/proto/frame.rs and h3/src/config.rs:

  • Define SettingId::WT_MAX_SESSIONS = 0xc671706a and mark it supported.
  • Send it (value = max_webtransport_sessions) alongside the legacy pair, so both dialects are advertised.
  • Parse it from peer settings: treat WT_MAX_SESSIONS > 0 as WebTransport support, and prefer its value for max_webtransport_sessions. The parse side matters independently of the send side: WebTransportSession::accept rejects sessions when the client's settings lack WebTransport support, and WebKit clients send only the RFC-track codepoint.

Not included: the capsule-protocol session close/drain semantics from the later drafts. This change is only the settings negotiation — the minimal fix that unblocks WebKit interop. In testing, Safari's close() still tears the session down cleanly at the QUIC layer.

Related but out of scope: #355 (the max_webtransport_sessions value is advertised but not enforced at runtime). This PR changes which codepoint the value is negotiated under, not its enforcement — the value remains declarative-only under both dialects, exactly as before.

Verification

  • Safari 26.6.2 (macOS, locally-trusted certificate): before the patch, every WT session attempt fails with the client cancelling its CONNECT; after the patch, sessions establish, bidirectional streams round-trip application data, and WebTransport.close() tears down cleanly. Same server, certificate, and page either side of the patch — the settings are the only variable.
  • Chrome remains green with both dialects advertised.
  • cargo test -p h3 --lib passes (230 tests), cargo fmt --check clean.
  • Also exercised end to end by a QUIC data server that pins this revision: its integration suite — including a wtransport-based interop client, i.e. an independent implementation that itself sends both dialects — passes against the patched crates.

Attribution

This investigation and patch were done together with Claude Code (Claude Fable 5): it isolated the failure to settings negotiation by A/B-testing Safari against draft-02-only and dual-dialect servers, wrote the patch, and verified it in a real browser. The commit carries a Co-Authored-By trailer accordingly. A human (me) reviewed and takes responsibility for the change.

WebKit-based browsers (Safari 26) negotiate WebTransport only via the
RFC-track codepoint (draft-ietf-webtrans-http3, draft-07+) and cancel
their extended CONNECTs when the server's SETTINGS carry just the
legacy draft-02 pair (0x2b603742/0x2b603743). Chrome accepts either
dialect.

Send both dialects, and treat an incoming WT_MAX_SESSIONS > 0 as
WebTransport support when parsing peer settings — the peer-side half
matters because WebTransportSession::accept rejects sessions when the
client's settings lack WebTransport support, and WebKit clients send
only the RFC-track codepoint.

Verified against Safari 26.6.2 (macOS, trusted local cert): session
establishes, bidirectional streams round-trip, and Chrome remains
green with both dialects advertised.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant