Skip to content

Commit 57badad

Browse files
quaesitor-scientiamRichard Wheelerclaude
authored
net.http: add HTTP/2 frame codec (RFC 7540) (#27356)
* net.http: add HTTP/2 frame codec (RFC 7540) for HTTP/2 Add the HTTP/2 binary framing layer: encoders and decoders for all ten frame types plus a fallthrough for unknown types. Like the HPACK PR, this is purely additive (new files in the http module) and does not touch any existing net.http code path; nothing calls it yet. Included: - H2FrameHeader parsing of the 9-byte header, ignoring the reserved bit. - A H2Frame sum type with DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING, GOAWAY, WINDOW_UPDATE, CONTINUATION, and an UnknownFrame variant. Unknown frame types are preserved rather than rejected, as required by RFC 7540 Section 4.1. - h2_read_frame / h2_parse_frame decoders and an .encode() method, with PADDED and PRIORITY handling for HEADERS/DATA/PUSH_PROMISE. - Structural validation that maps to FRAME_SIZE_ERROR / PROTOCOL_ERROR at the connection layer: fixed-size frames (PRIORITY, RST_STREAM, PING, WINDOW_UPDATE), SETTINGS payload as a multiple of 6 with empty ACK, and the stream-id rules (DATA/HEADERS/etc. non-zero; SETTINGS/PING/GOAWAY zero). - H2ErrorCode enum (Section 7) and the SETTINGS identifier and frame type/flag constants. Tests cover an encode/decode round-trip for every frame type, the on-wire header layout, reserved-bit masking, padding decode (including pad length exceeding the frame), the priority section on HEADERS, unknown-frame preservation and re-encoding, reading consecutive frames from one buffer, and the structural validation errors above. Passes under -W -cstrict -cc clang. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * net.http: document deferred HTTP/2 semantic checks in frame codec Add comments noting that PRIORITY self-dependency (RFC 7540 Section 5.3.1) and zero WINDOW_UPDATE increments (Section 6.9) are intentionally not rejected by the frame codec. Both are stream errors whose correct handling is RST_STREAM on the affected stream (and, for a zero increment on stream 0, a connection error). That stream-vs-connection distinction belongs to the connection layer, which needs the decoded frame to respond; rejecting in the codec would turn a recoverable stream error into a connection-fatal decode error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Richard Wheeler <quaesitor.scientiam@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c5fca67 commit 57badad

3 files changed

Lines changed: 869 additions & 0 deletions

File tree

‎vlib/net/http/h2_error.v‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2+
// Use of this source code is governed by an MIT license
3+
// that can be found in the LICENSE file.
4+
module http
5+
6+
// H2ErrorCode is an HTTP/2 error code, as used in RST_STREAM and GOAWAY
7+
// frames (RFC 7540 Section 7).
8+
pub enum H2ErrorCode as u32 {
9+
no_error = 0x0
10+
protocol_error = 0x1
11+
internal_error = 0x2
12+
flow_control_error = 0x3
13+
settings_timeout = 0x4
14+
stream_closed = 0x5
15+
frame_size_error = 0x6
16+
refused_stream = 0x7
17+
cancel = 0x8
18+
compression_error = 0x9
19+
connect_error = 0xa
20+
enhance_your_calm = 0xb
21+
inadequate_security = 0xc
22+
http_1_1_required = 0xd
23+
}
24+
25+
// str returns the RFC name of the error code.
26+
pub fn (e H2ErrorCode) str() string {
27+
return match e {
28+
.no_error { 'NO_ERROR' }
29+
.protocol_error { 'PROTOCOL_ERROR' }
30+
.internal_error { 'INTERNAL_ERROR' }
31+
.flow_control_error { 'FLOW_CONTROL_ERROR' }
32+
.settings_timeout { 'SETTINGS_TIMEOUT' }
33+
.stream_closed { 'STREAM_CLOSED' }
34+
.frame_size_error { 'FRAME_SIZE_ERROR' }
35+
.refused_stream { 'REFUSED_STREAM' }
36+
.cancel { 'CANCEL' }
37+
.compression_error { 'COMPRESSION_ERROR' }
38+
.connect_error { 'CONNECT_ERROR' }
39+
.enhance_your_calm { 'ENHANCE_YOUR_CALM' }
40+
.inadequate_security { 'INADEQUATE_SECURITY' }
41+
.http_1_1_required { 'HTTP_1_1_REQUIRED' }
42+
}
43+
}

0 commit comments

Comments
 (0)