Skip to content

Commit de91aca

Browse files
committed
MEDIUM: quic/mux-quic: adjust app-ops install
This patch adapts the installation of app-ops layer by QUIC MUX. Previously, app_ops field was stored directly into the quic_conn structure. The MUX reused it directly during qmux_init(). This patch removes app_ops field from quic_conn and replaces it with a copy of the negotiated ALPN. By using quic_alpn_to_app_ops(), it ensures it remains compatible with a known application layer. On the MUX layer, qcc_install_app_ops() now uses the standard conn_get_alpn() to retrieve the ALPN from the transport layer. This is done via the newly defined <get_alpn> QUIC xprt callback. This new architecture should be cleaner as it better highlights the responsibility of each layers in the ALPN/app negotiation.
1 parent 6efe60a commit de91aca

File tree

11 files changed

+61
-24
lines changed

11 files changed

+61
-24
lines changed

include/haproxy/mux_quic-t.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ enum qcc_app_ops_close_side {
200200

201201
/* QUIC application layer operations */
202202
struct qcc_app_ops {
203+
const char *alpn;
204+
203205
/* Initialize <qcc> connection app context. */
204206
int (*init)(struct qcc *qcc);
205207
/* Finish connection initialization if prelude required. */

include/haproxy/mux_quic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static inline char *qcs_st_to_str(enum qcs_state st)
9191
}
9292
}
9393

94-
int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops);
94+
int qcc_install_app_ops(struct qcc *qcc);
9595

9696
/* Register <qcs> stream for http-request timeout. If the stream is not yet
9797
* attached in the configured delay, qcc timeout task will be triggered. This

include/haproxy/quic_conn-t.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ struct quic_conn {
400400

401401
struct eb_root streams_by_id; /* qc_stream_desc tree */
402402

403+
const char *alpn;
404+
403405
/* MUX */
404406
struct qcc *qcc;
405407
struct task *timer_task;
@@ -408,7 +410,6 @@ struct quic_conn {
408410
/* Handshake expiration date */
409411
unsigned int hs_expire;
410412

411-
const struct qcc_app_ops *app_ops;
412413
int (*request_reject)(struct list *out, uint64_t stream_id);
413414
/* Proxy counters */
414415
struct quic_counters *prx_counters;

include/haproxy/quic_conn.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ static inline void *qc_counters(enum obj_type *o, const struct stats_module *m)
204204
void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
205205
void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err);
206206
void quic_set_tls_alert(struct quic_conn *qc, int alert);
207-
int quic_set_app_ops(struct quic_conn *qc, const char *alpn, int alpn_len);
207+
int qc_register_alpn(struct quic_conn *qc, const char *alpn, int alpn_len);
208208
int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len);
209209

210210
void qc_notify_err(struct quic_conn *qc);

src/h3.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,6 +3398,8 @@ int h3_reject(struct list *out, uint64_t id)
33983398

33993399
/* HTTP/3 application layer operations */
34003400
const struct qcc_app_ops h3_ops = {
3401+
.alpn = "h3",
3402+
34013403
.init = h3_init,
34023404
.finalize = h3_finalize,
34033405
.attach = h3_attach,

src/hq_interop.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ static int hq_interop_attach(struct qcs *qcs, void *conn_ctx)
324324
}
325325

326326
const struct qcc_app_ops hq_interop_ops = {
327+
.alpn = "hq-interop",
328+
327329
.rcv_buf = hq_interop_rcv_buf,
328330
.snd_buf = hq_interop_snd_buf,
329331
.nego_ff = hq_interop_nego_ff,

src/mux_quic.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,26 +1688,38 @@ void qcc_abort_stream_read(struct qcs *qcs)
16881688
TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn, qcs);
16891689
}
16901690

1691-
/* Install the <app_ops> applicative layer of a QUIC connection on mux <qcc>.
1691+
/* Install the applicative layer of a QUIC connection on mux <qcc>.
16921692
* Returns 0 on success else non-zero.
16931693
*/
1694-
int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops)
1694+
int qcc_install_app_ops(struct qcc *qcc)
16951695
{
1696-
TRACE_ENTER(QMUX_EV_QCC_NEW, qcc->conn);
1696+
struct connection *conn = qcc->conn;
1697+
const struct qcc_app_ops *app_ops;
1698+
const char *alpn;
1699+
int alpn_len;
1700+
1701+
TRACE_ENTER(QMUX_EV_QCC_NEW, conn);
1702+
1703+
if (!conn_get_alpn(conn, &alpn, &alpn_len))
1704+
goto err;
1705+
1706+
app_ops = quic_alpn_to_app_ops(alpn, alpn_len);
1707+
if (!app_ops)
1708+
goto err;
16971709

16981710
if (app_ops->init && !app_ops->init(qcc)) {
1699-
TRACE_ERROR("application layer install error", QMUX_EV_QCC_NEW, qcc->conn);
1711+
TRACE_ERROR("application layer install error", QMUX_EV_QCC_NEW, conn);
17001712
goto err;
17011713
}
17021714

1703-
TRACE_PROTO("application layer installed", QMUX_EV_QCC_NEW, qcc->conn);
1715+
TRACE_PROTO("application layer installed", QMUX_EV_QCC_NEW, conn);
17041716
qcc->app_ops = app_ops;
17051717

1706-
TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn);
1718+
TRACE_LEAVE(QMUX_EV_QCC_NEW, conn);
17071719
return 0;
17081720

