struct quic_connection_id *conn_id,
struct sockaddr_storage *local_addr,
struct sockaddr_storage *peer_addr,
- int server, int token, void *owner);
+ int server, int token, void *owner,
+ struct connection *conn);
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);
struct quic_connection_id *conn_id,
struct sockaddr_storage *local_addr,
struct sockaddr_storage *peer_addr,
- int server, int token, void *owner)
+ int server, int token, void *owner,
+ struct connection *conn)
{
struct quic_conn *qc = NULL;
struct listener *l = server ? owner : NULL;
qc->wait_event.events = 0;
qc->subs = NULL;
- if (qc_alloc_ssl_sock_ctx(qc) ||
+ if (qc_alloc_ssl_sock_ctx(qc, conn) ||
!quic_conn_init_timer(qc) ||
!quic_conn_init_idle_timer_task(qc, prx))
goto err;
* be set to 1 for a QUIC server, 0 for a client.
* Return 1 if succeeded, 0 if not.
*/
-static int qc_ssl_set_quic_transport_params(struct quic_conn *qc,
+static int qc_ssl_set_quic_transport_params(SSL *ssl, struct quic_conn *qc,
const struct quic_version *ver, int server)
{
int ret = 0;
goto leave;
}
- if (!SSL_set_quic_transport_params(qc->xprt_ctx->ssl, in, *enclen)) {
+ if (!SSL_set_quic_transport_params(ssl, in, *enclen)) {
TRACE_ERROR("SSL_set_quic_transport_params() failed", QUIC_EV_CONN_RWSEC);
goto leave;
}
/* Set the transport parameters in the TLS stack. */
if (level == ssl_encryption_handshake && qc_is_listener(qc) &&
- !qc_ssl_set_quic_transport_params(qc, ver, 1))
+ !qc_ssl_set_quic_transport_params(qc->xprt_ctx->ssl, qc, ver, 1))
goto leave;
keyupdate_init:
}
else {
if (!quic_transport_params_store(qc, 0, params, params + params_len) ||
- !qc_ssl_set_quic_transport_params(qc, ver, 1))
+ !qc_ssl_set_quic_transport_params(ssl, qc, ver, 1))
goto err;
}
*
* Returns 0 on success else non-zero.
*/
-int qc_alloc_ssl_sock_ctx(struct quic_conn *qc)
+int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn)
{
int ret = 0;
- struct bind_conf *bc = qc->li->bind_conf;
struct ssl_sock_ctx *ctx = NULL;
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
goto err;
}
- ctx->conn = NULL;
+ ctx->conn = conn;
ctx->bio = NULL;
ctx->xprt = NULL;
ctx->xprt_ctx = NULL;
ctx->qc = qc;
if (qc_is_listener(qc)) {
+ struct bind_conf *bc = qc->li->bind_conf;
+
if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl) == -1)
goto err;
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) && defined(HAVE_SSL_0RTT_QUIC)
SSL_set_accept_state(ctx->ssl);
}
+ else {
+ int ssl_err;
+ struct server *srv = __objt_server(ctx->conn->target);
+
+ if (qc_ssl_sess_init(qc, srv->ssl_ctx.ctx, &ctx->ssl) == -1)
+ goto err;
+
+ if (!qc_ssl_set_quic_transport_params(ctx->ssl, qc, quic_version_1, 0))
+ goto err;
+
+ SSL_set_connect_state(ctx->ssl);
+ ssl_err = SSL_do_handshake(ctx->ssl);
+ TRACE_PROTO("SSL_do_handshake() called", QUIC_EV_CONN_NEW, qc, &ssl_err);
+ if (ssl_err != 1) {
+ 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 in progress", QUIC_EV_CONN_NEW, qc, &ssl_err);
+ }
+ else {
+ TRACE_ERROR("SSL handshake error", QUIC_EV_CONN_NEW, qc, &ssl_err);
+ HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
+ qc_ssl_dump_errors(ctx->conn);
+ ERR_clear_error();
+ goto err;
+ }
+ }
+
+ /* Wakeup the handshake I/O handler tasklet asap to send data */
+ tasklet_wakeup(qc->wait_event.tasklet);
+ }
ctx->xprt = xprt_get(XPRT_QUIC);