MINOR: mux-quic: refine reception of standalone STREAM FIN

Reception of standalone STREAM FIN is a corner case, which may be
difficult to handle. In particular, care must be taken to ensure app_ops
rcv_buf() is always called to be notify about FIN, even if Rx buffer is
empty or full demux flag is set. If this is the case, it could prevent
closure of QCS Rx channel.

To ensure this, rcv_buf() was systematically called if FIN was received,
with or without data payload. This could called unnecessary invokation
when FIN is transmitted with data and full demux flag is set, or data
are received out-of-order.

This patches improve qcc_recv() by detecting explicitely a standalone
FIN case. Thus, rcv_buf() is only forcefully called in this case and if
all data were already previously received.
This commit is contained in:
Amaury Denoyelle 2025-03-04 09:41:44 +01:00
parent 20dc8e4ec2
commit 7dd1eec2b1

View File

@ -1499,6 +1499,7 @@ int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops)
int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset, int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
char fin, char *data) char fin, char *data)
{ {
const int fin_standalone = (!len && fin);
struct qcs *qcs; struct qcs *qcs;
enum ncb_ret ret; enum ncb_ret ret;
@ -1627,7 +1628,8 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
qcs_close_remote(qcs); qcs_close_remote(qcs);
} }
if ((ncb_data(&qcs->rx.ncbuf, 0) && !(qcs->flags & QC_SF_DEM_FULL)) || fin) { if ((ncb_data(&qcs->rx.ncbuf, 0) && !(qcs->flags & QC_SF_DEM_FULL)) ||
unlikely(fin_standalone && qcs_is_close_remote(qcs))) {
qcc_decode_qcs(qcc, qcs); qcc_decode_qcs(qcc, qcs);
LIST_DEL_INIT(&qcs->el_recv); LIST_DEL_INIT(&qcs->el_recv);
qcc_refresh_timeout(qcc); qcc_refresh_timeout(qcc);