DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
h3_frame.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file h3_frame.cpp
6 * @brief HTTP/3 framing - implementation. See h3_frame.h.
7 */
8
10
11#if DETWS_ENABLE_HTTP3
12
14#include <string.h>
15
16bool h3_frame_parse(const uint8_t *buf, size_t len, H3Frame *out)
17{
18 size_t c1 = 0;
19 size_t c2 = 0;
20 uint64_t type = 0;
21 uint64_t length = 0;
22 if (!quic_varint_decode(buf, len, &type, &c1))
23 return false;
24 if (!quic_varint_decode(buf + c1, len - c1, &length, &c2))
25 return false;
26 out->type = type;
27 out->length = length;
28 out->header_len = c1 + c2;
29 return true;
30}
31
32size_t h3_frame_write_header(uint8_t *out, size_t cap, uint64_t type, uint64_t length)
33{
34 size_t n = quic_varint_encode(out, cap, type);
35 if (!n)
36 return 0;
37 size_t m = quic_varint_encode(out + n, cap - n, length);
38 if (!m)
39 return 0;
40 return n + m;
41}
42
43bool h3_frame_type_reserved(uint64_t type)
44{
45 // The HTTP/2 frame types that have no HTTP/3 meaning (RFC 9114 sec 11.2.1).
46 return type == 0x02 || type == 0x06 || type == 0x08 || type == 0x09;
47}
48
49void h3_settings_defaults(H3Settings *s)
50{
51 s->qpack_max_table_capacity = 0;
52 s->max_field_section_size = 0xFFFFFFFFFFFFFFFFULL; // unlimited
53 s->qpack_blocked_streams = 0;
54}
55
56bool h3_parse_settings(const uint8_t *payload, size_t len, H3Settings *s)
57{
58 size_t off = 0;
59 while (off < len)
60 {
61 size_t c1 = 0;
62 size_t c2 = 0;
63 uint64_t id = 0;
64 uint64_t val = 0;
65 if (!quic_varint_decode(payload + off, len - off, &id, &c1))
66 return false;
67 off += c1;
68 if (!quic_varint_decode(payload + off, len - off, &val, &c2))
69 return false;
70 off += c2;
71 switch (id)
72 {
73 case H3Setting::H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY:
74 s->qpack_max_table_capacity = val;
75 break;
76 case H3Setting::H3_SETTINGS_MAX_FIELD_SECTION_SIZE:
77 s->max_field_section_size = val;
78 break;
79 case H3Setting::H3_SETTINGS_QPACK_BLOCKED_STREAMS:
80 s->qpack_blocked_streams = val;
81 break;
82 case 0x02:
83 case 0x03:
84 case 0x04:
85 case 0x05:
86 return false; // reserved HTTP/2 settings identifiers (RFC 9114 sec 7.2.4.1)
87 default:
88 break; // unknown / greased settings are ignored
89 }
90 }
91 return true;
92}
93
94size_t h3_build_data(uint8_t *out, size_t cap, const uint8_t *data, size_t len)
95{
96 size_t hn = h3_frame_write_header(out, cap, H3FrameType::H3_DATA, len);
97 if (!hn || hn + len > cap)
98 return 0;
99 if (len)
100 memcpy(out + hn, data, len);
101 return hn + len;
102}
103
104size_t h3_build_headers(uint8_t *out, size_t cap, const uint8_t *block, size_t len)
105{
106 size_t hn = h3_frame_write_header(out, cap, H3FrameType::H3_HEADERS, len);
107 if (!hn || hn + len > cap)
108 return 0;
109 if (len)
110 memcpy(out + hn, block, len);
111 return hn + len;
112}
113
114size_t h3_build_settings(uint8_t *out, size_t cap, const uint64_t *ids, const uint64_t *vals, size_t n)
115{
116 size_t plen = 0;
117 for (size_t i = 0; i < n; i++)
118 plen += quic_varint_len(ids[i]) + quic_varint_len(vals[i]);
119 size_t o = h3_frame_write_header(out, cap, H3FrameType::H3_SETTINGS, plen);
120 if (!o)
121 return 0;
122 for (size_t i = 0; i < n; i++)
123 {
124 size_t a = quic_varint_encode(out + o, cap - o, ids[i]);
125 if (!a)
126 return 0;
127 o += a;
128 size_t b = quic_varint_encode(out + o, cap - o, vals[i]);
129 if (!b)
130 return 0;
131 o += b;
132 }
133 return o;
134}
135
136size_t h3_build_goaway(uint8_t *out, size_t cap, uint64_t stream_id)
137{
138 size_t plen = quic_varint_len(stream_id);
139 size_t o = h3_frame_write_header(out, cap, H3FrameType::H3_GOAWAY, plen);
140 if (!o)
141 return 0;
142 size_t a = quic_varint_encode(out + o, cap - o, stream_id);
143 if (!a)
144 return 0;
145 return o + a;
146}
147
148#endif // DETWS_ENABLE_HTTP3
HTTP/3 framing (RFC 9114 sec 7) over QUIC varints.
QUIC variable-length integer coding (RFC 9000 sec 16).