MINOR: quic: Atomically get/set the connection state

As ->state quic_conn struct member field is shared between threads
we must atomically get and set its value.
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index 04c4722..96b6a47 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -594,7 +594,7 @@
 
 	if ((qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->flags & QUIC_FL_PKTNS_ACK_RECEIVED) ||
 	    (qc->els[QUIC_TLS_ENC_LEVEL_APP].pktns->flags & QUIC_FL_PKTNS_ACK_RECEIVED) ||
-	    (qc->state & QUIC_HS_ST_COMPLETE))
+	    HA_ATOMIC_LOAD(&qc->state) >= QUIC_HS_ST_COMPLETE)
 		return 1;
 
 	return 0;
@@ -608,6 +608,7 @@
 	struct quic_conn *qc;
 	struct quic_pktns *pktns;
 	unsigned int pto;
+	int handshake_complete;
 
 	TRACE_ENTER(QUIC_EV_CONN_STIMER, ctx->conn,
 	            NULL, NULL, &ctx->conn->qc->path->ifae_pkts);
@@ -629,7 +630,8 @@
 		goto out;
 	}
 
-	pktns = quic_pto_pktns(qc, qc->state & QUIC_HS_ST_COMPLETE, &pto);
+	handshake_complete = HA_ATOMIC_LOAD(&qc->state) >= QUIC_HS_ST_COMPLETE;
+	pktns = quic_pto_pktns(qc, handshake_complete, &pto);
 	if (tick_isset(pto))
 		qc->timer = pto;
  out:
@@ -1495,7 +1497,7 @@
                                    struct quic_rx_packet *pkt,
                                    struct quic_rx_crypto_frm *cf)
 {
-	int ssl_err;
+	int ssl_err, state;
 	struct quic_conn *qc;
 
 	TRACE_ENTER(QUIC_EV_CONN_SSLDATA, ctx->conn);
@@ -1511,43 +1513,44 @@
 	TRACE_PROTO("in order CRYPTO data",
 	            QUIC_EV_CONN_SSLDATA, ctx->conn,, cf, ctx->ssl);
 
-	if (qc->state < QUIC_HS_ST_COMPLETE) {
+	state = HA_ATOMIC_LOAD(&qc->state);
+	if (state < QUIC_HS_ST_COMPLETE) {
 		ssl_err = SSL_do_handshake(ctx->ssl);
 		if (ssl_err != 1) {
 			ssl_err = SSL_get_error(ctx->ssl, ssl_err);
 			if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
 				TRACE_PROTO("SSL handshake",
-				            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+				            QUIC_EV_CONN_HDSHK, ctx->conn, &state, &ssl_err);
 				goto out;
 			}
 
 			TRACE_DEVEL("SSL handshake error",
-			            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+			            QUIC_EV_CONN_HDSHK, ctx->conn, &state, &ssl_err);
 			goto err;
 		}
 
-		TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state);
+		TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_HDSHK, ctx->conn, &state);
 		if (objt_listener(ctx->conn->target))
-			qc->state = QUIC_HS_ST_CONFIRMED;
+			HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_CONFIRMED);
 		else
-			qc->state = QUIC_HS_ST_COMPLETE;
+			HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_COMPLETE);
 	} else {
 		ssl_err = SSL_process_quic_post_handshake(ctx->ssl);
 		if (ssl_err != 1) {
 			ssl_err = SSL_get_error(ctx->ssl, ssl_err);
 			if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
 				TRACE_DEVEL("SSL post handshake",
-				            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+				            QUIC_EV_CONN_HDSHK, ctx->conn, &state, &ssl_err);
 				goto out;
 			}
 
 			TRACE_DEVEL("SSL post handshake error",
-			            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+			            QUIC_EV_CONN_HDSHK, ctx->conn, &state, &ssl_err);
 			goto err;
 		}
 
 		TRACE_PROTO("SSL post handshake succeeded",
-		            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state);
+		            QUIC_EV_CONN_HDSHK, ctx->conn, &state);
 	}
 
  out:
