mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-04-03 10:01:03 +02:00
MINOR: quic: refactor frame parsing
This patch refactors parsing in QUIC frame module. Function qc_parse_frm() has been splitted in three : * qc_parse_frm_type() * qc_parse_frm_pkt() * qc_parse_frm_payload() No functional change. The main objective of this patch is to facilitate a QMux implementation. One of the gain is the ability to manipulate QUIC frames without any reference to a QUIC packet as it is irrelevant for QMux. Also, quic_set_connection_close() calls are extracted as this relies on qc type. The caller is now responsible to set the required error code.
This commit is contained in:
parent
1e08247961
commit
48e41e4ce0
@ -38,9 +38,16 @@ int qc_build_frm(unsigned char **pos, const unsigned char *end,
|
||||
struct quic_frame *frm, struct quic_tx_packet *pkt,
|
||||
struct quic_conn *conn);
|
||||
|
||||
int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *conn);
|
||||
int qc_parse_frm_type(struct quic_frame *frm,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *conn);
|
||||
|
||||
int qc_parse_frm_pkt(const struct quic_frame *frm,
|
||||
const struct quic_rx_packet *pkt, int *flags);
|
||||
|
||||
int qc_parse_frm_payload(struct quic_frame *frm,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *qc);
|
||||
|
||||
void qc_release_frm(struct quic_conn *qc, struct quic_frame *frm);
|
||||
|
||||
|
||||
@ -1150,17 +1150,19 @@ const struct quic_frame_builder *qf_builder(uint64_t type)
|
||||
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.
|
||||
/* Parse frame type in buffer starting at <pos> and ending at <end> and store
|
||||
* it in <frm> object.
|
||||
*
|
||||
* Returns 1 on success else 0.
|
||||
*/
|
||||
int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *qc)
|
||||
int qc_parse_frm_type(struct quic_frame *frm,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *qc)
|
||||
{
|
||||
int ret = 0;
|
||||
const struct quic_frame_parser *parser;
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
|
||||
|
||||
if (end <= *pos) {
|
||||
TRACE_DEVEL("wrong frame", QUIC_EV_CONN_PRSFRM, qc);
|
||||
goto leave;
|
||||
@ -1168,34 +1170,50 @@ int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
|
||||
|
||||
if (!quic_dec_int(&frm->type, pos, end)) {
|
||||
TRACE_ERROR("malformed frame type", QUIC_EV_CONN_PRSFRM, qc);
|
||||
quic_set_connection_close(qc, quic_err_transport(QC_ERR_FRAME_ENCODING_ERROR));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
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
|
||||
* connection error of type FRAME_ENCODING_ERROR.
|
||||
*/
|
||||
TRACE_DEVEL("wrong frame type", QUIC_EV_CONN_PRSFRM, qc, frm);
|
||||
quic_set_connection_close(qc, quic_err_transport(QC_ERR_FRAME_ENCODING_ERROR));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
leave:
|
||||
TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Checks that <frm> frame is authorized in <pkt> packet. Output parameter <flags>
|
||||
* may be updated if the frame characteristics impacts the containing packet.
|
||||
*
|
||||
* Returns true for a valid frame else false.
|
||||
*/
|
||||
int qc_parse_frm_pkt(const struct quic_frame *frm,
|
||||
const struct quic_rx_packet *pkt, int *flags)
|
||||
{
|
||||
const struct quic_frame_parser *parser = qf_parser(frm->type);
|
||||
if (!(parser->mask & (1U << pkt->type)))
|
||||
return 0;
|
||||
|
||||
*flags = parser->flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse frame content in buffer starting at <pos> and ending at <end>.
|
||||
*
|
||||
* Returns 1 on success else 0.
|
||||
*/
|
||||
int qc_parse_frm_payload(struct quic_frame *frm,
|
||||
const unsigned char **pos, const unsigned char *end,
|
||||
struct quic_conn *qc)
|
||||
{
|
||||
int ret = 0;
|
||||
const struct quic_frame_parser *parser;
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
|
||||
|
||||
parser = qf_parser(frm->type);
|
||||
if (!(parser->mask & (1U << pkt->type))) {
|
||||
/* RFC 9000 12.4. Frames and Frame Types
|
||||
*
|
||||
* An endpoint MUST treat
|
||||
* receipt of a frame in a packet type that is not permitted as a
|
||||
* connection error of type PROTOCOL_VIOLATION.
|
||||
*/
|
||||
TRACE_DEVEL("unauthorized frame", QUIC_EV_CONN_PRSFRM, qc, frm);
|
||||
quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!parser->func(frm, qc, pos, end)) {
|
||||
TRACE_DEVEL("parsing error", QUIC_EV_CONN_PRSFRM, qc, frm);
|
||||
goto leave;
|
||||
@ -1203,8 +1221,6 @@ int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
|
||||
|
||||
TRACE_PROTO("RX frm", QUIC_EV_CONN_PSTRM, qc, frm);
|
||||
|
||||
pkt->flags |= parser->flags;
|
||||
|
||||
ret = 1;
|
||||
leave:
|
||||
TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
|
||||
|
||||
@ -840,7 +840,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
{
|
||||
struct quic_frame *frm = NULL;
|
||||
const unsigned char *pos, *end;
|
||||
int fast_retrans = 0, ret;
|
||||
int fast_retrans = 0, pkt_flags = 0, ret;
|
||||
|
||||
TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
|
||||
/* Skip the AAD */
|
||||
@ -867,7 +867,32 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!qc_parse_frm(frm, pkt, &pos, end, qc)) {
|
||||
if (!qc_parse_frm_type(frm, &pos, end, qc)) {
|
||||
/* RFC 9000 12.4. Frames and Frame Types
|
||||
*
|
||||
* An endpoint MUST treat the receipt of a frame of unknown type as a
|
||||
* connection error of type FRAME_ENCODING_ERROR.
|
||||
*/
|
||||
quic_set_connection_close(qc, quic_err_transport(QC_ERR_FRAME_ENCODING_ERROR));
|
||||
/* trace already emitted by above function */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* RFC 9000 12.4. Frames and Frame Types
|
||||
*
|
||||
* An endpoint MUST treat
|
||||
* receipt of a frame in a packet type that is not permitted as a
|
||||
* connection error of type PROTOCOL_VIOLATION.
|
||||
*/
|
||||
if (!qc_parse_frm_pkt(frm, pkt, &pkt_flags)) {
|
||||
TRACE_ERROR("unauthorized frame", QUIC_EV_CONN_PRSFRM, qc, frm);
|
||||
quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
|
||||
goto err;
|
||||
}
|
||||
|
||||
pkt->flags |= pkt_flags;
|
||||
|
||||
if (!qc_parse_frm_payload(frm, &pos, end, qc)) {
|
||||
// trace already emitted by function above
|
||||
goto err;
|
||||
}
|
||||
@ -1147,7 +1172,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
|
||||
qc->state = QUIC_HS_ST_CONFIRMED;
|
||||
break;
|
||||
default:
|
||||
/* Unknown frame type must be rejected by qc_parse_frm(). */
|
||||
/* Unknown frame type must be rejected by qc_parse_frm_type(). */
|
||||
ABORT_NOW();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user