3.9 KiB
HTTP/2 connection control
Http2Connection owns only connection-level protocol state. It verifies the preface, drives the
frame reader, dispatches control frames and performs shutdown. HPACK fragment extraction and decode
live in Http2HeaderBlockDecoder; socket serialization remains exclusively in
Http2FrameWriter. Stream dispatch and application handlers are separate layers.
Each accepted HTTP/2 socket receives a new Http2Connection. Sharing the stateless
Http1Connection implementation is safe, but sharing an HTTP/2 instance would leak dynamic HPACK,
SETTINGS, flow-control and GOAWAY state between peers.
Demultiplexing invariant
The demux thread never invokes application work. It reads and validates frames, updates bounded
connection state, and enqueues or directly writes control frames. A registered handler cannot delay
SETTINGS or PING processing. The connection reader polls at a short interval so server shutdown is
observed promptly, while Http2FrameReader retains one non-renewable absolute deadline for a
partially received frame; polling therefore does not weaken slow-frame protection.
Settings
| Identifier | Default | Validation and handling |
|---|---|---|
HEADER_TABLE_SIZE |
4096 | Unsigned 32-bit; locally capped |
ENABLE_PUSH |
1 | Only 0 or 1; Flash advertises 0 |
MAX_CONCURRENT_STREAMS |
unlimited | Unsigned 32-bit |
INITIAL_WINDOW_SIZE |
65535 | At most 2^31-1 |
MAX_FRAME_SIZE |
16384 | 16384 through 16777215 |
MAX_HEADER_LIST_SIZE |
unlimited | Unsigned 32-bit |
Unknown identifiers are ignored. A payload is validated as a transaction before values are
committed. The initial-window delta is handed to the stream table as one operation: negative stream
windows are valid, but any result above 2^31-1 rejects the complete update with
FLOW_CONTROL_ERROR. Every non-ACK SETTINGS frame receives an empty ACK; locally sent settings are
bounded and have an acknowledgement deadline.
Priority control writes
Http2FrameWriter has one priority MPSC lane in front of its ordinary stream-data lane. PING and
SETTINGS acknowledgements, RST_STREAM and GOAWAY use reusable control intents from the connection
scratch. They can overtake queued DATA but never split or interrupt a socket write already in
progress. Both PING and SETTINGS response queues are bounded.
Shutdown
Graceful shutdown follows the two-stage protocol:
- Send GOAWAY with last-stream-id 2^31-1 and
NO_ERROR. - Send a connection PING and wait for its matching ACK, establishing a round trip.
- Send a second GOAWAY with the real last processed stream id, then close after current work.
A connection error instead sends one GOAWAY with the precise error code, the real last processed stream id and a bounded diagnostic string. A preface mismatch closes silently because the peer has not established a valid HTTP/2 connection.
Verification
The reusable control lifecycle (preface, SETTINGS/ACK, PING/PONG, WINDOW_UPDATE and received
GOAWAY) measures 974.263 ns/op and 0.008 B/op on JDK 21.0.11; the allocation figure is the JMH GC
profiler noise floor with no collections. curl 8.5.0 using h2c prior knowledge completed the
handshake and observed both clean GOAWAY stages. It exits with code 56 because this phase
deliberately sends no response HEADERS or DATA; those arrive with the response and stream phases.
h2spec 2.6.0 passes 28 of the 35 selected section 3, 4, 6.5, 6.7, 6.8 and 6.9 cases, including all connection-owned SETTINGS validation, PING, GOAWAY, frame-format, HPACK interleaving and connection-window cases. Six failures require response HEADERS/DATA or per-stream flow control and remain assigned to the response, stream and DATA phases. The seventh is h2spec's expectation of a GOAWAY after an invalid preface; Flash intentionally closes without writing because no valid HTTP/2 connection exists yet, as permitted by RFC 7540 §3.5 and required by this implementation's preface contract.