QUIC_FT_MAX
};
+/* Extra frame types larger than QUIC_FT_MAX should be declared here.
+ * For every new value, an associated builder and parser instances should be
+ * defined in quic_frame.c. Do not forget to complete the associated function
+ * quic_frame_type_is_known() and both qf_builder()/qf_parser().
+ */
+
#define QUIC_FT_PKT_TYPE_I_BITMASK (1 << QUIC_PACKET_TYPE_INITIAL)
#define QUIC_FT_PKT_TYPE_0_BITMASK (1 << QUIC_PACKET_TYPE_0RTT)
#define QUIC_FT_PKT_TYPE_H_BITMASK (1 << QUIC_PACKET_TYPE_HANDSHAKE)
struct quic_frame {
struct list list; /* List elem from parent elem (typically a Tx packet instance, a PKTNS or a MUX element). */
struct quic_tx_packet *pkt; /* Last Tx packet used to send the frame. */
- unsigned char type; /* QUIC frame type. */
+ uint64_t type; /* QUIC frame type. */
union {
struct qf_padding padding;
struct qf_ack ack;
[QUIC_FT_HANDSHAKE_DONE] = { .func = quic_parse_handshake_done_frame, .flags = QUIC_FL_RX_PACKET_ACK_ELICITING, .mask = QUIC_FT_PKT_TYPE____1_BITMASK, },
};
+/* Extra frame types with their associated builder and parser instances.
+ * Complete quic_frame_type_is_known() and both qf_builder()/qf_parser() to use them.
+ *
+ * Definition example:
+ *
+ * const uint64_t QUIC_FT_MY_CUSTOM_FRM = 0x01020304;
+ * const struct quic_frame_builder qf_ft_qs_tp_builder = {
+ * .func = quic_build_my_custom_frm,
+ * .mask = 0,
+ * .flags = 0,
+ * };
+ * const struct quic_frame_parser qf_ft_qs_tp_parser = {
+ * .func = quic_parse_my_custom_frm,
+ * .mask = 0,
+ * .flags = 0,
+ * };
+ */
+
+/* Returns true if frame <type> is supported. */
+static inline int quic_frame_type_is_known(uint64_t type)
+{
+ /* Complete here for extra frame types greater than QUIC_FT_MAX. */
+ return type < QUIC_FT_MAX;
+}
+
+static const struct quic_frame_parser *qf_parser(uint64_t type)
+{
+ if (type < QUIC_FT_MAX)
+ return &quic_frame_parsers[type];
+
+ /* Complete here for extra frame types greater than QUIC_FT_MAX. */
+
+ ABORT_NOW();
+ return NULL;
+}
+
+const struct quic_frame_builder *qf_builder(uint64_t type)
+{
+ if (type < QUIC_FT_MAX)
+ return &quic_frame_builders[type];
+
+ /* Complete here for extra frame types greater than QUIC_FT_MAX. */
+
+ ABORT_NOW();
+ return NULL;
+}
+
/* Decode a QUIC frame at <pos> buffer position into <frm> frame.
* Returns 1 if succeeded (enough data at <pos> buffer position to parse the frame), 0 if not.
*/
goto leave;
}
- frm->type = *(*pos)++;
- if (frm->type >= QUIC_FT_MAX) {
+ quic_dec_int(&frm->type, pos, end);
+ if (!quic_frame_type_is_known(frm->type)) {
/* RFC 9000 12.4. Frames and Frame Types
*
* An endpoint MUST treat the receipt of a frame of unknown type as a
goto leave;
}
- parser = &quic_frame_parsers[frm->type];
+ parser = qf_parser(frm->type);
if (!(parser->mask & (1U << pkt->type))) {
TRACE_DEVEL("unauthorized frame", QUIC_EV_CONN_PRSFRM, qc, frm);
goto leave;
unsigned char *p = *pos;
TRACE_ENTER(QUIC_EV_CONN_BFRM, qc);
- builder = &quic_frame_builders[frm->type];
+ builder = qf_builder(frm->type);
if (!(builder->mask & (1U << pkt->type))) {
/* XXX This it a bug to send an unauthorized frame with such a packet type XXX */
TRACE_ERROR("unauthorized frame", QUIC_EV_CONN_BFRM, qc, frm);
BUG_ON(!(builder->mask & (1U << pkt->type)));
}
- if (end <= p) {
+ if (!quic_enc_int(&p, end, frm->type)) {
TRACE_DEVEL("not enough room", QUIC_EV_CONN_BFRM, qc, frm);
goto leave;
}
TRACE_PROTO("TX frm", QUIC_EV_CONN_BFRM, qc, frm);
- *p++ = frm->type;
- if (!quic_frame_builders[frm->type].func(&p, end, frm, qc)) {
+ if (!builder->func(&p, end, frm, qc)) {
TRACE_ERROR("frame building error", QUIC_EV_CONN_BFRM, qc, frm);
goto leave;
}