MINOR: quic/mux-quic: define CONNECTION_CLOSE send API
Define an API to easily set a CONNECTION_CLOSE. This will mainly be
useful for the MUX when an error is detected which require to close the
whole connection.
On the MUX side, a new flag is added when a CONNECTION_CLOSE has been
prepared. This will disable add future send operations.
diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h
index 12b66eb..b2d0aad 100644
--- a/include/haproxy/mux_quic-t.h
+++ b/include/haproxy/mux_quic-t.h
@@ -26,8 +26,9 @@
QCS_MAX_TYPES
};
-#define QC_CF_BLK_MFCTL 0x00000001 /* sending blocked due to connection flow-control */
-#define QC_CF_CONN_FULL 0x00000002 /* no stream buffers available on connection */
+#define QC_CF_CC_EMIT 0x00000001 /* A CONNECTION_CLOSE is set by the MUX */
+#define QC_CF_BLK_MFCTL 0x00000002 /* sending blocked due to connection flow-control */
+#define QC_CF_CONN_FULL 0x00000004 /* no stream buffers available on connection */
struct qcc {
struct connection *conn;
diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h
index 9602b3a..ac6a8e2 100644
--- a/include/haproxy/xprt_quic.h
+++ b/include/haproxy/xprt_quic.h
@@ -1255,6 +1255,7 @@
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_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 5205f0a..0e3e2c2 100644
--- a/src/mux_quic.c
+++ b/src/mux_quic.c
@@ -102,6 +102,16 @@
#define TRACE_SOURCE &trace_qmux
INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
+/* Emit a CONNECTION_CLOSE with error <err>. This will interrupt all future
+ * send operations.
+ */
+static void qcc_emit_cc(struct qcc *qcc, int err)
+{
+ quic_set_connection_close(qcc->conn->handle.qc, err);
+ qcc->flags |= QC_CF_CC_EMIT;
+ tasklet_wakeup(qcc->wait_event.tasklet);
+}
+
/* Allocate a new QUIC streams with id <id> and type <type>. */
struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type)
{
@@ -1009,7 +1019,7 @@
TRACE_ENTER(QMUX_EV_QCC_SEND);
- if (qcc->conn->flags & CO_FL_SOCK_WR_SH) {
+ if (qcc->conn->flags & CO_FL_SOCK_WR_SH || qcc->flags & QC_CF_CC_EMIT) {
qcc->conn->flags |= CO_FL_ERROR;
TRACE_DEVEL("leaving on error", QMUX_EV_QCC_SEND, qcc->conn);
return 0;
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index f3bdddc..b2b1f60 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -1107,13 +1107,24 @@
return len == 0;
}
+/* 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)
+{
+ if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)
+ return;
+
+ qc->err_code = err;
+ qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
+}
/* 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);
- qc->err_code = QC_ERR_CRYPTO_ERROR | alert;
- qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE | QUIC_FL_CONN_TLS_ALERT;
+ quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert);
+ qc->flags |= QUIC_FL_CONN_TLS_ALERT;
TRACE_PROTO("Alert set", QUIC_EV_CONN_SSLDATA, qc);
}