From cd7e2762eb7a4b5f96973031ac4ca2d0486d7450 Mon Sep 17 00:00:00 2001 From: Tim Perry Date: Thu, 25 Jun 2026 16:10:51 +0200 Subject: [PATCH] quic: defer server session emit until TLS ClientHello is processed This ensures we don't fire session events for totally invalid TLS handshakes - fundamental errors, bad SNI/ALPN values, or anything else that our TLS config would reject. Instead, it means servers can access servername & alpnProtocol synchronously as soon as the event is fired - all key session data is available and it's immediately usable. We don't want to defer further to handshake completed, since that'd be an extra RT, and defeat 0RTT benefits entirely. ClientHello processed without errors is sufficient for now. This isn't a security mechanism. Existing structures will defer actually sending & receiving anything that's not marked explicitly as early data until the handshake completes anyway. Signed-off-by: Tim Perry --- doc/api/quic.md | 30 ++++- lib/internal/quic/quic.js | 24 +++- src/quic/endpoint.cc | 30 +++-- src/quic/session.cc | 112 +++++++++++++++++- src/quic/session.h | 23 ++++ src/quic/tlscontext.cc | 1 + test/parallel/test-quic-alpn-mismatch.mjs | 17 ++- .../test-quic-session-emit-ordering.mjs | 48 ++++++++ test/parallel/test-quic-sni-mismatch.mjs | 24 ++-- test/parallel/test-quic-zero-rtt.mjs | 6 +- 10 files changed, 272 insertions(+), 43 deletions(-) create mode 100644 test/parallel/test-quic-session-emit-ordering.mjs diff --git a/doc/api/quic.md b/doc/api/quic.md index d36825d6943264..ac3f5712ba2fa6 100644 --- a/doc/api/quic.md +++ b/doc/api/quic.md @@ -1418,6 +1418,30 @@ will be silently dropped and `0n` returned. The local `maxDatagramFrameSize` transport parameter (default: `1200` bytes) controls what this endpoint advertises to the peer as its own maximum. +### `session.servername` + + + +* Type: {string|undefined} + +The SNI (Server Name Indication) host name associated with the session, or +`undefined` if none was set. On a client this is the `servername` requested via +[`quic.connect()`][]. On a server it is the name sent by the peer. + +### `session.alpnProtocol` + + + +* Type: {string|undefined} + +The negotiated ALPN protocol. On a server this is available synchronously as +soon as the session is surfaced to the `onsession` callback; on a client it is +`undefined` until the handshake completes. + ### `session.certificate`