diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index 71a988c8..b8f209db 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -125,6 +125,21 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms) /* any socket with events to service? */ for (n = 0; n < context->fds_count; n++) { +#ifdef LWS_OPENSSL_SUPPORT + struct libwebsocket *wsi; + + wsi = context->lws_lookup[context->fds[n].fd]; + if (wsi == NULL) + continue; + /* + * if he's not flowcontrolled, make sure we service ssl + * pending read data + */ + if (wsi->ssl && wsi->buffered_reads_pending) { + lwsl_debug("wsi %p: forcing POLLIN\n", wsi); + context->fds[n].revents |= context->fds[n].events & POLLIN; + } +#endif if (!context->fds[n].revents) continue; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 3ec5d022..9f9c63ad 100755 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -747,6 +747,7 @@ struct libwebsocket { SSL *ssl; BIO *client_bio; unsigned int use_ssl:2; + unsigned int buffered_reads_pending:1; #endif #ifdef _WIN32 @@ -950,7 +951,6 @@ enum lws_ssl_capable_status { #define lws_context_init_server_ssl(_a, _b) (0) #define lws_ssl_destroy(_a) #define lws_context_init_http2_ssl(_a) -#define lws_ssl_pending(_a) (0) #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl #define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0) @@ -958,7 +958,6 @@ enum lws_ssl_capable_status { #define lws_ssl_context_destroy(_a) #else #define LWS_SSL_ENABLED(context) (context->use_ssl) -LWS_EXTERN int lws_ssl_pending(struct libwebsocket *wsi); LWS_EXTERN int openssl_websocket_private_data_index; LWS_EXTERN int lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len); diff --git a/lib/service.c b/lib/service.c index 9ab0ea16..a914e345 100644 --- a/lib/service.c +++ b/lib/service.c @@ -436,7 +436,6 @@ libwebsocket_service_fd(struct libwebsocket_context *context, if (!(pollfd->revents & LWS_POLLIN)) break; -read_pending: eff_buf.token_len = lws_ssl_capable_read(wsi, context->service_buffer, sizeof(context->service_buffer)); @@ -505,8 +504,6 @@ drain: n = _libwebsocket_rx_flow_control(wsi); /* n ignored, needed for NO_SERVER case */ } - if (lws_ssl_pending(wsi)) - goto read_pending; break; default: diff --git a/lib/ssl.c b/lib/ssl.c index 3a2a2db6..89935f9d 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -361,11 +361,23 @@ lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len) if (!wsi->ssl) return lws_ssl_capable_read_no_ssl(wsi, buf, len); + + wsi->buffered_reads_pending = 0; n = SSL_read(wsi->ssl, buf, len); - if (n >= 0) + if (n >= 0) { + /* + * if it was our buffer that limited what we read, + * check if SSL has additional data pending inside SSL buffers. + * + * Because these won't signal at the network layer with POLLIN + * and if we don't realize, this data will sit there forever + */ + if (n == len && wsi->ssl && SSL_pending(wsi->ssl)) + wsi->buffered_reads_pending = 1; + return n; - + } n = SSL_get_error(wsi->ssl, n); if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) return LWS_SSL_CAPABLE_MORE_SERVICE; @@ -395,14 +407,6 @@ lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len) return LWS_SSL_CAPABLE_ERROR; } -LWS_VISIBLE int -lws_ssl_pending(struct libwebsocket *wsi) -{ - if (wsi->ssl) - return SSL_pending(wsi->ssl); - return 0; -} - LWS_VISIBLE int lws_ssl_close(struct libwebsocket *wsi) {