joule-moq-relay: a WebTransport session closes with its MOQT code and reason (WT_CLOSE_SESSION), on a vendored wtransport 0.7.2 #365

Merged
dcharlot merged 11 commits from joule-moq/wt-session-close into main 2026-10-20 17:21:17 -04:00

2026-10-20

Transaction Science
joule-moq-relay README and the changelog: a closing session's streams are held until its connection closes
Some checks failed
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 53s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 1m24s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 1m36s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 4m2s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m7s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 6s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 5s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m52s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 59s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Failing after 6m6s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 13:38:19 -04:00
Transaction Science
joule-moq-relay: hold a closing WebTransport session's streams until its connection closes
A stream dropped once the relay has asked to close a WebTransport session
would send its FIN or STOP_SENDING at once, ahead of the WT_CLOSE_SESSION
capsule. In a browser on the build host, a page whose stream was stopped
just before the close lost its renderer (reproduced on loopback: a page
writing a stream the relay refused crashed in most runs). The binding now
keeps such streams (WtSend, WtRecv hold the connection's Closing) until the
QUIC connection has closed, at most ten seconds, when they end with nothing
more on the wire; read_setup keeps the stream it refuses in `early`, so it
too is dropped after the close.

tests/webtransport_close.rs: a stream that breaks a rule before SETUP is
refused with PROTOCOL_VIOLATION, and the client reads the close and no
STOP_SENDING ahead of it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 13:21:33 -04:00
Transaction Science
joule-moq-relay: close a WebTransport session with its MOQT code and reason
WtConnection::close closes the WebTransport session (moq-transport-22 §6.6):
the MOQT code is the WT_CLOSE_SESSION capsule's 32-bit application error
code, unmapped, with the reason. closed() reads a peer's capsule as its code
and reason (by_peer); a QUIC close with the session still open gives no
MOQT code (u64::MAX), since its code is HTTP/3's.

tests/webtransport_close.rs: the relay refusing a grant without its proof,
refusing a session past its count, and ending one at its time limit, each
read by the client as the exact code and reason; a client's close recorded
as the peer's in the relay's summary. The browser e2e check of a bare grant
now requires code 2 and the reason over WebTransport too.

CI: the vendored crate's unit tests in the relay job; the browser and room
workflows also run on a change under vendor/. README and CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:30:35 -04:00
Transaction Science
vendored wtransport: close a WebTransport session with WT_CLOSE_SESSION
Connection::close_session(code, reason) has the driver's worker write one
DATA frame holding a WT_CLOSE_SESSION capsule (draft-ietf-webtrans-http3-16
§6) on the CONNECT stream at the highest send priority, FIN it, and wait at
most two seconds for the peer to close its side before closing the QUIC
connection with H3_NO_ERROR, so the connection's close cannot overtake the
capsule. The reason is cut to 1024 bytes at a character boundary. After it,
this end opens no stream and sends no datagram; a close asked for just as
the last handle drops still goes out.

A session the peer closes is ConnectionError::SessionClosed (the release
reported it as ApplicationClosed, the variant of the QUIC connection's
close, whose code under HTTP/3 is an HTTP/3 error code), and
Connection::closed() reports the session's end as the driver saw it.

Unit tests of the capsule's bytes against the draft's layout. The
upstream's examples and dev-dependencies are left out so the crate's unit
tests run from the workspace (cargo test -p wtransport --lib). VENDORED.md
lists every change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:30:35 -04:00
Transaction Science
joule-code: vendor wtransport 0.7.2 as published, patched in
The crate exactly as published (its .crate's SHA-256 is the lock's checksum,
b4273ce3...), with the upstream's MIT and Apache-2.0 licence files from the
commit its .cargo_vcs_info.json names. Patched into the joule-code workspace
and into joule-moq-room, a workspace of its own that builds the relay; both
locks lose only the registry source and checksum. check-lockfiles.sh skips
the vendored crate's own lock, as it does the other vendored tree's.

No change to the crate yet: the next commit adds the session close.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 04:54:03 -04:00