diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 68add0ce0..b75e023ea 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -809,6 +809,7 @@ struct lws { unsigned int client_proxy_onward:1; #endif unsigned int tls_borrowed:1; + unsigned int tls_read_wanted_write:1; #ifdef LWS_WITH_ACCESS_LOG unsigned int access_log_pending:1; diff --git a/lib/core-net/service.c b/lib/core-net/service.c index 840f32929..c7b15f320 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -636,6 +636,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, { struct lws_context_per_thread *pt; struct lws *wsi; + char cow = 0; if (!context || context->service_no_longer_possible) return -1; @@ -731,6 +732,22 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, } } #endif + + if ((pollfd->revents & LWS_POLLOUT) == LWS_POLLOUT && + wsi->tls_read_wanted_write) { + /* + * If this wsi has a pending WANT_WRITE from SSL_read(), it has + * asked for a callback on writeable so it can retry the read. + * + * Let's consume the POLLOUT by turning it into a POLLIIN, and + * setting a flag to request a new writeable + */ + wsi->tls_read_wanted_write = 0; + pollfd->revents &= ~(LWS_POLLOUT); + pollfd->revents |= LWS_POLLIN; + cow = 1; + } + wsi->could_have_pending = 0; /* clear back-to-back write detection */ pt->inside_lws_service = 1; @@ -781,6 +798,8 @@ close_and_handled: handled: #endif pollfd->revents = 0; + if (cow) + lws_callback_on_writable(wsi); pt->inside_lws_service = 0; return 0; diff --git a/lib/tls/mbedtls/mbedtls-ssl.c b/lib/tls/mbedtls/mbedtls-ssl.c index e2ad69b56..436f34aa0 100644 --- a/lib/tls/mbedtls/mbedtls-ssl.c +++ b/lib/tls/mbedtls/mbedtls-ssl.c @@ -90,8 +90,10 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) return LWS_SSL_CAPABLE_MORE_SERVICE; } if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { - lwsl_debug("%s: WANT_WRITE\n", __func__); + lwsl_info("%s: WANT_WRITE\n", __func__); lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); + wsi->tls_read_wanted_write = 1; + lws_callback_on_writable(wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; } diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 9f878ed5f..669ef4ef4 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -353,6 +353,7 @@ int ssl_pm_handshake(SSL *ssl) } if (errno == 11) { + lwsl_info("%s: ambiguous EAGAIN taken as WANT_READ\n", __func__); ssl->err = ret == MBEDTLS_ERR_SSL_WANT_READ; return 0; diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index bd889f77d..09844a42a 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -275,8 +275,10 @@ do_err: return LWS_SSL_CAPABLE_MORE_SERVICE; } if (SSL_want_write(wsi->tls.ssl)) { - lwsl_debug("%s: WANT_WRITE\n", __func__); + lwsl_info("%s: WANT_WRITE\n", __func__); lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); + wsi->tls_read_wanted_write = 1; + lws_callback_on_writable(wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; }