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.
This commit is contained in:
Amaury Denoyelle 2025-04-10 11:51:05 +02:00
parent 243bc95de0
commit 99b2e52f89

View File

@ -856,46 +856,60 @@ static void h2c_update_timeout(struct h2c *h2c)
if (br_data(h2c->mbuf)) { if (br_data(h2c->mbuf)) {
/* pending output data: always the regular data timeout */ /* pending output data: always the regular data timeout */
h2c->task->expire = tick_add_ifset(now_ms, h2c->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)) { if (h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED)) {
/* GOAWAY sent (or failed), closing in progress */ /* 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); /* Use {client,server}-fin but do not reset if
/* if a timeout above was not set, fall back to the default one */ * already defined. Fallback to client/server if needed.
if (!tick_isset(h2c->task->expire)) */
h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout); 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; is_idle_conn = 1;
} }
else if (!(h2c->flags & H2_CF_IS_BACK)) { else {
if (!(h2c->flags & H2_CF_IS_BACK)) {
int to; int to;
dft = tick_add_ifset(now_ms, h2c->timeout);
if (h2c->max_id > 0 && !b_data(&h2c->dbuf) && if (h2c->max_id > 0 && !b_data(&h2c->dbuf) &&
tick_isset(h2c->proxy->timeout.httpka)) { tick_isset(h2c->proxy->timeout.httpka)) {
/* idle after having seen one stream => keep-alive */ /* idle after having seen one stream => keep-alive */
to = h2c->proxy->timeout.httpka; to = h2c->proxy->timeout.httpka;
} else { }
else {
/* before first request, or started to deserialize a /* before first request, or started to deserialize a
* new req => http-request. * new req => http-request.
*/ */
to = h2c->proxy->timeout.httpreq; to = h2c->proxy->timeout.httpreq;
} }
h2c->task->expire = tick_add_ifset(h2c->idle_start, to); /* Use hr/ka timers. Fallback to client timeout only if unset. */
/* if a timeout above was not set, fall back to the default one */ exp = tick_add_ifset(h2c->idle_start, to);
if (!tick_isset(h2c->task->expire)) if (!tick_isset(exp))
h2c->task->expire = tick_add_ifset(now_ms, h2c->timeout); exp = dft;
is_idle_conn = 1; is_idle_conn = 1;
} }
else { else {
/* No timeout on backend idle conn. */ /* No timeout on backend idle conn. */
h2c->task->expire = TICK_ETERNITY; exp = TICK_ETERNITY;
} }
} }
h2c->task->expire = exp;
}
if ((h2c->proxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && if ((h2c->proxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) &&
is_idle_conn && tick_isset(global.close_spread_end)) { is_idle_conn && tick_isset(global.close_spread_end)) {
/* If a soft-stop is in progress and a close-spread-time /* If a soft-stop is in progress and a close-spread-time
@ -925,8 +939,8 @@ static void h2c_update_timeout(struct h2c *h2c)
task_wakeup(h2c->task, TASK_WOKEN_TIMER); task_wakeup(h2c->task, TASK_WOKEN_TIMER);
} }
} }
}
} else { else {
h2c->task->expire = TICK_ETERNITY; h2c->task->expire = TICK_ETERNITY;
} }