[MEDIUM] introduce separation between contimeout, and tarpit + queue

Now the connect timeout, tarpit timeout and queue timeout are
distinct. In order to retain compatibility with older versions,
if either queue or tarpit is left unset both in the proxy and
in the default proxy, then it is inherited from the connect
timeout as before.
diff --git a/src/backend.c b/src/backend.c
index 1eed377..57b421c 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1460,8 +1460,8 @@
 		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 4ebb9ff..91b9f3c 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -502,6 +502,8 @@
 	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 @@
 		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 @@
 
 		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 @@
 		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 @@
 				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 370fded..55c67c1 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2038,17 +2038,17 @@
 			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;
 		}