]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h1: Add a idle expiration date on the H1 connection
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 5 Oct 2020 15:50:58 +0000 (17:50 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 4 Dec 2020 13:41:49 +0000 (14:41 +0100)
An idle expiration date is added on the H1 connection with the function to
set it depending on connection state. First, there is no idle timeout on
backend connections, For idle frontend connections, the http-request or
keep-alive timeout are used depending on which timeout is defined and if it
is the first request or not. For embryonic connections, the http-request is
always used, if defined. For attached or shutted down connections, no idle
timeout is applied.

For now the idle expiration date is never set and the h1_set_idle_expiration
function remains unused.

src/mux_h1.c

index 4a518accb5b8cd487df05763d0f66d34d907ac51..ad9eb51935f1b0e2f826739a70b876196e5777fd 100644 (file)
@@ -98,8 +98,9 @@ struct h1c {
 
        struct h1s *h1s;                 /* H1 stream descriptor */
        struct task *task;               /* timeout management task */
-       int timeout;                     /* idle timeout duration in ticks */
-       int shut_timeout;                /* idle timeout duration in ticks after stream shutdown */
+       int idle_exp;                    /* idle expiration date (http-keep-alive or http-request timeout) */
+       int timeout;                     /* client/server timeout duration */
+       int shut_timeout;                /* client-fin/server-fin timeout duration */
 };
 
 /* H1 stream descriptor */
@@ -512,10 +513,46 @@ static void h1_refresh_timeout(struct h1c *h1c)
                        TRACE_DEVEL("no connection timeout (alive back h1c or front h1c with a CS)", H1_EV_H1C_SEND|H1_EV_H1C_RECV, h1c->conn);
                }
 
+               /* Finally set the idle expiration date if shorter */
+               h1c->task->expire = tick_first(h1c->task->expire, h1c->idle_exp);
                TRACE_DEVEL("new expiration date", H1_EV_H1C_SEND|H1_EV_H1C_RECV, h1c->conn, 0, 0, (size_t[]){h1c->task->expire});
                task_queue(h1c->task);
        }
 }
+
+static __maybe_unused void h1_set_idle_expiration(struct h1c *h1c)
+{
+       if (h1c->flags & H1C_F_IS_BACK || !h1c->task) {
+               TRACE_DEVEL("no idle expiration (backend connection || no task)", H1_EV_H1C_RECV, h1c->conn);
+               h1c->idle_exp = TICK_ETERNITY;
+               return;
+       }
+
+       if (h1c->flags & H1C_F_CS_IDLE) {
+               if (!tick_isset(h1c->idle_exp)) {
+                       if ((h1c->flags & H1C_F_WAIT_NEXT_REQ) &&   /* Not the first request */
+                           !b_data(&h1c->ibuf) &&                 /*  No input data */
+                           tick_isset(h1c->px->timeout.httpka)) { /*  K-A timeout set */
+                               h1c->idle_exp = tick_add_ifset(now_ms, h1c->px->timeout.httpka);
+                               TRACE_DEVEL("set idle expiration (keep-alive timeout)", H1_EV_H1C_RECV, h1c->conn);
+                       }
+                       else {
+                               h1c->idle_exp = tick_add_ifset(now_ms, h1c->px->timeout.httpreq);
+                               TRACE_DEVEL("set idle expiration (http-request timeout)", H1_EV_H1C_RECV, h1c->conn);
+                       }
+               }
+       }
+       else if (h1c->flags & H1C_F_CS_EMBRYONIC) {
+               if (!tick_isset(h1c->idle_exp)) {
+                       h1c->idle_exp = tick_add_ifset(now_ms, h1c->px->timeout.httpreq);
+                       TRACE_DEVEL("set idle expiration (http-request timeout)", H1_EV_H1C_RECV, h1c->conn);
+               }
+       }
+       else { // CS_ATTACHED or SHUTDOWN
+               h1c->idle_exp = TICK_ETERNITY;
+               TRACE_DEVEL("unset idle expiration (attached || shutdown)", H1_EV_H1C_RECV, h1c->conn);
+       }
+}
 /*****************************************************************/
 /* functions below are dedicated to the mux setup and management */
 /*****************************************************************/
@@ -736,6 +773,7 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session
        h1c->wait_event.tasklet->process = h1_io_cb;
        h1c->wait_event.tasklet->context = h1c;
        h1c->wait_event.events   = 0;
+       h1c->idle_exp = TICK_ETERNITY;
 
        if (conn_is_back(conn)) {
                h1c->flags |= (H1C_F_IS_BACK|H1C_F_WAIT_OPPOSITE);