]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] introduce the "timeout" keyword
authorWilly Tarreau <w@1wt.eu>
Mon, 3 Dec 2007 00:30:13 +0000 (01:30 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 3 Dec 2007 00:30:13 +0000 (01:30 +0100)
A new "timeout" keyword replaces old "{con|cli|srv}timeout", and
provides the ability to independantly set the following timeouts :

  - client
  - tarpit
  - queue
  - connect
  - server
  - appsession

Additionally, the "clitimeout", "contimeout" and "srvtimeout" values
are supported but deprecated. No warning is emitted yet when they are
used since the option is very new.

Other timeouts should follow soon now.

doc/configuration.txt
include/proto/proxy.h
src/cfgparse.c
src/proxy.c
tests/test-timeout.cfg [new file with mode: 0644]

index 6a0da4e169d8840702cb8d51e4c98e2ce6189c5b..c9ba70dcb2053c6e78e77641e1d619e3046f37fa 100644 (file)
@@ -244,8 +244,8 @@ block                       -          X         X         X
 capture cookie              X          X         X         X
 capture request header      X          X         X         X
 capture response header     X          X         X         X
-clitimeout                  X          X         X         -
-contimeout                  X          X         X         X
+clitimeout                  X          X         X         -  (deprecated)
+contimeout                  X          X         X         X  (deprecated)
 cookie                      X          -         X         X
 default_backend             -          X         X         -
 disabled                    -          X         X         X
@@ -314,7 +314,7 @@ rspirep                     -          X         X         X
 rsprep                      -          X         X         X
 server                      -          -         X         X
 source                      X          -         X         X
-srvtimeout                  X          -         X         X
+srvtimeout                  X          -         X         X  (deprecated)
 stats auth                  X          -         X         X
 stats enable                X          -         X         X
 stats realm                 X          -         X         X
@@ -322,6 +322,15 @@ stats refresh               X          -         X         X
 stats scope                 X          -         X         X
 stats uri                   X          -         X         X
 stats hide-version          X          -         X         X
+timeout appsession          X          -         X         X
+timeout client              X          X         X         -
+timeout clitimeout          X          X         X         -  (deprecated)
+timeout connect             X          -         X         X
+timeout contimeout          X          -         X         X  (deprecated)
+timeout queue               X          -         X         X
+timeout server              X          -         X         X
+timeout srvtimeout          X          -         X         X  (deprecated)
+timeout tarpit              X          X         X         -
 transparent                 X          X         X         -
 use_backend                 -          X         X         -
 usesrc                      X          -         X         X
index a0c86cb877fdc7cafb228bbe4bda98a6279e2ee0..f00f6469739ac015eebd1f8f0bc4ee1dd20f27c3 100644 (file)
@@ -36,6 +36,8 @@ void listen_proxies(void);
 const char *proxy_cap_str(int cap);
 const char *proxy_mode_str(int mode);
 struct proxy *findproxy(const char *name, int mode, int cap);
+int proxy_parse_timeout(const char **args, struct proxy *proxy,
+                       struct proxy *defpx, char *err, int errlen);
 
 /*
  * This function returns a string containing the type of the proxy in a format
index 91b9f3ccd05d3879d0d7fc4edf08eae0eecb39e0..8bb787e8869a0cb9ac447d10c55d64fbeea84ab5 100644 (file)
@@ -976,78 +976,26 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                        return -1;
                }
        }
-       else if (!strcmp(args[0], "contimeout")) {  /* connect timeout */
-               if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
-                       Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
-                       return 0;
-               }
-               else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+       else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
+                !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
 
-               if (*(args[1]) == 0) {
-                       Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
-                             file, linenum, args[0]);
-                       return -1;
-               }
-               err = parse_time_err(args[1], &val, TIME_UNIT_MS);
-               if (err) {
-                       Alert("parsing [%s:%d] : unexpected character '%c' in %s.\n",
-                             file, linenum, *err, args[0]);
-                       return -1;
-               }
-               if (val > 0)
-                       __tv_from_ms(&curproxy->contimeout, val);
-               else
-                       tv_eternity(&curproxy->contimeout);
-       }
-       else if (!strcmp(args[0], "clitimeout")) {  /*  client timeout */
-               if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
-                       Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
-                             file, linenum, args[0]);
-                       return 0;
-               }
-               else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
-                       return 0;
+               /* either we have {con|srv|cli}timeout <value> or we have the
+                * new form: timeout <type> <value>. The parser needs the word
+                * preceeding the value.
+                */
+               const char **start_arg = (const char **)args;
 
-               if (*(args[1]) == 0) {
-                       Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
-                             file, linenum, args[0]);
-                       return -1;
-               }
-               err = parse_time_err(args[1], &val, TIME_UNIT_MS);
-               if (err) {
-                       Alert("parsing [%s:%d] : unexpected character '%c' in %s.\n",
-                             file, linenum, *err, args[0]);
-                       return -1;
-               }
-               if (val > 0)
-                       __tv_from_ms(&curproxy->clitimeout, val);
-               else
-                       tv_eternity(&curproxy->clitimeout);
-       }
-       else if (!strcmp(args[0], "srvtimeout")) {  /*  server timeout */
-               if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
-                       Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
-                       return 0;
-               }
-               else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
-                       return 0;
+               if (strcmp(args[0], "timeout") == 0)
+                       start_arg++;
 