@@ -1938,7 +1941,7 @@
 			if (objt_listener(ctx->conn->target))
 				goto err;
 
-			conn->state = QUIC_HS_ST_CONFIRMED;
+			HA_ATOMIC_STORE(&conn->state, QUIC_HS_ST_CONFIRMED);
 			break;
 		default:
 			goto err;
@@ -1949,12 +1952,12 @@
 	 * has successfully parse a Handshake packet. The Initial encryption must also
 	 * be discarded.
 	 */
-	if (conn->state == QUIC_HS_ST_SERVER_INITIAL &&
+	if (HA_ATOMIC_LOAD(&conn->state) == QUIC_HS_ST_SERVER_INITIAL &&
 	    pkt->type == QUIC_PACKET_TYPE_HANDSHAKE) {
 		quic_tls_discard_keys(&conn->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
 		quic_pktns_discard(conn->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, conn);
 		qc_set_timer(ctx);
-		conn->state = QUIC_HS_ST_SERVER_HANDSHAKE;
+		HA_ATOMIC_STORE(&conn->state, QUIC_HS_ST_SERVER_HANDSHAKE);
 	}
 
 	TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, ctx->conn);
@@ -2004,7 +2007,7 @@
 
 	TRACE_ENTER(QUIC_EV_CONN_PHPKTS, ctx->conn);
 	qc = ctx->conn->qc;
-	if (!quic_get_tls_enc_levels(&tel, &next_tel, qc->state)) {
+	if (!quic_get_tls_enc_levels(&tel, &next_tel, HA_ATOMIC_LOAD(&qc->state))) {
 		TRACE_DEVEL("unknown enc. levels", QUIC_EV_CONN_PHPKTS, ctx->conn);
 		goto err;
 	}
@@ -2088,12 +2091,12 @@
 			/* Discard the Initial encryption keys as soon as
 			 * a handshake packet could be built.
 			 */
-			if (qc->state == QUIC_HS_ST_CLIENT_INITIAL &&
+			if (HA_ATOMIC_LOAD(&qc->state) == QUIC_HS_ST_CLIENT_INITIAL &&
 			    pkt_type == QUIC_PACKET_TYPE_HANDSHAKE) {
 				quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
 				quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc);
 				qc_set_timer(ctx);
-				qc->state = QUIC_HS_ST_CLIENT_HANDSHAKE;
+				HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_CLIENT_HANDSHAKE);
 			}
 			/* Special case for Initial packets: when they have all
 			 * been sent, select the next level.
@@ -2478,7 +2481,7 @@
 	app_qel = &ctx->conn->qc->els[QUIC_TLS_ENC_LEVEL_APP];
 	/* A server must not process incoming 1-RTT packets before the handshake is complete. */
 	if (el == app_qel && objt_listener(ctx->conn->target) &&
-	    ctx->conn->qc->state < QUIC_HS_ST_COMPLETE) {
+	    HA_ATOMIC_LOAD(&ctx->conn->qc->state) < QUIC_HS_ST_COMPLETE) {
 		TRACE_PROTO("hp not removed (handshake not completed)",
 		            QUIC_EV_CONN_ELRMHP, ctx->conn);
 		goto out;
@@ -2622,9 +2625,10 @@
 	ctx = context;
 	qc = ctx->conn->qc;
 	qr = NULL;
-	TRACE_ENTER(QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state);
+	st = HA_ATOMIC_LOAD(&qc->state);
+	TRACE_ENTER(QUIC_EV_CONN_HDSHK, ctx->conn, &st);
 	ssl_err = SSL_ERROR_NONE;
-	if (!quic_get_tls_enc_levels(&tel, &next_tel, qc->state))
+	if (!quic_get_tls_enc_levels(&tel, &next_tel, st))
 		goto err;
 
 	qel = &qc->els[tel];
@@ -2674,15 +2678,14 @@
 		goto next_level;
 	}
 
- out:
 	MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
-	TRACE_LEAVE(QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state);
+	TRACE_LEAVE(QUIC_EV_CONN_HDSHK, ctx->conn, &st);
 	return t;
 
  err:
 	if (qr)
 		MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
-	TRACE_DEVEL("leaving in error", QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+	TRACE_DEVEL("leaving in error", QUIC_EV_CONN_HDSHK, ctx->conn, &st, &ssl_err);
 	return t;
 }
 
@@ -2768,7 +2771,7 @@
 	struct ssl_sock_ctx *conn_ctx;
 	struct quic_conn *qc;
 	struct quic_pktns *pktns;
-
+	int st;
 
 	conn_ctx = task->context;
 	qc = conn_ctx->conn->qc;
@@ -2786,11 +2789,12 @@
 		goto out;
 	}
 
