diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index bed933226..af6ffdee8 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -315,6 +315,12 @@ enum renegotiate_mode { SSL_RENEGOTIATE_ON /* Enable secure renegotiation */ }; +#define MAX_ALPN_SIZE 16 + +struct path_parameters { + char nego_alpn[MAX_ALPN_SIZE]; +}; + struct proxy; struct server { /* mostly config or admin stuff, doesn't change often */ @@ -494,6 +500,7 @@ struct server { #ifdef USE_QUIC struct quic_transport_params quic_params; /* QUIC transport parameters */ #endif + struct path_parameters path_params; /* Connection parameters for that server */ struct resolv_srvrq *srvrq; /* Pointer representing the DNS SRV requeest, if any */ struct list srv_rec_item; /* to attach server to a srv record item */ struct list ip_rec_item; /* to attach server to a A or AAAA record item */ diff --git a/src/server.c b/src/server.c index 83257e151..514a1c61f 100644 --- a/src/server.c +++ b/src/server.c @@ -137,6 +137,11 @@ static const char *srv_op_st_chg_cause_str[] = { [SRV_OP_STCHGC_STATEFILE] = "changed from server-state after a reload" }; +static void srv_reset_path_parameters(struct server *s) +{ + s->path_params.nego_alpn[0] = 0; +} + const char *srv_op_st_chg_cause(enum srv_op_st_chg_cause cause) { return srv_op_st_chg_cause_str[cause]; @@ -6642,6 +6647,7 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS) srv_shutdown_streams(s, SF_ERR_DOWN); + srv_reset_path_parameters(s); /* we might have streams queued on this server and waiting for * a connection. Those which are redispatchable will be queued * to another server or to the proxy itself. @@ -6669,6 +6675,7 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus else if ((s->cur_state != SRV_ST_STOPPING) && (s->next_state == SRV_ST_STOPPING)) { srv_lb_propagate(s); + srv_reset_path_parameters(s); /* we might have streams queued on this server and waiting for * a connection. Those which are redispatchable will be queued * to another server or to the proxy itself. @@ -6783,6 +6790,8 @@ static int _srv_update_status_adm(struct server *s, enum srv_adm_st_chg_cause ca s->next_state = SRV_ST_STOPPED; srv_lb_propagate(s); + srv_reset_path_parameters(s); + if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS) srv_shutdown_streams(s, SF_ERR_DOWN); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 4e0072e0b..f8640e2f1 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -6487,8 +6487,31 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state) if (ctx->conn->xprt_ctx == ctx) { int closed_connection = 0; - if (!ctx->conn->mux) + if (!ctx->conn->mux) { ret = conn_create_mux(ctx->conn, &closed_connection); + /* + * For backend connections, attempt to + * retrieve the ALPN, and store it into + * the server's path_params, so that for + * next connections, we'll know the ALPN + * already, and immediately know which mux + * to use, in case we want to use 0RTT. + */ + if (conn_is_back(conn)) { + struct server *srv; + const char *alpn; + int len; + + if (ssl_sock_get_alpn(conn, ctx, &alpn, &len)) { + srv = objt_server(conn->target); + if (srv && len < sizeof(srv->path_params.nego_alpn)) { + memcpy(&srv->path_params.nego_alpn, alpn, len); + srv->path_params.nego_alpn[len] = 0; + } + } + } + + } if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake) { ret = ctx->conn->mux->wake(ctx->conn); if (ret < 0)