MEDIUM: stconn: Replace read and write timeouts by a unique I/O timeout

Read and write timeouts (.rto and .wto) are now replaced by an unique
timeout, call .ioto. Since the recent refactoring on channel's timeouts,
both use the same value, the client timeout on client side and the server
timeout on the server side. Thus, this part may be simplified. Now it
represents the I/O timeout.
diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h
index ddaf733..5eddd88 100644
--- a/include/haproxy/stconn-t.h
+++ b/include/haproxy/stconn-t.h
@@ -235,8 +235,7 @@
 
 	unsigned int flags;                  /* SC_FL_* */
 	unsigned int hcto;                   /* half-closed timeout (0 = unset) */
-	unsigned int rto;                    /* read timeout, in ticks */
-	unsigned int wto;                    /* write timeout, in ticks */
+	unsigned int ioto;                   /* I/O activity timeout */
 	struct wait_event wait_event;        /* We're in a wait list */
 	struct sedesc *sedesc;               /* points to the stream endpoint descriptor */
 	enum obj_type *app;                  /* points to the applicative point (stream or check) */
diff --git a/src/cli.c b/src/cli.c
index d1d5a56..b683652 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -1597,7 +1597,7 @@
 		if (res || timeout < 1)
 			return cli_err(appctx, "Invalid timeout value.\n");
 
-		s->scf->rto = s->scf->wto = 1 + MS_TO_TICKS(timeout*1000);
+		s->scf->ioto = 1 + MS_TO_TICKS(timeout*1000);
 		task_wakeup(s->task, TASK_WOKEN_MSG); // recompute timeouts
 		return 1;
 	}
@@ -2825,11 +2825,8 @@
 		/* Now we can realign the response buffer */
 		c_realign_if_empty(&s->res);
 
-		s->scf->rto = strm_fe(s)->timeout.client;
-		s->scf->wto = strm_fe(s)->timeout.client;
-
-		s->scb->rto = TICK_ETERNITY;
-		s->scb->wto = TICK_ETERNITY;
+		s->scf->ioto = strm_fe(s)->timeout.client;
+		s->scb->ioto = TICK_ETERNITY;
 
 		sc_ep_reset_rex(s->scf);
 		sc_ep_reset_wex(s->scf);
diff --git a/src/dns.c b/src/dns.c
index d3114fb..003169f 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -835,10 +835,9 @@
 	s->uniq_id = 0;
 
 	s->res.flags |= CF_READ_DONTWAIT;
-	/* for rto and rex to eternity to not expire on idle recv:
+	/* set rex to eternity to not expire on idle recv:
 	 * We are using a syslog server.
 	 */
-	s->scb->rto = TICK_ETERNITY;
 	sc_ep_reset_rex(s->scb);
 
 	ds->appctx = appctx;
diff --git a/src/hlua.c b/src/hlua.c
index 864771a..1771d14 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -3016,8 +3016,8 @@
 	s = appctx_strm(container_of(peer, struct hlua_csk_ctx, xref)->appctx);
 
 	s->sess->fe->timeout.connect = tmout;
-	s->scf->rto = s->scf->wto = tmout;
-	s->scb->rto = s->scb->wto = tmout;
+	s->scf->ioto = tmout;
+	s->scb->ioto = tmout;
 	sc_ep_set_rex(s->scf, tmout);
 	sc_ep_set_wex(s->scf, tmout);
 	sc_ep_set_rex(s->scb, tmout);
@@ -8084,7 +8084,7 @@
 		channel_auto_close(req);
 		channel_erase(req);
 
-		sc_ep_set_wex(s->scb, s->scf->wto);
+		sc_ep_set_wex(s->scb, s->scf->ioto);
 		channel_auto_read(res);
 		channel_auto_close(res);
 		channel_shutr_now(res);
diff --git a/src/http_ana.c b/src/http_ana.c
index 3f15695..cc4163c 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -4438,7 +4438,7 @@
 		channel_auto_close(req);
 		channel_htx_erase(req, htxbuf(&req->buf));
 
-		sc_ep_set_wex(s->scb, s->scf->wto);
+		sc_ep_set_wex(s->scb, s->scf->ioto);
 		channel_auto_read(res);
 		channel_auto_close(res);
 		channel_shutr_now(res);
