MINOR: quic: Post handshake I/O callback switching
Implement a simple task quic_conn_app_io_cb() to be used after the handshakes
have completed.
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index e225286..9e31a75 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -93,7 +93,7 @@
{ .mask = QUIC_EV_CONN_HPKT, .name = "hdshk_pkt", .desc = "handhshake packet building" },
{ .mask = QUIC_EV_CONN_PAPKT, .name = "phdshk_apkt", .desc = "post handhshake application packet preparation" },
{ .mask = QUIC_EV_CONN_PAPKTS, .name = "phdshk_apkts", .desc = "post handhshake application packets preparation" },
- { .mask = QUIC_EV_CONN_HDSHK, .name = "hdshk", .desc = "SSL handhshake processing" },
+ { .mask = QUIC_EV_CONN_IO_CB, .name = "qc_io_cb", .desc = "QUIC conn. I/O processin" },
{ .mask = QUIC_EV_CONN_RMHP, .name = "rm_hp", .desc = "Remove header protection" },
{ .mask = QUIC_EV_CONN_PRSHPKT, .name = "parse_hpkt", .desc = "parse handshake packet" },
{ .mask = QUIC_EV_CONN_PRSAPKT, .name = "parse_apkt", .desc = "parse application packet" },
@@ -173,6 +173,7 @@
struct quic_enc_level *qel,
struct quic_conn *qc, size_t dglen, int pkt_type,
int padding, int ack, int probe, int cc, int *err);
+static struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state);
/* Only for debug purpose */
struct enc_debug_info {
@@ -319,7 +320,7 @@
}
}
- if (mask & QUIC_EV_CONN_HDSHK) {
+ if (mask & QUIC_EV_CONN_IO_CB) {
const enum quic_handshake_state *state = a2;
const int *err = a3;
@@ -1904,18 +1905,20 @@
ssl_err = SSL_get_error(ctx->ssl, ssl_err);
if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
TRACE_PROTO("SSL handshake",
- QUIC_EV_CONN_HDSHK, qc, &state, &ssl_err);
+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
goto out;
}
TRACE_DEVEL("SSL handshake error",
- QUIC_EV_CONN_HDSHK, qc, &state, &ssl_err);
+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
qc_ssl_dump_errors(ctx->conn);
ERR_clear_error();
goto err;
}
- TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_HDSHK, qc, &state);
+ TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
+ /* I/O callback switch */
+ ctx->wait_event.tasklet->process = quic_conn_app_io_cb;
if (qc_is_listener(ctx->qc)) {
HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_CONFIRMED);
/* The connection is ready to be accepted. */
@@ -1930,17 +1933,17 @@
ssl_err = SSL_get_error(ctx->ssl, ssl_err);
if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
TRACE_DEVEL("SSL post handshake",
- QUIC_EV_CONN_HDSHK, qc, &state, &ssl_err);
+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
goto out;
}
TRACE_DEVEL("SSL post handshake error",
- QUIC_EV_CONN_HDSHK, qc, &state, &ssl_err);
+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
goto err;
}
TRACE_PROTO("SSL post handshake succeeded",
- QUIC_EV_CONN_HDSHK, qc, &state);
+ QUIC_EV_CONN_IO_CB, qc, &state);
}
out:
@@ -3155,6 +3158,68 @@
return 1;
}
+/* Sends application level packets from <qc> QUIC connection */
+static int qc_send_app_pkts(struct quic_conn *qc)
+{
+ int ret;
+ struct qring *qr;
+
+ qr = MT_LIST_POP(qc->tx.qring_list, typeof(qr), mt_list);
+ if (!qr)
+ /* Never happens */
+ return 1;
+
+ ret = qc_prep_pkts(qc, qr, QUIC_TLS_ENC_LEVEL_APP, QUIC_TLS_ENC_LEVEL_NONE);
+ if (ret == -1)
+ goto err;
+ else if (ret == 0)
+ goto out;
+
+ if (!qc_send_ppkts(qr, qc->xprt_ctx))
+ goto err;
+
+ out:
+ MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
+ return 1;
+
+ err:
+ MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
+ TRACE_DEVEL("leaving in error", QUIC_EV_CONN_IO_CB, qc);
+ return 0;
+}
+
+/* QUIC connection packet handler task (post handshake) */
+static struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state)
+{
+ struct ssl_sock_ctx *ctx;
+ struct quic_conn *qc;
+ struct quic_enc_level *qel;
+ int st;
+
+
+ ctx = context;
+ qc = ctx->qc;
+ qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
+ st = HA_ATOMIC_LOAD(&qc->state);
+
+ TRACE_PROTO("state", QUIC_EV_CONN_IO_CB, qc, &st);
+
+ if (!MT_LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
+ qc_rm_hp_pkts(qc, qel);
+
+ if (!qc_treat_rx_pkts(qel, NULL, ctx, 0))
+ goto err;
+
+ if (!qc_send_app_pkts(qc))
+ goto err;
+
+ return t;
+
+ err:
+ TRACE_DEVEL("leaving in error", QUIC_EV_CONN_IO_CB, qc, &st);
+ return t;
+}
+
/* QUIC connection packet handler task. */
struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
{
@@ -3168,10 +3233,10 @@
ctx = context;
qc = ctx->qc;
- TRACE_ENTER(QUIC_EV_CONN_HDSHK, qc);
+ TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
qr = NULL;
st = HA_ATOMIC_LOAD(&qc->state);
- TRACE_PROTO("state", QUIC_EV_CONN_HDSHK, qc, &st);
+ TRACE_PROTO("state", QUIC_EV_CONN_IO_CB, qc, &st);
if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IO_CB_WAKEUP) {
HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
/* The I/O handler has been woken up by the dgram listener
@@ -3267,13 +3332,13 @@
}
MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
- TRACE_LEAVE(QUIC_EV_CONN_HDSHK, qc, &st);
+ TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc, &st);
return t;
err:
if (qr)
MT_LIST_APPEND(qc->tx.qring_list, &qr->mt_list);
- TRACE_DEVEL("leaving in error", QUIC_EV_CONN_HDSHK, qc, &st, &ssl_err);
+ TRACE_DEVEL("leaving in error", QUIC_EV_CONN_IO_CB, qc, &st, &ssl_err);
return t;
}