diff --git a/include/haproxy/quic_frame-t.h b/include/haproxy/quic_frame-t.h index 71835ce37..d75a1c84d 100644 --- a/include/haproxy/quic_frame-t.h +++ b/include/haproxy/quic_frame-t.h @@ -87,6 +87,7 @@ enum quic_frame_type { * defined in quic_frame.c. Do not forget to complete the associated function * quic_frame_type_is_known() and both qf_builder()/qf_parser(). */ +extern const uint64_t QUIC_FT_QS_TP; #define QUIC_FT_PKT_TYPE_I_BITMASK (1 << QUIC_PACKET_TYPE_INITIAL) #define QUIC_FT_PKT_TYPE_0_BITMASK (1 << QUIC_PACKET_TYPE_0RTT) @@ -249,6 +250,10 @@ struct qf_connection_close_app { unsigned char reason_phrase[QUIC_CC_REASON_PHRASE_MAXLEN]; }; +struct qf_qs_tp { + struct quic_transport_params tps; +}; + 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. */ @@ -276,6 +281,7 @@ struct quic_frame { struct qf_path_challenge_response path_challenge_response; struct qf_connection_close connection_close; struct qf_connection_close_app connection_close_app; + struct qf_qs_tp qs_tp; }; struct quic_frame *origin; /* Parent frame. Set if frame is a duplicate (used for retransmission). */ struct list reflist; /* List head containing duplicated children frames. */ diff --git a/src/quic_frame.c b/src/quic_frame.c index d7a081e1a..1f2f6004b 100644 --- a/src/quic_frame.c +++ b/src/quic_frame.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1007,6 +1007,43 @@ static int quic_build_handshake_done_frame(unsigned char **pos, const unsigned c return 1; } +static int quic_build_qs_tp_frame(unsigned char **pos, const unsigned char *end, + struct quic_frame *frm, struct quic_conn *conn) +{ + unsigned char *old = *pos; + struct buffer buf; + + if (end - *pos < 8) + return 0; + + buf = b_make((char *)*pos, end - *pos, 0, 0); + if (!b_quic_enc_int(&buf, 0, 8)) + return 0; + + //if (!quic_enc_int(pos, end, 0)) + // return 0; + *pos += 8; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_MAX_IDLE_TIMEOUT, 30000)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_DATA, 16384)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, 16384)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, 16384)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI, 16384)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAMS_BIDI, 100)) + return 0; + if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAMS_UNI, 100)) + return 0; + + buf = b_make((char *)old, 8, 0, 0); + b_quic_enc_int(&buf, *pos - 8 - old, 8); + + return 1; +} + /* Parse a HANDSHAKE_DONE frame at QUIC layer at buffer position with as end into frame. * Always succeed. */ @@ -1017,6 +1054,17 @@ static int quic_parse_handshake_done_frame(struct quic_frame *frm, struct quic_c return 1; } +static int quic_parse_qs_tp(struct quic_frame *frm, struct quic_conn *qc, + const unsigned char **pos, const unsigned char *end) +{ + struct qf_qs_tp *qs_tp_frm = &frm->qs_tp; + uint64_t len; + + quic_dec_int(&len, pos, end); + quic_transport_params_decode(&qs_tp_frm->tps, 1, *pos, end); + return 1; +} + struct quic_frame_builder { int (*func)(unsigned char **pos, const unsigned char *end, struct quic_frame *frm, struct quic_conn *conn); @@ -1117,11 +1165,25 @@ const struct quic_frame_parser quic_frame_parsers[] = { * }; */ +/* quic-on-streams transport parameters frame. */ +const uint64_t QUIC_FT_QS_TP = 0x3f5153300d0a0d0a; +const struct quic_frame_parser qf_ft_qs_tp_parser = { + .func = quic_parse_qs_tp, + .mask = 0, + .flags = 0, +}; +const struct quic_frame_builder qf_ft_qs_tp_builder = { + .func = quic_build_qs_tp_frame, + .mask = 0, + .flags = 0, +}; + /* Returns true if frame 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; + return type < QUIC_FT_MAX || + (type == QUIC_FT_QS_TP); } static const struct quic_frame_parser *qf_parser(uint64_t type) @@ -1130,6 +1192,8 @@ static const struct quic_frame_parser *qf_parser(uint64_t type) return &quic_frame_parsers[type]; /* Complete here for extra frame types greater than QUIC_FT_MAX. */ + if (type == QUIC_FT_QS_TP) + return &qf_ft_qs_tp_parser; ABORT_NOW(); return NULL; @@ -1141,6 +1205,8 @@ const struct quic_frame_builder *qf_builder(uint64_t type) return &quic_frame_builders[type]; /* Complete here for extra frame types greater than QUIC_FT_MAX. */ + if (type == QUIC_FT_QS_TP) + return &qf_ft_qs_tp_builder; ABORT_NOW(); return NULL;