From c604b9cb21dae2121076b418f058fd03132fc29c 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 f1c4afd9a..8e1fed53e 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 0b9a22489..c7e84b41b 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -910,6 +910,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 d98d8386b..e5fb25a5b 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -699,6 +699,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_TLS_JIT_TRUST) int vh_idle_grace_ms; #endif diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index 9e8443c4c..6009e4352 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) { @@ -190,6 +227,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 cbbbf9ed9..d8a95603f 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 @@ -583,6 +583,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");