From f9e190e49ab2859eade317734261b7c22d0fe83d Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 23 May 2022 16:12:15 +0200 Subject: [PATCH] MINOR: quic: support CONNECTION_CLOSE_APP emission Complete quic-conn API for error reporting. A new parameter 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 | 1 + include/haproxy/xprt_quic-t.h | 2 ++ include/haproxy/xprt_quic.h | 2 +- src/mux_quic.c | 12 +++++++++++- src/xprt_quic.c | 14 +++++++++----- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index c9bb8bf55..1d71abde8 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -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); diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index a85b47c46..5231583f4 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -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) diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h index ac6a8e269..fa13c4cfa 100644 --- a/include/haproxy/xprt_quic.h +++ b/include/haproxy/xprt_quic.h @@ -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); diff --git a/src/mux_quic.c b/src/mux_quic.c index d744f91b3..91dffdf05 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -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 . 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 . Payload is pointed by * with length and represents the offset . is set if * the QUIC frame FIN bit is set. diff --git a/src/xprt_quic.c b/src/xprt_quic.c index acb90bfe4..b081c88fe 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -1109,20 +1109,23 @@ static int quic_crypto_data_cpy(struct quic_enc_level *qel, /* Prepare the emission of CONNECTION_CLOSE with error . All send/receive * activity for 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 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;