goto leave;
}
}
- else {
+ else if (qc->mux_state != QC_MUX_READY) {
const unsigned char *alpn;
size_t alpn_len;
}
}
- /* Wakeup the handshake I/O handler tasklet asap to send data */
- tasklet_wakeup(qc->wait_event.tasklet);
+ /* Wakeup the handshake I/O handler tasklet asap to send data except for
+ * a QUIC client, if the early data encryption level has been initialized.
+ * Some early data will be directly sent by the mux alongside Initial
+ * CRYPTO data.
+ *
+ * Note that a QUIC server never installs its RX early data keys from here
+ * (->eel is always null for a QUIC server during this SSL context
+ * initialization).
+ */
+ if (!qc->eel)
+ tasklet_wakeup(qc->wait_event.tasklet);
}
ctx->xprt = xprt_get(XPRT_QUIC);
/* Start the QUIC transport layer */
static int qc_xprt_start(struct connection *conn, void *ctx)
{
- int ret = 0;
+ int ret = -1;
struct quic_conn *qc;
qc = conn->handle.qc;
qc->mux_state = QC_MUX_READY;
}
else {
- conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
+ if (!qc->eel) {
+ /* Connection without O-RTT */
+ conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
+ }
+ else {
+ struct ssl_sock_ctx *ssl_ctx = ctx;
+
+ /* Start the mux asap when early data encryption level is available. */
+ conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_WAIT_XPRT;
+ if (conn_create_mux(ssl_ctx->conn, NULL) < 0) {
+ TRACE_ERROR("mux creation failed", QUIC_EV_CONN_IO_CB, qc, &qc->state);
+ goto err;
+ }
+
+ ssl_ctx->conn->flags &= ~CO_FL_WAIT_XPRT;
+ qc->mux_state = QC_MUX_READY;
+ /* Wake up MUX after its creation. Operation similar to TLS+ALPN on TCP stack. */
+ ssl_ctx->conn->mux->wake(ssl_ctx->conn);
+ }
}
/* Schedule quic-conn to ensure post handshake frames are emitted. This
tasklet_wakeup(qc->wait_event.tasklet);
ret = 1;
- out:
+ leave:
TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
return ret;
+ err:
+ TRACE_DEVEL("leaving on error", QUIC_EV_CONN_NEW, qc);
+ goto leave;
}
static struct ssl_sock_ctx *qc_get_ssl_sock_ctx(struct connection *conn)