MINOR: quic: define a generic QUIC error type

Define a new structure quic_err to abstract a QUIC error type. This
allows to easily differentiate a transport and an application error
code. This simplifies error transmission from QUIC MUX and H3 layers.

This new type is defined in quic_frame module. It is used to replace
<err_code> field in <quic_conn>. QUIC_FL_CONN_APP_ALERT flag is removed
as it is now useless.

Utility functions are defined to be able to quickly instantiate
transport, tls and application errors.
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index 88cf4fd..d736dcb 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -438,8 +438,8 @@
 				              quic_enc_level_char(ssl_to_quic_enc_level(level)));
 			}
 
-			if (qc->err_code)
-				chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err_code);
+			if (qc->err.code)
+				chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err.code);
 		}
 
 		if (mask & (QUIC_EV_CONN_PRSFRM|QUIC_EV_CONN_BFRM)) {
@@ -1057,16 +1057,14 @@
 /* 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, int app)
+void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err)
 {
 	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;
+	qc->err.code = err.code;
+	qc->err.app  = err.app;
 }
 
 /* Set <alert> TLS alert as QUIC CRYPTO_ERROR error */
@@ -1076,7 +1074,7 @@
 		qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
 		HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
 	}
-	quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert, 0);
+	quic_set_connection_close(qc, quic_err_tls(alert));
 	qc->flags |= QUIC_FL_CONN_TLS_ALERT;
 	TRACE_PROTO("Alert set", QUIC_EV_CONN_SSLDATA, qc);
 }
@@ -4319,6 +4317,7 @@
 		qc->dcid.len = dcid->len;
 	}
 	qc->mux_state = QC_MUX_NULL;
+	qc->err = quic_err_transport(QC_ERR_NO_ERROR);
 
 	icid = new_quic_cid(&qc->cids, qc, 0);
 	if (!icid) {
@@ -6141,10 +6140,10 @@
 		len += QUIC_TLS_TAG_LEN;
 	/* CONNECTION_CLOSE frame */
 	if (cc) {
-		cc_frm.type = qc->flags & QUIC_FL_CONN_APP_ALERT ?
+		cc_frm.type = qc->err.app ?
 		  QUIC_FT_CONNECTION_CLOSE_APP : QUIC_FT_CONNECTION_CLOSE;
 
-		cc_frm.connection_close.error_code = qc->err_code;
+		cc_frm.connection_close.error_code = qc->err.code;
 		len += qc_frm_len(&cc_frm);
 	}
 	add_ping_frm = 0;
@@ -6441,8 +6440,7 @@
 	if (qcc_install_app_ops(qc->qcc, qc->app_ops)) {
 		TRACE_PROTO("Cannot install app layer", QUIC_EV_CONN_LPKT, qc);
 		/* prepare a CONNECTION_CLOSE frame */
-		qc->err_code = QC_ERR_APPLICATION_ERROR;
-		qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
+		quic_set_connection_close(qc, quic_err_transport(QC_ERR_APPLICATION_ERROR));
 		return -1;
 	}