introduce timeout system
authorAndy Green <andy@warmcat.com>
Mon, 14 Feb 2011 17:59:43 +0000 (17:59 +0000)
committerAndy Green <andy@warmcat.com>
Mon, 14 Feb 2011 17:59:43 +0000 (17:59 +0000)
This adds a concept of timeouts for operations enforced by
connection closure if the timeout is reached.

Once a second all sockets are checked for timing out, every time
there is a service call it checks to see if a second has passed since
the last check and checks if so.

You can also call libwebsocket_service_fd() with a NULL fd to give
the timeouts a chance to be detected; if it's less than a second since
the last check it returns immediately.

Signed-off-by: Andy Green <andy@warmcat.com>
lib/client-handshake.c
lib/libwebsockets.c
lib/private-libwebsockets.h

index 8c821ef..c6f8ba3 100644 (file)
@@ -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 */
 
index c6477ce..a35193d 100644 (file)
@@ -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;
index e4a6425..d588541 100644 (file)
@@ -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;