From bae99f63a3f69f36a374573bd12f7e4814ae1420 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Sun, 4 Jul 2021 14:26:48 -0700 Subject: [PATCH] tls: add option to serialize ssl handshake This is useful for memory constrained systems such as esp32 to improve heap usage minfree/watermark. On esp32 with simultaneous_ssl_restriction = 2 (MQTT+H1), Without this change, sys heap minfree ranges from 59k to 71k in 100 iterations, average 66.5k. With this change, sys heap minfree ranges from 64k to 71k in 100 interations, average 68.7k --- include/libwebsockets/lws-context-vhost.h | 3 ++ lib/core/context.c | 1 + lib/core/private-lib-core.h | 1 + lib/tls/tls-client.c | 45 +++++++++++++++++++ .../minimal-http-client-multi.c | 7 +++ 5 files changed, 57 insertions(+) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index ee7d57dae..da38c3523 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -453,6 +453,9 @@ struct lws_context_creation_info { int simultaneous_ssl_restriction; /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions * possible.*/ + int ssl_handshake_serialize; + /**< CONTEXT: 0 disables ssl handshake serialization (default). + * 1 enables ssl handshake serialization. */ int ssl_info_event_mask; /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO * callback for connections on this vhost. The mask values are of diff --git a/lib/core/context.c b/lib/core/context.c index 5d95e34dc..6194801a3 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -877,6 +877,7 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) context->simultaneous_ssl_restriction = info->simultaneous_ssl_restriction; + context->ssl_handshake_serialize = info->ssl_handshake_serialize; #endif context->options = info->options; diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index ab8221751..3b0a46b43 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -685,6 +685,7 @@ struct lws_context { unsigned int max_http_header_pool; int simultaneous_ssl_restriction; int simultaneous_ssl; + int ssl_handshake_serialize; #if defined(LWS_WITH_PEER_LIMITS) uint32_t pl_hash_elements; /* protected by context->lock */ uint32_t count_peers; /* protected by context->lock */ diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index 3914987cc..fc58d1d75 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -24,6 +24,43 @@ #include "private-lib-core.h" +static int +lws_ssl_handshake_serialize(struct lws_context *ctx, struct lws *wsi) +{ + struct lws_vhost *vh = ctx->vhost_list; +#if LWS_MAX_SMP > 1 + int tsi = lws_pthread_self_to_tsi(ctx); +#else + int tsi = 0; +#endif + struct lws_context_per_thread *pt = &ctx->pt[tsi]; + unsigned int n; + + while (vh) { + for (n = 0; n < pt->fds_count; n++) { + struct lws *w = wsi_from_fd(ctx, pt->fds[n].fd); + + if (!w || w->tsi != tsi || w->a.vhost != vh || wsi == w) + continue; + + /* Now we found other vhost's wsi in process */ + if (lwsi_role_mqtt(w)) { + /* MQTT TLS connection not established yet. + * Let it finish. + */ + if (lwsi_state(w) != LRS_ESTABLISHED) + return 1; + } else { + /* H1/H2 not finished yet. Let it finish. */ + if (lwsi_state(w) != LRS_DEAD_SOCKET) + return 1; + } + } + vh = vh->vhost_next; + } + return 0; +} + static int lws_ssl_client_connect1(struct lws *wsi, char *errbuf, size_t len) { @@ -195,6 +232,14 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) return CCTLS_RETURN_ERROR; } wsi->tls_borrowed = 1; + if (wsi->a.context->ssl_handshake_serialize) { + if (lws_ssl_handshake_serialize(wsi->a.context, wsi)) { + lws_tls_restrict_return(wsi->a.context); + wsi->tls_borrowed = 0; + *pcce = "ssl handshake serialization"; + return CCTLS_RETURN_ERROR; + } + } } #endif } diff --git a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c index 8ea7d29a7..c8bb035cc 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +++ b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c @@ -582,6 +582,13 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "--limit"))) info.simultaneous_ssl_restriction = atoi(p); + if (lws_cmdline_option(argc, argv, "--ssl-handshake-serialize")) + /* We only consider simultaneous_ssl_restriction > 1 use cases. + * If ssl isn't limited or only 1 is allowed, we don't care. + */ + if (info.simultaneous_ssl_restriction > 1) + info.ssl_handshake_serialize = 1; + context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n");