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).
This commit is contained in:
Frédéric Lécaille 2023-11-27 17:04:32 +01:00
parent 3482455ddd
commit c93ebcc59b
4 changed files with 96 additions and 94 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 <max> 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)
{

View File

@ -17,6 +17,7 @@
#include <haproxy/pool.h>
#include <haproxy/trace.h>
#include <haproxy/quic_cid.h>
#include <haproxy/quic_conn.h>
#include <haproxy/quic_sock.h>
#include <haproxy/quic_tls.h>
#include <haproxy/quic_trace.h>
@ -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 <max> 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 <qc> connection. This must be called prior to a packet
* preparation when txbuf contains older data. A send will be conducted for
* these data.