From aeb3397c8f288c7647654d61b25fb5ffa48a00f9 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Thu, 6 Apr 2017 19:37:14 +0200 Subject: [PATCH] Subject: ssl: stop spinning on close --- lib/libwebsockets.c | 28 +++++++++++++++++++++------- lib/service.c | 50 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 6917070..98b8df9 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -510,14 +510,28 @@ just_kill_connection: !wsi->socket_is_permanently_unusable) { #ifdef LWS_OPENSSL_SUPPORT if (lws_is_ssl(wsi) && wsi->ssl) - { - lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state); + { + lwsl_info("%s: shutting down SSL connection: %p (ssl %p, sock %d, state %d)\n", __func__, wsi, wsi->ssl, (int)(long)wsi->desc.sockfd, wsi->state); n = SSL_shutdown(wsi->ssl); - if (n == 1) /* If finished the SSL shutdown, then do socket shutdown, else need to retry SSL shutdown */ - n = shutdown(wsi->desc.sockfd, SHUT_WR); - else - lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); - } + if (n == 1) /* If finished the SSL shutdown, then do socket shutdown, else need to retry SSL shutdown */ + n = shutdown(wsi->desc.sockfd, SHUT_WR); + else if (n == 0) + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); + else /* n < 0 */ + { + int shutdown_error = SSL_get_error(wsi->ssl, n); + lwsl_debug("SSL_shutdown returned %d, SSL_get_error: %d\n", n, shutdown_error); + if (shutdown_error == SSL_ERROR_WANT_READ) { + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); + n = 0; + } else if (shutdown_error == SSL_ERROR_WANT_WRITE) { + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLOUT); + n = 0; + } else { // actual error occurred, just close the connection + n = shutdown(wsi->desc.sockfd, SHUT_WR); + } + } + } else #endif { diff --git a/lib/service.c b/lib/service.c index 159dd8c..5d402d0 100644 --- a/lib/service.c +++ b/lib/service.c @@ -911,22 +911,40 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t #ifdef LWS_OPENSSL_SUPPORT - if ((wsi->state == LWSS_SHUTDOWN) && lws_is_ssl(wsi) && wsi->ssl) - { - n = SSL_shutdown(wsi->ssl); - lwsl_debug("SSH_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); - if (n == 1) - { - n = shutdown(wsi->desc.sockfd, SHUT_WR); - goto close_and_handled; - } - else - { - lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); - n = 0; - goto handled; - } - } + if ((wsi->state == LWSS_SHUTDOWN) && lws_is_ssl(wsi) && wsi->ssl) + { + n = SSL_shutdown(wsi->ssl); + lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); + if (n == 1) + { + n = shutdown(wsi->desc.sockfd, SHUT_WR); + goto close_and_handled; + } + else if (n == 0) + { + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); + n = 0; + goto handled; + } + else /* n < 0 */ + { + int shutdown_error = SSL_get_error(wsi->ssl, n); + lwsl_debug("SSL_shutdown returned %d, SSL_get_error: %d\n", n, shutdown_error); + if (shutdown_error == SSL_ERROR_WANT_READ) { + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN); + n = 0; + goto handled; + } else if (shutdown_error == SSL_ERROR_WANT_WRITE) { + lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLOUT); + n = 0; + goto handled; + } + + // actual error occurred, just close the connection + n = shutdown(wsi->desc.sockfd, SHUT_WR); + goto close_and_handled; + } + } #endif /* okay, what we came here to do... */ -- 2.7.4