-               if (*(args[1]) == 0) {
-                       Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
-                             file, linenum, args[0]);
-                       return -1;
-               }
-               err = parse_time_err(args[1], &val, TIME_UNIT_MS);
-               if (err) {
-                       Alert("parsing [%s:%d] : unexpected character '%c' in %s.\n",
-                             file, linenum, *err, args[0]);
+               snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
+               rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
+               if (rc < 0) {
+                       Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
                        return -1;
                }
-               if (val > 0)
-                       __tv_from_ms(&curproxy->srvtimeout, val);
-               else
-                       tv_eternity(&curproxy->srvtimeout);
+               if (rc > 0)
+                       Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
        }
        else if (!strcmp(args[0], "retries")) {  /* connection retries */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
index 06424c62c13411dbd9897f16ae1534e2a4e045ee..8263964974dd613846b363db0213aec92f401dea 100644 (file)
@@ -75,6 +75,89 @@ const char *proxy_mode_str(int mode) {
                return "unknown";
 }
 
+/* This function parses a "timeout" statement in a proxy section. It returns
+ * -1 if there is any error, 1 for a warning, otherwise zero. If it does not
+ * return zero, it may write an error message into the <err> buffer, for at
+ * most <errlen> bytes, trailing zero included. The trailing '\n' must not
+ * be written. The function must be called with <args> pointing to the first
+ * word after "timeout", with <proxy> pointing to the proxy being parsed, and
+ * <defpx> to the default proxy or NULL. As a special case for compatibility
+ * with older configs, it also accepts "{cli|srv|con}timeout" in args[0].
+ */
+int proxy_parse_timeout(const char **args, struct proxy *proxy,
+                       struct proxy *defpx, char *err, int errlen)
+{
+       unsigned timeout;
+       int retval, cap;
+       const char *res, *name;
+       struct timeval *tv = NULL;
+       struct timeval *td = NULL;
+
+       retval = 0;
+       name = args[0];
+       if (!strcmp(args[0], "client") || !strcmp(args[0], "clitimeout")) {
+               name = "client";
+               tv = &proxy->clitimeout;
+               td = &defpx->clitimeout;
+               cap = PR_CAP_FE;
+       } else if (!strcmp(args[0], "tarpit")) {
+               tv = &proxy->timeout.tarpit;
+               td = &defpx->timeout.tarpit;
+               cap = PR_CAP_FE;
+       } else if (!strcmp(args[0], "server") || !strcmp(args[0], "srvtimeout")) {
+               name = "server";
+               tv = &proxy->srvtimeout;
+               td = &defpx->srvtimeout;
+               cap = PR_CAP_BE;
+       } else if (!strcmp(args[0], "connect") || !strcmp(args[0], "contimeout")) {
+               name = "connect";
+               tv = &proxy->contimeout;
+               td = &defpx->contimeout;
+               cap = PR_CAP_BE;
+       } else if (!strcmp(args[0], "appsession")) {
+               tv = &proxy->appsession_timeout;
+               td = &defpx->appsession_timeout;
+               cap = PR_CAP_BE;
+       } else if (!strcmp(args[0], "queue")) {
+               tv = &proxy->timeout.queue;
+               td = &defpx->timeout.queue;
+               cap = PR_CAP_BE;
+       } else {
+               snprintf(err, errlen, "timeout '%s': must be 'client', 'server', 'connect', 'appsession', 'queue', or 'tarpit'",
+                        args[0]);
+               return -1;
+       }
+
+       if (*args[1] == 0) {
+               snprintf(err, errlen, "%s timeout expects an integer value (in milliseconds)", name);
+               return -1;
+       }
+
+       res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
+       if (res) {
+               snprintf(err, errlen, "unexpected character '%c' in %s timeout", *err, name);
+               return -1;
+       }
+
+       if (!(proxy->cap & cap)) {
+               snprintf(err, errlen, "%s timeout will be ignored because %s '%s' has no %s capability",
+                        name, proxy_type_str(proxy), proxy->id,
+                        (cap & PR_CAP_BE) ? "backend" : "frontend");
+               retval = 1;
+       }
+       else if (defpx && !__tv_iseq(tv, td)) {
+               snprintf(err, errlen, "overwriting %s timeout which was already specified", name);
+               retval = 1;
+       }
+
+       if (timeout)
+               __tv_from_ms(tv, timeout);
+       else
+               tv_eternity(tv);
+
+       return retval;
+}
+
 /*
  * This function finds a proxy with matching name, mode and with satisfying
  * capabilities. It also checks if there are more matching proxies with
diff --git a/tests/test-timeout.cfg b/tests/test-timeout.cfg
new file mode 100644 (file)
index 0000000..7053f5c
--- /dev/null
@@ -0,0 +1,26 @@
+# This is a test configuration.
+# It is used to check that time units are correctly parsed.
+
+global
+       maxconn    1000
+        stats timeout 3s
+
+listen  sample1
+        mode       http
+        retries    1
+        redispatch
+        timeout    client  15m
+        timeout    tarpit  20s
+        timeout    queue   60s
+        timeout    connect 5s
+        timeout    server  15m
+        maxconn    40000
+        bind       :8000
+        balance    roundrobin
+       option     allbackups
+        server     act1 127.0.0.1:80 weight 10 check port 81 inter 500ms fall 1
+        server     act2 127.0.0.2:80 weight 20 check port 81 inter 500ms fall 1
+        server     act3 127.0.0.3:80 weight 30 check port 81 inter 500ms fall 1
+        option     httpclose
+       stats      uri /stats
+       stats      refresh 5000ms