MINOR: quic: extend return value of CRYPTO parsing

qc_handle_crypto_frm() is the function used to handled a newly received
CRYPTO frame. Change its API to use a newly dedicated return type. This
allows to report if the frame was properly handled, ignored if already
parsed previously or rejected after a fatal error.

This commit does not have any functional changes. However, it allows to
simplify qc_handle_crypto_frm() API by removing <fast_retrans> as output
parameter. Also, this patch will be necessary to support multiple
iteration of packet parsing for CRYPTO frames.
This commit is contained in:
Amaury Denoyelle 2024-11-04 17:27:39 +01:00
parent 190fc97606
commit d65e782c8c
2 changed files with 41 additions and 17 deletions

View File

@ -58,4 +58,10 @@ struct quic_rx_packet {
unsigned int time_received; unsigned int time_received;
}; };
enum quic_rx_ret_frm {
QUIC_RX_RET_FRM_DONE = 0, /* frame handled correctly */
QUIC_RX_RET_FRM_DUP, /* frame ignored as already handled previously */
QUIC_RX_RET_FRM_FATAL, /* error during frame handling, packet must not be acknowledged */
};
#endif /* _HAPROXY_RX_T_H */ #endif /* _HAPROXY_RX_T_H */

View File

@ -616,17 +616,22 @@ static int qc_handle_strm_frm(struct quic_rx_packet *pkt,
return !ret; return !ret;
} }
/* Parse <frm> CRYPTO frame coming with <pkt> packet at <qel> <qc> connectionn. /* Parse <frm> CRYPTO frame coming with <pkt> packet at <qel> <qc> connection.
* Returns 1 if succeeded, 0 if not. Also set <*fast_retrans> to 1 if the *
* speed up handshake completion may be run after having received duplicated * Returns 0 on success or a negative error code. A positive value is used to
* CRYPTO data. * indicate that the current frame cannot be handled immediately, but it could
* be solved by running a new packet parsing iteration.
*
* Also set <*fast_retrans> as output parameter to 1 if the speed up handshake
* completion may be run after having received duplicated CRYPTO data.
*/ */
static int qc_handle_crypto_frm(struct quic_conn *qc, static enum quic_rx_ret_frm qc_handle_crypto_frm(struct quic_conn *qc,
struct qf_crypto *crypto_frm, struct quic_rx_packet *pkt, struct qf_crypto *crypto_frm,
struct quic_enc_level *qel, int *fast_retrans) struct quic_rx_packet *pkt,
struct quic_enc_level *qel)
{ {
int ret = 0;
enum ncb_ret ncb_ret; enum ncb_ret ncb_ret;
enum quic_rx_ret_frm ret = QUIC_RX_RET_FRM_DONE;
/* XXX TO DO: <cfdebug> is used only for the traces. */ /* XXX TO DO: <cfdebug> is used only for the traces. */
struct quic_rx_crypto_frm cfdebug = { struct quic_rx_crypto_frm cfdebug = {
.offset_node.key = crypto_frm->offset, .offset_node.key = crypto_frm->offset,
@ -644,9 +649,7 @@ static int qc_handle_crypto_frm(struct quic_conn *qc,
/* Nothing to do */ /* Nothing to do */
TRACE_PROTO("Already received CRYPTO data", TRACE_PROTO("Already received CRYPTO data",
QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug); QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
if (qc_is_listener(qc) && qel == qc->iel && ret = QUIC_RX_RET_FRM_DUP;
!(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP))
*fast_retrans = 1;
goto done; goto done;
} }
@ -661,7 +664,7 @@ static int qc_handle_crypto_frm(struct quic_conn *qc,
if (!quic_get_ncbuf(ncbuf) || ncb_is_null(ncbuf)) { if (!quic_get_ncbuf(ncbuf) || ncb_is_null(ncbuf)) {
TRACE_ERROR("CRYPTO ncbuf allocation failed", QUIC_EV_CONN_PRSHPKT, qc); TRACE_ERROR("CRYPTO ncbuf allocation failed", QUIC_EV_CONN_PRSHPKT, qc);
goto leave; goto err;
} }
/* crypto_frm->offset > cstream-trx.offset */ /* crypto_frm->offset > cstream-trx.offset */
@ -677,7 +680,7 @@ static int qc_handle_crypto_frm(struct quic_conn *qc,
TRACE_ERROR("cannot bufferize frame due to gap size limit", TRACE_ERROR("cannot bufferize frame due to gap size limit",
QUIC_EV_CONN_PRSHPKT, qc); QUIC_EV_CONN_PRSHPKT, qc);
} }
goto leave; goto err;
} }
/* Reschedule with TASK_HEAVY if CRYPTO data ready for decoding. */ /* Reschedule with TASK_HEAVY if CRYPTO data ready for decoding. */
@ -687,10 +690,12 @@ static int qc_handle_crypto_frm(struct quic_conn *qc,
} }
done: done:
ret = 1;
leave:
TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc); TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
return ret; return ret;
err:
TRACE_DEVEL("leaving on error", QUIC_EV_CONN_PRSHPKT, qc);
return QUIC_RX_RET_FRM_FATAL;
} }
/* Handle RETIRE_CONNECTION_ID frame from <frm> frame. /* Handle RETIRE_CONNECTION_ID frame from <frm> frame.
@ -770,6 +775,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
{ {
struct quic_frame *frm = NULL; struct quic_frame *frm = NULL;
const unsigned char *pos, *end; const unsigned char *pos, *end;
enum quic_rx_ret_frm ret;
int fast_retrans = 0; int fast_retrans = 0;
TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
@ -848,8 +854,20 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
break; break;
} }
case QUIC_FT_CRYPTO: case QUIC_FT_CRYPTO:
if (!qc_handle_crypto_frm(qc, &frm->crypto, pkt, qel, &fast_retrans)) ret = qc_handle_crypto_frm(qc, &frm->crypto, pkt, qel);
switch (ret) {
case QUIC_RX_RET_FRM_FATAL:
goto err; goto err;
case QUIC_RX_RET_FRM_DUP:
if (qc_is_listener(qc) && qel == qc->iel &&
!(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP)) {
fast_retrans = 1;
}
break;
case QUIC_RX_RET_FRM_DONE:
/* nothing to do here */
break;
}
break; break;
case QUIC_FT_NEW_TOKEN: case QUIC_FT_NEW_TOKEN:
/* TODO */ /* TODO */