MINOR: qmux: change API for snd_buf FIN transmission

Previous patches have fixes interim response encoding via
h3_resp_headers_send(). However, it is still necessary to adjust h3
layer state-machine so that several successive HTTP responses are
accepted for a single stream.

Prior to this, QMUX was responsible to decree that the final HTX message
was encoded so that FIN stream can be emitted. However, with interim
response, MUX is in fact unable to properly determine this. As such,
this is the responsibility of the application protocol layer. To reflect
this, app_ops snd_buf callback is modified so that a new output argument
<fin> is added to it.

Note that for now this commit does not bring any functional change.
However, it will be necessary for the following patch. As such, it
should be backported prior to it to every versions as necessary.
This commit is contained in:
Amaury Denoyelle 2025-07-10 15:27:23 +02:00
parent d8b34459b5
commit f349df44b4
4 changed files with 18 additions and 7 deletions

View File

@ -209,7 +209,7 @@ struct qcc_app_ops {
ssize_t (*rcv_buf)(struct qcs *qcs, struct buffer *b, int fin);
/* Convert HTX to HTTP payload for sending. */
size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count);
size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count, char *fin);
/* Negotiate and commit fast-forward data from opposite MUX. */
size_t (*nego_ff)(struct qcs *qcs, size_t count);

View File

@ -2635,11 +2635,14 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx,
* stream instance. Successfully transcoded HTX blocks are removed from input
* buffer.
*
* <fin> is used as an output boolean. It will be set if the last blocks of the
* HTX message were encoded, which should trigger a FIN STREAM emission.
*
* Returns the amount of consumed bytes from <buf>. In case of error,
* connection is flagged and transcoding is interrupted. The returned value is
* unchanged though.
*/
static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count)
static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, char *fin)
{
size_t total = 0;
enum htx_blk_type btype;
@ -2647,11 +2650,15 @@ static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count)
struct htx_blk *blk;
uint32_t bsize;
int32_t idx;
char eom;
int ret = 0;
TRACE_ENTER(H3_EV_STRM_SEND, qcs->qcc->conn, qcs);
*fin = 0;
htx = htx_from_buf(buf);
/* EOM is saved here, useful if 0-copy is performed with HTX buf. */
eom = htx->flags & HTX_FL_EOM;
while (count && !htx_is_empty(htx) && qcc_stream_can_send(qcs) && ret >= 0) {
idx = htx_get_head(htx);
@ -2752,6 +2759,10 @@ static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count)
#endif
out:
if (eom && htx_is_empty(htx)) {
TRACE_USER("transcoding last HTX message", H3_EV_STRM_SEND, qcs->qcc->conn, qcs);
*fin = 1;
}
htx_to_buf(htx, buf);
TRACE_LEAVE(H3_EV_STRM_SEND, qcs->qcc->conn, qcs);

View File

@ -161,7 +161,7 @@ static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
/* Returns the amount of consumed bytes from <buf>. */
static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
size_t count)
size_t count, char *fin)
{
enum htx_blk_type btype;
struct htx *htx = NULL;
@ -173,6 +173,7 @@ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
size_t total = 0;
int err;
*fin = 0;
htx = htx_from_buf(buf);
while (count && !htx_is_empty(htx) && qcc_stream_can_send(qcs)) {
@ -266,6 +267,8 @@ static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
}
end:
if (htx->flags & HTX_FL_EOM && htx_is_empty(htx))
*fin = 1;
htx_to_buf(htx, buf);
return total;

View File

@ -94,7 +94,6 @@ size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
{
struct htx *htx;
size_t ret;
int eom = 0;
TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
@ -108,9 +107,7 @@ size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
if (htx->extra && htx->extra == HTX_UNKOWN_PAYLOAD_LENGTH)
qcs->flags |= QC_SF_UNKNOWN_PL_LENGTH;
eom = (htx->flags & HTX_FL_EOM);
ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count);
*fin = (eom && !b_data(buf));
ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count, fin);
TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);