]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: also send RESET_STREAM if MUX released
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 20 Feb 2023 09:31:27 +0000 (10:31 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 20 Feb 2023 09:52:51 +0000 (10:52 +0100)
When the MUX is freed, the quic-conn layer may stay active until all
streams acknowledgment are processed. In this interval, if a new stream
is opened by the client, the quic-conn is thus now responsible to handle
it. This is done by the emission of a STOP_SENDING.

This process has been completed to also emit a RESET_STREAM with the
same error code H3_REQUEST_REJECTED. This is done to conform with the H3
specification to invite the client to retry its request on a new
connection.

This should be backported up to 2.6.

src/quic_conn.c

index 4b1d56ccec0a659768133dfa9679994ece8a5beb..81b111903fe646c6bd6009f548fcdc43122be96a 100644 (file)
@@ -2699,7 +2699,7 @@ static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
 
 /* Cancel a request on connection <qc> for stream id <id>. This is useful when
  * the client opens a new stream but the MUX has already been released. A
- * STOP_SENDING frame is prepared for emission.
+ * STOP_SENDING + RESET_STREAM frames are prepared for emission.
  *
  * TODO this function is closely related to H3. Its place should be in H3 layer
  * instead of quic-conn but this requires an architecture adjustment.
@@ -2709,7 +2709,7 @@ static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
 static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
 {
        int ret = 0;
-       struct quic_frame *frm;
+       struct quic_frame *ss, *rs;
        struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
        const uint64_t app_error_code = H3_REQUEST_REJECTED;
 
@@ -2724,15 +2724,28 @@ static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
                goto out;
        }
 
-       frm = qc_frm_alloc(QUIC_FT_STOP_SENDING);
-       if (!frm) {
+       ss = qc_frm_alloc(QUIC_FT_STOP_SENDING);
+       if (!ss) {
                TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
                goto out;
        }
 
-       frm->stop_sending.id = id;
-       frm->stop_sending.app_error_code = app_error_code;
-       LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
+       ss->stop_sending.id = id;
+       ss->stop_sending.app_error_code = app_error_code;
+
+       rs = qc_frm_alloc(QUIC_FT_RESET_STREAM);
+       if (!rs) {
+               TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
+               qc_frm_free(&ss);
+               goto out;
+       }
+
+       rs->reset_stream.id = id;
+       rs->reset_stream.app_error_code = app_error_code;
+       rs->reset_stream.final_size = 0;
+
+       LIST_APPEND(&qel->pktns->tx.frms, &ss->list);
+       LIST_APPEND(&qel->pktns->tx.frms, &rs->list);
        ret = 1;
  out:
        TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);