]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Send STOP_SENDING frames if mux is released
authorFrédéric Lécaille <flecaille@haproxy.com>
Sun, 29 May 2022 09:36:03 +0000 (11:36 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 30 May 2022 07:59:26 +0000 (09:59 +0200)
If the connection client timeout has expired, the mux is released.
If the client decides to initiate a new request, we do not ack its
request. This leads the client to endlessly sent it request.

This patch makes a QUIC listener send a STOP_SENDING frame in such
a situation.

src/xprt_quic.c

index 16478d7d9eeb149058864d51605482eccfe4fd77..115339eeeceaac7732e13b3cb87e44508759ce26 100644 (file)
@@ -2379,6 +2379,35 @@ static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
        }
 }
 
+/* Enqueue a STOP_SENDING frame to send into 1RTT packet number space
+ * frame list to send.
+ * Return 1 if succeeded, 0 if not.
+ */
+static int qc_stop_sending_frm_enqueue(struct quic_conn *qc, uint64_t id)
+{
+       struct quic_frame *frm;
+       struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
+       uint64_t app_error_code;
+
+       /* TODO: the mux may be released, we cannot have more
+        * information about the application error code to send
+        * at this time.
+        */
+       app_error_code = H3_REQUEST_REJECTED;
+
+       frm = pool_zalloc(pool_head_quic_frame);
+       if (!frm)
+               return 0;
+
+       frm->type = QUIC_FT_STOP_SENDING;
+       frm->stop_sending.id = id;
+       frm->stop_sending.app_error_code = app_error_code;
+       LIST_INIT(&frm->reflist);
+       LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
+
+       return 1;
+}
+
 /* Parse all the frames of <pkt> QUIC packet for QUIC connection with <ctx>
  * as I/O handler context and <qel> as encryption level.
  * Returns 1 if succeeded, 0 if failed.
@@ -2521,6 +2550,9 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
                                }
                                else {
                                        TRACE_PROTO("Stream not found", QUIC_EV_CONN_PRSHPKT, qc);
+                                       if (!qc_stop_sending_frm_enqueue(qc, stream->id))
+                                               TRACE_PROTO("could not enqueue STOP_SENDING frame", QUIC_EV_CONN_PRSHPKT, qc);
+
                                        goto err;
                                }
                        }