MINOR: quic: use server cache for ALPN on BE side

On the backend side, QUIC MUX may be started preemptively before the
ALPN negotiation. This is useful notably for 0-RTT implementation.

However, this was a source of crashes. ALPN was expected to be retrieved
from the server cache, however QUIC MUX still used the ALPN from the
transport layer. This could cause a crash, especially when several
connections runs in parallel as the server cache is shared among
threads.

Thanks to the previous patch which reworks QUIC MUX init, this solution
can now be fixed. Indeed, if conn_get_alpn() is not successful, MUX can
look at the server cache again to use the expected value.

Note that this could still prevent the MUX to work as expected if the
server cache is resetted between connect_server() and MUX init. Thus,
the ultimate solution would be to copy the cached ALPN into the
connection. This problem is not specific to QUIC though, and must be
fixed in a separate patch.
This commit is contained in:
Amaury Denoyelle 2026-03-03 10:02:39 +01:00
parent 940e1820f6
commit b1441c6440
2 changed files with 15 additions and 2 deletions

View File

@ -1695,13 +1695,25 @@ int qcc_install_app_ops(struct qcc *qcc)
{
struct connection *conn = qcc->conn;
const struct qcc_app_ops *app_ops;
struct server *srv;
const char *alpn;
int alpn_len;
TRACE_ENTER(QMUX_EV_QCC_NEW, conn);
if (!conn_get_alpn(conn, &alpn, &alpn_len))
goto err;
if (!conn_get_alpn(conn, &alpn, &alpn_len)) {
if (!conn_is_back(conn))
goto err;
srv = __objt_server(conn->target);
HA_RWLOCK_RDLOCK(SERVER_LOCK, &srv->path_params.param_lock);
alpn = srv->path_params.nego_alpn;
HA_RWLOCK_RDUNLOCK(SERVER_LOCK, &srv->path_params.param_lock);
if (!alpn)
goto err;
alpn_len = strlen(srv->path_params.nego_alpn);
}
app_ops = quic_alpn_to_app_ops(alpn, alpn_len);
if (!app_ops)

View File

@ -245,6 +245,7 @@ static int qc_get_alpn(const struct connection *conn, void *xprt_ctx, const char
int ret = 0;
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
if (qc->alpn) {
*str = qc->alpn;
*len = strlen(qc->alpn);