MEDIUM: stream: support a dynamic tunnel timeout

Allow the modification of the tunnel timeout on the stream side.
Use a new field in the stream for the tunnel timeout. It is initialized
by the tunnel timeout from backend unless it has already been set by a
set-timeout tunnel rule.
diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h
index b2c8378..5d9d245 100644
--- a/include/haproxy/stream-t.h
+++ b/include/haproxy/stream-t.h
@@ -191,6 +191,8 @@
 		/* 4 unused bytes here */
 		struct act_rule *parent;        /* rule which requested this resolution */
 	} dns_ctx;                              /* context information for DNS resolution */
+
+	int tunnel_timeout;
 };
 
 #endif /* _HAPROXY_STREAM_T_H */
diff --git a/src/stream.c b/src/stream.c
index bed65b2..e43eace 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -504,6 +504,8 @@
 	s->dns_ctx.hostname_dn_len = 0;
 	s->dns_ctx.parent = NULL;
 
+	s->tunnel_timeout = TICK_ETERNITY;
+
 	HA_SPIN_LOCK(STRMS_LOCK, &streams_lock);
 	LIST_ADDQ(&streams, &s->list);
 	HA_SPIN_UNLOCK(STRMS_LOCK, &streams_lock);
@@ -819,6 +821,10 @@
 		s->res.rto = timeout;
 		return 1;
 
+	case ACT_TIMEOUT_TUNNEL:
+		s->tunnel_timeout = timeout;
+		return 1;
+
 	default:
 		return 0;
 	}
@@ -900,6 +906,8 @@
 			req->wto = s->be->timeout.server;
 		if (!tick_isset(rep->rto))
 			rep->rto = s->be->timeout.server;
+		if (!tick_isset(s->tunnel_timeout))
+			s->tunnel_timeout = s->be->timeout.tunnel;
 
 		/* The connection is now established, try to read data from the
 		 * underlying layer, and subscribe to recv events. We use a
@@ -2186,9 +2194,9 @@
 		 * tunnel timeout set, use it now. Note that we must respect
 		 * the half-closed timeouts as well.
 		 */
-		if (!req->analysers && s->be->timeout.tunnel) {
+		if (!req->analysers && s->tunnel_timeout) {
 			req->rto = req->wto = res->rto = res->wto =
-				s->be->timeout.tunnel;
+				s->tunnel_timeout;
 
 			if ((req->flags & CF_SHUTR) && tick_isset(sess->fe->timeout.clientfin))
 				res->wto = sess->fe->timeout.clientfin;