]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: support CONNECTION_CLOSE_APP emission
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 23 May 2022 14:12:15 +0000 (16:12 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 25 May 2022 13:41:25 +0000 (15:41 +0200)
Complete quic-conn API for error reporting. A new parameter <app> is
defined in the function quic_set_connection_close(). This will transform
the frame into a CONNECTION_CLOSE_APP type.

This type of frame will be generated by the applicative layer, h3 or
hq-interop for the moment. A new function qcc_emit_cc_app() is exported
by the MUX layer for them.

include/haproxy/mux_quic.h
include/haproxy/xprt_quic-t.h
include/haproxy/xprt_quic.h
src/mux_quic.c
src/xprt_quic.c

index c9bb8bf5581ed10df35b5e6c9b30a9dd33262ca2..1d71abde8402ca43d747da6aea80774447e4cf43 100644 (file)
@@ -25,6 +25,7 @@ void qcs_notify_recv(struct qcs *qcs);
 void qcs_notify_send(struct qcs *qcs);
 void qcs_consume(struct qcs *qcs, uint64_t bytes);
 
+void qcc_emit_cc_app(struct qcc *qcc, int err);
 int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
              char fin, char *data);
 int qcc_recv_max_data(struct qcc *qcc, uint64_t max);
index a85b47c46a8651eca8cf57fa50e13486e9ad9ef5..5231583f40551824a8e6d5c74d814cab6ac5c1af 100644 (file)
@@ -684,10 +684,12 @@ enum qc_mux_state {
 #define QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT (1U << 2)
 #define QUIC_FL_CONN_LISTENER                    (1U << 3)
 #define QUIC_FL_CONN_ACCEPT_REGISTERED           (1U << 4)
+/* gap here */
 #define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
 #define QUIC_FL_CONN_RETRANS_NEEDED              (1U << 7)
 #define QUIC_FL_CONN_RETRANS_OLD_DATA            (1U << 8)
 #define QUIC_FL_CONN_TLS_ALERT                   (1U << 9)
+#define QUIC_FL_CONN_APP_ALERT                   (1U << 10) /* A connection error of type CONNECTION_CLOSE_APP must be emitted. */
 #define QUIC_FL_CONN_NOTIFY_CLOSE                (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */
 #define QUIC_FL_CONN_EXP_TIMER                   (1U << 28) /* timer has expired, quic-conn can be freed */
 #define QUIC_FL_CONN_CLOSING                     (1U << 29)
index ac6a8e269aa0dce1dff3121750793a5c4dd00f04..fa13c4cfae75eae7d82efd9c5c375c37c91a1ed8 100644 (file)
@@ -1255,7 +1255,7 @@ static inline void qc_list_all_rx_pkts(struct quic_conn *qc)
 
 void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
 
-void quic_set_connection_close(struct quic_conn *qc, int err);
+void quic_set_connection_close(struct quic_conn *qc, int err, int app);
 void quic_set_tls_alert(struct quic_conn *qc, int alert);
 int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len);
 struct task *quic_lstnr_dghdlr(struct task *t, void *ctx, unsigned int state);
index d744f91b361c1279a25d75b2cd935d204254aa23..91dffdf05b4ced6ca296e6fddd178c62b2520832 100644 (file)
@@ -106,7 +106,7 @@ INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
  */
 static void qcc_emit_cc(struct qcc *qcc, int err)
 {
-       quic_set_connection_close(qcc->conn->handle.qc, err);
+       quic_set_connection_close(qcc->conn->handle.qc, err, 0);
        qcc->flags |= QC_CF_CC_EMIT;
        tasklet_wakeup(qcc->wait_event.tasklet);
 }
@@ -445,6 +445,16 @@ static int qcc_decode_qcs(struct qcc *qcc, struct qcs *qcs)
        return 0;
 }
 
+/* Emit a CONNECTION_CLOSE_APP with error <err>. Reserved for application error
+ * code. This will interrupt all future send/receive operations.
+ */
+void qcc_emit_cc_app(struct qcc *qcc, int err)
+{
+       quic_set_connection_close(qcc->conn->handle.qc, err, 1);
+       qcc->flags |= QC_CF_CC_EMIT;
+       tasklet_wakeup(qcc->wait_event.tasklet);
+}
+
 /* Handle a new STREAM frame for stream with id <id>. Payload is pointed by
  * <data> with length <len> and represents the offset <offset>. <fin> is set if
  * the QUIC frame FIN bit is set.
index acb90bfe49d01c9ad9a7c45702cd70fe6696c173..b081c88fe1fe10da89fa751f952eb7c2bc05a1c1 100644 (file)
@@ -1109,20 +1109,23 @@ static int quic_crypto_data_cpy(struct quic_enc_level *qel,
 /* Prepare the emission of CONNECTION_CLOSE with error <err>. All send/receive
  * activity for <qc> will be interrupted.
  */
-void quic_set_connection_close(struct quic_conn *qc, int err)
+void quic_set_connection_close(struct quic_conn *qc, int err, int app)
 {
        if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)
                return;
 
        qc->err_code = err;
        qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
+
+       if (app)
+               qc->flags |= QUIC_FL_CONN_APP_ALERT;
 }
 
 /* Set <alert> TLS alert as QUIC CRYPTO_ERROR error */
 void quic_set_tls_alert(struct quic_conn *qc, int alert)
 {
        HA_ATOMIC_DEC(&qc->prx_counters->conn_opening);
-       quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert);
+       quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert, 0);
        qc->flags |= QUIC_FL_CONN_TLS_ALERT;
        TRACE_PROTO("Alert set", QUIC_EV_CONN_SSLDATA, qc);
 }
@@ -5985,7 +5988,7 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
        size_t len, len_sz, len_frms, padding_len;
        struct quic_frame frm = { .type = QUIC_FT_CRYPTO, };
        struct quic_frame ack_frm = { .type = QUIC_FT_ACK, };
-       struct quic_frame cc_frm = { . type = QUIC_FT_CONNECTION_CLOSE, };
+       struct quic_frame cc_frm = { };
        size_t ack_frm_len, head_len;
        int64_t rx_largest_acked_pn;
        int add_ping_frm;
@@ -6084,9 +6087,10 @@ static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
                len += QUIC_TLS_TAG_LEN;
        /* CONNECTION_CLOSE frame */
        if (cc) {
-               struct quic_connection_close *cc = &cc_frm.connection_close;
+               cc_frm.type = qc->flags & QUIC_FL_CONN_APP_ALERT ?
+                 QUIC_FT_CONNECTION_CLOSE_APP : QUIC_FT_CONNECTION_CLOSE;
 
-               cc->error_code = qc->err_code;
+               cc_frm.connection_close.error_code = qc->err_code;
                len += qc_frm_len(&cc_frm);
        }
        add_ping_frm = 0;