MEDIUM: mux-h1: Wait for connection establishment before consuming channel's data

When a server is down, the channel's data must not be consumed. This is
required to allow redispatch and connection retry. So now, we wait for
the connection to be marked as connected, with the flag CO_FL_CONNECTED,
before starting to consume channel's data. In the mux, this event is
tracked with the flag H1C_F_CS_WAIT_CONN.
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 456d703..178465a 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -47,6 +47,7 @@
 #define H1C_F_CS_ERROR       0x00001000 /* connection must be closed ASAP because an error occurred */
 #define H1C_F_CS_SHUTW_NOW   0x00002000 /* connection must be shut down for writes ASAP */
 #define H1C_F_CS_SHUTW       0x00004000 /* connection is already shut down */
+#define H1C_F_CS_WAIT_CONN   0x00008000 /* waiting for the connection establishment */
 
 #define H1C_F_WAIT_NEXT_REQ  0x00010000 /*  waiting for the next request to start, use keep-alive timeout */
 
@@ -361,6 +362,9 @@
 	h1c->wait_event.task->context = h1c;
 	h1c->wait_event.wait_reason   = 0;
 
+	if (!(conn->flags & CO_FL_CONNECTED))
+		h1c->flags |= H1C_F_CS_WAIT_CONN;
+
 	/* Always Create a new H1S */
 	if (!h1s_create(h1c, conn->mux_ctx))
 		goto fail;
@@ -843,8 +847,6 @@
 		}
 	}
 
-	// FIXME: check and set HTTP version
-
 	if (!(h1m->flags & H1_MF_RESP)) {
 		if (!htx_add_reqline(htx, sl) || !htx_add_all_headers(htx, hdrs))
 			goto error;
@@ -1196,6 +1198,12 @@
 		b_set_data(&h1s->rxbuf, b_size(&h1s->rxbuf));
 		if (!htx_free_data_space(htx))
 			h1c->flags |= H1C_F_RX_FULL;
+
+		if (h1s->recv_wait) {
+			h1s->recv_wait->wait_reason &= ~SUB_CAN_RECV;
+			tasklet_wakeup(h1s->recv_wait->task);
+			h1s->recv_wait = NULL;
+		}
 	}
 	else
 		h1_release_buf(h1c, &h1s->rxbuf);
@@ -1521,6 +1529,12 @@
 	if (conn->flags & CO_FL_ERROR)
 		return 0;
 
+	if (h1c->flags & H1C_F_CS_WAIT_CONN) {
+		if (!(h1c->wait_event.wait_reason & SUB_CAN_SEND))
+			conn->xprt->subscribe(conn, SUB_CAN_SEND, &h1c->wait_event);
+		return 0;
+	}
+
 	if (!b_data(&h1c->obuf))
 		goto end;
 
@@ -1532,6 +1546,12 @@
 		h1c->flags &= ~H1C_F_OUT_FULL;
 		b_del(&h1c->obuf, ret);
 		sent = 1;
+
+		if (h1c->h1s && h1c->h1s->send_wait) {
+			h1c->h1s->send_wait->wait_reason &= ~SUB_CAN_SEND;
+			tasklet_wakeup(h1c->h1s->send_wait->task);
+			h1c->h1s->send_wait = NULL;
+		}
 	}
 
   end:
@@ -1602,12 +1622,19 @@
 
 	h1_send(h1c);
 
-	h1_wake_stream(h1c);
-
 	if (!conn->mux_ctx)
 		return -1;
 
+	if (h1c->flags & H1C_F_CS_WAIT_CONN) {
+		if (conn->flags & (CO_FL_CONNECTED|CO_FL_ERROR)) {
+			h1c->flags &= ~H1C_F_CS_WAIT_CONN;
+			h1_wake_stream(h1c);
+		}
+		return 0;
+	}
+
 	if ((h1c->flags & H1C_F_CS_ERROR) || (conn->flags & CO_FL_ERROR) || conn_xprt_read0_pending(conn)) {
+		h1_wake_stream(h1c);
 		if (!h1c->h1s || !h1c->h1s->cs) {
 			h1_release(conn);
 			return -1;
@@ -1945,12 +1972,8 @@
 
 	h1c = h1s->h1c;
 
-	/* FIXME: There is a problem when the backend server is down. Channel
-	 * data are consumed, so CF_WROTE_DATA is set by the stream
-	 * interface. We should wait the connection is established before, but
-	 * to do so, we need to have a notification of the connection
-	 * establishment.
-	 */
+	if (h1c->flags & H1C_F_CS_WAIT_CONN)
+		return 0;
 
 	if (!(h1c->flags & (H1C_F_OUT_FULL|H1C_F_OUT_ALLOC)) && b_data(buf))
 		ret = h1_process_output(h1c, buf, count);
@@ -1962,7 +1985,6 @@
 			ret = count;
 	}
 	return ret;
-
 }
 
 #if defined(CONFIG_HAP_LINUX_SPLICE)
diff --git a/src/stream.c b/src/stream.c
index 515dc0d..ae8318d 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -666,11 +666,8 @@
 		return 1;
 	}
 
-	/* FIXME: Add CF_WROTE_DATA because data was already move in the mux in
-	 * h1. Without it, the SI remains in SI_ST_CON state.
-	 */
 	/* we need to wait a bit more if there was no activity either */
-	if (!(req->flags & (CF_WROTE_DATA|CF_WRITE_ACTIVITY)))
+	if (!(req->flags & CF_WRITE_ACTIVITY))
 		return 1;
 
 	/* OK, this means that a connection succeeded. The caller will be