MINOR: h3/hq-interop: restore function for standalone FIN receive

Previously, a function qcs_http_handle_standalone_fin() was implemented
to handle a received standalone FIN, bypassing app_ops layer decoding.
However, this was removed as app_ops layer interaction is necessary. For
example, HTTP/3 checks that FIN is never sent on the control uni stream.

This patch reintroduces qcs_http_handle_standalone_fin(), albeit in a
slightly diminished version. Most importantly, it is now the
responsibility of the app_ops layer itself to use it, to avoid the
shortcoming described above.

The main objective of this patch is to be able to support standalone FIN
in HTTP/0.9 layer. This is easily done via the reintroduction of
qcs_http_handle_standalone_fin() usage. This will be useful to perform
testing, as standalone FIN is a corner case which can easily be broken.
This commit is contained in:
Amaury Denoyelle 2025-02-27 11:33:21 +01:00
parent 6f95d0dad0
commit 861b11334c
4 changed files with 31 additions and 14 deletions

View file

@ -8,6 +8,9 @@
size_t qcs_http_rcv_buf(struct qcs *qcs, struct buffer *buf, size_t count,
char *fin);
int qcs_http_handle_standalone_fin(struct qcs *qcs);
size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
char *fin);

View file

@ -1322,21 +1322,8 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
}
if (!b_data(b) && fin && quic_stream_is_bidi(qcs->id)) {
struct buffer *appbuf;
struct htx *htx;
int eom;
TRACE_PROTO("received FIN without data", H3_EV_RX_FRAME, qcs->qcc->conn, qcs);
if (!(appbuf = qcc_get_stream_rxbuf(qcs))) {
TRACE_ERROR("data buffer alloc failure", H3_EV_RX_FRAME, qcs->qcc->conn, qcs);
qcc_set_error(qcs->qcc, H3_ERR_INTERNAL_ERROR, 1);
goto err;
}
htx = htx_from_buf(appbuf);
eom = htx_set_eom(htx);
htx_to_buf(htx, appbuf);
if (!eom) {
if (qcs_http_handle_standalone_fin(qcs)) {
TRACE_ERROR("cannot set EOM", H3_EV_RX_FRAME, qcs->qcc->conn, qcs);
qcc_set_error(qcs->qcc, H3_ERR_INTERNAL_ERROR, 1);
goto err;

View file

@ -23,6 +23,12 @@ static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
/* hq-interop parser does not support buffer wrapping. */
BUG_ON(b_data(b) != b_contig_data(b, 0));
if (!b_data(b) && fin && quic_stream_is_bidi(qcs->id)) {
if (qcs_http_handle_standalone_fin(qcs))
return -1;
return 0;
}
/* skip method */
while (data && HTTP_IS_TOKEN(*ptr)) {
ptr++;

View file

@ -62,6 +62,27 @@ size_t qcs_http_rcv_buf(struct qcs *qcs, struct buffer *buf, size_t count,
return ret;
}
int qcs_http_handle_standalone_fin(struct qcs *qcs)
{
struct buffer *appbuf;
struct htx *htx;
int eom;
if (!(appbuf = qcc_get_stream_rxbuf(qcs)))
goto err;
htx = htx_from_buf(appbuf);
eom = htx_set_eom(htx);
htx_to_buf(htx, appbuf);
if (!eom)
goto err;
return 0;
err:
return -1;
}
/* QUIC MUX snd_buf operation using HTX data. HTX data will be transferred from
* <buf> to <qcs> stream buffer. Input buffer is expected to be of length
* <count>. <fin> will be set to signal the last data to send for this stream.