@@ -4492,7 +4492,7 @@
 	}
 
 end:
-	sc_ep_set_wex(s->scb, s->scf->wto);
+	sc_ep_set_wex(s->scb, s->scf->ioto);
 
 	/* At this staged, HTTP analysis is finished */
 	s->req.analysers &= AN_REQ_FLT_END;
diff --git a/src/http_client.c b/src/http_client.c
index 04e1367..a30a941 100644
--- a/src/http_client.c
+++ b/src/http_client.c
@@ -1059,8 +1059,7 @@
 	s = appctx_strm(appctx);
 	s->target = target;
 	/* set the "timeout server" */
-	s->scb->rto = hc->timeout_server;
-	s->scb->wto = hc->timeout_server;
+	s->scb->ioto = hc->timeout_server;
 
 	if (doresolve) {
 		/* in order to do the set-dst we need to put the address on the front */
diff --git a/src/sink.c b/src/sink.c
index 8d52184..d15de4e 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -327,8 +327,6 @@
 	 * with a syslog server
 	 */
 	sc_ep_reset_rex(sc_opposite(sc));
-	/* rto should not change but it seems the case */
-	sc_opposite(sc)->rto = TICK_ETERNITY;
 
 	if (unlikely(sc_ic(sc)->flags & CF_SHUTW))
 		goto close;
@@ -475,8 +473,6 @@
 	 * with a syslog server
 	 */
 	sc_ep_reset_rex(sc_opposite(sc));
-	/* rto should not change but it seems the case */
-	sc_opposite(sc)->rto = TICK_ETERNITY;
 
 	/* an error was detected */
 	if (unlikely(sc_ic(sc)->flags & CF_SHUTW))
@@ -632,10 +628,9 @@
 	s->uniq_id = 0;
 
 	s->res.flags |= CF_READ_DONTWAIT;
-	/* for rto and rex to eternity to not expire on idle recv:
+	/* Set rex to eternity to not expire on idle recv:
 	 * We are using a syslog server.
 	 */
-	s->scb->rto = TICK_ETERNITY;
 	sc_ep_reset_rex(s->scb);
 	sft->appctx = appctx;
 
diff --git a/src/stconn.c b/src/stconn.c
index f834f70..f65ae15 100644
--- a/src/stconn.c
+++ b/src/stconn.c
@@ -134,7 +134,7 @@
 	sc->obj_type = OBJ_TYPE_SC;
 	sc->flags = SC_FL_NONE;
 	sc->state = SC_ST_INI;
-	sc->rto = sc->wto = sc->hcto = TICK_ETERNITY;
+	sc->ioto = sc->hcto = TICK_ETERNITY;
 	sc->app = NULL;
 	sc->app_ops = NULL;
 	sc->src = NULL;
@@ -570,8 +570,8 @@
 	sc_ep_reset_wex(sc);
 
 	if (tick_isset(sc->hcto)) {
-		sc->rto = sc->hcto;
-		sc_ep_set_rex(sc, sc->rto);
+		sc->ioto = sc->hcto;
+		sc_ep_set_rex(sc, sc->ioto);
 	}
 
 	switch (sc->state) {
@@ -649,7 +649,7 @@
 	 */
 	sc_ep_clr(sc, SE_FL_WAIT_DATA);
 	if (!tick_isset(sc_ep_wex(sc)))
-		sc_ep_set_wex(sc, sc->wto);
+		sc_ep_set_wex(sc, sc->ioto);
 
 	if (!(sc->flags & SC_FL_DONT_WAKE))
 		task_wakeup(sc_strm_task(sc), TASK_WOKEN_IO);
@@ -711,8 +711,8 @@
 	sc_ep_reset_wex(sc);
 
 	if (tick_isset(sc->hcto)) {
-		sc->rto = sc->hcto;
-		sc_ep_set_rex(sc, sc->rto);
+		sc->ioto = sc->hcto;
+		sc_ep_set_rex(sc, sc->ioto);
 	}
 
 	switch (sc->state) {
@@ -844,13 +844,13 @@
 		 */
 		sc_ep_clr(sc, SE_FL_WAIT_DATA);
 		if (!tick_isset(sc_ep_wex(sc)))
-			sc_ep_set_wex(sc, sc->wto);
+			sc_ep_set_wex(sc, sc->ioto);
 	}
 
 	if (likely(oc->flags & CF_WRITE_EVENT)) {
 		/* update timeout if we have written something */
 		if (!(oc->flags & CF_SHUTW) && !channel_is_empty(oc))
-			sc_ep_set_wex(sc, sc->wto);
+			sc_ep_set_wex(sc, sc->ioto);
 
 		if (tick_isset(sc_ep_rex(sc)) && !(sc->flags & SC_FL_INDEP_STR)) {
 			/* Note: to prevent the client from expiring read timeouts
@@ -861,7 +861,7 @@
 			 * of data which can full the socket buffers long before a
 			 * write timeout is detected.
 			 */
-			sc_ep_set_rex(sc, sc->rto);
+			sc_ep_set_rex(sc, sc->ioto);
 		}
 	}
 
@@ -934,8 +934,8 @@
 	sc_ep_reset_wex(sc);
 
 	if (tick_isset(sc->hcto)) {
-		sc->rto = sc->hcto;
-		sc_ep_set_rex(sc, sc->rto);
+		sc->ioto = sc->hcto;
+		sc_ep_set_rex(sc, sc->ioto);
 	}
 
 	/* on shutw we always wake the applet up */
@@ -1008,7 +1008,7 @@
 		return;
 
 	if (!tick_isset(sc_ep_wex(sc)))
-		sc_ep_set_wex(sc, sc->wto);
+		sc_ep_set_wex(sc, sc->ioto);
 
 	if (!channel_is_empty(oc)) {
 		/* (re)start sending */
@@ -1042,7 +1042,7 @@
 	if ((ic->flags & CF_EOI) || sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM))
 		sc_ep_reset_rex(sc);
 	else if (!tick_isset(sc_ep_rex(sc)))
-		sc_ep_set_rex(sc, sc->rto);
+		sc_ep_set_rex(sc, sc->ioto);
 
 	sc_chk_rcv(sc);
 }
@@ -1081,7 +1081,7 @@
 	 */
 	sc_ep_clr(sc, SE_FL_WAIT_DATA);
 	if (!tick_isset(sc_ep_wex(sc))) {
-		sc_ep_set_wex(sc, sc->wto);
+		sc_ep_set_wex(sc, sc->ioto);
 		if (tick_isset(sc_ep_rex(sc)) && !(sc->flags & SC_FL_INDEP_STR)) {
 			/* Note: depending on the protocol, we don't know if we're waiting
 			 * for incoming data or not. So in order to prevent the socket from
@@ -1089,7 +1089,7 @@
 			 * except if it was already infinite or if we have explicitly setup
 			 * independent streams.
 			 */
-			sc_ep_set_rex(sc, sc->rto);
+			sc_ep_set_rex(sc, sc->ioto);
 		}
 	}
 }
