19bool rd(
const uint8_t *buf,
size_t len,
size_t *pos, uint64_t *v)
22 if (!pc_quic_varint_decode(buf + *pos, len - *pos, v, &c))
31size_t pc_quic_frame_parse(
const uint8_t *buf,
size_t len, QuicFrame *out)
35 if (!rd(buf, len, &pos, &type))
41 if (type == QuicFrameType::QUIC_FT_PADDING || type == QuicFrameType::QUIC_FT_PING ||
42 type == QuicFrameType::QUIC_FT_HANDSHAKE_DONE)
47 if (type == QuicFrameType::QUIC_FT_ACK || type == QuicFrameType::QUIC_FT_ACK_ECN)
49 if (!rd(buf, len, &pos, &out->ack.largest) || !rd(buf, len, &pos, &out->ack.delay) ||
50 !rd(buf, len, &pos, &out->ack.range_count) || !rd(buf, len, &pos, &out->ack.first_range))
54 for (uint64_t i = 0; i < out->ack.range_count; i++)
57 if (!rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp))
62 if (type == QuicFrameType::QUIC_FT_ACK_ECN)
65 if (!rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp) || !rd(buf, len, &pos, &tmp))
73 if (type == QuicFrameType::QUIC_FT_CRYPTO)
75 if (!rd(buf, len, &pos, &out->crypto.offset) || !rd(buf, len, &pos, &out->crypto.length))
79 if (pos + out->crypto.length > len)
83 out->crypto.data = buf + pos;
84 pos += out->crypto.length;
88 if (type >= QuicFrameType::QUIC_FT_STREAM && type <= 0x0f)
90 if (!rd(buf, len, &pos, &out->stream.id))
94 out->stream.offset = 0;
95 if (type & QuicStreamFlag::QUIC_STREAM_OFF)
97 if (!rd(buf, len, &pos, &out->stream.offset))
102 if (type & QuicStreamFlag::QUIC_STREAM_LEN)
104 if (!rd(buf, len, &pos, &out->stream.length))
111 out->stream.length = len - pos;
113 if (pos + out->stream.length > len)
117 out->stream.data = buf + pos;
118 out->stream.fin = (uint8_t)((type & QuicStreamFlag::QUIC_STREAM_FIN) ? 1 : 0);
119 pos += out->stream.length;
123 if (type == QuicFrameType::QUIC_FT_MAX_DATA)
125 if (!rd(buf, len, &pos, &out->max_data.max))
132 if (type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE || type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE_APP)
134 out->close.app = (uint8_t)((type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE_APP) ? 1 : 0);
135 out->close.frame_type = 0;
136 if (!rd(buf, len, &pos, &out->close.error_code))
140 if (type == QuicFrameType::QUIC_FT_CONNECTION_CLOSE)
142 if (!rd(buf, len, &pos, &out->close.frame_type))
147 if (!rd(buf, len, &pos, &out->close.reason_len))
151 if (pos + out->close.reason_len > len)
155 out->close.reason = buf + pos;
156 pos += out->close.reason_len;
165 if (type == QuicFrameType::QUIC_FT_MAX_STREAMS_BIDI || type == QuicFrameType::QUIC_FT_MAX_STREAMS_UNI ||
166 type == QuicFrameType::QUIC_FT_DATA_BLOCKED || type == QuicFrameType::QUIC_FT_STREAMS_BLOCKED_BIDI ||
167 type == QuicFrameType::QUIC_FT_STREAMS_BLOCKED_UNI || type == QuicFrameType::QUIC_FT_RETIRE_CONNECTION_ID)
170 if (!rd(buf, len, &pos, &v))
176 if (type == QuicFrameType::QUIC_FT_STOP_SENDING || type == QuicFrameType::QUIC_FT_MAX_STREAM_DATA ||
177 type == QuicFrameType::QUIC_FT_STREAM_DATA_BLOCKED)
180 if (!rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v))
186 if (type == QuicFrameType::QUIC_FT_RESET_STREAM)
189 if (!rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v) || !rd(buf, len, &pos, &v))
195 if (type == QuicFrameType::QUIC_FT_NEW_TOKEN)
198 if (!rd(buf, len, &pos, &tlen) || pos + tlen > len)
205 if (type == QuicFrameType::QUIC_FT_NEW_CONNECTION_ID)
209 if (!rd(buf, len, &pos, &seq) || !rd(buf, len, &pos, &retire) || pos >= len)
213 uint8_t cidlen = buf[pos++];
214 if (pos + (
size_t)cidlen + 16 > len)
218 pos += (size_t)cidlen + 16;
221 if (type == QuicFrameType::QUIC_FT_PATH_CHALLENGE || type == QuicFrameType::QUIC_FT_PATH_RESPONSE)
234size_t pc_quic_build_padding(uint8_t *out,
size_t cap,
size_t n)
244size_t pc_quic_build_ping(uint8_t *out,
size_t cap)
250 out[0] = QuicFrameType::QUIC_FT_PING;
254size_t pc_quic_build_handshake_done(uint8_t *out,
size_t cap)
260 out[0] = QuicFrameType::QUIC_FT_HANDSHAKE_DONE;
267bool wr(uint8_t *out,
size_t cap,
size_t *pos, uint64_t v)
269 size_t c = pc_quic_varint_encode(out + *pos, cap - *pos, v);
279size_t pc_quic_build_ack(uint8_t *out,
size_t cap, uint64_t largest, uint64_t delay, uint64_t first_range)
282 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_ACK) || !wr(out, cap, &pos, largest) || !wr(out, cap, &pos, delay) ||
283 !wr(out, cap, &pos, 0) || !wr(out, cap, &pos, first_range))
290size_t pc_quic_build_crypto(uint8_t *out,
size_t cap, uint64_t offset,
const uint8_t *data,
size_t len)
293 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_CRYPTO) || !wr(out, cap, &pos, offset) || !wr(out, cap, &pos, len))
303 memcpy(out + pos, data, len);
308size_t pc_quic_build_stream(uint8_t *out,
size_t cap, uint64_t
id, uint64_t offset,
const uint8_t *data,
size_t len,
311 uint64_t type = QuicFrameType::QUIC_FT_STREAM | QuicStreamFlag::QUIC_STREAM_LEN |
312 (offset ? QuicStreamFlag::QUIC_STREAM_OFF : 0) | (fin ? QuicStreamFlag::QUIC_STREAM_FIN : 0);
314 if (!wr(out, cap, &pos, type) || !wr(out, cap, &pos,
id))
318 if (offset && !wr(out, cap, &pos, offset))
322 if (!wr(out, cap, &pos, len))
332 memcpy(out + pos, data, len);
337size_t pc_quic_build_max_data(uint8_t *out,
size_t cap, uint64_t max)
340 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_MAX_DATA) || !wr(out, cap, &pos, max))
347size_t pc_quic_build_connection_close(uint8_t *out,
size_t cap, uint64_t error_code, uint64_t frame_type,
348 const char *reason,
size_t reason_len)
351 if (!wr(out, cap, &pos, QuicFrameType::QUIC_FT_CONNECTION_CLOSE) || !wr(out, cap, &pos, error_code) ||
352 !wr(out, cap, &pos, frame_type) || !wr(out, cap, &pos, reason_len))
356 if (pos + reason_len > cap)
362 memcpy(out + pos, reason, reason_len);
364 return pos + reason_len;