blob: 6f93ddf8d0efcf4d673f63d38cbbcc7dcf904ad7 [file] [log] [blame]
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001/*
Willy Tarreau3dfb7da2022-03-02 22:33:39 +01002 * Copyright 2019 HAProxy Technologies, Frederic Lecaille <flecaille@haproxy.com>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01003 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
Amaury Denoyelle5c25dc52022-09-30 17:44:15 +020010#include <string.h>
11
Frédéric Lécaille8090b512020-11-30 16:19:22 +010012#include <import/eb64tree.h>
Amaury Denoyelle40c24f12023-01-27 17:47:49 +010013#include <haproxy/buf-t.h>
14#include <haproxy/chunk.h>
15#include <haproxy/pool.h>
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020016#include <haproxy/quic_conn-t.h>
Amaury Denoyelle5c25dc52022-09-30 17:44:15 +020017#include <haproxy/quic_enc.h>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010018#include <haproxy/quic_frame.h>
Amaury Denoyelle5c25dc52022-09-30 17:44:15 +020019#include <haproxy/quic_tp-t.h>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010020#include <haproxy/trace.h>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010021
22#define TRACE_SOURCE &trace_quic
23
24const char *quic_frame_type_string(enum quic_frame_type ft)
25{
26 switch (ft) {
27 case QUIC_FT_PADDING:
28 return "PADDING";
29 case QUIC_FT_PING:
30 return "PING";
31 case QUIC_FT_ACK:
32 return "ACK";
33 case QUIC_FT_ACK_ECN:
Frédéric Lécaille904caac2023-03-06 15:34:19 +010034 return "ACK_ECN";
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010035 case QUIC_FT_RESET_STREAM:
36 return "RESET_STREAM";
37 case QUIC_FT_STOP_SENDING:
38 return "STOP_SENDING";
39 case QUIC_FT_CRYPTO:
40 return "CRYPTO";
41 case QUIC_FT_NEW_TOKEN:
42 return "NEW_TOKEN";
43
44 case QUIC_FT_STREAM_8:
45 return "STREAM_8";
46 case QUIC_FT_STREAM_9:
47 return "STREAM_9";
48 case QUIC_FT_STREAM_A:
49 return "STREAM_A";
50 case QUIC_FT_STREAM_B:
51 return "STREAM_B";
52 case QUIC_FT_STREAM_C:
53 return "STREAM_C";
54 case QUIC_FT_STREAM_D:
55 return "STREAM_D";
56 case QUIC_FT_STREAM_E:
57 return "STREAM_E";
58 case QUIC_FT_STREAM_F:
59 return "STREAM_F";
60
61 case QUIC_FT_MAX_DATA:
62 return "MAX_DATA";
63 case QUIC_FT_MAX_STREAM_DATA:
64 return "MAX_STREAM_DATA";
65 case QUIC_FT_MAX_STREAMS_BIDI:
66 return "MAX_STREAMS_BIDI";
67 case QUIC_FT_MAX_STREAMS_UNI:
68 return "MAX_STREAMS_UNI";
69 case QUIC_FT_DATA_BLOCKED:
70 return "DATA_BLOCKED";
71 case QUIC_FT_STREAM_DATA_BLOCKED:
72 return "STREAM_DATA_BLOCKED";
73 case QUIC_FT_STREAMS_BLOCKED_BIDI:
74 return "STREAMS_BLOCKED_BIDI";
75 case QUIC_FT_STREAMS_BLOCKED_UNI:
76 return "STREAMS_BLOCKED_UNI";
77 case QUIC_FT_NEW_CONNECTION_ID:
78 return "NEW_CONNECTION_ID";
79 case QUIC_FT_RETIRE_CONNECTION_ID:
80 return "RETIRE_CONNECTION_ID";
81 case QUIC_FT_PATH_CHALLENGE:
82 return "PATH_CHALLENGE";
83 case QUIC_FT_PATH_RESPONSE:
84 return "PATH_RESPONSE";
85 case QUIC_FT_CONNECTION_CLOSE:
86 return "CONNECTION_CLOSE";
87 case QUIC_FT_CONNECTION_CLOSE_APP:
88 return "CONNECTION_CLOSE_APP";
89 case QUIC_FT_HANDSHAKE_DONE:
90 return "HANDSHAKE_DONE";
91 default:
92 return "UNKNOWN";
93 }
94}
95
Frédéric Lécaille010e5322021-12-23 15:19:15 +010096static void chunk_cc_phrase_appendf(struct buffer *buf,
97 const unsigned char *phr, size_t phrlen)
98{
99 chunk_appendf(buf, " reason_phrase: '");
100 while (phrlen--)
101 chunk_appendf(buf, "%c", *phr++);
102 chunk_appendf(buf, "'");
103}
104
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100105/* Add traces to <buf> depending on <frm> frame type. */
106void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm)
107{
108 chunk_appendf(buf, " %s", quic_frame_type_string(frm->type));
109 switch (frm->type) {
110 case QUIC_FT_CRYPTO:
111 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200112 const struct qf_crypto *crypto_frm = &frm->crypto;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100113 chunk_appendf(buf, " cfoff=%llu cflen=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200114 (ull)crypto_frm->offset, (ull)crypto_frm->len);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100115 break;
116 }
117 case QUIC_FT_RESET_STREAM:
118 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200119 const struct qf_reset_stream *rs_frm = &frm->reset_stream;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100120 chunk_appendf(buf, " id=%llu app_error_code=%llu final_size=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200121 (ull)rs_frm->id, (ull)rs_frm->app_error_code, (ull)rs_frm->final_size);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100122 break;
123 }
124 case QUIC_FT_STOP_SENDING:
125 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200126 const struct qf_stop_sending *ss_frm = &frm->stop_sending;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100127 chunk_appendf(&trace_buf, " id=%llu app_error_code=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200128 (ull)ss_frm->id, (ull)ss_frm->app_error_code);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100129 break;
130 }
131 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
132 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200133 const struct qf_stream *strm_frm = &frm->stream;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100134 chunk_appendf(&trace_buf, " uni=%d fin=%d id=%llu off=%llu len=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200135 !!(strm_frm->id & QUIC_STREAM_FRAME_ID_DIR_BIT),
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100136 !!(frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT),
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200137 (ull)strm_frm->id, (ull)strm_frm->offset.key, (ull)strm_frm->len);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100138 break;
139 }
140 case QUIC_FT_MAX_DATA:
141 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200142 const struct qf_max_data *md_frm = &frm->max_data;
143 chunk_appendf(&trace_buf, " max_data=%llu", (ull)md_frm->max_data);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100144 break;
145 }
146 case QUIC_FT_MAX_STREAM_DATA:
147 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200148 const struct qf_max_stream_data *msd_frm = &frm->max_stream_data;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100149 chunk_appendf(&trace_buf, " id=%llu max_stream_data=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200150 (ull)msd_frm->id, (ull)msd_frm->max_stream_data);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100151 break;
152 }
153 case QUIC_FT_MAX_STREAMS_BIDI:
154 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200155 const struct qf_max_streams *ms_frm = &frm->max_streams_bidi;
156 chunk_appendf(&trace_buf, " max_streams=%llu", (ull)ms_frm->max_streams);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100157 break;
158 }
159 case QUIC_FT_MAX_STREAMS_UNI:
160 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200161 const struct qf_max_streams *ms_frm = &frm->max_streams_uni;
162 chunk_appendf(&trace_buf, " max_streams=%llu", (ull)ms_frm->max_streams);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100163 break;
164 }
165 case QUIC_FT_DATA_BLOCKED:
166 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200167 const struct qf_data_blocked *db_frm = &frm->data_blocked;
168 chunk_appendf(&trace_buf, " limit=%llu", (ull)db_frm->limit);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100169 break;
170 }
171 case QUIC_FT_STREAM_DATA_BLOCKED:
172 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200173 const struct qf_stream_data_blocked *sdb_frm = &frm->stream_data_blocked;
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100174 chunk_appendf(&trace_buf, " id=%llu limit=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200175 (ull)sdb_frm->id, (ull)sdb_frm->limit);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100176 break;
177 }
178 case QUIC_FT_STREAMS_BLOCKED_BIDI:
179 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200180 const struct qf_streams_blocked *sb_frm = &frm->streams_blocked_bidi;
181 chunk_appendf(&trace_buf, " limit=%llu", (ull)sb_frm->limit);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100182 break;
183 }
184 case QUIC_FT_STREAMS_BLOCKED_UNI:
185 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200186 const struct qf_streams_blocked *sb_frm = &frm->streams_blocked_uni;
187 chunk_appendf(&trace_buf, " limit=%llu", (ull)sb_frm->limit);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100188 break;
189 }
190 case QUIC_FT_RETIRE_CONNECTION_ID:
191 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200192 const struct qf_retire_connection_id *rcid_frm = &frm->retire_connection_id;
193 chunk_appendf(&trace_buf, " seq_num=%llu", (ull)rcid_frm->seq_num);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100194 break;
195 }
196 case QUIC_FT_CONNECTION_CLOSE:
197 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200198 const struct qf_connection_close *cc_frm = &frm->connection_close;
199 size_t plen = QUIC_MIN((size_t)cc_frm->reason_phrase_len, sizeof cc_frm->reason_phrase);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100200 chunk_appendf(&trace_buf,
201 " error_code=%llu frame_type=%llu reason_phrase_len=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200202 (ull)cc_frm->error_code, (ull)cc_frm->frame_type,
203 (ull)cc_frm->reason_phrase_len);
Frédéric Lécaille010e5322021-12-23 15:19:15 +0100204 if (plen)
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200205 chunk_cc_phrase_appendf(&trace_buf, cc_frm->reason_phrase, plen);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100206 break;
207 }
208 case QUIC_FT_CONNECTION_CLOSE_APP:
209 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200210 const struct qf_connection_close_app *cc_frm = &frm->connection_close_app;
211 size_t plen = QUIC_MIN((size_t)cc_frm->reason_phrase_len, sizeof cc_frm->reason_phrase);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100212 chunk_appendf(&trace_buf,
213 " error_code=%llu reason_phrase_len=%llu",
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200214 (ull)cc_frm->error_code, (ull)cc_frm->reason_phrase_len);
Frédéric Lécaille010e5322021-12-23 15:19:15 +0100215 if (plen)
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200216 chunk_cc_phrase_appendf(&trace_buf, cc_frm->reason_phrase, plen);
Frédéric Lécaille1ede8232021-12-23 14:11:25 +0100217 break;
218 }
219 }
220}
221
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200222/* Encode <frm> PADDING frame at <pos> buffer position, <end> being one byte past the end
223 * of this buffer.
224 * Returns 1 if succeeded (enough room in the buffer to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100225 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200226static int quic_build_padding_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100227 struct quic_frame *frm, struct quic_conn *conn)
228{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200229 struct qf_padding *padding_frm = &frm->padding;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100230
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200231 if (end - *pos < padding_frm->len - 1)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100232 return 0;
233
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200234 memset(*pos, 0, padding_frm->len - 1);
235 *pos += padding_frm->len - 1;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100236
237 return 1;
238}
239
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200240/* Parse a PADDING frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100241 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
242 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100243static int quic_parse_padding_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200244 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100245{
246 const unsigned char *beg;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200247 struct qf_padding *padding_frm = &frm->padding;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100248
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200249 beg = *pos;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200250 padding_frm->len = 1;
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200251 while (*pos < end && !**pos)
252 (*pos)++;
253 padding_frm->len += *pos - beg;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100254
255 return 1;
256}
257
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200258/* Encode a ACK frame at <pos> buffer position.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100259 * Always succeeds.
260 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200261static int quic_build_ping_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100262 struct quic_frame *frm, struct quic_conn *conn)
263{
264 /* No field */
265 return 1;
266}
267
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200268/* Parse a PADDING frame from <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100269 * Always succeeds.
270 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100271static int quic_parse_ping_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200272 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100273{
274 /* No field */
275 return 1;
276}
277
278/* Encode a ACK frame.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200279 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100280 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200281static int quic_build_ack_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillefde2a982021-12-27 15:12:09 +0100282 struct quic_frame *frm, struct quic_conn *qc)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100283{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200284 struct qf_tx_ack *ack_frm = &frm->tx_ack;
Frédéric Lécaille8090b512020-11-30 16:19:22 +0100285 struct eb64_node *ar, *prev_ar;
286 struct quic_arng_node *ar_node, *prev_ar_node;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100287
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200288 ar = eb64_last(&ack_frm->arngs->root);
Frédéric Lécaillea54e49d2022-05-10 15:15:24 +0200289 ar_node = eb64_entry(ar, struct quic_arng_node, first);
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100290 TRACE_PROTO("TX ack range", QUIC_EV_CONN_PRSAFRM,
Frédéric Lécaillefde2a982021-12-27 15:12:09 +0100291 qc,, &ar_node->last, &ar_node->first.key);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200292 if (!quic_enc_int(pos, end, ar_node->last) ||
293 !quic_enc_int(pos, end, ack_frm->ack_delay) ||
294 !quic_enc_int(pos, end, ack_frm->arngs->sz - 1) ||
295 !quic_enc_int(pos, end, ar_node->last - ar_node->first.key))
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100296 return 0;
297
Frédéric Lécaille8090b512020-11-30 16:19:22 +0100298 while ((prev_ar = eb64_prev(ar))) {
Frédéric Lécaillea54e49d2022-05-10 15:15:24 +0200299 prev_ar_node = eb64_entry(prev_ar, struct quic_arng_node, first);
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100300 TRACE_PROTO("TX ack range", QUIC_EV_CONN_PRSAFRM, qc,,
Frédéric Lécaille8090b512020-11-30 16:19:22 +0100301 &prev_ar_node->last, &prev_ar_node->first.key);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200302 if (!quic_enc_int(pos, end, ar_node->first.key - prev_ar_node->last - 2) ||
303 !quic_enc_int(pos, end, prev_ar_node->last - prev_ar_node->first.key))
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100304 return 0;
305
Frédéric Lécaille8090b512020-11-30 16:19:22 +0100306 ar = prev_ar;
Frédéric Lécaillea54e49d2022-05-10 15:15:24 +0200307 ar_node = eb64_entry(ar, struct quic_arng_node, first);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100308 }
309
310 return 1;
311}
312
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200313/* Parse an ACK frame header at <pos> buffer position with <end> as end into <frm> frame.
314 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100315 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100316static int quic_parse_ack_frame_header(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200317 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100318{
319 int ret;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200320 struct qf_ack *ack_frm = &frm->ack;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100321
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200322 ret = quic_dec_int(&ack_frm->largest_ack, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100323 if (!ret)
324 return 0;
325
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200326 ret = quic_dec_int(&ack_frm->ack_delay, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100327 if (!ret)
328 return 0;
329
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200330 ret = quic_dec_int(&ack_frm->ack_range_num, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100331 if (!ret)
332 return 0;
333
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200334 ret = quic_dec_int(&ack_frm->first_ack_range, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100335 if (!ret)
336 return 0;
337
338 return 1;
339}
340
341/* Encode a ACK_ECN frame.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200342 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100343 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200344static int quic_build_ack_ecn_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100345 struct quic_frame *frm, struct quic_conn *conn)
346{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200347 struct qf_ack *ack_frm = &frm->ack;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100348
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200349 return quic_enc_int(pos, end, ack_frm->largest_ack) &&
350 quic_enc_int(pos, end, ack_frm->ack_delay) &&
351 quic_enc_int(pos, end, ack_frm->first_ack_range) &&
352 quic_enc_int(pos, end, ack_frm->ack_range_num);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100353}
354
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200355/* Parse an ACK_ECN frame at <pos> buffer position with <end> as end into <frm> frame.
356 * Return 1 if succeeded (enough at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100357 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100358static int quic_parse_ack_ecn_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200359 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100360{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200361 struct qf_ack *ack_frm = &frm->ack;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100362
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200363 return quic_dec_int(&ack_frm->largest_ack, pos, end) &&
364 quic_dec_int(&ack_frm->ack_delay, pos, end) &&
365 quic_dec_int(&ack_frm->first_ack_range, pos, end) &&
366 quic_dec_int(&ack_frm->ack_range_num, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100367}
368
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200369/* Encode a RESET_STREAM frame at <pos> buffer position.
370 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100371 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200372static int quic_build_reset_stream_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100373 struct quic_frame *frm, struct quic_conn *conn)
374{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200375 struct qf_reset_stream *rs_frm = &frm->reset_stream;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100376
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200377 return quic_enc_int(pos, end, rs_frm->id) &&
378 quic_enc_int(pos, end, rs_frm->app_error_code) &&
379 quic_enc_int(pos, end, rs_frm->final_size);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100380}
381
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200382/* Parse a RESET_STREAM frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100383 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
384 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100385static int quic_parse_reset_stream_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200386 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100387{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200388 struct qf_reset_stream *rs_frm = &frm->reset_stream;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100389
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200390 return quic_dec_int(&rs_frm->id, pos, end) &&
391 quic_dec_int(&rs_frm->app_error_code, pos, end) &&
392 quic_dec_int(&rs_frm->final_size, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100393}
394
395/* Encode a STOP_SENDING frame.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200396 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100397 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200398static int quic_build_stop_sending_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100399 struct quic_frame *frm, struct quic_conn *conn)
400{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200401 struct qf_stop_sending *ss_frm = &frm->stop_sending;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100402
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200403 return quic_enc_int(pos, end, ss_frm->id) &&
404 quic_enc_int(pos, end, ss_frm->app_error_code);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100405}
406
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200407/* Parse a STOP_SENDING frame at <pos> buffer position with <end> as end into <frm> frame.
408 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100409 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100410static int quic_parse_stop_sending_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200411 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100412{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200413 struct qf_stop_sending *ss_frm = &frm->stop_sending;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100414
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200415 return quic_dec_int(&ss_frm->id, pos, end) &&
416 quic_dec_int(&ss_frm->app_error_code, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100417}
418
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200419/* Encode a CRYPTO frame at <pos> buffer position.
420 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100421 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200422static int quic_build_crypto_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100423 struct quic_frame *frm, struct quic_conn *conn)
424{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200425 struct qf_crypto *crypto_frm = &frm->crypto;
426 const struct quic_enc_level *qel = crypto_frm->qel;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100427 size_t offset, len;
428
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200429 if (!quic_enc_int(pos, end, crypto_frm->offset) ||
430 !quic_enc_int(pos, end, crypto_frm->len) || end - *pos < crypto_frm->len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100431 return 0;
432
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200433 len = crypto_frm->len;
434 offset = crypto_frm->offset;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100435 while (len) {
436 int idx;
437 size_t to_copy;
438 const unsigned char *data;
439
440 idx = offset >> QUIC_CRYPTO_BUF_SHIFT;
441 to_copy = qel->tx.crypto.bufs[idx]->sz - (offset & QUIC_CRYPTO_BUF_MASK);
442 if (to_copy > len)
443 to_copy = len;
444 data = qel->tx.crypto.bufs[idx]->data + (offset & QUIC_CRYPTO_BUF_MASK);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200445 memcpy(*pos, data, to_copy);
446 *pos += to_copy;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100447 offset += to_copy;
448 len -= to_copy;
449 }
450
451 return 1;
452}
453
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200454/* Parse a CRYPTO frame from <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100455 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
456 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100457static int quic_parse_crypto_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200458 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100459{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200460 struct qf_crypto *crypto_frm = &frm->crypto;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100461
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200462 if (!quic_dec_int(&crypto_frm->offset, pos, end) ||
463 !quic_dec_int(&crypto_frm->len, pos, end) || end - *pos < crypto_frm->len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100464 return 0;
465
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200466 crypto_frm->data = *pos;
467 *pos += crypto_frm->len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100468
469 return 1;
470}
471
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200472/* Encode a NEW_TOKEN frame at <pos> buffer position.
473 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100474 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200475static int quic_build_new_token_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100476 struct quic_frame *frm, struct quic_conn *conn)
477{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200478 struct qf_new_token *new_token_frm = &frm->new_token;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100479
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200480 if (!quic_enc_int(pos, end, new_token_frm->len) || end - *pos < new_token_frm->len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100481 return 0;
482
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200483 memcpy(*pos, new_token_frm->data, new_token_frm->len);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100484
485 return 1;
486}
487
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200488/* Parse a NEW_TOKEN frame at <pos> buffer position with <end> as end into <frm> frame.
489 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100490 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100491static int quic_parse_new_token_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200492 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100493{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200494 struct qf_new_token *new_token_frm = &frm->new_token;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100495
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200496 if (!quic_dec_int(&new_token_frm->len, pos, end) || end - *pos < new_token_frm->len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100497 return 0;
498
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200499 new_token_frm->data = *pos;
500 *pos += new_token_frm->len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100501
502 return 1;
503}
504
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200505/* Encode a STREAM frame at <pos> buffer position.
506 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100507 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200508static int quic_build_stream_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100509 struct quic_frame *frm, struct quic_conn *conn)
510{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200511 struct qf_stream *strm_frm = &frm->stream;
Amaury Denoyelle642ab062022-02-23 10:54:42 +0100512 const unsigned char *wrap;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100513
Amaury Denoyelle1dac0182023-02-02 16:45:07 +0100514 /* Caller must set OFF bit if and only if a non-null offset is used. */
515 BUG_ON(!!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) !=
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200516 !!strm_frm->offset.key);
Amaury Denoyelle1dac0182023-02-02 16:45:07 +0100517
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200518 if (!quic_enc_int(pos, end, strm_frm->id) ||
519 ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(pos, end, strm_frm->offset.key)) ||
Frédéric Lécaille242fb1b2020-12-31 12:45:38 +0100520 ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) &&
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200521 (!quic_enc_int(pos, end, strm_frm->len) || end - *pos < strm_frm->len)))
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100522 return 0;
523
Amaury Denoyelle19eaf882023-04-25 15:52:24 +0200524 /* No need for data memcpy if no payload. */
525 if (!strm_frm->len)
526 return 1;
527
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200528 wrap = (const unsigned char *)b_wrap(strm_frm->buf);
529 if (strm_frm->data + strm_frm->len > wrap) {
530 size_t to_copy = wrap - strm_frm->data;
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200531 memcpy(*pos, strm_frm->data, to_copy);
532 *pos += to_copy;
Amaury Denoyelle642ab062022-02-23 10:54:42 +0100533
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200534 to_copy = strm_frm->len - to_copy;
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200535 memcpy(*pos, b_orig(strm_frm->buf), to_copy);
536 *pos += to_copy;
Amaury Denoyelle642ab062022-02-23 10:54:42 +0100537 }
538 else {
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200539 memcpy(*pos, strm_frm->data, strm_frm->len);
540 *pos += strm_frm->len;
Frédéric Lécaille785d3bd2021-09-10 09:13:39 +0200541 }
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100542
543 return 1;
544}
545
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200546/* Parse a STREAM frame at <pos> buffer position with <end> as end into <frm> frame.
547 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100548 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100549static int quic_parse_stream_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200550 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100551{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200552 struct qf_stream *strm_frm = &frm->stream;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100553
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200554 if (!quic_dec_int(&strm_frm->id, pos, end))
Frédéric Lécaille129a3512020-12-31 10:57:04 +0100555 return 0;
556
557 /* Offset parsing */
Frédéric Lécaille242fb1b2020-12-31 12:45:38 +0100558 if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT)) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200559 strm_frm->offset.key = 0;
Frédéric Lécaille129a3512020-12-31 10:57:04 +0100560 }
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200561 else if (!quic_dec_int((uint64_t *)&strm_frm->offset.key, pos, end))
Frédéric Lécaille129a3512020-12-31 10:57:04 +0100562 return 0;
563
564 /* Length parsing */
Frédéric Lécaille242fb1b2020-12-31 12:45:38 +0100565 if (!(frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT)) {
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200566 strm_frm->len = end - *pos;
Frédéric Lécaille129a3512020-12-31 10:57:04 +0100567 }
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200568 else if (!quic_dec_int(&strm_frm->len, pos, end) || end - *pos < strm_frm->len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100569 return 0;
570
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200571 strm_frm->data = *pos;
572 *pos += strm_frm->len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100573
574 return 1;
575}
576
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200577/* Encode a MAX_DATA frame at <pos> buffer position.
578 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100579 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200580static int quic_build_max_data_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100581 struct quic_frame *frm, struct quic_conn *conn)
582{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200583 struct qf_max_data *md_frm = &frm->max_data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100584
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200585 return quic_enc_int(pos, end, md_frm->max_data);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100586}
587
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200588/* Parse a MAX_DATA frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100589 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
590 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100591static int quic_parse_max_data_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200592 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100593{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200594 struct qf_max_data *md_frm = &frm->max_data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100595
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200596 return quic_dec_int(&md_frm->max_data, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100597}
598
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200599/* Encode a MAX_STREAM_DATA frame at <pos> buffer position.
600 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100601 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200602static int quic_build_max_stream_data_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100603 struct quic_frame *frm, struct quic_conn *conn)
604{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200605 struct qf_max_stream_data *msd_frm = &frm->max_stream_data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100606
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200607 return quic_enc_int(pos, end, msd_frm->id) &&
608 quic_enc_int(pos, end, msd_frm->max_stream_data);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100609}
610
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200611/* Parse a MAX_STREAM_DATA frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100612 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
613 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100614static int quic_parse_max_stream_data_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200615 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100616{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200617 struct qf_max_stream_data *msd_frm = &frm->max_stream_data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100618
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200619 return quic_dec_int(&msd_frm->id, pos, end) &&
620 quic_dec_int(&msd_frm->max_stream_data, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100621}
622
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200623/* Encode a MAX_STREAMS frame for bidirectional streams at <buf> buffer position.
624 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100625 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200626static int quic_build_max_streams_bidi_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100627 struct quic_frame *frm, struct quic_conn *conn)
628{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200629 struct qf_max_streams *ms_frm = &frm->max_streams_bidi;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100630
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200631 return quic_enc_int(pos, end, ms_frm->max_streams);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100632}
633
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200634/* Parse a MAX_STREAMS frame for bidirectional streams at <pos> buffer position with <end>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100635 * as end into <frm> frame.
636 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
637 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100638static int quic_parse_max_streams_bidi_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200639 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100640{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200641 struct qf_max_streams *ms_frm = &frm->max_streams_bidi;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100642
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200643 return quic_dec_int(&ms_frm->max_streams, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100644}
645
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200646/* Encode a MAX_STREAMS frame for unidirectional streams at <pos> buffer position.
647 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100648 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200649static int quic_build_max_streams_uni_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100650 struct quic_frame *frm, struct quic_conn *conn)
651{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200652 struct qf_max_streams *ms_frm = &frm->max_streams_uni;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100653
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200654 return quic_enc_int(pos, end, ms_frm->max_streams);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100655}
656
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200657/* Parse a MAX_STREAMS frame for undirectional streams at <pos> buffer position with <end>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100658 * as end into <frm> frame.
659 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
660 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100661static int quic_parse_max_streams_uni_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200662 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100663{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200664 struct qf_max_streams *ms_frm = &frm->max_streams_uni;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100665
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200666 return quic_dec_int(&ms_frm->max_streams, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100667}
668
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200669/* Encode a DATA_BLOCKED frame at <pos> buffer position.
670 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100671 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200672static int quic_build_data_blocked_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100673 struct quic_frame *frm, struct quic_conn *conn)
674{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200675 struct qf_data_blocked *db_frm = &frm->data_blocked;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100676
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200677 return quic_enc_int(pos, end, db_frm->limit);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100678}
679
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200680/* Parse a DATA_BLOCKED frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100681 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
682 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100683static int quic_parse_data_blocked_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200684 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100685{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200686 struct qf_data_blocked *db_frm = &frm->data_blocked;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100687
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200688 return quic_dec_int(&db_frm->limit, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100689}
690
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200691/* Encode a STREAM_DATA_BLOCKED at <pos> buffer position.
692 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100693 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200694static int quic_build_stream_data_blocked_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100695 struct quic_frame *frm, struct quic_conn *conn)
696{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200697 struct qf_stream_data_blocked *sdb_frm = &frm->stream_data_blocked;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100698
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200699 return quic_enc_int(pos, end, sdb_frm->id) &&
700 quic_enc_int(pos, end, sdb_frm->limit);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100701}
702
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200703/* Parse a STREAM_DATA_BLOCKED frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100704 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
705 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100706static int quic_parse_stream_data_blocked_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200707 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100708{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200709 struct qf_stream_data_blocked *sdb_frm = &frm->stream_data_blocked;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100710
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200711 return quic_dec_int(&sdb_frm->id, pos, end) &&
712 quic_dec_int(&sdb_frm->limit, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100713}
714
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200715/* Encode a STREAMS_BLOCKED frame for bidirectional streams at <pos> buffer position.
716 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100717 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200718static int quic_build_streams_blocked_bidi_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100719 struct quic_frame *frm, struct quic_conn *conn)
720{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200721 struct qf_streams_blocked *sb_frm = &frm->streams_blocked_bidi;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100722
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200723 return quic_enc_int(pos, end, sb_frm->limit);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100724}
725
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200726/* Parse a STREAMS_BLOCKED frame for bidirectional streams at <pos> buffer position with <end>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100727 * as end into <frm> frame.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200728 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100729 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100730static int quic_parse_streams_blocked_bidi_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200731 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100732{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200733 struct qf_streams_blocked *sb_frm = &frm->streams_blocked_bidi;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100734
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200735 return quic_dec_int(&sb_frm->limit, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100736}
737
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200738/* Encode a STREAMS_BLOCKED frame for unidirectional streams at <pos> buffer position.
739 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100740 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200741static int quic_build_streams_blocked_uni_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100742 struct quic_frame *frm, struct quic_conn *conn)
743{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200744 struct qf_streams_blocked *sb_frm = &frm->streams_blocked_uni;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100745
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200746 return quic_enc_int(pos, end, sb_frm->limit);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100747}
748
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200749/* Parse a STREAMS_BLOCKED frame for unidirectional streams at <pos> buffer position with <end>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100750 * as end into <frm> frame.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200751 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100752 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100753static int quic_parse_streams_blocked_uni_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200754 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100755{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200756 struct qf_streams_blocked *sb_frm = &frm->streams_blocked_uni;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100757
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200758 return quic_dec_int(&sb_frm->limit, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100759}
760
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200761/* Encode a NEW_CONNECTION_ID frame at <pos> buffer position.
762 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100763 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200764static int quic_build_new_connection_id_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100765 struct quic_frame *frm, struct quic_conn *conn)
766{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200767 struct qf_new_connection_id *ncid_frm = &frm->new_connection_id;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100768
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200769 if (!quic_enc_int(pos, end, ncid_frm->seq_num) ||
770 !quic_enc_int(pos, end, ncid_frm->retire_prior_to) ||
771 end - *pos < sizeof ncid_frm->cid.len + ncid_frm->cid.len + QUIC_STATELESS_RESET_TOKEN_LEN)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100772 return 0;
773
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200774 *(*pos)++ = ncid_frm->cid.len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100775
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200776 if (ncid_frm->cid.len) {
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200777 memcpy(*pos, ncid_frm->cid.data, ncid_frm->cid.len);
778 *pos += ncid_frm->cid.len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100779 }
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200780 memcpy(*pos, ncid_frm->stateless_reset_token, QUIC_STATELESS_RESET_TOKEN_LEN);
781 *pos += QUIC_STATELESS_RESET_TOKEN_LEN;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100782
783 return 1;
784}
785
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200786/* Parse a NEW_CONNECTION_ID frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100787 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
788 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100789static int quic_parse_new_connection_id_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200790 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100791{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200792 struct qf_new_connection_id *ncid_frm = &frm->new_connection_id;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100793
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200794 if (!quic_dec_int(&ncid_frm->seq_num, pos, end) ||
795 !quic_dec_int(&ncid_frm->retire_prior_to, pos, end) || end <= *pos)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100796 return 0;
797
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200798 ncid_frm->cid.len = *(*pos)++;
799 if (end - *pos < ncid_frm->cid.len + QUIC_STATELESS_RESET_TOKEN_LEN)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100800 return 0;
801
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200802 if (ncid_frm->cid.len) {
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200803 ncid_frm->cid.data = *pos;
804 *pos += ncid_frm->cid.len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100805 }
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200806 ncid_frm->stateless_reset_token = *pos;
807 *pos += QUIC_STATELESS_RESET_TOKEN_LEN;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100808
809 return 1;
810}
811
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200812/* Encode a RETIRE_CONNECTION_ID frame at <pos> buffer position.
813 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100814 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200815static int quic_build_retire_connection_id_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100816 struct quic_frame *frm, struct quic_conn *conn)
817{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200818 struct qf_retire_connection_id *rcid_frm = &frm->retire_connection_id;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100819
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200820 return quic_enc_int(pos, end, rcid_frm->seq_num);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100821}
822
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200823/* Parse a RETIRE_CONNECTION_ID frame at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100824 * Return 1 if succeeded (enough room to parse this frame), 0 if not.
825 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100826static int quic_parse_retire_connection_id_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200827 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100828{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200829 struct qf_retire_connection_id *rcid_frm = &frm->retire_connection_id;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100830
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200831 return quic_dec_int(&rcid_frm->seq_num, pos, end);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100832}
833
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200834/* Encode a PATH_CHALLENGE frame at <pos> buffer position.
835 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100836 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200837static int quic_build_path_challenge_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100838 struct quic_frame *frm, struct quic_conn *conn)
839{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200840 struct qf_path_challenge *pc_frm = &frm->path_challenge;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100841
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200842 if (end - *pos < sizeof pc_frm->data)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100843 return 0;
844
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200845 memcpy(*pos, pc_frm->data, sizeof pc_frm->data);
846 *pos += sizeof pc_frm->data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100847
848 return 1;
849}
850
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200851/* Parse a PATH_CHALLENGE frame at <pos> buffer position with <end> as end into <frm> frame.
852 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100853 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100854static int quic_parse_path_challenge_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200855 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100856{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200857 struct qf_path_challenge *pc_frm = &frm->path_challenge;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100858
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200859 if (end - *pos < sizeof pc_frm->data)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100860 return 0;
861
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200862 memcpy(pc_frm->data, *pos, sizeof pc_frm->data);
863 *pos += sizeof pc_frm->data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100864
865 return 1;
866}
867
868
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200869/* Encode a PATH_RESPONSE frame at <pos> buffer position.
870 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100871 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200872static int quic_build_path_response_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100873 struct quic_frame *frm, struct quic_conn *conn)
874{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200875 struct qf_path_challenge_response *pcr_frm = &frm->path_challenge_response;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100876
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200877 if (end - *pos < sizeof pcr_frm->data)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100878 return 0;
879
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200880 memcpy(*pos, pcr_frm->data, sizeof pcr_frm->data);
881 *pos += sizeof pcr_frm->data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100882
883 return 1;
884}
885
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200886/* Parse a PATH_RESPONSE frame at <pos> buffer position with <end> as end into <frm> frame.
887 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100888 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100889static int quic_parse_path_response_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200890 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100891{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200892 struct qf_path_challenge_response *pcr_frm = &frm->path_challenge_response;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100893
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200894 if (end - *pos < sizeof pcr_frm->data)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100895 return 0;
896
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200897 memcpy(pcr_frm->data, *pos, sizeof pcr_frm->data);
898 *pos += sizeof pcr_frm->data;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100899
900 return 1;
901}
902
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200903/* Encode a CONNECTION_CLOSE frame at QUIC layer at <pos> buffer position.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100904 * Note there exist two types of CONNECTION_CLOSE frame, one for the application layer
905 * and another at QUIC layer.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200906 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100907 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200908static int quic_build_connection_close_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100909 struct quic_frame *frm, struct quic_conn *conn)
910{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200911 struct qf_connection_close *cc_frm = &frm->connection_close;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100912
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200913 if (!quic_enc_int(pos, end, cc_frm->error_code) ||
914 !quic_enc_int(pos, end, cc_frm->frame_type) ||
915 !quic_enc_int(pos, end, cc_frm->reason_phrase_len) ||
916 end - *pos < cc_frm->reason_phrase_len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100917 return 0;
918
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200919 memcpy(*pos, cc_frm->reason_phrase, cc_frm->reason_phrase_len);
920 *pos += cc_frm->reason_phrase_len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100921
922 return 1;
923}
924
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200925/* Parse a CONNECTION_CLOSE frame at QUIC layer at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100926 * Note there exist two types of CONNECTION_CLOSE frame, one for the application layer
927 * and another at QUIC layer.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200928 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100929 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100930static int quic_parse_connection_close_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200931 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100932{
Frédéric Lécaille010e5322021-12-23 15:19:15 +0100933 size_t plen;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200934 struct qf_connection_close *cc_frm = &frm->connection_close;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100935
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200936 if (!quic_dec_int(&cc_frm->error_code, pos, end) ||
937 !quic_dec_int(&cc_frm->frame_type, pos, end) ||
938 !quic_dec_int(&cc_frm->reason_phrase_len, pos, end) ||
939 end - *pos < cc_frm->reason_phrase_len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100940 return 0;
941
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200942 plen = QUIC_MIN((size_t)cc_frm->reason_phrase_len, sizeof cc_frm->reason_phrase);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200943 memcpy(cc_frm->reason_phrase, *pos, plen);
944 *pos += cc_frm->reason_phrase_len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100945
946 return 1;
947}
948
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200949/* Encode a CONNECTION_CLOSE frame at application layer at <pos> buffer position.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100950 * Note there exist two types of CONNECTION_CLOSE frame, one for application layer
951 * and another at QUIC layer.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200952 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100953 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200954static int quic_build_connection_close_app_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100955 struct quic_frame *frm, struct quic_conn *conn)
956{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200957 struct qf_connection_close_app *cc_frm = &frm->connection_close_app;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100958
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200959 if (!quic_enc_int(pos, end, cc_frm->error_code) ||
960 !quic_enc_int(pos, end, cc_frm->reason_phrase_len) ||
961 end - *pos < cc_frm->reason_phrase_len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100962 return 0;
963
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200964 memcpy(*pos, cc_frm->reason_phrase, cc_frm->reason_phrase_len);
965 *pos += cc_frm->reason_phrase_len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100966
967 return 1;
968}
969
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200970/* Parse a CONNECTION_CLOSE frame at QUIC layer at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100971 * Note there exist two types of CONNECTION_CLOSE frame, one for the application layer
972 * and another at QUIC layer.
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200973 * Return 1 if succeeded (enough room at <pos> buffer position to parse this frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100974 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +0100975static int quic_parse_connection_close_app_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200976 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100977{
Frédéric Lécaille010e5322021-12-23 15:19:15 +0100978 size_t plen;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200979 struct qf_connection_close_app *cc_frm = &frm->connection_close_app;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100980
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200981 if (!quic_dec_int(&cc_frm->error_code, pos, end) ||
982 !quic_dec_int(&cc_frm->reason_phrase_len, pos, end) ||
983 end - *pos < cc_frm->reason_phrase_len)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100984 return 0;
985
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200986 plen = QUIC_MIN((size_t)cc_frm->reason_phrase_len, sizeof cc_frm->reason_phrase);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200987 memcpy(cc_frm->reason_phrase, *pos, plen);
988 *pos += cc_frm->reason_phrase_len;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100989
990 return 1;
991}
992
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200993/* Encode a HANDSHAKE_DONE frame at <pos> buffer position.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100994 * Always succeeds.
995 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +0200996static int quic_build_handshake_done_frame(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100997 struct quic_frame *frm, struct quic_conn *conn)
998{
999 /* No field */
1000 return 1;
1001}
1002
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001003/* Parse a HANDSHAKE_DONE frame at QUIC layer at <pos> buffer position with <end> as end into <frm> frame.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001004 * Always succeed.
1005 */
Frédéric Lécaille50044ad2020-12-29 11:42:08 +01001006static int quic_parse_handshake_done_frame(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001007 const unsigned char **pos, const unsigned char *end)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001008{
1009 /* No field */
1010 return 1;
1011}
1012
1013struct quic_frame_builder {
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001014 int (*func)(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001015 struct quic_frame *frm, struct quic_conn *conn);
Frédéric Lécaillece2ecc92022-02-02 14:37:37 +01001016 uint32_t mask;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001017 unsigned char flags;
1018};
1019
Frédéric Lécaille2cb130c2021-09-17 17:05:44 +02001020const struct quic_frame_builder quic_frame_builders[] = {
Frédéric Lécaille156a59b2021-09-17 16:51:51 +02001021 [QUIC_FT_PADDING] = { .func = quic_build_padding_frame, .flags = QUIC_FL_TX_PACKET_PADDING, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
1022 [QUIC_FT_PING] = { .func = quic_build_ping_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
Frédéric Lécaillef5821dc2021-07-30 14:42:33 +02001023 [QUIC_FT_ACK] = { .func = quic_build_ack_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
1024 [QUIC_FT_ACK_ECN] = { .func = quic_build_ack_ecn_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
Frédéric Lécaille156a59b2021-09-17 16:51:51 +02001025 [QUIC_FT_RESET_STREAM] = { .func = quic_build_reset_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1026 [QUIC_FT_STOP_SENDING] = { .func = quic_build_stop_sending_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1027 [QUIC_FT_CRYPTO] = { .func = quic_build_crypto_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
1028 [QUIC_FT_NEW_TOKEN] = { .func = quic_build_new_token_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE____1_BITMASK, },
1029 [QUIC_FT_STREAM_8] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1030 [QUIC_FT_STREAM_9] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1031 [QUIC_FT_STREAM_A] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1032 [QUIC_FT_STREAM_B] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1033 [QUIC_FT_STREAM_C] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1034 [QUIC_FT_STREAM_D] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1035 [QUIC_FT_STREAM_E] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1036 [QUIC_FT_STREAM_F] = { .func = quic_build_stream_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1037 [QUIC_FT_MAX_DATA] = { .func = quic_build_max_data_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1038 [QUIC_FT_MAX_STREAM_DATA] = { .func = quic_build_max_stream_data_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1039 [QUIC_FT_MAX_STREAMS_BIDI] = { .func = quic_build_max_streams_bidi_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1040 [QUIC_FT_MAX_STREAMS_UNI] = { .func = quic_build_max_streams_uni_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1041 [QUIC_FT_DATA_BLOCKED] = { .func = quic_build_data_blocked_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1042 [QUIC_FT_STREAM_DATA_BLOCKED] = { .func = quic_build_stream_data_blocked_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1043 [QUIC_FT_STREAMS_BLOCKED_BIDI] = { .func = quic_build_streams_blocked_bidi_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1044 [QUIC_FT_STREAMS_BLOCKED_UNI] = { .func = quic_build_streams_blocked_uni_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1045 [QUIC_FT_NEW_CONNECTION_ID] = { .func = quic_build_new_connection_id_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1046 [QUIC_FT_RETIRE_CONNECTION_ID] = { .func = quic_build_retire_connection_id_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1047 [QUIC_FT_PATH_CHALLENGE] = { .func = quic_build_path_challenge_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1048 [QUIC_FT_PATH_RESPONSE] = { .func = quic_build_path_response_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
Frédéric Lécaillef5821dc2021-07-30 14:42:33 +02001049 [QUIC_FT_CONNECTION_CLOSE] = { .func = quic_build_connection_close_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
1050 [QUIC_FT_CONNECTION_CLOSE_APP] = { .func = quic_build_connection_close_app_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
Frédéric Lécaille156a59b2021-09-17 16:51:51 +02001051 [QUIC_FT_HANDSHAKE_DONE] = { .func = quic_build_handshake_done_frame, .flags = QUIC_FL_TX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE____1_BITMASK, },
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001052};
1053
1054struct quic_frame_parser {
Frédéric Lécaille50044ad2020-12-29 11:42:08 +01001055 int (*func)(struct quic_frame *frm, struct quic_conn *qc,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001056 const unsigned char **pos, const unsigned char *end);
Frédéric Lécaillece2ecc92022-02-02 14:37:37 +01001057 uint32_t mask;
Frédéric Lécaillef7fe9652020-12-09 14:56:18 +01001058 unsigned char flags;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001059};
1060
Frédéric Lécaille2cb130c2021-09-17 17:05:44 +02001061const struct quic_frame_parser quic_frame_parsers[] = {
Frédéric Lécaillef7fe9652020-12-09 14:56:18 +01001062 [QUIC_FT_PADDING] = { .func = quic_parse_padding_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
1063 [QUIC_FT_PING] = { .func = quic_parse_ping_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
1064 [QUIC_FT_ACK] = { .func = quic_parse_ack_frame_header, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
1065 [QUIC_FT_ACK_ECN] = { .func = quic_parse_ack_ecn_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
1066 [QUIC_FT_RESET_STREAM] = { .func = quic_parse_reset_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1067 [QUIC_FT_STOP_SENDING] = { .func = quic_parse_stop_sending_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1068 [QUIC_FT_CRYPTO] = { .func = quic_parse_crypto_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE_IH_1_BITMASK, },
1069 [QUIC_FT_NEW_TOKEN] = { .func = quic_parse_new_token_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE____1_BITMASK, },
1070 [QUIC_FT_STREAM_8] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1071 [QUIC_FT_STREAM_9] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1072 [QUIC_FT_STREAM_A] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1073 [QUIC_FT_STREAM_B] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1074 [QUIC_FT_STREAM_C] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1075 [QUIC_FT_STREAM_D] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1076 [QUIC_FT_STREAM_E] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1077 [QUIC_FT_STREAM_F] = { .func = quic_parse_stream_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1078 [QUIC_FT_MAX_DATA] = { .func = quic_parse_max_data_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1079 [QUIC_FT_MAX_STREAM_DATA] = { .func = quic_parse_max_stream_data_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1080 [QUIC_FT_MAX_STREAMS_BIDI] = { .func = quic_parse_max_streams_bidi_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1081 [QUIC_FT_MAX_STREAMS_UNI] = { .func = quic_parse_max_streams_uni_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1082 [QUIC_FT_DATA_BLOCKED] = { .func = quic_parse_data_blocked_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1083 [QUIC_FT_STREAM_DATA_BLOCKED] = { .func = quic_parse_stream_data_blocked_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1084 [QUIC_FT_STREAMS_BLOCKED_BIDI] = { .func = quic_parse_streams_blocked_bidi_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1085 [QUIC_FT_STREAMS_BLOCKED_UNI] = { .func = quic_parse_streams_blocked_uni_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1086 [QUIC_FT_NEW_CONNECTION_ID] = { .func = quic_parse_new_connection_id_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1087 [QUIC_FT_RETIRE_CONNECTION_ID] = { .func = quic_parse_retire_connection_id_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1088 [QUIC_FT_PATH_CHALLENGE] = { .func = quic_parse_path_challenge_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1089 [QUIC_FT_PATH_RESPONSE] = { .func = quic_parse_path_response_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1090 [QUIC_FT_CONNECTION_CLOSE] = { .func = quic_parse_connection_close_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE_IH01_BITMASK, },
1091 [QUIC_FT_CONNECTION_CLOSE_APP] = { .func = quic_parse_connection_close_app_frame, .flags = 0, .mask = QUIC_FT_PKT_TYPE___01_BITMASK, },
1092 [QUIC_FT_HANDSHAKE_DONE] = { .func = quic_parse_handshake_done_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE____1_BITMASK, },
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001093};
1094
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001095/* Decode a QUIC frame at <pos> buffer position into <frm> frame.
1096 * Returns 1 if succeeded (enough data at <pos> buffer position to parse the frame), 0 if not.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001097 */
1098int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001099 const unsigned char **pos, const unsigned char *end,
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001100 struct quic_conn *qc)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001101{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001102 int ret = 0;
Frédéric Lécaille2cb130c2021-09-17 17:05:44 +02001103 const struct quic_frame_parser *parser;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001104
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001105 TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001106 if (end <= *pos) {
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001107 TRACE_DEVEL("wrong frame", QUIC_EV_CONN_PRSFRM, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001108 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001109 }
1110
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001111 frm->type = *(*pos)++;
Frédéric Lécaille0c80e692022-02-15 10:27:34 +01001112 if (frm->type >= QUIC_FT_MAX) {
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001113 TRACE_DEVEL("wrong frame type", QUIC_EV_CONN_PRSFRM, qc, frm);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001114 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001115 }
1116
1117 parser = &quic_frame_parsers[frm->type];
Frédéric Lécaillece2ecc92022-02-02 14:37:37 +01001118 if (!(parser->mask & (1U << pkt->type))) {
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001119 TRACE_DEVEL("unauthorized frame", QUIC_EV_CONN_PRSFRM, qc, frm);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001120 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001121 }
1122
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001123 if (!parser->func(frm, qc, pos, end)) {
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001124 TRACE_DEVEL("parsing error", QUIC_EV_CONN_PRSFRM, qc, frm);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001125 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001126 }
1127
Frédéric Lécaille8f991942023-03-24 15:14:45 +01001128 TRACE_PROTO("RX frm", QUIC_EV_CONN_PSTRM, qc, frm);
1129
Frédéric Lécaillef7fe9652020-12-09 14:56:18 +01001130 pkt->flags |= parser->flags;
1131
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001132 ret = 1;
1133 leave:
1134 TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
1135 return ret;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001136}
1137
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001138/* Encode <frm> QUIC frame at <pos> buffer position.
1139 * Returns 1 if succeeded (enough room at <pos> buffer position to encode the frame), 0 if not.
Frédéric Lécailleb8047de2022-08-23 17:40:09 +02001140 * The buffer is updated to point to one byte past the end of the built frame
1141 * only if succeeded.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001142 */
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001143int qc_build_frm(unsigned char **pos, const unsigned char *end,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001144 struct quic_frame *frm, struct quic_tx_packet *pkt,
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001145 struct quic_conn *qc)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001146{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001147 int ret = 0;
Frédéric Lécaille2cb130c2021-09-17 17:05:44 +02001148 const struct quic_frame_builder *builder;
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001149 unsigned char *p = *pos;
Frédéric Lécaillef7fe9652020-12-09 14:56:18 +01001150
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001151 TRACE_ENTER(QUIC_EV_CONN_BFRM, qc);
Frédéric Lécaillef5821dc2021-07-30 14:42:33 +02001152 builder = &quic_frame_builders[frm->type];
Frédéric Lécaillece2ecc92022-02-02 14:37:37 +01001153 if (!(builder->mask & (1U << pkt->type))) {
Frédéric Lécaillef5821dc2021-07-30 14:42:33 +02001154 /* XXX This it a bug to send an unauthorized frame with such a packet type XXX */
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001155 TRACE_ERROR("unauthorized frame", QUIC_EV_CONN_BFRM, qc, frm);
Frédéric Lécaillece2ecc92022-02-02 14:37:37 +01001156 BUG_ON(!(builder->mask & (1U << pkt->type)));
Frédéric Lécaillef5821dc2021-07-30 14:42:33 +02001157 }
1158
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001159 if (end <= p) {
Frédéric Lécaillefde2a982021-12-27 15:12:09 +01001160 TRACE_DEVEL("not enough room", QUIC_EV_CONN_BFRM, qc, frm);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001161 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001162 }
1163
Frédéric Lécaille8f991942023-03-24 15:14:45 +01001164 TRACE_PROTO("TX frm", QUIC_EV_CONN_BFRM, qc, frm);
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001165 *p++ = frm->type;
1166 if (!quic_frame_builders[frm->type].func(&p, end, frm, qc)) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01001167 TRACE_ERROR("frame building error", QUIC_EV_CONN_BFRM, qc, frm);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001168 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001169 }
1170
Frédéric Lécailledc2593e2021-09-17 16:57:14 +02001171 pkt->flags |= builder->flags;
Frédéric Lécaille1bc6e312023-04-24 17:45:01 +02001172 *pos = p;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001173
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +02001174 ret = 1;
1175 leave:
1176 TRACE_LEAVE(QUIC_EV_CONN_BFRM, qc);
1177 return ret;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001178}
1179
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001180/* Detach all duplicated frames from <frm> reflist. */
1181void qc_frm_unref(struct quic_frame *frm, struct quic_conn *qc)
1182{
1183 struct quic_frame *f, *tmp;
1184
1185 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1186
1187 list_for_each_entry_safe(f, tmp, &frm->reflist, ref) {
1188 f->origin = NULL;
1189 LIST_DEL_INIT(&f->ref);
1190 if (f->pkt) {
1191 TRACE_DEVEL("remove frame reference",
1192 QUIC_EV_CONN_PRSAFRM, qc, f, &f->pkt->pn_node.key);
1193 }
1194 else {
1195 TRACE_DEVEL("remove frame reference for unsent frame",
1196 QUIC_EV_CONN_PRSAFRM, qc, f);
1197 }
1198 }
1199
1200 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1201}