diff --git a/include/types/proxy.h b/include/types/proxy.h index 61247e644..ae6e337d5 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -173,6 +173,10 @@ struct proxy { struct timeval srvtimeout; /* server I/O timeout (in milliseconds) */ struct timeval contimeout; /* connect timeout (in milliseconds) */ struct timeval appsession_timeout; + struct { + struct timeval queue; /* queue timeout, defaults to contimeout if unspecified */ + struct timeval tarpit; /* tarpit timeout, defaults to contimeout if unspecified */ + } timeout; char *id; /* proxy id */ struct list pendconns; /* pending connections with no server assigned yet */ int nbpend, nbpend_max; /* number of pending connections with no server assigned yet */ diff --git a/src/backend.c b/src/backend.c index 1eed377e9..57b421cf0 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1460,8 +1460,8 @@ int srv_redispatch_connect(struct session *t) return 1; case SRV_STATUS_QUEUED: - /* FIXME-20060503 : we should use the queue timeout instead */ - if (!tv_add_ifset(&t->req->cex, &now, &t->be->contimeout)) + /* note: we use the connect expiration date for the queue. */ + if (!tv_add_ifset(&t->req->cex, &now, &t->be->timeout.queue)) tv_eternity(&t->req->cex); t->srv_state = SV_STIDLE; /* do nothing else and do not wake any other session up */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 4ebb9ff17..91b9f3ccd 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -502,6 +502,8 @@ static void init_default_instance() tv_eternity(&defproxy.contimeout); tv_eternity(&defproxy.srvtimeout); tv_eternity(&defproxy.appsession_timeout); + tv_eternity(&defproxy.timeout.queue); + tv_eternity(&defproxy.timeout.tarpit); } /* @@ -582,6 +584,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args) tv_eternity(&curproxy->srvtimeout); tv_eternity(&curproxy->contimeout); tv_eternity(&curproxy->appsession_timeout); + tv_eternity(&curproxy->timeout.queue); + tv_eternity(&curproxy->timeout.tarpit); curproxy->last_change = now.tv_sec; curproxy->id = strdup(args[1]); @@ -640,6 +644,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (curproxy->cap & PR_CAP_FE) { curproxy->clitimeout = defproxy.clitimeout; + curproxy->timeout.tarpit = defproxy.timeout.tarpit; curproxy->uri_auth = defproxy.uri_auth; curproxy->mon_net = defproxy.mon_net; curproxy->mon_mask = defproxy.mon_mask; @@ -653,6 +658,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (curproxy->cap & PR_CAP_BE) { curproxy->contimeout = defproxy.contimeout; curproxy->srvtimeout = defproxy.srvtimeout; + curproxy->timeout.queue = defproxy.timeout.queue; curproxy->source_addr = defproxy.source_addr; } @@ -2738,6 +2744,39 @@ int readcfgfile(const char *file) file, proxy_type_str(curproxy), curproxy->id); } + /* Historically, the tarpit and queue timeouts were inherited from contimeout. + * We must still support older configurations, so let's find out whether those + * parameters have been set or must be copied from contimeouts. + */ + if (curproxy != &defproxy) { + if ((curproxy->cap & PR_CAP_FE) && + (!tv_isset(&curproxy->timeout.tarpit) || + __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit))) { + /* tarpit timeout not set. We search in the following order: + * default.tarpit, curr.connect, default.connect. + */ + if (tv_isset(&defproxy.timeout.tarpit)) + curproxy->timeout.tarpit = defproxy.timeout.tarpit; + else if (tv_isset(&curproxy->contimeout)) + curproxy->timeout.tarpit = curproxy->contimeout; + else if (tv_isset(&defproxy.contimeout)) + curproxy->timeout.tarpit = defproxy.contimeout; + } + if ((curproxy->cap & PR_CAP_BE) && + (!tv_isset(&curproxy->timeout.queue) || + __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) { + /* queue timeout not set. We search in the following order: + * default.queue, curr.connect, default.connect. + */ + if (tv_isset(&defproxy.timeout.queue)) + curproxy->timeout.queue = defproxy.timeout.queue; + else if (tv_isset(&curproxy->contimeout)) + curproxy->timeout.queue = curproxy->contimeout; + else if (tv_isset(&defproxy.contimeout)) + curproxy->timeout.queue = defproxy.contimeout; + } + } + if (curproxy->options & PR_O_SSL3_CHK) { curproxy->check_len = sizeof(sslv3_client_hello_pkt); curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt)); diff --git a/src/proto_http.c b/src/proto_http.c index 370fded29..55c67c1b8 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2038,17 +2038,17 @@ int process_cli(struct session *t) tv_eternity(&req->rex); } - /* When a connection is tarpitted, we use the queue timeout for the - * tarpit delay, which currently happens to be the server's connect - * timeout. If unset, then set it to zero because we really want it - * to expire at one moment. + /* When a connection is tarpitted, we use the tarpit timeout, + * which may be the same as the connect timeout if unspecified. + * If unset, then set it to zero because we really want it to + * eventually expire. */ if (txn->flags & TX_CLTARPIT) { t->req->l = 0; /* flush the request so that we can drop the connection early * if the client closes first. */ - if (!tv_add_ifset(&req->cex, &now, &t->be->contimeout)) + if (!tv_add_ifset(&req->cex, &now, &t->be->timeout.tarpit)) req->cex = now; }