From ff47ae60f3453e0c7dd3b7546bf7e7073c64a0ec Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Mon, 8 Sep 2025 22:14:42 +0200 Subject: [PATCH] MEDIUM: server: Introduce the concept of path parameters Add a new field in struct server, path parameters. It will contain connection informations for the server that are not expected to change. For now, just store the ALPN negociated with the server. Each time an handhskae is done, we'll update it, even though it is not supposed to change. This will be useful when trying to send early data, that way we'll know which mux to use. Each time the server goes down or is disabled, those informations are erased, as we can't be sure those parameters will be the same once the server will be back up. --- include/haproxy/server-t.h | 7 +++++++ src/server.c | 9 +++++++++ src/ssl_sock.c | 25 ++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) 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)