17091721
err:
1710-
TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn);
1722+
TRACE_LEAVE(QMUX_EV_QCC_NEW, conn);
17111723
return 1;
17121724
}
17131725

@@ -3740,7 +3752,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
37403752
/* Register conn as app_ops may use it. */
37413753
qcc->conn = conn;
37423754

3743-
if (qcc_install_app_ops(qcc, conn->handle.qc->app_ops)) {
3755+
if (qcc_install_app_ops(qcc)) {
37443756
TRACE_PROTO("Cannot install app layer", QMUX_EV_QCC_NEW|QMUX_EV_QCC_ERR, conn);
37453757
goto err;
37463758
}

src/quic_conn.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,21 +267,23 @@ void quic_set_tls_alert(struct quic_conn *qc, int alert)
267267
TRACE_LEAVE(QUIC_EV_CONN_SSLALERT, qc);
268268
}
269269

270-
/* Set the application for <qc> QUIC connection.
271-
* Return 1 if succeeded, 0 if not.
270+
/* Register the negotiated TLS ALPN <alpn> of length <alpn_len> for <qc> QUIC
271+
* connection. This checks that the protocol is compatible with the QUIC stack.
272+
*
273+
* Returns 1 on success else 0.
272274
*/
273-
int quic_set_app_ops(struct quic_conn *qc, const char *alpn, int alpn_len)
275+
int qc_register_alpn(struct quic_conn *qc, const char *alpn, int alpn_len)
274276
{
275-
if (!(qc->app_ops = quic_alpn_to_app_ops(alpn, alpn_len)))
277+
const struct qcc_app_ops *app_ops;
278+
279+
if (!(app_ops = quic_alpn_to_app_ops(alpn, alpn_len)))
276280
return 0;
277281

282+
qc->alpn = app_ops->alpn;
278283
return 1;
279-
280284
}
281285

282286
/* Try to reuse <alpn> ALPN and <etps> early transport parameters.
283-
* This function also sets the application operations calling
284-
* quic_set_app_ops().
285287
* Return 1 if succeeded, 0 if not.
286288
*/
287289
int quic_reuse_srv_params(struct quic_conn *qc,
@@ -292,7 +294,7 @@ int quic_reuse_srv_params(struct quic_conn *qc,
292294

293295
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
294296

295-
if (!alpn || !quic_set_app_ops(qc, alpn, strlen(alpn)))
297+
if (!alpn || !qc_register_alpn(qc, alpn, strlen(alpn)))
296298
goto err;
297299

298300
qc_early_transport_params_reuse(qc, &qc->tx.params, etps);
@@ -1124,6 +1126,7 @@ struct quic_conn *qc_new_conn(void *target,
11241126
LIST_INIT(&qc->rx.pkt_list);
11251127

11261128
qc->streams_by_id = EB_ROOT_UNIQUE;
1129+
qc->alpn = NULL;
11271130

11281131
/* Required to call free_quic_conn_cids() from quic_conn_release() */
11291132
qc->cids = NULL;
@@ -1143,7 +1146,6 @@ struct quic_conn *qc_new_conn(void *target,
11431146
qc->xprt_ctx = NULL;
11441147
qc->conn = conn;
11451148
qc->qcc = NULL;
1146-
qc->app_ops = NULL;
11471149
qc->request_reject = NULL;
11481150
qc->path = NULL;
11491151

src/quic_ssl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
10041004

10051005
/* Check the alpn could be negotiated */
10061006
if (!qc_is_back(qc)) {
1007-
if (!qc->app_ops) {
1007+
if (!qc->alpn) {
10081008
TRACE_ERROR("No negotiated ALPN", QUIC_EV_CONN_IO_CB, qc, &state);
10091009
quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
10101010
goto err;
@@ -1016,7 +1016,7 @@ int qc_ssl_do_hanshake(struct quic_conn *qc, struct ssl_sock_ctx *ctx)
10161016

10171017
qc->conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
10181018
if (!ssl_sock_get_alpn(qc->conn, ctx, &alpn, &alpn_len) ||
1019-
!quic_set_app_ops(qc, alpn, alpn_len)) {
1019+
!qc_register_alpn(qc, alpn, alpn_len)) {
10201020
TRACE_ERROR("No negotiated ALPN", QUIC_EV_CONN_IO_CB, qc, &state);
10211021
quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
10221022
goto err;

src/ssl_sock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2242,7 +2242,7 @@ static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
22422242
}
22432243

22442244
#ifdef USE_QUIC
2245-
if (qc && !quic_set_app_ops(qc, (const char *)*out, *outlen)) {
2245+
if (qc && !qc_register_alpn(qc, (const char *)*out, *outlen)) {
22462246
quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
22472247
return SSL_TLSEXT_ERR_NOACK;
22482248
}

0 commit comments

Comments
 (0)