From c93ebcc59b8b61d2f4dbcc1f74c2a9430ffa0681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Mon, 27 Nov 2023 17:04:32 +0100 Subject: [PATCH] REORG: quic: Move quic_build_post_handshake_frames() to quic_conn module Move quic_build_post_handshake_frames() from quic_rx.c to quic_conn.c. This is a function which is also called from the TX part (quic_tx.c). --- include/haproxy/quic_conn.h | 1 + include/haproxy/quic_tx.h | 1 - src/quic_conn.c | 94 +++++++++++++++++++++++++++++++++++++ src/quic_tx.c | 94 +------------------------------------ 4 files changed, 96 insertions(+), 94 deletions(-) diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 73d178940..af712a8d1 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -75,6 +75,7 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4, struct sockaddr_storage *local_addr, struct sockaddr_storage *peer_addr, int server, int token, void *owner); +int quic_build_post_handshake_frames(struct quic_conn *qc); const struct quic_version *qc_supported_version(uint32_t version); int quic_peer_validated_addr(struct quic_conn *qc); void qc_set_timer(struct quic_conn *qc); diff --git a/include/haproxy/quic_tx.h b/include/haproxy/quic_tx.h index dfe44a39a..8ec5d83bc 100644 --- a/include/haproxy/quic_tx.h +++ b/include/haproxy/quic_tx.h @@ -36,7 +36,6 @@ struct buffer *qc_get_txb(struct quic_conn *qc); int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels); int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx); int qc_may_probe_ipktns(struct quic_conn *qc); -int quic_build_post_handshake_frames(struct quic_conn *qc); int qc_send_app_pkts(struct quic_conn *qc, struct list *frms); int qc_dgrams_retransmit(struct quic_conn *qc); int qc_notify_send(struct quic_conn *qc); diff --git a/src/quic_conn.c b/src/quic_conn.c index 4d599fade..2c43d62d8 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -480,6 +480,100 @@ int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len, return ret; } +/* Build all the frames which must be sent just after the handshake have succeeded. + * This is essentially NEW_CONNECTION_ID frames. A QUIC server must also send + * a HANDSHAKE_DONE frame. + * Return 1 if succeeded, 0 if not. + */ +int quic_build_post_handshake_frames(struct quic_conn *qc) +{ + int ret = 0, max; + struct quic_enc_level *qel; + struct quic_frame *frm, *frmbak; + struct list frm_list = LIST_HEAD_INIT(frm_list); + struct eb64_node *node; + + TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); + + qel = qc->ael; + /* Only servers must send a HANDSHAKE_DONE frame. */ + if (qc_is_listener(qc)) { + frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE); + if (!frm) { + TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc); + goto leave; + } + + LIST_APPEND(&frm_list, &frm->list); + } + + /* Initialize connection IDs minus one: there is + * already one connection ID used for the current connection. Also limit + * the number of connection IDs sent to the peer to 4 (3 from this function + * plus 1 for the current connection. + * Note that active_connection_id_limit >= 2: this has been already checked + * when receiving this parameter. + */ + max = QUIC_MIN(qc->tx.params.active_connection_id_limit - 1, (uint64_t)3); + while (max--) { + struct quic_connection_id *conn_id; + + frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID); + if (!frm) { + TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc); + goto err; + } + + conn_id = new_quic_cid(qc->cids, qc, NULL, NULL); + if (!conn_id) { + qc_frm_free(qc, &frm); + TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc); + goto err; + } + + /* TODO To prevent CID tree locking, all CIDs created here + * could be allocated at the same time as the first one. + */ + quic_cid_insert(conn_id); + + quic_connection_id_to_frm_cpy(frm, conn_id); + LIST_APPEND(&frm_list, &frm->list); + } + + LIST_SPLICE(&qel->pktns->tx.frms, &frm_list); + qc->flags &= ~QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; + + ret = 1; + leave: + TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc); + return ret; + + err: + /* free the frames */ + list_for_each_entry_safe(frm, frmbak, &frm_list, list) + qc_frm_free(qc, &frm); + + /* The first CID sequence number value used to allocated CIDs by this function is 1, + * 0 being the sequence number of the CID for this connection. + */ + node = eb64_lookup_ge(qc->cids, 1); + while (node) { + struct quic_connection_id *conn_id; + + conn_id = eb64_entry(node, struct quic_connection_id, seq_num); + if (conn_id->seq_num.key >= max) + break; + + node = eb64_next(node); + quic_cid_delete(conn_id); + + eb64_delete(&conn_id->seq_num); + pool_free(pool_head_quic_connection_id, conn_id); + } + goto leave; +} + + /* QUIC connection packet handler task (post handshake) */ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state) { diff --git a/src/quic_tx.c b/src/quic_tx.c index c1beabd7f..5ac05713b 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -721,99 +722,6 @@ leave: return ret; } -/* Build all the frames which must be sent just after the handshake have succeeded. - * This is essentially NEW_CONNECTION_ID frames. A QUIC server must also send - * a HANDSHAKE_DONE frame. - * Return 1 if succeeded, 0 if not. - */ -int quic_build_post_handshake_frames(struct quic_conn *qc) -{ - int ret = 0, max; - struct quic_enc_level *qel; - struct quic_frame *frm, *frmbak; - struct list frm_list = LIST_HEAD_INIT(frm_list); - struct eb64_node *node; - - TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc); - - qel = qc->ael; - /* Only servers must send a HANDSHAKE_DONE frame. */ - if (qc_is_listener(qc)) { - frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE); - if (!frm) { - TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc); - goto leave; - } - - LIST_APPEND(&frm_list, &frm->list); - } - - /* Initialize connection IDs minus one: there is - * already one connection ID used for the current connection. Also limit - * the number of connection IDs sent to the peer to 4 (3 from this function - * plus 1 for the current connection. - * Note that active_connection_id_limit >= 2: this has been already checked - * when receiving this parameter. - */ - max = QUIC_MIN(qc->tx.params.active_connection_id_limit - 1, (uint64_t)3); - while (max--) { - struct quic_connection_id *conn_id; - - frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID); - if (!frm) { - TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc); - goto err; - } - - conn_id = new_quic_cid(qc->cids, qc, NULL, NULL); - if (!conn_id) { - qc_frm_free(qc, &frm); - TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc); - goto err; - } - - /* TODO To prevent CID tree locking, all CIDs created here - * could be allocated at the same time as the first one. - */ - quic_cid_insert(conn_id); - - quic_connection_id_to_frm_cpy(frm, conn_id); - LIST_APPEND(&frm_list, &frm->list); - } - - LIST_SPLICE(&qel->pktns->tx.frms, &frm_list); - qc->flags &= ~QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS; - - ret = 1; - leave: - TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc); - return ret; - - err: - /* free the frames */ - list_for_each_entry_safe(frm, frmbak, &frm_list, list) - qc_frm_free(qc, &frm); - - /* The first CID sequence number value used to allocated CIDs by this function is 1, - * 0 being the sequence number of the CID for this connection. - */ - node = eb64_lookup_ge(qc->cids, 1); - while (node) { - struct quic_connection_id *conn_id; - - conn_id = eb64_entry(node, struct quic_connection_id, seq_num); - if (conn_id->seq_num.key >= max) - break; - - node = eb64_next(node); - quic_cid_delete(conn_id); - - eb64_delete(&conn_id->seq_num); - pool_free(pool_head_quic_connection_id, conn_id); - } - goto leave; -} - /* Flush txbuf for connection. This must be called prior to a packet * preparation when txbuf contains older data. A send will be conducted for * these data.