19bool rd(
const uint8_t *buf,
size_t len,
size_t *pos, uint64_t *v)
22 if (!quic_varint_decode(buf + *pos, len - *pos, v, &c))
29size_t quic_frame_parse(
const uint8_t *buf,
size_t len, QuicFrame *out)
33 if (!rd(buf, len, &pos, &type))
37 if (type == QuicFrameType::QUIC_FT_PADDING || type == QuicFrameType::QUIC_FT_PING ||
38 type == QuicFrameType::QUIC_FT_HANDSHAKE_DONE)
41 if (type == QuicFrameType::QUIC_FT_ACK || type == QuicFrameType::QUIC_FT_ACK_ECN)
43 if (!rd(buf, len, &pos, &out->ack.largest) || !rd(buf, len, &pos, &out->ack.delay) ||
44 !rd(buf, len, &pos, &out->ack.range_count) || !rd(buf, len, &pos, &out->ack.first_range))
46 for (uint64_t i = 0; i < out->ack.range_count; i++)
49 if (!rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp))
52 if (type == QuicFrameType::QUIC_FT_ACK_ECN)
55 if (!rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp))
61 if (type == QuicFrameType::QUIC_FT_CRYPTO)
63 if (!rd(buf, len, &pos, &out->crypto.offset) || !rd(buf, len, &pos, &out->crypto.length))
65 if (pos + out->crypto.length > len)
67 out->crypto.data = buf + pos;
68 pos += out->crypto.length;
72 if (type >= QuicFrameType::QUIC_FT_STREAM && type <= 0x0f)
74 if (!rd(buf, len, &pos, &out->stream.id))
76 out->stream.offset = 0;
77 if (type & QuicStreamFlag::QUIC_STREAM_OFF)
78 if (!rd(buf, len, &pos, &out->stream.offset))
80 if (type & QuicStreamFlag::QUIC_STREAM_LEN)
82 if (!rd(buf, len, &pos, &out->stream.length))
87 out->stream.length = len - pos;
89 if (pos + out->stream.length > len)
91 out->stream.data = buf + pos;
92 out->stream.fin = (uint8_t)((type & QuicStreamFlag::QUIC_STREAM_FIN) ? 1 : 0);
93 pos += out->stream.length;
97 if (type == QuicFrameType::QUIC_FT_MAX_DATA)
99 if (!rd(buf, len, &pos, &out->max_data.max))
104 if (type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE || type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE_APP)
106 out->close.app = (uint8_t)((type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE_APP) ? 1 : 0);
107 out->close.frame_type = 0;
108 if (!rd(buf, len, &pos, &out->close.error_code))
110 if (type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE)
111 if (!rd(buf, len, &pos, &out->close.frame_type))
113 if (!rd(buf, len, &pos, &out->close.reason_len))
115 if (pos + out->close.reason_len > len)
117 out->close.reason = buf + pos;
118 pos += out->close.reason_len;
127 if (type == QuicFrameType::QUIC_FT_MAX_STREAMS_BIDI || type == QuicFrameType::QUIC_FT_MAX_STREAMS_UNI ||
128 type == QuicFrameType::QUIC_FT_DATA_BLOCKED || type == QuicFrameType::QUIC_FT_STREAMS_BLOCKED_BIDI ||
129 type == QuicFrameType::QUIC_FT_STREAMS_BLOCKED_UNI || type == QuicFrameType::QUIC_FT_RETIRE_CONNECTION_ID)
132 if (!rd(buf, len, &pos, &v))
136 if (type == QuicFrameType::QUIC_FT_STOP_SENDING || type == QuicFrameType::QUIC_FT_MAX_STREAM_DATA ||
137 type == QuicFrameType::QUIC_FT_STREAM_DATA_BLOCKED)
140 if (!rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v))
144 if (type == QuicFrameType::QUIC_FT_RESET_STREAM)
147 if (!rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v))
151 if (type == QuicFrameType::QUIC_FT_NEW_TOKEN)
154 if (!rd(buf, len, &pos, &tlen) || pos + tlen > len)
159 if (type == QuicFrameType::QUIC_FT_NEW_CONNECTION_ID)
163 if (!rd(buf, len, &pos, &seq) || !rd(buf, len, &pos, &retire) || pos >= len)
165 uint8_t cidlen = buf[pos++];
166 if (pos + (
size_t)cidlen + 16 > len)
168 pos += (size_t)cidlen + 16;
171 if (type == QuicFrameType::QUIC_FT_PATH_CHALLENGE || type == QuicFrameType::QUIC_FT_PATH_RESPONSE)
182size_t quic_build_padding(uint8_t *out,
size_t cap,
size_t n)
190size_t quic_build_ping(uint8_t *out,
size_t cap)
194 out[0] = QuicFrameType::QUIC_FT_PING;
198size_t quic_build_handshake_done(uint8_t *out,
size_t cap)
202 out[0] = QuicFrameType::QUIC_FT_HANDSHAKE_DONE;
209bool wr(uint8_t *out,
size_t cap,
size_t *pos, uint64_t v)
211 size_t c = quic_varint_encode(out + *pos, cap - *pos, v);
219size_t quic_build_ack(uint8_t *out,
size_t cap, uint64_t largest, uint64_t delay, uint64_t first_range)
222 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_ACK) || !wr(out, cap, &pos, largest) || !wr(out, cap, &pos, delay) ||
223 !wr(out, cap, &pos, 0) || !wr(out, cap, &pos, first_range))
228size_t quic_build_crypto(uint8_t *out,
size_t cap, uint64_t offset,
const uint8_t *data,
size_t len)
231 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_CRYPTO) || !wr(out, cap, &pos, offset) || !wr(out, cap, &pos, len))
236 memcpy(out + pos, data, len);
240size_t quic_build_stream(uint8_t *out,
size_t cap, uint64_t
id, uint64_t offset,
const uint8_t *data,
size_t len,
243 uint64_t type = QuicFrameType::QUIC_FT_STREAM | QuicStreamFlag::QUIC_STREAM_LEN |
244 (offset ? QuicStreamFlag::QUIC_STREAM_OFF : 0) | (fin ? QuicStreamFlag::QUIC_STREAM_FIN : 0);
246 if (!wr(out, cap, &pos, type) || !wr(out, cap, &pos,
id))
248 if (offset && !wr(out, cap, &pos, offset))
250 if (!wr(out, cap, &pos, len))
255 memcpy(out + pos, data, len);
259size_t quic_build_max_data(uint8_t *out,
size_t cap, uint64_t max)
262 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_MAX_DATA) || !wr(out, cap, &pos, max))
267size_t quic_build_connection_close(uint8_t *out,
size_t cap, uint64_t error_code, uint64_t frame_type,
268 const char *reason,
size_t reason_len)
271 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_CONNECTION_CLOSE) || !wr(out, cap, &pos, error_code) ||
272 !wr(out, cap, &pos, frame_type) || !wr(out, cap, &pos, reason_len))
274 if (pos + reason_len > cap)
277 memcpy(out + pos, reason, reason_len);
278 return pos + reason_len;
QUIC frame parsing and building (RFC 9000 sec 19).
QUIC variable-length integer coding (RFC 9000 sec 16).