diff --git a/lib/client-handshake.c b/lib/client-handshake.c index 8c821efb..c6f8ba3e 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -92,6 +92,7 @@ libwebsocket_client_connect(struct libwebsocket_context *this, wsi->state = WSI_STATE_CLIENT_UNCONNECTED; wsi->pings_vs_pongs = 0; wsi->protocol = NULL; + wsi->pending_timeout = NO_PENDING_TIMEOUT; /* set up appropriate masking */ diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index c6477cea..a35193de 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -276,7 +276,7 @@ libwebsocket_service_fd(struct libwebsocket_context *this, { unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_BROADCAST_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING]; - struct libwebsocket *wsi = wsi_from_fd(this, pollfd->fd); + struct libwebsocket *wsi; struct libwebsocket *new_wsi; int n; int m; @@ -284,6 +284,44 @@ libwebsocket_service_fd(struct libwebsocket_context *this, int accept_fd; unsigned int clilen; struct sockaddr_in cli_addr; + struct timeval tv; + + /* + * you can call us with pollfd = NULL to just allow the once-per-second + * global timeout checks; if less than a second since the last check + * it returns immediately then. + */ + + gettimeofday(&tv, NULL); + + if (this->last_timeout_check_s != tv.tv_sec) { + this->last_timeout_check_s = tv.tv_sec; + + /* global timeout check once per second */ + + for (n = 0; n < this->fds_count; n++) { + wsi = wsi_from_fd(this, this->fds[n].fd); + if (!wsi->pending_timeout) + continue; + + /* + * if we went beyond the allowed time, kill the + * connection + */ + + if (tv.tv_sec > wsi->pending_timeout_limit) + libwebsocket_close_and_free_session(this, wsi); + } + } + + /* just here for timeout management? */ + + if (pollfd == NULL) + return 0; + + /* no, here to service a socket descriptor */ + + wsi = wsi_from_fd(this, pollfd->fd); if (wsi == NULL) return 1; @@ -336,6 +374,7 @@ libwebsocket_service_fd(struct libwebsocket_context *this, memset(new_wsi, 0, sizeof (struct libwebsocket)); new_wsi->sock = accept_fd; + new_wsi->pending_timeout = NO_PENDING_TIMEOUT; #ifdef LWS_OPENSSL_SUPPORT new_wsi->ssl = NULL; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index e4a64258..d5885413 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -166,6 +166,7 @@ struct libwebsocket_context { char canonical_hostname[1024]; unsigned int http_proxy_port; unsigned int options; + unsigned long last_timeout_check_s; int fd_random; @@ -179,6 +180,12 @@ struct libwebsocket_context { }; +enum pending_timeout { + NO_PENDING_TIMEOUT = 0, + PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, + PENDING_TIMEOUT_AWAITING_PING, +}; + /* * This is totally opaque to code using the library. It's exported as a @@ -201,6 +208,8 @@ struct libwebsocket { LWS_SEND_BUFFER_POST_PADDING]; int rx_user_buffer_head; int protocol_index_for_broadcast_proxy; + enum pending_timeout pending_timeout; + unsigned long pending_timeout_limit; int sock;