diff --git a/src/quic_conn.c b/src/quic_conn.c index cf0d6f2ab..88adc84f8 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -1108,9 +1108,9 @@ struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state) * into the Retry token sent to the client before instantiated this connection. * Endpoints addresses are specified via and . * Returns the connection if succeeded, NULL if not. - * For QUIC clients, , , , must be null, - * and value must be 0. This is the responsibility of the caller to ensure - * this is the case. + * For QUIC clients, , and must be null, and + * value must be 0. This is the responsibility of the caller to ensure this is + * the case. */ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, struct quic_cid *dcid, struct quic_cid *scid, @@ -1243,8 +1243,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, } /* QUIC Client (outgoing connection to servers) */ else { - struct quic_connection_id *conn_cid = NULL; - qc->flags = QUIC_FL_CONN_IS_BACK|QUIC_FL_CONN_PEER_VALIDATED_ADDR; /* Duplicate GSO status on server to connection */ if (HA_ATOMIC_LOAD(&srv->flags) & SRV_F_UDP_GSO_NOTSUPP) @@ -1263,26 +1261,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, memcpy(&qc->odcid, qc->dcid.data, sizeof(qc->dcid.data)); qc->odcid.len = qc->dcid.len; - conn_cid = quic_cid_alloc(); - if (!conn_cid) { - TRACE_ERROR("error on CID allocation", QUIC_EV_CONN_INIT, qc); - goto err; - } - - if (quic_cid_generate_random(conn_cid)) { - TRACE_ERROR("error on CID generation", QUIC_EV_CONN_INIT, qc); - pool_free(pool_head_quic_connection_id, conn_cid); - goto err; - } - - if (quic_cid_insert(conn_cid, NULL)) { - pool_free(pool_head_quic_connection_id, conn_cid); - goto err; - } - - quic_cid_register_seq_num(conn_cid, qc); dcid = &qc->dcid; - conn_id = conn_cid; } qc->err = quic_err_transport(QC_ERR_NO_ERROR); @@ -1420,15 +1399,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, return qc; err: - if (!l && !conn_id) { - /* For QUIC clients, is locally used and initialized to - * value as soon as this latter is attached to the CIDs tree. It must - * be freed only if it has not been attached to this tree. This is - * quic_conn_release() which free this CID when it is attached to the tree. - */ - pool_free(pool_head_quic_connection_id, conn_id); - } - quic_conn_release(qc); /* Decrement global counters. Done only for errors happening before or diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 5ab196a3b..7c21cd71d 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -125,26 +125,56 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx) { int ret = -1; struct quic_conn *qc = NULL; + struct quic_connection_id *conn_id; TRACE_ENTER(QUIC_EV_CONN_NEW, qc); if (objt_listener(conn->target)) { qc = conn->handle.qc; + if (!qc) + goto out; } else { + int retry_rand_cid = 3; /* Number of random retries on CID collision. */ int ipv4 = conn->dst->ss_family == AF_INET; struct server *srv = objt_server(conn->target); - qc = qc_new_conn(quic_version_1, ipv4, NULL, NULL, NULL, - NULL, NULL, &srv->addr, 0, srv); - if (qc) { - conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; - conn->handle.qc = qc; - qc->conn = conn; - } - } - if (!qc) - goto out; + conn_id = quic_cid_alloc(); + if (!conn_id) { + TRACE_ERROR("error on CID allocation", QUIC_EV_CONN_NEW); + goto out; + } + + while (retry_rand_cid--) { + if (quic_cid_generate_random(conn_id)) { + TRACE_ERROR("error on CID generation", QUIC_EV_CONN_NEW); + pool_free(pool_head_quic_connection_id, conn_id); + goto out; + } + + if (quic_cid_insert(conn_id, NULL) == 0) + break; + } + + if (retry_rand_cid < 0) { + TRACE_ERROR("CID pool exhausted", QUIC_EV_CONN_NEW); + pool_free(pool_head_quic_connection_id, conn_id); + goto out; + } + + qc = qc_new_conn(quic_version_1, ipv4, NULL, NULL, NULL, + conn_id, NULL, &srv->addr, 0, srv); + if (!qc) { + pool_free(pool_head_quic_connection_id, conn_id); + goto out; + } + + quic_cid_register_seq_num(conn_id, qc); + + conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; + conn->handle.qc = qc; + qc->conn = conn; + } ret = 0; /* Ensure thread connection migration is finalized ASAP. */