yaid.c: Time out idle connections after 30s.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 21 Oct 2012 14:08:30 +0000 (15:08 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 24 Oct 2012 09:24:31 +0000 (10:24 +0100)
yaid.c
yaid.h

diff --git a/yaid.c b/yaid.c
index cde2069..1d45fb8 100644 (file)
--- a/yaid.c
+++ b/yaid.c
@@ -56,6 +56,7 @@ struct client {
   int fd;                              /* The connection to the client */
   selbuf b;                            /* Accumulate lines of input */
   struct query q;                      /* The clients query and our reply */
+  struct sel_timer t;                  /* Timeout for idle or doomed conn */
   struct listen *l;                    /* Back to the listener (and ops) */
   struct writebuf wb;                  /* Write buffer for our reply */
   struct proxy *px;                    /* Proxy if conn goes via NAT */
@@ -521,11 +522,34 @@ static void disconnect_client(struct client *c)
 {
   close(c->fd);
   selbuf_destroy(&c->b);
+  sel_rmtimer(&c->t);
   free_writebuf(&c->wb);
   if (c->px) cancel_proxy(c->px);
   xfree(c);
 }
 
+/* Time out a client because it's been idle for too long. */
+static void timeout_client(struct timeval *tv, void *p)
+{
+  struct client *c = p;
+  logmsg(&c->q, LOG_NOTICE, "timing out idle or stuck client");
+  sel_addtimer(&sel, &c->t, tv, timeout_client, 0);
+  disconnect_client(c);
+}
+
+/* Reset the client idle timer, as a result of activity.  Set EXISTP if
+ * there is an existing timer which needs to be removed.
+ */
+static void reset_client_timer(struct client *c, int existp)
+{
+  struct timeval tv;
+
+  gettimeofday(&tv, 0);
+  tv.tv_sec += 30;
+  if (existp) sel_rmtimer(&c->t);
+  sel_addtimer(&sel, &c->t, &tv, timeout_client, c);
+}
+
 /* Write a pseudorandom token into the buffer at P, which must have space for
  * at least TOKENSZ bytes.
  */
@@ -592,6 +616,9 @@ static void client_line(char *line, size_t len, void *p)
     return;
   }
 
+  /* Client activity, so update the timer. */
+  reset_client_timer(c, 1);
+
   /* See if the policy file has changed since we last looked.  If so, try to
    * read the new version.
    */
@@ -790,6 +817,7 @@ static void accept_client(int fd, unsigned mode, void *p)
   /* Set stuff up for reading the query and sending responses. */
   selbuf_init(&c->b, &sel, sk, client_line, c);
   selbuf_setsize(&c->b, 1024);
+  reset_client_timer(c, 0);
   c->fd = sk;
   c->px = 0;
   init_writebuf(&c->wb, sk, done_client_write, c);
diff --git a/yaid.h b/yaid.h
index 387f76e..daae4f6 100644 (file)
--- a/yaid.h
+++ b/yaid.h
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
+#include <time.h>
 
 #include <sys/types.h>
+#include <sys/time.h>
 #include <unistd.h>
 #include <fcntl.h>