afe11ac651
Adds two debugging hooks to :quic so the interop endpoint can produce
artifacts that make the runner actually useful for finding bugs:
- TlsClient.clientRandom: capture and expose the 32-byte ClientHello
random so a SSLKEYLOG line can correlate to this connection.
- QuicConnection.extraSecretsListener: optional chained secrets
listener (default null, no-op for production callers). Fires
alongside the connection's own key-installation listener at every
encryption-level transition.
- QuicConnection.cipherSuites: knob to override the offered TLS
cipher suites in ClientHello.
InteropClient now:
- Writes NSS Key Log Format lines to $SSLKEYLOGFILE when set, so
Wireshark can decrypt the sim's pcap captures.
- Implements the `chacha20` testcase by offering only
TLS_CHACHA20_POLY1305_SHA256 — exercises the ChaCha20 AEAD path
end-to-end against a peer.
Defers QLOGDIR (needs qlog observer infrastructure across packet/
frame/recovery layers — own design doc) and `versionnegotiation`
(needs the writer to accept a configurable initial QUIC version).
https://claude.ai/code/session_01HcvfQq1ttPV9PkRoJb4nyT
3.6 KiB
3.6 KiB
quic-interop-runner endpoint — Phase 0 scaffolding
Date: 2026-05-06
Why
We want the quic-interop-runner
matrix as a bug-finding harness, not a vanity scoreboard. Each peer impl
(quiche, aioquic, picoquic, ngtcp2, msquic, mvfst, lsquic, neqo, kwik) enforces
different parts of RFC 9000/9001/9002/9114 strictly, so failures triangulate
to specific bugs in :quic. The runner's ns-3 sim also exposes loss /
reorder / migration scenarios that are awkward to reproduce in unit tests.
What's in Phase 0
:quic-interopGradle module (JVM-only application, registered atquic/interop/viasettings.gradle).InteropClient.ktreads the runner's env-var contract (ROLE,TESTCASE,REQUESTS, …) and dispatches by testcase. Phase 0 implements onlyhandshake; everything else returns127(runner-skip).Dockerfilebased onmartenseemann/quic-network-simulator-endpoint+ OpenJDK 21 runtime, copies theinstallDistoutput.run_endpoint.shsources the base image's/setup.shthen execs our JVM binary.Makefilewrappers:make build,make smoke,make clean.
Local iteration loop
# In our repo:
make -C quic/interop build
# In a sibling clone of quic-interop-runner, add to implementations.json:
"amethyst": {
"image": "amethyst-quic-interop:latest",
"url": "https://github.com/vitorpamplona/amethyst",
"role": "client"
}
python run.py -d -i amethyst -s aioquic -t handshake --log-dir ./logs
Inspect ./logs/<run>/client_qlog/*.qlog in qvis when something breaks.
Phase ladder (excerpt — full plan in conversation)
| Phase | Goal | Tests | Exit criterion |
|---|---|---|---|
| 0 | Minimum harness | handshake |
one test reproducible end-to-end ✅ |
| 1 | Triangulate handshake bugs | + versionnegotiation, chacha20 |
green vs aioquic + quiche + picoquic |
| 2 | Streams + loss + multiplexing | + transfer, multiplexing, *loss, http3 |
green vs aioquic + quiche; soak 500/500 |
| 3 | Edge cases | retry, resumption, zerortt, keyupdate, rebinding-*, blackhole, amplificationlimit |
every test green or unsupported-127 with a written reason |
| 4 | CI gate | nightly Phases 1–2; PR-blocking subset on every push | qlogs uploaded as artifacts on red |
Phase 1a — landed 2026-05-06
SSLKEYLOGFILEwriter inInteropClient(NSS Key Log Format) so Wireshark decrypts the sim's pcap captures. Backed by:TlsClient.clientRandom(new public read-only property, captured instart()before sending ClientHello).QuicConnection.extraSecretsListener(new optional constructor param, chained after the connection's own key-installation listener; no-op default, so production callers are unaffected).
chacha20testcase: forces ChaCha20-Poly1305 only via newQuicConnection.cipherSuitesknob (threaded throughTlsClient→buildQuicClientHello→TlsClientHello).
Phase 1b — open
QLOGDIR::quichas no qlog observer infrastructure yet. Wiring needs hooks at packet send/recv, frame dispatch, recovery, and TLS state transitions, plus the qlog JSON-NDJSON schema. Sized as its own design doc before implementation.versionnegotiation:QuicConnectionWriterhard-codesQuicVersion.V1in two call sites; threading a configurable initial-version through and wiring the response-handling path is non-trivial. Defer.- Server role: we are client-first. Reassess after Phase 3.
- WebTransport is not part of the standard interop matrix; it needs a
separate harness against
moq-rs/ chrome-headless.