@@ -1134,11 +1134,11 @@
 		if (sc_ep_test(sc, SE_FL_ERR_PENDING|SE_FL_ERROR) &&
 		    !channel_is_empty(oc))
 			if (tick_isset(sc_ep_wex(sc)))
-				sc_ep_set_wex(sc, sc->wto);
+				sc_ep_set_wex(sc, sc->ioto);
 
 		if (!(sc->flags & SC_FL_INDEP_STR))
 			if (tick_isset(sc_ep_rex(sc)))
-				sc_ep_set_rex(sc, sc->rto);
+				sc_ep_set_rex(sc, sc->ioto);
 	}
 
 	if (oc->flags & CF_DONT_READ)
@@ -1193,7 +1193,7 @@
 	else if ((ic->flags & (CF_SHUTR|CF_READ_EVENT)) == CF_READ_EVENT) {
 		/* we must re-enable reading if sc_chk_snd() has freed some space */
 		if (tick_isset(sc_ep_rex(sc)))
-			sc_ep_set_rex(sc, sc->rto);
+			sc_ep_set_rex(sc, sc->ioto);
 	}
 
 	/* wake the task up only when needed */
diff --git a/src/stream.c b/src/stream.c
index 0c8fad5..96739fa 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -518,8 +518,7 @@
 		channel_auto_close(&s->req);    /* let the producer forward close requests */
 	}
 