+	st = HA_ATOMIC_LOAD(&qc->state);
 	if (qc->path->in_flight) {
-		pktns = quic_pto_pktns(qc, qc->state >= QUIC_HS_ST_COMPLETE, NULL);
+		pktns = quic_pto_pktns(qc, st >= QUIC_HS_ST_COMPLETE, NULL);
 		pktns->tx.pto_probe = 1;
 	}
-	else if (objt_server(qc->conn->target) && qc->state <= QUIC_HS_ST_COMPLETE) {
+	else if (objt_server(qc->conn->target) && st <= QUIC_HS_ST_COMPLETE) {
 		struct quic_enc_level *iel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
 		struct quic_enc_level *hel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
 
@@ -2837,7 +2841,7 @@
 	if (server) {
 		struct listener *l = owner;
 
-		qc->state = QUIC_HS_ST_SERVER_INITIAL;
+		HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_SERVER_INITIAL);
 		/* Copy the initial DCID. */
 		qc->odcid.len = dcid_len;
 		if (qc->odcid.len)
@@ -2851,7 +2855,7 @@
 	}
 	/* QUIC Client (outgoing connection to servers) */
 	else {
-		qc->state = QUIC_HS_ST_CLIENT_INITIAL;
+		HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_CLIENT_INITIAL);
 		if (dcid_len)
 			memcpy(qc->dcid.data, dcid, dcid_len);
 		qc->dcid.len = dcid_len;
@@ -3000,7 +3004,8 @@
 	}
 
 	if (((*qel)->tls_ctx.rx.flags & QUIC_FL_TLS_SECRETS_SET) &&
-	    (tel != QUIC_TLS_ENC_LEVEL_APP || ctx->conn->qc->state >= QUIC_HS_ST_COMPLETE))
+	    (tel != QUIC_TLS_ENC_LEVEL_APP ||
+	     HA_ATOMIC_LOAD(&ctx->conn->qc->state) >= QUIC_HS_ST_COMPLETE))
 		return 1;
 
 	return 0;
@@ -4276,14 +4281,15 @@
 		SSL_set_connect_state(ctx->ssl);
 		ssl_err = SSL_do_handshake(ctx->ssl);
 		if (ssl_err != 1) {
+			int st;
+
+			st = HA_ATOMIC_LOAD(&qc->state);
 			ssl_err = SSL_get_error(ctx->ssl, ssl_err);
 			if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
-				TRACE_PROTO("SSL handshake",
-				            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+				TRACE_PROTO("SSL handshake", QUIC_EV_CONN_HDSHK, ctx->conn, &st, &ssl_err);
 			}
 			else {
-				TRACE_DEVEL("SSL handshake error",
-				            QUIC_EV_CONN_HDSHK, ctx->conn, &qc->state, &ssl_err);
+				TRACE_DEVEL("SSL handshake error", QUIC_EV_CONN_HDSHK, ctx->conn, &st, &ssl_err);
 				goto err;
 			}
 		}