From 11d7586ebfacf05d74441b8e355cda14cea1fd00 Mon Sep 17 00:00:00 2001
From: Shantanu Goel <sgoel@trade4.test-jc.tower-research.com>
Date: Mon, 18 Jun 2012 10:54:44 -0400
Subject: [PATCH 4/5] Add support for terminating idle connections

---
 src/responder/common/responder.h        |    2 +
 src/responder/common/responder_common.c |   67 ++++++++++++++++++++++++++++++-
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 2cc85445c6d802ba2de275c143c8aeccd2eb5ece..67884ed7659d3d99ac8d693ad083b4f7e293bf71 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -126,6 +126,8 @@ struct cli_ctx {
     int netgrent_cur;
 
     char *automntmap_name;
+
+    struct tevent_timer *idle;
 };
 
 struct sss_cmd_table {
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 5d5248809d095420e8a4d11ce80fc13e1949c873..3c269725256c88cfad65a0fc9f1b0d4ac4009797 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -219,12 +219,24 @@ static void client_recv(struct cli_ctx *cctx)
     return;
 }
 
+static errno_t reset_idle_timer(struct cli_ctx *cctx);
+
 static void client_fd_handler(struct tevent_context *ev,
                               struct tevent_fd *fde,
                               uint16_t flags, void *ptr)
 {
+    errno_t ret;
     struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
 
+    /* Always reset the idle timer on any activity */
+    ret = reset_idle_timer(cctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Could not create idle timer for client. "
+               "This connection may not auto-terminate\n"));
+        /* Non-fatal, continue */
+    }
+
     if (flags & TEVENT_FD_READ) {
         client_recv(cctx);
         return;
@@ -240,6 +252,11 @@ struct accept_fd_ctx {
     bool is_private;
 };
 
+static void idle_handler(struct tevent_context *ev,
+                         struct tevent_timer *te,
+                         struct timeval current_time,
+                         void *data);
+
 static void accept_fd_handler(struct tevent_context *ev,
                               struct tevent_fd *fde,
                               uint16_t flags, void *ptr)
@@ -317,12 +334,58 @@ static void accept_fd_handler(struct tevent_context *ev,
 
     talloc_set_destructor(cctx, client_destructor);
 
-    DEBUG(4, ("Client connected%s!\n",
-              accept_ctx->is_private ? " to privileged pipe" : ""));
+    /* Set up the idle timer */
+    ret = reset_idle_timer(cctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Could not create idle timer for client. "
+               "This connection may not auto-terminate\n"));
+        /* Non-fatal, continue */
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC,
+          ("Client connected%s!\n",
+           accept_ctx->is_private ? " to privileged pipe" : ""));
 
     return;
 }
 
+static errno_t reset_idle_timer(struct cli_ctx *cctx)
+{
+    struct timeval tv;
+
+    /* TODO: make this configurable */
+    tv = tevent_timeval_current_ofs(60, 0);
+
+    talloc_zfree(cctx->idle);
+
+    cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, idle_handler, cctx);
+    if (!cctx->idle) return ENOMEM;
+
+    DEBUG(SSSDBG_TRACE_ALL,
+          ("Idle timer re-set for client [%p][%d]\n",
+           cctx, cctx->cfd));
+
+    return EOK;
+}
+
+static void idle_handler(struct tevent_context *ev,
+                         struct tevent_timer *te,
+                         struct timeval current_time,
+                         void *data)
+{
+    /* This connection is idle. Terminate it */
+    struct cli_ctx *cctx =
+            talloc_get_type(data, struct cli_ctx);
+
+    DEBUG(SSSDBG_TRACE_INTERNAL,
+          ("Terminating idle client [%p][%d]\n",
+           cctx, cctx->cfd));
+
+    /* The cli_ctx destructor will handle the rest */
+    talloc_free(cctx);
+}
+
 static int sss_dp_init(struct resp_ctx *rctx,
                        struct sbus_interface *intf,
                        const char *cli_name,
-- 
1.7.10.2

