diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 90bc7be91..f68d0e318 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -5770,6 +5770,35 @@ static int ssl_sock_init(struct connection *conn, void **xprt_ctx) SSL_set_tlsext_host_name(ctx->ssl, srv->ssl_ctx.reused_sess[tid].sni); HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[tid].sess_lock); } + } else { + /* No session available yet, let's see if we can pick one + * from another thread. If old_tid is non-null, it designates + * the index of a recently updated thread that might still have + * a usable session. All threads are collectively responsible + * for resetting the index if it fails. + */ + const unsigned char *ptr; + SSL_SESSION *sess; + uint old_tid = HA_ATOMIC_LOAD(&srv->ssl_ctx.last_ssl_sess_tid); // 0=none, >0 = tid + 1 + + if (old_tid) { + HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[old_tid-1].sess_lock); + + ptr = srv->ssl_ctx.reused_sess[old_tid-1].ptr; + if (ptr) { + sess = d2i_SSL_SESSION(NULL, &ptr, srv->ssl_ctx.reused_sess[old_tid-1].size); + if (sess) { + if (!SSL_set_session(ctx->ssl, sess)) + HA_ATOMIC_CAS(&srv->ssl_ctx.last_ssl_sess_tid, &old_tid, 0); // no more valid + SSL_SESSION_free(sess); + } + } + + if (srv->ssl_ctx.reused_sess[old_tid-1].sni) + SSL_set_tlsext_host_name(ctx->ssl, srv->ssl_ctx.reused_sess[old_tid-1].sni); + + HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.reused_sess[old_tid-1].sess_lock); + } } HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &srv->ssl_ctx.lock);