mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-16 00:00:07 +01:00
ssl pending buffered reads use linked list
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
7e37d10e47
commit
5281560000
4 changed files with 74 additions and 34 deletions
|
@ -209,6 +209,8 @@ just_kill_connection:
|
|||
* delete socket from the internal poll list if still present
|
||||
*/
|
||||
|
||||
lws_ssl_remove_wsi_from_buffered_list(context, wsi);
|
||||
|
||||
remove_wsi_socket_from_fds(context, wsi);
|
||||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
|
|
@ -97,6 +97,7 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
int n;
|
||||
int m;
|
||||
char buf;
|
||||
struct libwebsocket *wsi, *wsi_next;
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
|
@ -110,25 +111,20 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/* if we know we have non-network pending data, do not wait in poll */
|
||||
if (context->ssl_flag_buffered_reads)
|
||||
if (lws_ssl_anybody_has_buffered_read(context))
|
||||
timeout_ms = 0;
|
||||
#endif
|
||||
n = poll(context->fds, context->fds_count, timeout_ms);
|
||||
context->service_tid = 0;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
if (!context->ssl_flag_buffered_reads && n == 0) {
|
||||
if (!lws_ssl_anybody_has_buffered_read(context) && n == 0) {
|
||||
#else
|
||||
if (n == 0) /* poll timeout */ {
|
||||
#endif
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/* any more will have to set it fresh this time around */
|
||||
context->ssl_flag_buffered_reads = 0;
|
||||
#endif
|
||||
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO != LWS_EINTR)
|
||||
|
@ -136,29 +132,36 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/*
|
||||
* For all guys with buffered SSL read data already saved up, if they
|
||||
* are not flowcontrolled, fake their POLLIN status so they'll get
|
||||
* service to use up the buffered incoming data, even though their
|
||||
* network socket may have nothing
|
||||
*/
|
||||
|
||||
wsi = context->pending_read_list;
|
||||
while (wsi) {
|
||||
wsi_next = wsi->pending_read_list_next;
|
||||
context->fds[wsi->sock].revents |=
|
||||
context->fds[wsi->sock].events & POLLIN;
|
||||
if (context->fds[wsi->sock].revents & POLLIN) {
|
||||
/*
|
||||
* he's going to get serviced now, take him off the
|
||||
* list of guys with buffered SSL. If he still has some
|
||||
* at the end of the service, he'll get put back on the
|
||||
* list then.
|
||||
*/
|
||||
lws_ssl_remove_wsi_from_buffered_list(context, wsi);
|
||||
}
|
||||
wsi = wsi_next;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
if (context->fds[n].revents & POLLIN)
|
||||
wsi->buffered_reads_pending = 0;
|
||||
else
|
||||
/* somebody left with pending SSL read data */
|
||||
context->ssl_flag_buffered_reads = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!context->fds[n].revents)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -474,7 +474,10 @@ struct libwebsocket_context {
|
|||
unsigned int user_supplied_ssl_ctx:1;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL_CTX *ssl_client_ctx;
|
||||
unsigned int ssl_flag_buffered_reads:1;
|
||||
struct libwebsocket *pending_read_list; /* linked list */
|
||||
#define lws_ssl_anybody_has_buffered_read(ctx) (ctx->use_ssl && ctx->pending_read_list)
|
||||
#else
|
||||
#define lws_ssl_anybody_has_buffered_read(ctx) (0)
|
||||
#endif
|
||||
struct libwebsocket_protocols *protocols;
|
||||
int count_protocols;
|
||||
|
@ -840,8 +843,8 @@ struct libwebsocket {
|
|||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
SSL *ssl;
|
||||
BIO *client_bio;
|
||||
struct libwebsocket *pending_read_list_prev, *pending_read_list_next;
|
||||
unsigned int use_ssl:2;
|
||||
unsigned int buffered_reads_pending:1;
|
||||
unsigned int upgraded:1;
|
||||
#endif
|
||||
|
||||
|
@ -1089,6 +1092,7 @@ enum lws_ssl_capable_status {
|
|||
#define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_ssl_close(_a) (0)
|
||||
#define lws_ssl_context_destroy(_a)
|
||||
#define lws_ssl_remove_wsi_from_buffered_list(_a, _b)
|
||||
#else
|
||||
#define LWS_SSL_ENABLED(context) (context->use_ssl)
|
||||
LWS_EXTERN int openssl_websocket_private_data_index;
|
||||
|
@ -1106,6 +1110,9 @@ LWS_EXTERN int
|
|||
lws_ssl_close(struct libwebsocket *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_ssl_context_destroy(struct libwebsocket_context *context);
|
||||
LWS_VISIBLE void
|
||||
lws_ssl_remove_wsi_from_buffered_list(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
#ifndef LWS_NO_SERVER
|
||||
LWS_EXTERN int
|
||||
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
||||
|
|
38
lib/ssl.c
38
lib/ssl.c
|
@ -392,6 +392,32 @@ int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
|||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_ssl_remove_wsi_from_buffered_list(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
if (!wsi->pending_read_list_prev &&
|
||||
!wsi->pending_read_list_next &&
|
||||
context->pending_read_list != wsi)
|
||||
/* we are not on the list */
|
||||
return;
|
||||
|
||||
/* point previous guy's next to our next */
|
||||
if (!wsi->pending_read_list_prev)
|
||||
context->pending_read_list = wsi->pending_read_list_next;
|
||||
else
|
||||
wsi->pending_read_list_prev->pending_read_list_next =
|
||||
wsi->pending_read_list_next;
|
||||
|
||||
/* point next guy's previous to our previous */
|
||||
if (wsi->pending_read_list_next)
|
||||
wsi->pending_read_list_next->pending_read_list_prev =
|
||||
wsi->pending_read_list_prev;
|
||||
|
||||
wsi->pending_read_list_prev = NULL;
|
||||
wsi->pending_read_list_next = NULL;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_read(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
|
@ -400,8 +426,6 @@ lws_ssl_capable_read(struct libwebsocket_context *context,
|
|||
|
||||
if (!wsi->ssl)
|
||||
return lws_ssl_capable_read_no_ssl(context, wsi, buf, len);
|
||||
|
||||
wsi->buffered_reads_pending = 0;
|
||||
|
||||
n = SSL_read(wsi->ssl, buf, len);
|
||||
if (n >= 0) {
|
||||
|
@ -413,10 +437,14 @@ lws_ssl_capable_read(struct libwebsocket_context *context,
|
|||
* and if we don't realize, this data will sit there forever
|
||||
*/
|
||||
if (n == len && wsi->ssl && SSL_pending(wsi->ssl)) {
|
||||
context->ssl_flag_buffered_reads = 1;
|
||||
wsi->buffered_reads_pending = 1;
|
||||
assert(!wsi->pending_read_list_next && !wsi->pending_read_list_prev);
|
||||
/* add us to the linked list of guys with pending ssl */
|
||||
context->pending_read_list->pending_read_list_prev = wsi;
|
||||
wsi->pending_read_list_next = context->pending_read_list;
|
||||
wsi->pending_read_list_prev = NULL;
|
||||
context->pending_read_list = wsi;
|
||||
}
|
||||
|
||||
|
||||
return n;
|
||||
}
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
|
Loading…
Add table
Reference in a new issue