-	s->scf->rto = sess->fe->timeout.client;
-	s->scf->wto = sess->fe->timeout.client;
+	s->scf->ioto = sess->fe->timeout.client;
 	s->req.analyse_exp = TICK_ETERNITY;
 
 	channel_init(&s->res);
@@ -531,8 +530,7 @@
 		s->res.flags |= CF_NEVER_WAIT;
 	}
 
-	s->scb->wto = TICK_ETERNITY;
-	s->scb->rto = TICK_ETERNITY;
+	s->scb->ioto = TICK_ETERNITY;
 	s->res.analyse_exp = TICK_ETERNITY;
 
 	s->txn = NULL;
@@ -851,7 +849,7 @@
 	if (likely(msg && msg->data))
 		co_inject(oc, msg->area, msg->data);
 
-	sc_ep_set_wex(s->scf, s->scf->wto);
+	sc_ep_set_wex(s->scf, s->scf->ioto);
 	channel_auto_read(oc);
 	channel_auto_close(oc);
 	channel_shutr_now(oc);
@@ -861,8 +859,7 @@
 {
 	switch (name) {
 	case ACT_TIMEOUT_SERVER:
-		s->scb->wto = timeout;
-		s->scb->rto = timeout;
+		s->scb->ioto = timeout;
 		return 1;
 
 	case ACT_TIMEOUT_TUNNEL:
@@ -933,10 +930,8 @@
 		 * if already defined, it means that a set-timeout rule has
 		 * been executed so do not overwrite them
 		 */
-		if (!tick_isset(s->scb->wto))
-			s->scb->wto = s->be->timeout.server;
-		if (!tick_isset(s->scb->rto))
-			s->scb->rto = s->be->timeout.server;
+		if (!tick_isset(s->scb->ioto))
+			s->scb->ioto = s->be->timeout.server;
 		if (!tick_isset(s->tunnel_timeout))
 			s->tunnel_timeout = s->be->timeout.tunnel;
 
@@ -2419,22 +2414,17 @@
 		 * the half-closed timeouts as well.
 		 */
 		if (!req->analysers && s->tunnel_timeout) {
-			scf->rto = scf->wto = scb->rto = scb->wto =
-				s->tunnel_timeout;
+			scf->ioto = scb->ioto = s->tunnel_timeout;
 
-			if ((req->flags & CF_SHUTR) && tick_isset(sess->fe->timeout.clientfin))
-				scf->wto = sess->fe->timeout.clientfin;
-			if ((req->flags & CF_SHUTW) && tick_isset(s->be->timeout.serverfin))
-				scb->rto = s->be->timeout.serverfin;
-			if ((res->flags & CF_SHUTR) && tick_isset(s->be->timeout.serverfin))
-				scb->wto = s->be->timeout.serverfin;
-			if ((res->flags & CF_SHUTW) && tick_isset(sess->fe->timeout.clientfin))
-				scf->rto = sess->fe->timeout.clientfin;
+			if ((req->flags & (CF_SHUTR|CF_SHUTW)) && tick_isset(sess->fe->timeout.clientfin))
+				scf->ioto = sess->fe->timeout.clientfin;
+			if ((req->flags & (CF_SHUTR|CF_SHUTW)) && tick_isset(s->be->timeout.serverfin))
+				scb->ioto = s->be->timeout.serverfin;
 
-			sc_ep_set_rex(scf, scf->rto);
-			sc_ep_set_wex(scf, scb->wto);
-			sc_ep_set_rex(scb, scb->rto);
-			sc_ep_set_wex(scb, scf->wto);
+			sc_ep_set_rex(scf, scf->ioto);
+			sc_ep_set_wex(scf, scb->ioto);
+			sc_ep_set_rex(scb, scb->ioto);
+			sc_ep_set_wex(scb, scf->ioto);
 		}
 	}
 
@@ -3899,7 +3889,7 @@
 	if (!smp->strm)
 		return 0;
 
-	smp->data.u.sint = TICKS_TO_MS(smp->strm->scb->rto);
+	smp->data.u.sint = TICKS_TO_MS(smp->strm->scb->ioto);
 	return 1;
 }