From: Amaury Denoyelle Date: Thu, 10 Apr 2025 09:51:05 +0000 (+0200) Subject: MINOR: mux-h2: refactor idle timeout calculation X-Git-Tag: v3.2-dev11~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=99b2e52f89b91573ae97bd18ffdca6da2742df33;p=thirdparty%2Fhaproxy.git MINOR: mux-h2: refactor idle timeout calculation Reorganize code for timeout calculation in case the connection is idle. The objective is to better reflect the relations between each timeouts as follow : * if GOAWAY already emitted, use shut-timeout, or if unset fallback to client/server one. However, an already set timeout is never erased. * else, for frontend connection, http-request or keep-alive timeout is applied depending on the current demux state. If the selected value is unset, fallback to client timeout * for backend connection, no timeout is set to perform http-reuse This commit is pure refactoring, so no functional change should occur. --- diff --git a/src/mux_h2.c b/src/mux_h2.c index 6fb76aec7..cf780cc25 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -856,44 +856,58 @@ static void h2c_update_timeout(struct h2c *h2c) if (br_data(h2c->mbuf)) { /* pending output data: always the regular data timeout */ h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout); - } else { - /* no stream, no output data */ + } + else { + int dft = TICK_ETERNITY; + int exp = TICK_ETERNITY; + + /* idle connection : no stream, no output data */ if (h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED)) { /* GOAWAY sent (or failed), closing in progress */ - int exp = tick_add_ifset(now_ms, h2c->shut_timeout); + dft = tick_add_ifset(now_ms, h2c->timeout); - h2c->task->expire = tick_first(h2c->task->expire, exp); - /* if a timeout above was not set, fall back to the default one */ - if (!tick_isset(h2c->task->expire)) - h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout); + /* Use {client,server}-fin but do not reset if + * already defined. Fallback to client/server if needed. + */ + exp = tick_add_ifset(now_ms, h2c->shut_timeout); + exp = tick_first(exp, h2c->task->expire); + if (!tick_isset(exp)) + exp = dft; is_idle_conn = 1; } - else if (!(h2c->flags & H2_CF_IS_BACK)) { - int to; - - if (h2c->max_id > 0 && !b_data(&h2c->dbuf) && - tick_isset(h2c->proxy->timeout.httpka)) { - /* idle after having seen one stream => keep-alive */ - to = h2c->proxy->timeout.httpka; - } else { - /* before first request, or started to deserialize a - * new req => http-request. - */ - to = h2c->proxy->timeout.httpreq; - } + else { + if (!(h2c->flags & H2_CF_IS_BACK)) { + int to; - h2c->task->expire = tick_add_ifset(h2c->idle_start, to); - /* if a timeout above was not set, fall back to the default one */ - if (!tick_isset(h2c->task->expire)) - h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout); + dft = tick_add_ifset(now_ms, h2c->timeout); - is_idle_conn = 1; - } - else { - /* No timeout on backend idle conn. */ - h2c->task->expire = TICK_ETERNITY; + if (h2c->max_id > 0 && !b_data(&h2c->dbuf) && + tick_isset(h2c->proxy->timeout.httpka)) { + /* idle after having seen one stream => keep-alive */ + to = h2c->proxy->timeout.httpka; + } + else { + /* before first request, or started to deserialize a + * new req => http-request. + */ + to = h2c->proxy->timeout.httpreq; + } + + /* Use hr/ka timers. Fallback to client timeout only if unset. */ + exp = tick_add_ifset(h2c->idle_start, to); + if (!tick_isset(exp)) + exp = dft; + + is_idle_conn = 1; + } + else { + /* No timeout on backend idle conn. */ + exp = TICK_ETERNITY; + } } + + h2c->task->expire = exp; } if ((h2c->proxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && @@ -925,8 +939,8 @@ static void h2c_update_timeout(struct h2c *h2c) task_wakeup(h2c->task, TASK_WOKEN_TIMER); } } - - } else { + } + else { h2c->task->expire = TICK_ETERNITY; }