]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-quic: fix transfer of empty HTTP response
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 10 Jan 2023 09:41:41 +0000 (10:41 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 10 Jan 2023 15:44:53 +0000 (16:44 +0100)
QUIC stream did not transferred its response if it was an empty HTTP
response without headers nor entity body. This is caused by an
incomplete condition on qc_send() which skips streams with empty
<tx.buf>.

Fix this by extending the condition. Sending will be conducted on a
stream if <tx.buf> is not empty or FIN notification must be provided.
This allows to send the last STREAM frame for this stream.

Such HTTP responses should be extremely rare so this bug is labelled as
MINOR. It was encountered with a HTTP/0.9 request on an empty payload.
The bug was triggered as HTTP/0.9 does not support header in response
message.

Also, note that condition to wakeup MUX tasklet has been changed
similarly in qc_send_buf(). It is not mandatory to work properly
however, most probably because another tasklet_wakeup() is done
before/after.

This should be backported up to 2.6.

src/mux_quic.c

index e64480beb98943ab5ec9d9b82d14acd77f014dc0..3af85203699eb4e42c0e920e67dc5293f7591981 100644 (file)
@@ -1739,7 +1739,9 @@ static int qc_send(struct qcc *qcc)
                        continue;
                }
 
-               if (!b_data(&qcs->tx.buf) && !qc_stream_buf_get(qcs->stream)) {
+               /* Check if there is something to send. */
+               if (!b_data(&qcs->tx.buf) && !qcs_stream_fin(qcs) &&
+                   !qc_stream_buf_get(qcs->stream)) {
                        node = eb64_next(node);
                        continue;
                }
@@ -2293,7 +2295,7 @@ static size_t qc_send_buf(struct stconn *sc, struct buffer *buf,
        if (fin)
                qcs->flags |= QC_SF_FIN_STREAM;
 
-       if (ret) {
+       if (ret || fin) {
                if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
                        tasklet_wakeup(qcs->qcc->wait_event.tasklet);
        }