diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index ad081ec1..f8c60a38 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -68,6 +68,19 @@ lws_free_wsi(struct lws *wsi) lws_free(wsi); } + +static void +lws_remove_from_timeout_list(struct lws *wsi) +{ + if (!wsi->timeout_list_prev) + return; + + *wsi->timeout_list_prev = wsi->timeout_list; + wsi->timeout_list_prev = NULL; + wsi->timeout_list = NULL; +} + + void lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) { @@ -234,6 +247,7 @@ just_kill_connection: * delete socket from the internal poll list if still present */ lws_ssl_remove_wsi_from_buffered_list(wsi); + lws_remove_from_timeout_list(wsi); /* checking return redundant since we anyway close */ remove_wsi_socket_from_fds(wsi); @@ -563,8 +577,19 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) time(&now); + if (!wsi->pending_timeout) { + wsi->timeout_list = wsi->context->timeout_list; + if (wsi->timeout_list) + wsi->timeout_list->timeout_list_prev = &wsi->timeout_list; + wsi->timeout_list_prev = &wsi->context->timeout_list; + *wsi->timeout_list_prev = wsi; + } + wsi->pending_timeout_limit = now + secs; wsi->pending_timeout = reason; + + if (!reason) + lws_remove_from_timeout_list(wsi); } @@ -1144,7 +1169,7 @@ lws_parse_uri(char *p, const char **prot, const char **ads, int *port, const cha *port = 80; else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss")) *port = 443; - + while (*p && *p != ':' && *p != '/') p++; if (*p == ':') { diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 92ea713f..7a16cb50 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -290,7 +290,7 @@ extern "C" { #define LWS_MAX_PROTOCOLS 5 #endif #ifndef LWS_MAX_EXTENSIONS_ACTIVE -#define LWS_MAX_EXTENSIONS_ACTIVE 3 +#define LWS_MAX_EXTENSIONS_ACTIVE 2 #endif #ifndef LWS_MAX_EXT_OFFERS #define LWS_MAX_EXT_OFFERS 8 @@ -522,6 +522,8 @@ struct lws_context { const char *iface; const struct lws_token_limits *token_limits; void *user_space; + struct lws *timeout_list; + #ifndef LWS_NO_SERVER struct lws *wsi_listening; #endif @@ -907,6 +909,8 @@ struct lws { struct lws_context *context; const struct lws_protocols *protocol; + struct lws *timeout_list; + struct lws **timeout_list_prev; void *user_space; /* rxflow handling */ unsigned char *rxflow_buffer; @@ -929,7 +933,6 @@ struct lws { lws_sockfd_type sock; /* ints */ - enum lws_pending_protocol_send pps; int position_in_fds_table; int rxflow_len; int rxflow_pos; @@ -962,6 +965,7 @@ struct lws { char lws_rx_parse_state; /* enum lws_rx_parse_state */ char rx_frame_type; /* enum lws_write_protocol */ char pending_timeout; /* enum pending_timeout */ + char pps; /* enum lws_pending_protocol_send */ }; LWS_EXTERN int log_level; diff --git a/lib/service.c b/lib/service.c index 4544b501..9ddbeaea 100644 --- a/lib/service.c +++ b/lib/service.c @@ -298,8 +298,7 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec) * if extensions want in on it (eg, we are a mux parent) * give them a chance to service child timeouts */ - if (lws_ext_cb_active(wsi, LWS_EXT_CB_1HZ, - NULL, sec) < 0) + if (lws_ext_cb_active(wsi, LWS_EXT_CB_1HZ, NULL, sec) < 0) return 0; if (!wsi->pending_timeout) @@ -380,7 +379,6 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd) struct lws_tokens eff_buf; unsigned int pending = 0; char draining_flow = 0; - lws_sockfd_type mfd; int timed_out = 0; struct lws *wsi; time_t now; @@ -410,18 +408,15 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd) if (pollfd) our_fd = pollfd->fd; - for (n = 0; n < context->fds_count; n++) { - mfd = context->fds[n].fd; - wsi = wsi_from_fd(context, mfd); - if (!wsi) - continue; - + wsi = context->timeout_list; + while (wsi) { if (lws_service_timeout_check(wsi, (unsigned int)now)) /* he did time out... */ - if (mfd == our_fd) + if (wsi->sock == our_fd) /* it was the guy we came to service! */ timed_out = 1; /* he's gone, no need to mark as handled */ + wsi = wsi->timeout_list; } }