int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv);
#endif
+int increment_sslconn();
SSL_CTX *ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl);
SSL_CTX *ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf);
int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int key, struct bind_conf *bind_conf);
return 0;
}
+/* Similar to increment_actconn() but for SSL connections. */
+int increment_sslconn()
+{
+ unsigned int count, next_sslconn;
+
+ do {
+ count = global.sslconns;
+ if (global.maxsslconn && count >= global.maxsslconn) {
+ /* maxconn reached */
+ next_sslconn = 0;
+ goto end;
+ }
+
+ /* try to increment sslconns */
+ next_sslconn = count + 1;
+ } while (!_HA_ATOMIC_CAS(&global.sslconns, &count, next_sslconn) && __ha_cpu_relax());
+
+ end:
+ return next_sslconn;
+}
+
/*
* This function is called if SSL * context is not yet allocated. The function
* is designed to be called before any other data-layer operation and sets the
static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
{
struct ssl_sock_ctx *ctx;
+ int next_sslconn = 0;
+
/* already initialized */
if (*xprt_ctx)
return 0;
ctx->xprt_ctx = NULL;
ctx->error_code = 0;
+ next_sslconn = increment_sslconn();
+ if (!next_sslconn) {
+ conn->err_code = CO_ER_SSL_TOO_MANY;
+ goto err;
+ }
+
/* Only work with sockets for now, this should be adapted when we'll
* add QUIC support.
*/
goto err;
}
- if (global.maxsslconn && global.sslconns >= global.maxsslconn) {
- conn->err_code = CO_ER_SSL_TOO_MANY;
- goto err;
- }
-
/* If it is in client mode initiate SSL session
in connect state otherwise accept state */
if (objt_server(conn->target)) {
/* leave init state and start handshake */
conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
- _HA_ATOMIC_INC(&global.sslconns);
_HA_ATOMIC_INC(&global.totalsslconns);
*xprt_ctx = ctx;
return 0;
conn->flags |= CO_FL_EARLY_SSL_HS;
#endif
- _HA_ATOMIC_INC(&global.sslconns);
_HA_ATOMIC_INC(&global.totalsslconns);
*xprt_ctx = ctx;
return 0;
/* don't know how to handle such a target */
conn->err_code = CO_ER_SSL_NO_TARGET;
err:
+ if (next_sslconn)
+ _HA_ATOMIC_DEC(&global.sslconns);
if (ctx && ctx->wait_event.tasklet)
tasklet_free(ctx->wait_event.tasklet);
pool_free(ssl_sock_ctx_pool, ctx);