* into the Retry token sent to the client before instantiated this connection.
* Endpoints addresses are specified via <local_addr> and <peer_addr>.
* Returns the connection if succeeded, NULL if not.
- * For QUIC clients, <dcid>, <scid>, <token_odcid>, <conn_id> must be null,
- * and <token> value must be 0. This is the responsibility of the caller to ensure
- * this is the case.
+ * For QUIC clients, <dcid>, <scid> and <token_odcid> must be null, and <token>
+ * 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,
}
/* 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)
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);
return qc;
err:
- if (!l && !conn_id) {
- /* For QUIC clients, <conn_id> is locally used and initialized to <conn_cid>
- * 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
{
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);
+
+ 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,
- 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;
+ conn_id, NULL, &srv->addr, 0, srv);
+ if (!qc) {
+ pool_free(pool_head_quic_connection_id, conn_id);
+ goto out;
}
- }
- if (!qc)
- 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. */