From 4c0ba02771e56dfd50ca7d01b76f536c6e10be95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3FJos=3DC3=3DA9=3D20Luis=3D20Mill=3DC3=3DA?= =?UTF-8?q?1n=3F=3D?= Date: Wed, 19 Aug 2015 16:23:33 +0200 Subject: [PATCH] fix #309. Receive large messages over WSS Read the full incoming TLS/SSL record at once in libwebsocket_service_fd(). SSL_read() is called until no more pending data for the current record is buffered in SSL. SSL_read() is never requested more than the pending data size for the current record to ensure that the fd is not read again for new data, which would be copied in the SSL buffer otherwise. --- lib/output.c | 6 ++++++ lib/private-libwebsockets.h | 7 ++++++- lib/service.c | 11 ++++++++++- lib/ssl.c | 9 +++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/output.c b/lib/output.c index 6c5be88a..ce426dab 100644 --- a/lib/output.c +++ b/lib/output.c @@ -605,3 +605,9 @@ lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int l lwsl_debug("ERROR writing len %d to skt %d\n", len, n); return LWS_SSL_CAPABLE_ERROR; } + +LWS_VISIBLE int +lws_ssl_pending_no_ssl(struct libwebsocket *wsi) +{ + return 0; +} diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index a862234a..2ab369a9 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1111,6 +1111,7 @@ enum lws_ssl_capable_status { #define lws_context_init_http2_ssl(_a) #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl +#define lws_ssl_pending lws_ssl_pending_no_ssl #define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0) #define lws_ssl_close(_a) (0) #define lws_ssl_context_destroy(_a) @@ -1121,10 +1122,11 @@ LWS_EXTERN int openssl_websocket_private_data_index; LWS_EXTERN int lws_ssl_capable_read(struct libwebsocket_context *context, struct libwebsocket *wsi, unsigned char *buf, int len); - LWS_EXTERN int lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len); LWS_EXTERN int +lws_ssl_pending(struct libwebsocket *wsi); +LWS_EXTERN int lws_server_socket_service_ssl(struct libwebsocket_context *context, struct libwebsocket **wsi, struct libwebsocket *new_wsi, int accept_fd, struct libwebsocket_pollfd *pollfd); @@ -1162,6 +1164,9 @@ lws_ssl_capable_read_no_ssl(struct libwebsocket_context *context, LWS_EXTERN int lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len); +LWS_EXTERN int +lws_ssl_pending_no_ssl(struct libwebsocket *wsi); + #ifndef LWS_NO_CLIENT LWS_EXTERN int lws_client_socket_service( struct libwebsocket_context *context, diff --git a/lib/service.c b/lib/service.c index 691861cd..057b5692 100644 --- a/lib/service.c +++ b/lib/service.c @@ -365,6 +365,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context, char draining_flow = 0; int more; struct lws_tokens eff_buf; + int pending = 0; if (context->listen_service_fd) listen_socket_fds_index = wsi_from_fd(context,context->listen_service_fd)->position_in_fds_table; @@ -521,10 +522,11 @@ libwebsocket_service_fd(struct libwebsocket_context *context, if (!(pollfd->revents & LWS_POLLIN)) break; +read: eff_buf.token_len = lws_ssl_capable_read(context, wsi, context->service_buffer, - sizeof(context->service_buffer)); + pending?pending:sizeof(context->service_buffer)); switch (eff_buf.token_len) { case 0: lwsl_info("service_fd: closing due to 0 length read\n"); @@ -581,6 +583,13 @@ drain: eff_buf.token_len = 0; } while (more); + pending = lws_ssl_pending(wsi); + if (pending) { + pending = pending > sizeof(context->service_buffer)? + sizeof(context->service_buffer):pending; + goto read; + } + if (draining_flow && wsi->rxflow_buffer && wsi->rxflow_pos == wsi->rxflow_len) { lwsl_info("flow buffer: drained\n"); diff --git a/lib/ssl.c b/lib/ssl.c index f6276932..95d41c9e 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -457,6 +457,15 @@ lws_ssl_capable_read(struct libwebsocket_context *context, return LWS_SSL_CAPABLE_ERROR; } +LWS_VISIBLE int +lws_ssl_pending(struct libwebsocket *wsi) +{ + if (!wsi->ssl) + return 0; + + return SSL_pending(wsi->ssl); +} + LWS_VISIBLE int lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len) {