[MEDIUM] process_cli: don't rely at all on server state

A new buffer flag BF_MAY_FORWARD has been added so that the client
FSM can check whether it is allowed to forward the response to the
client. The client FSM does not have to monitor the server state
anymore.
diff --git a/include/types/buffers.h b/include/types/buffers.h
index 8cc8d29..417fe44 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -54,6 +54,7 @@
 #define BF_STREAMER_FAST     8192
 
 #define BF_MAY_CONNECT      16384  /* consumer side is allowed to forward the connection */
+#define BF_MAY_FORWARD      32768  /* consumer side is allowed to forward the data */
 
 /* describes a chunk of string */
 struct chunk {
diff --git a/src/proto_http.c b/src/proto_http.c
index 5d45f02..ea7c764 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -547,6 +547,7 @@
 	t->srv_state = SV_STCLOSE;
 	buffer_shutw_done(t->req);
 	buffer_shutr_done(t->rep);
+	t->rep->flags |= BF_MAY_FORWARD;
 	if (status > 0 && msg) {
 		t->txn.status = status;
 		if (t->fe->mode == PR_MODE_HTTP)
@@ -1644,7 +1645,7 @@
 			t->txn.exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq);
 		} else {
 			t->cli_state = CL_STDATA;
-			req->flags |= BF_MAY_CONNECT;
+			req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
 		}
 		t->inspect_exp = TICK_ETERNITY;
 		return 1;
@@ -2366,14 +2367,14 @@
 		 ************************************************************/
 
 		t->cli_state = CL_STDATA;
-		req->flags |= BF_MAY_CONNECT;
+		req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
 
 		req->rlim = req->data + BUFSIZE; /* no more rewrite needed */
 
 		t->logs.tv_request = now;
 
 		if (!t->fe->timeout.client ||
-		    (t->srv_state < SV_STDATA && t->be->timeout.server)) {
+		    (!(rep->flags & BF_MAY_FORWARD) && t->be->timeout.server)) {
 			/* If the client has no timeout, or if the server is not ready yet,
 			 * and we know for sure that it can expire, then it's cleaner to
 			 * disable the timeout on the client side so that too low values
@@ -2443,14 +2444,14 @@
 			return 1;
 		}
 		/* last read, or end of server write */
-		else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
+		else if (req->flags & (BF_READ_NULL | BF_SHUTW_STATUS)) {
 			EV_FD_CLR(t->cli_fd, DIR_RD);
 			buffer_shutr(req);
 			t->cli_state = CL_STSHUTR;
 			return 1;
 		}	
 		/* last server read and buffer empty */
-		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
+		else if (rep->flags & BF_SHUTR_STATUS && rep->l == 0) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
 			buffer_shutw_done(rep);
 			shutdown(t->cli_fd, SHUT_WR);
@@ -2513,11 +2514,12 @@
 			/* there's still some space in the buffer */
 			if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
 				if (!t->fe->timeout.client ||
-				    (t->srv_state < SV_STDATA && t->be->timeout.server))
+				    (!(rep->flags & BF_MAY_FORWARD) && t->be->timeout.server))
 					/* If the client has no timeout, or if the server not ready yet, and we
 					 * know for sure that it can expire, then it's cleaner to disable the
 					 * timeout on the client side so that too low values cannot make the
-					 * sessions abort too early.
+					 * sessions abort too early. NB: we should only do this in HTTP states
+					 * before HEADERS.
 					 */
 					req->rex = TICK_ETERNITY;
 				else
@@ -2525,8 +2527,8 @@
 			}
 		}
 
-		if ((rep->l == 0) ||
-		    ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
+		/* we don't enable client write if the buffer is empty, nor if the server has to analyze it */
+		if ((rep->l == 0) || !(rep->flags & BF_MAY_FORWARD)) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
 				rep->wex = TICK_ETERNITY;
@@ -2562,7 +2564,7 @@
 			}
 			return 1;
 		}
-		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)
+		else if ((rep->flags & BF_SHUTR_STATUS) && (rep->l == 0)
 			 && !(t->flags & SN_SELF_GEN)) {
 			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
@@ -2596,8 +2598,7 @@
 			}
 		}
 
-		if ((rep->l == 0)
-		    || ((s == SV_STHEADERS) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
+		if ((rep->l == 0) || !(rep->flags & BF_MAY_FORWARD)) {
 			if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
 				/* stop writing */
 				rep->wex = TICK_ETERNITY;
@@ -2628,7 +2629,7 @@
 			}
 			return 1;
 		}
-		else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
+		else if (req->flags & (BF_READ_NULL | BF_SHUTW_STATUS)) {
 			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
@@ -2950,6 +2951,7 @@
 				EV_FD_SET(t->srv_fd, DIR_RD);
 				rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
 				t->srv_state = SV_STDATA;
+				rep->flags |= BF_MAY_FORWARD;
 				rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */
 
 				/* if the user wants to log as soon as possible, without counting
@@ -3468,6 +3470,7 @@
 		 ************************************************************/
 
 		t->srv_state = SV_STDATA;
+		rep->flags |= BF_MAY_FORWARD;
 		rep->rlim = rep->data + BUFSIZE; /* no more rewrite needed */
 		t->logs.t_data = tv_ms_elapsed(&t->logs.tv_accept, &now);