diff --git a/include/haproxy/qmux_http.h b/include/haproxy/qmux_http.h index 218bd012c..e016be354 100644 --- a/include/haproxy/qmux_http.h +++ b/include/haproxy/qmux_http.h @@ -13,6 +13,7 @@ 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); +size_t qcs_http_reset_buf(struct qcs *qcs, struct buffer *buf, size_t count); #endif /* USE_QUIC */ diff --git a/src/mux_quic.c b/src/mux_quic.c index 2db2e3320..7816b63ab 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -4077,9 +4077,6 @@ static size_t qmux_strm_snd_buf(struct stconn *sc, struct buffer *buf, TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); - /* Sending forbidden if QCS is locally closed (FIN or RESET_STREAM sent). */ - BUG_ON(qcs_is_close_local(qcs) || (qcs->flags & QC_SF_TO_RESET)); - /* stream layer has been detached so no transfer must occur after. */ BUG_ON_HOT(qcs->flags & QC_SF_DETACH); @@ -4090,6 +4087,12 @@ static size_t qmux_strm_snd_buf(struct stconn *sc, struct buffer *buf, goto end; } + /* Cannot emit data after FIN/RESET_STREAM, drain extra payload. */ + if (qcs_is_close_local(qcs) || (qcs->flags & QC_SF_TO_RESET)) { + ret = qcs_http_reset_buf(qcs, buf, count); + goto end; + } + if (LIST_INLIST(&qcs->el_buf)) { TRACE_DEVEL("leaving on no buf avail", QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); goto end; @@ -4145,9 +4148,6 @@ static size_t qmux_strm_nego_ff(struct stconn *sc, struct buffer *input, TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); - /* Sending forbidden if QCS is locally closed (FIN or RESET_STREAM sent). */ - BUG_ON(qcs_is_close_local(qcs) || (qcs->flags & QC_SF_TO_RESET)); - /* stream layer has been detached so no transfer must occur after. */ BUG_ON_HOT(qcs->flags & QC_SF_DETACH); diff --git a/src/qmux_http.c b/src/qmux_http.c index b5494ad29..d67ed4b93 100644 --- a/src/qmux_http.c +++ b/src/qmux_http.c @@ -102,3 +102,23 @@ size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, return ret; } + +/* QUIC MUX snd_buf reset. HTX data stored in of length will be + * cleared. This can be used when data should not be transmitted any longer. + * + * Return the size in bytes of cleared data. + */ +size_t qcs_http_reset_buf(struct qcs *qcs, struct buffer *buf, size_t count) +{ + struct htx *htx; + + TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); + + htx = htx_from_buf(buf); + htx_reset(htx); + htx_to_buf(htx, buf); + + TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs); + + return count; +}