MEDIUM: conn-stream: Move remaning flags from CS to endpoint

All old flags CS_FL_* are now moved in the endpoint scope and renamed
CS_EP_* accordingly. It is a systematic replacement. There is no true change
except for the health-check and the endpoint reset. Here it is a bit special
because the same conn-stream is reused. Thus, we must handle endpoint
allocation errors. To do so, cs_reset_endp() has been adapted.

Thanks to this last change, it will now be possible to simplify the
multiplexer and probably the applets too. A review must also be performed to
remove some flags in the channel or the stream-interface. The HTX will
probably be simplified too. Finally, there is now some place in the
conn-stream to move info from the stream-interface.
diff --git a/addons/promex/service-prometheus.c b/addons/promex/service-prometheus.c
index 61bf465..e02da75 100644
--- a/addons/promex/service-prometheus.c
+++ b/addons/promex/service-prometheus.c
@@ -1523,7 +1523,7 @@
 				channel_add_input(res, 1);
 			}
 		        res_htx->flags |= HTX_FL_EOM;
-			si->cs->flags |= CS_FL_EOI;
+			si->cs->endp->flags |= CS_EP_EOI;
 			res->flags |= CF_EOI;
 			appctx->st0 = PROMEX_ST_END;
 			/* fall through */
diff --git a/dev/flags/flags.c b/dev/flags/flags.c
index 08cb2e8..ddfd879 100644
--- a/dev/flags/flags.c
+++ b/dev/flags/flags.c
@@ -189,6 +189,12 @@
 	}
 	SHOW_FLAG(f, CS_EP_KILL_CONN);
 	SHOW_FLAG(f, CS_EP_WAIT_FOR_HS);
+	SHOW_FLAG(f, CS_EP_WANT_ROOM);
+	SHOW_FLAG(f, CS_EP_ERROR);
+	SHOW_FLAG(f, CS_EP_ERR_PENDING);
+	SHOW_FLAG(f, CS_EP_EOS);
+	SHOW_FLAG(f, CS_EP_EOI);
+	SHOW_FLAG(f, CS_EP_RCV_MORE);
 	SHOW_FLAG(f, CS_EP_MAY_SPLICE);
 	SHOW_FLAG(f, CS_EP_WEBSOCKET);
 	SHOW_FLAG(f, CS_EP_NOT_FIRST);
@@ -213,12 +219,6 @@
 		printf("0\n");
 		return;
 	}
-	SHOW_FLAG(f, CS_FL_EOI);
-	SHOW_FLAG(f, CS_FL_EOS);
-	SHOW_FLAG(f, CS_FL_ERR_PENDING);
-	SHOW_FLAG(f, CS_FL_WANT_ROOM);
-	SHOW_FLAG(f, CS_FL_RCV_MORE);
-	SHOW_FLAG(f, CS_FL_ERROR);
 
 	if (f) {
 		printf("EXTRA(0x%08x)", f);
diff --git a/include/haproxy/conn_stream-t.h b/include/haproxy/conn_stream-t.h
index 842ce84..bde6600 100644
--- a/include/haproxy/conn_stream-t.h
+++ b/include/haproxy/conn_stream-t.h
@@ -54,30 +54,30 @@
 	/* following flags are supposed to be set by the endpoint and read by
 	 * the app layer :
 	 */
+	 /* Permanent flags */
 	CS_EP_NOT_FIRST  = 0x00001000,  /* This conn-stream is not the first one for the endpoint */
 	CS_EP_WEBSOCKET  = 0x00002000,  /* The endpoint uses the websocket proto */
-	CS_EP_MAY_SPLICE = 0x00004000,  /* The endpoint may use the kernel splicing to forward data to the other side (implies CS_EP_CAN_SPLICE) */
+	CS_EP_EOI        = 0x00004000,  /* end-of-input reached */
+	CS_EP_EOS        = 0x00008000,  /* End of stream delivered to data layer */
+	CS_EP_ERROR      = 0x00010000,  /* a fatal error was reported */
+	/* Transient flags */
+	CS_EP_ERR_PENDING= 0x00020000,  /* An error is pending, but there's still data to be read */
+	CS_EP_MAY_SPLICE = 0x00040000,  /* The endpoint may use the kernel splicing to forward data to the other side (implies CS_EP_CAN_SPLICE) */
+	CS_EP_RCV_MORE   = 0x00080000,  /* Endpoint may have more bytes to transfer */
+	CS_EP_WANT_ROOM  = 0x00100000,  /* More bytes to transfer, but not enough room */
 
-	 /* unused: 0x00008000 */
+	 /* unused: 0x00200000 ..  0x00800000 */
 
 	/* following flags are supposed to be set by the app layer and read by
 	 * the endpoint :
 	 */
-	CS_EP_WAIT_FOR_HS   = 0x00010000,  /* This stream is waiting for handhskae */
-	CS_EP_KILL_CONN     = 0x00020000,  /* must kill the connection when the CS closes */
+	CS_EP_WAIT_FOR_HS   = 0x01000000,  /* This stream is waiting for handhskae */
+	CS_EP_KILL_CONN     = 0x02000000,  /* must kill the connection when the CS closes */
  };
 
 /* conn_stream flags */
 enum {
 	CS_FL_NONE          = 0x00000000,  /* Just for initialization purposes */
-
-	CS_FL_ERROR         = 0x00000100,  /* a fatal error was reported */
-	CS_FL_RCV_MORE      = 0x00000200,  /* We may have more bytes to transfer */
-	CS_FL_WANT_ROOM     = 0x00000400,  /* More bytes to transfer, but not enough room */
-	CS_FL_ERR_PENDING   = 0x00000800,  /* An error is pending, but there's still data to be read */
-	CS_FL_EOS           = 0x00001000,  /* End of stream delivered to data layer */
-	/* unused: 0x00002000 */
-	CS_FL_EOI           = 0x00004000,  /* end-of-input reached */
 };
 
 /* cs_shutr() modes */
diff --git a/include/haproxy/conn_stream.h b/include/haproxy/conn_stream.h
index ca5a99c..aa708c7 100644
--- a/include/haproxy/conn_stream.h
+++ b/include/haproxy/conn_stream.h
@@ -210,13 +210,13 @@
 	cs_shutr(cs, CS_SHR_DRAIN);
 }
 
-/* sets CS_FL_ERROR or CS_FL_ERR_PENDING on the cs */
+/* sets CS_EP_ERROR or CS_EP_ERR_PENDING on the cs */
 static inline void cs_set_error(struct conn_stream *cs)
 {
-	if (cs->flags & CS_FL_EOS)
-		cs->flags |= CS_FL_ERROR;
+	if (cs->endp->flags & CS_EP_EOS)
+		cs->endp->flags |= CS_EP_ERROR;
 	else
-		cs->flags |= CS_FL_ERR_PENDING;
+		cs->endp->flags |= CS_EP_ERR_PENDING;
 }
 
 /* Retrieves any valid conn_stream from this connection, preferably the first
diff --git a/src/backend.c b/src/backend.c
index f57d05d..09f10e8 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1743,7 +1743,7 @@
 	 * sockets, socket pairs, and occasionally TCP connections on the
 	 * loopback on a heavily loaded system.
 	 */
-	if ((srv_conn->flags & CO_FL_ERROR || s->csb->flags & CS_FL_ERROR))
+	if ((srv_conn->flags & CO_FL_ERROR || s->csb->endp->flags & CS_EP_ERROR))
 		cs_si(s->csb)->flags |= SI_FL_ERR;
 
 	/* If we had early data, and the handshake ended, then
@@ -1769,7 +1769,7 @@
 	 *       wake callback. Otherwise si_cs_recv()/si_cs_send() already take
 	 *       care of it.
 	 */
-	if ((s->csb->flags & CS_FL_EOI) && !(si_ic(cs_si(s->csb))->flags & CF_EOI))
+	if ((s->csb->endp->flags & CS_EP_EOI) && !(si_ic(cs_si(s->csb))->flags & CF_EOI))
 		si_ic(cs_si(s->csb))->flags |= (CF_EOI|CF_READ_PARTIAL);
 
 	/* catch all sync connect while the mux is not already installed */
diff --git a/src/cache.c b/src/cache.c
index 1aa1103..ce6c7ea 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1500,7 +1500,7 @@
 	if (appctx->st0 == HTX_CACHE_EOM) {
 		 /* no more data are expected. */
 		res_htx->flags |= HTX_FL_EOM;
-		si->cs->flags |= CS_FL_EOI;
+		si->cs->endp->flags |= CS_EP_EOI;
 		res->flags |= CF_EOI;
 		appctx->st0 = HTX_CACHE_END;
 	}
diff --git a/src/check.c b/src/check.c
index 47a53db..058b233 100644
--- a/src/check.c
+++ b/src/check.c
@@ -795,7 +795,7 @@
 		retrieve_errno_from_socket(conn);
 
 	if (conn && !(conn->flags & CO_FL_ERROR) &&
-	    cs && !(cs->flags & CS_FL_ERROR) && !expired)
+	    cs && !(cs->endp->flags & CS_EP_ERROR) && !expired)
 		return;
 
 	TRACE_ENTER(CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check, 0, 0, (size_t[]){expired});
@@ -914,7 +914,7 @@
 	}
 	else if (conn->flags & CO_FL_WAIT_L4_CONN) {
 		/* L4 not established (yet) */
-		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
+		if (conn->flags & CO_FL_ERROR || cs->endp->flags & CS_EP_ERROR)
 			set_server_check_status(check, HCHK_STATUS_L4CON, err_msg);
 		else if (expired)
 			set_server_check_status(check, HCHK_STATUS_L4TOUT, err_msg);
@@ -929,12 +929,12 @@
 	}
 	else if (conn->flags & CO_FL_WAIT_L6_CONN) {
 		/* L6 not established (yet) */
-		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
+		if (conn->flags & CO_FL_ERROR || cs->endp->flags & CS_EP_ERROR)
 			set_server_check_status(check, HCHK_STATUS_L6RSP, err_msg);
 		else if (expired)
 			set_server_check_status(check, HCHK_STATUS_L6TOUT, err_msg);
 	}
-	else if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
+	else if (conn->flags & CO_FL_ERROR || cs->endp->flags & CS_EP_ERROR) {
 		/* I/O error after connection was established and before we could diagnose */
 		set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
 	}
@@ -1037,7 +1037,7 @@
 	cs = check->cs;
 	conn = cs_conn(cs);
 
-	if (unlikely(!conn || !cs || conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) {
+	if (unlikely(!conn || !cs || conn->flags & CO_FL_ERROR || cs->endp->flags & CS_EP_ERROR)) {
 		/* We may get error reports bypassing the I/O handlers, typically
 		 * the case when sending a pure TCP check which fails, then the I/O
 		 * handlers above are not called. This is completely handled by the
@@ -1135,13 +1135,17 @@
 
 		check->current_step = NULL;
 
-		if (check->cs->flags & CS_FL_ERROR) {
-			check->cs->flags &= ~CS_FL_ERROR;
+		if (!check->cs->endp) {
+			/* CS endpoint may be NULL if a previous reset
+			 * failed. Try to allocate a new one and report a
+			 * SOCKERR if it fails.
+			 */
 			check->cs->endp = cs_endpoint_new();
-			if (!check->cs->endp)
-				check->cs->flags |= CS_FL_ERROR;
-			else
-				check->cs->endp->flags |=  CS_EP_DETACHED;
+			if (!check->cs->endp) {
+				set_server_check_status(check, HCHK_STATUS_SOCKERR, NULL);
+				goto end;
+			}
+			check->cs->endp->flags |= CS_EP_DETACHED;
 		}
 		tcpcheck_main(check);
 		expired = 0;
@@ -1157,7 +1161,7 @@
 		/* Here the connection must be defined. Otherwise the
 		 * error would have already been detected
 		 */
-		if ((conn && ((conn->flags & CO_FL_ERROR) || (check->cs->flags & CS_FL_ERROR))) || expired) {
+		if ((conn && ((conn->flags & CO_FL_ERROR) || (check->cs->endp->flags & CS_EP_ERROR))) || expired) {
 			TRACE_ERROR("report connection error", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
 			chk_report_conn_err(check, 0, expired);
 		}
@@ -1165,9 +1169,8 @@
 			if (check->state & CHK_ST_CLOSE_CONN) {
 				TRACE_DEVEL("closing current connection", CHK_EV_TASK_WAKE|CHK_EV_HCHK_RUN, check);
 				check->state &= ~CHK_ST_CLOSE_CONN;
-				if (cs_reset_endp(check->cs) < 0)
-					check->cs->flags |= CS_FL_ERROR;
 				conn = NULL;
+				cs_reset_endp(check->cs); /* error will be handled by tcpcheck_main() */
 				tcpcheck_main(check);
 			}
 			if (check->result == CHK_RES_UNKNOWN) {
@@ -1201,12 +1204,9 @@
 	 */
 	tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
 
-	if (cs_reset_endp(check->cs) < 0) {
-		/* If an error occurred at this stage, it will be fixed by the
-		 * next check
-		 */
-		check->cs->flags |= CS_FL_ERROR;
-	}
+	/* Force detach on error. the endpoint will be recreated on the next start */
+	if (cs_reset_endp(check->cs) < 0)
+		cs_detach_endp(check->cs);
 
 	if (check->sess != NULL) {
 		vars_prune(&check->vars, check->sess, NULL);
@@ -1214,6 +1214,7 @@
 		check->sess = NULL;
 	}
 
+  end:
 	if (check->server && likely(!(check->state & CHK_ST_PURGE))) {
 		if (check->result == CHK_RES_FAILED) {
 			/* a failure or timeout detected */
diff --git a/src/conn_stream.c b/src/conn_stream.c
index d45eba6..bb51784 100644
--- a/src/conn_stream.c
+++ b/src/conn_stream.c
@@ -222,6 +222,9 @@
  */
 void cs_detach_endp(struct conn_stream *cs)
 {
+	if (!cs->endp)
+		goto reset_cs;
+
 	if (cs->endp->flags & CS_EP_T_MUX) {
 		struct connection *conn = cs_conn(cs);
 
@@ -260,6 +263,7 @@
 		cs->endp->flags |= CS_EP_DETACHED;
 	}
 
+  reset_cs:
 	/* FIXME: Rest CS for now but must be reviewed. CS flags are only
 	 *        connection related for now but this will evolved
 	 */
@@ -285,15 +289,29 @@
 
 int cs_reset_endp(struct conn_stream *cs)
 {
+	struct cs_endpoint *new_endp;
+
 	BUG_ON(!cs->app);
-	cs_detach_endp(cs);
-	if (!cs->endp) {
-		cs->endp = cs_endpoint_new();
-		if (!cs->endp) {
-			cs->flags |= CS_FL_ERROR;
-			return -1;
-		}
-		cs->endp->flags |= CS_EP_DETACHED;
+	if (!__cs_endp_target(cs)) {
+		/* endpoint not attached or attached to a mux with no
+		 * target. Thus the endpoint will not be release but just
+		 * reset
+		 */
+		cs_detach_endp(cs);
+		return 0;
 	}
+
+	/* allocate the new endpoint first to be able to set error if it
+	 * fails */
+	new_endp = cs_endpoint_new();
+	if (!unlikely(new_endp)) {
+		cs->endp->flags |= CS_EP_ERROR;
+		return -1;
+	}
+
+	cs_detach_endp(cs);
+	BUG_ON(cs->endp);
+	cs->endp = new_endp;
+	cs->endp->flags |= CS_EP_DETACHED;
 	return 0;
 }
diff --git a/src/hlua.c b/src/hlua.c
index af26aae..931e741 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -9576,7 +9576,7 @@
 		}
 
 		res_htx->flags |= HTX_FL_EOM;
-		si->cs->flags |= CS_FL_EOI;
+		si->cs->endp->flags |= CS_EP_EOI;
 		res->flags |= CF_EOI;
 		strm->txn->status = ctx->ctx.hlua_apphttp.status;
 		ctx->ctx.hlua_apphttp.flags |= APPLET_RSP_SENT;
diff --git a/src/http_ana.c b/src/http_ana.c
index 57bb3f1..05b62fe 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -1256,7 +1256,6 @@
 	res->total = 0;
 
 	if (cs_reset_endp(s->csb) < 0) {
-		s->csb->flags |= CS_FL_ERROR;
 		if (!(s->flags & SF_ERR_MASK))
 			s->flags |= SF_ERR_INTERNAL;
 		return -1;
diff --git a/src/http_client.c b/src/http_client.c
index 1e87a50..c067736 100644
--- a/src/http_client.c
+++ b/src/http_client.c
@@ -735,7 +735,7 @@
 
 					/* if the request contains the HTX_FL_EOM, we finished the request part. */
 					if (htx->flags & HTX_FL_EOM) {
-						si->cs->flags |= CS_FL_EOI;
+						si->cs->endp->flags |= CS_EP_EOI;
 						req->flags |= CF_EOI;
 						appctx->st0 = HTTPCLIENT_S_RES_STLINE;
 					}
diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c
index a74554e..9af915d 100644
--- a/src/mux_fcgi.c
+++ b/src/mux_fcgi.c
@@ -1011,7 +1011,7 @@
 		if (!fstrm->id)
 			fstrm->fconn->nb_reserved--;
 		if (fstrm->cs) {
-			if (!(fstrm->cs->flags & CS_FL_EOS) && !b_data(&fstrm->rxbuf))
+			if (!(fstrm->endp->flags & CS_EP_EOS) && !b_data(&fstrm->rxbuf))
 				fcgi_strm_notify_recv(fstrm);
 		}
 		fstrm->state = FCGI_SS_CLOSED;
@@ -1148,8 +1148,8 @@
 	return NULL;
 }
 
-/* Wakes a specific stream and assign its conn_stream some CS_FL_* flags among
- * CS_FL_ERR_PENDING and CS_FL_ERROR if needed. The stream's state is
+/* Wakes a specific stream and assign its conn_stream some CS_EP_* flags among
+ * CS_EP_ERR_PENDING and CS_EP_ERROR if needed. The stream's state is
  * automatically updated accordingly. If the stream is orphaned, it is
  * destroyed.
  */
@@ -1176,9 +1176,9 @@
 	}
 
 	if ((fconn->state == FCGI_CS_CLOSED || fconn->conn->flags & CO_FL_ERROR)) {
-		fstrm->cs->flags |= CS_FL_ERR_PENDING;
-		if (fstrm->cs->flags & CS_FL_EOS)
-			fstrm->cs->flags |= CS_FL_ERROR;
+		fstrm->endp->flags |= CS_EP_ERR_PENDING;
+		if (fstrm->endp->flags & CS_EP_EOS)
+			fstrm->endp->flags |= CS_EP_ERROR;
 
 		if (fstrm->state < FCGI_SS_ERROR) {
 			fstrm->state = FCGI_SS_ERROR;
@@ -2626,10 +2626,10 @@
 		     fcgi_conn_read0_pending(fconn) ||
 		     fstrm->state == FCGI_SS_CLOSED ||
 		     (fstrm->flags & FCGI_SF_ES_RCVD) ||
-		     (fstrm->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
+		     (fstrm->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING|CS_EP_EOS)))) {
 			/* we may have to signal the upper layers */
 			TRACE_DEVEL("notifying stream before switching SID", FCGI_EV_RX_RECORD|FCGI_EV_STRM_WAKE, fconn->conn, fstrm);
-			fstrm->cs->flags |= CS_FL_RCV_MORE;
+			fstrm->endp->flags |= CS_EP_RCV_MORE;
 			fcgi_strm_notify_recv(fstrm);
 		}
 		fstrm = tmp_fstrm;
@@ -2707,10 +2707,10 @@
 	     fcgi_conn_read0_pending(fconn) ||
 	     fstrm->state == FCGI_SS_CLOSED ||
 	     (fstrm->flags & FCGI_SF_ES_RCVD) ||
-	     (fstrm->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
+	     (fstrm->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING|CS_EP_EOS)))) {
 		/* we may have to signal the upper layers */
 		TRACE_DEVEL("notifying stream before switching SID", FCGI_EV_RX_RECORD|FCGI_EV_STRM_WAKE, fconn->conn, fstrm);
-		fstrm->cs->flags |= CS_FL_RCV_MORE;
+		fstrm->endp->flags |= CS_EP_RCV_MORE;
 		fcgi_strm_notify_recv(fstrm);
 	}
 
@@ -3961,18 +3961,18 @@
 		TRACE_STATE("fstrm rxbuf not allocated", FCGI_EV_STRM_RECV|FCGI_EV_FSTRM_BLK, fconn->conn, fstrm);
 
 	if (b_data(&fstrm->rxbuf))
-		cs->flags |= (CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags |= (CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 	else {
-		cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 		if (fstrm->state == FCGI_SS_ERROR || (fstrm->h1m.state == H1_MSG_DONE)) {
-			cs->flags |= CS_FL_EOI;
+			cs->endp->flags |= CS_EP_EOI;
 			if (!(fstrm->h1m.flags & (H1_MF_VER_11|H1_MF_XFER_LEN)))
-				cs->flags |= CS_FL_EOS;
+				cs->endp->flags |= CS_EP_EOS;
 		}
 		if (fcgi_conn_read0_pending(fconn))
-			cs->flags |= CS_FL_EOS;
-		if (cs->flags & CS_FL_ERR_PENDING)
-			cs->flags |= CS_FL_ERROR;
+			cs->endp->flags |= CS_EP_EOS;
+		if (cs->endp->flags & CS_EP_ERR_PENDING)
+			cs->endp->flags |= CS_EP_ERROR;
 		fcgi_release_buf(fconn, &fstrm->rxbuf);
 	}
 
@@ -4025,7 +4025,7 @@
 
 		if (id < 0) {
 			fcgi_strm_close(fstrm);
-			cs->flags |= CS_FL_ERROR;
+			cs->endp->flags |= CS_EP_ERROR;
 			TRACE_DEVEL("couldn't get a stream ID, leaving in error", FCGI_EV_STRM_SEND|FCGI_EV_FSTRM_ERR|FCGI_EV_STRM_ERR, fconn->conn, fstrm);
 			return 0;
 		}
diff --git a/src/mux_h1.c b/src/mux_h1.c
index c504c01..803cd88 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -1900,7 +1900,7 @@
 	 */
 	if (((h1m->state == H1_MSG_DONE) && (h1m->flags & H1_MF_RESP)) ||
 	    ((h1m->state == H1_MSG_DONE) && (h1s->meth != HTTP_METH_CONNECT) && !(h1m->flags & H1_MF_CONN_UPG)))
-		h1s->cs->flags |= CS_FL_EOI;
+		h1s->endp->flags |= CS_EP_EOI;
 
   out:
 	/* When Input data are pending for this message, notify upper layer that
@@ -1910,20 +1910,20 @@
 	 *   - Headers or trailers are pending to be copied.
 	 */
 	if (h1s->flags & (H1S_F_RX_CONGESTED)) {
-		h1s->cs->flags |= CS_FL_RCV_MORE | CS_FL_WANT_ROOM;
+		h1s->endp->flags |= CS_EP_RCV_MORE | CS_EP_WANT_ROOM;
 		TRACE_STATE("waiting for more room", H1_EV_RX_DATA|H1_EV_H1S_BLK, h1c->conn, h1s);
 	}
 	else {
-		h1s->cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		h1s->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 		if (h1s->flags & H1S_F_REOS) {
-			h1s->cs->flags |= CS_FL_EOS;
+			h1s->endp->flags |= CS_EP_EOS;
 			if (h1m->state >= H1_MSG_DONE || !(h1m->flags & H1_MF_XFER_LEN)) {
 				/* DONE or TUNNEL or SHUTR without XFER_LEN, set
 				 * EOI on the conn-stream */
-				h1s->cs->flags |= CS_FL_EOI;
+				h1s->endp->flags |= CS_EP_EOI;
 			}
 			else if (h1m->state > H1_MSG_LAST_LF && h1m->state < H1_MSG_DONE) {
-				h1s->cs->flags |= CS_FL_ERROR;
+				h1s->endp->flags |= CS_EP_ERROR;
 				TRACE_ERROR("message aborted, set error on CS", H1_EV_RX_DATA|H1_EV_H1S_ERR, h1c->conn, h1s);
 			}
 
@@ -1942,7 +1942,7 @@
   err:
 	htx_to_buf(htx, buf);
 	if (h1s->cs)
-		h1s->cs->flags |= CS_FL_EOI;
+		h1s->endp->flags |= CS_EP_EOI;
 	TRACE_DEVEL("leaving on error", H1_EV_RX_DATA|H1_EV_STRM_ERR, h1c->conn, h1s);
 	return 0;
 }
@@ -2556,7 +2556,7 @@
 			h1c->flags |= H1C_F_ST_ERROR;
 			TRACE_ERROR("txn done but data waiting to be sent, set error on h1c", H1_EV_H1C_ERR, h1c->conn, h1s);
 		}
-		h1s->cs->flags |= CS_FL_EOI;
+		h1s->endp->flags |= CS_EP_EOI;
 	}
 
 	TRACE_LEAVE(H1_EV_TX_DATA, h1c->conn, h1s, chn_htx, (size_t[]){total});
@@ -3037,7 +3037,7 @@
 				TRACE_STATE("read0 on connection", H1_EV_H1C_RECV, conn, h1s);
 			}
 			if ((h1c->flags & H1C_F_ST_ERROR) || ((conn->flags & CO_FL_ERROR) && !b_data(&h1c->ibuf)))
-				h1s->cs->flags |= CS_FL_ERROR;
+				h1s->endp->flags |= CS_EP_ERROR;
 			TRACE_POINT(H1_EV_STRM_WAKE, h1c->conn, h1s);
 			h1_alert(h1s);
 		}
@@ -3091,9 +3091,9 @@
 		BUG_ON(!h1s || h1c->flags & H1C_F_ST_READY);
 
 		if (conn_xprt_read0_pending(conn) || (h1s->flags & H1S_F_REOS))
-			h1s->cs->flags |= CS_FL_EOS;
+			h1s->endp->flags |= CS_EP_EOS;
 		if ((h1c->flags & H1C_F_ST_ERROR) || (conn->flags & CO_FL_ERROR))
-			h1s->cs->flags |= CS_FL_ERROR;
+			h1s->endp->flags |= CS_EP_ERROR;
 		h1_alert(h1s);
 		TRACE_DEVEL("waiting to release the CS before releasing the connection", H1_EV_H1C_WAKE);
 	}
@@ -3245,7 +3245,7 @@
 		if (h1c->flags & H1C_F_ST_ATTACHED) {
 			/* Don't release the H1 connection right now, we must destroy the
 			 * attached CS first. Here, the H1C must not be READY */
-			h1c->h1s->cs->flags |= (CS_FL_EOS|CS_FL_ERROR);
+			h1c->h1s->endp->flags |= (CS_EP_EOS|CS_EP_ERROR);
 			h1_alert(h1c->h1s);
 			h1_refresh_timeout(h1c);
 			HA_SPIN_UNLOCK(OTHER_LOCK, &idle_conns[tid].idle_conns_lock);
@@ -3685,7 +3685,7 @@
 	}
 
 	if (h1c->flags & H1C_F_ST_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_ERROR("H1C on error, leaving in error", H1_EV_STRM_SEND|H1_EV_H1C_ERR|H1_EV_H1S_ERR|H1_EV_STRM_ERR, h1c->conn, h1s);
 		return 0;
 	}
@@ -3717,7 +3717,7 @@
 	}
 
 	if (h1c->flags & H1C_F_ST_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_ERROR("reporting error to the app-layer stream", H1_EV_STRM_SEND|H1_EV_H1S_ERR|H1_EV_STRM_ERR, h1c->conn, h1s);
 	}
 
@@ -3762,7 +3762,7 @@
 			if (ret > h1m->curr_len) {
 				h1s->flags |= H1S_F_PARSING_ERROR;
 				h1c->flags |= H1C_F_ST_ERROR;
-				cs->flags  |= CS_FL_ERROR;
+				cs->endp->flags  |= CS_EP_ERROR;
 				TRACE_ERROR("too much payload, more than announced",
 					    H1_EV_RX_DATA|H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
 				goto end;
@@ -3820,7 +3820,7 @@
 		if (ret > h1m->curr_len) {
 			h1s->flags |= H1S_F_PROCESSING_ERROR;
 			h1c->flags |= H1C_F_ST_ERROR;
-			cs->flags  |= CS_FL_ERROR;
+			cs->endp->flags  |= CS_EP_ERROR;
 			TRACE_ERROR("too much payload, more than announced",
 				    H1_EV_TX_DATA|H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
 			goto end;
diff --git a/src/mux_h2.c b/src/mux_h2.c
index d4f5320..37f86bc 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -1482,7 +1482,7 @@
 		if (!h2s->id)
 			h2s->h2c->nb_reserved--;
 		if (h2s->cs) {
-			if (!(h2s->cs->flags & CS_FL_EOS) && !b_data(&h2s->rxbuf))
+			if (!(h2s->endp->flags & CS_EP_EOS) && !b_data(&h2s->rxbuf))
 				h2s_notify_recv(h2s);
 		}
 		HA_ATOMIC_DEC(&h2s->h2c->px_counters->open_streams);
@@ -2170,8 +2170,8 @@
 	return ret;
 }
 
-/* wake a specific stream and assign its conn_stream some CS_FL_* flags among
- * CS_FL_ERR_PENDING and CS_FL_ERROR if needed. The stream's state
+/* wake a specific stream and assign its conn_stream some CS_EP_* flags among
+ * CS_EP_ERR_PENDING and CS_EP_ERROR if needed. The stream's state
  * is automatically updated accordingly. If the stream is orphaned, it is
  * destroyed.
  */
@@ -2197,9 +2197,9 @@
 
 	if ((h2s->h2c->st0 >= H2_CS_ERROR || h2s->h2c->conn->flags & CO_FL_ERROR) ||
 	    (h2s->h2c->last_sid > 0 && (!h2s->id || h2s->id > h2s->h2c->last_sid))) {
-		h2s->cs->flags |= CS_FL_ERR_PENDING;
-		if (h2s->cs->flags & CS_FL_EOS)
-			h2s->cs->flags |= CS_FL_ERROR;
+		h2s->endp->flags |= CS_EP_ERR_PENDING;
+		if (h2s->endp->flags & CS_EP_EOS)
+			h2s->endp->flags |= CS_EP_ERROR;
 
 		if (h2s->st < H2_SS_ERROR)
 			h2s->st = H2_SS_ERROR;
@@ -2962,7 +2962,7 @@
 	if (h2c->dff & H2_F_HEADERS_END_STREAM)
 		h2s->flags |= H2_SF_ES_RCVD;
 
-	if (h2s->cs && h2s->cs->flags & CS_FL_ERROR && h2s->st < H2_SS_ERROR)
+	if (h2s->cs && (h2s->endp->flags & CS_EP_ERROR) && h2s->st < H2_SS_ERROR)
 		h2s->st = H2_SS_ERROR;
 	else if (h2s->flags & H2_SF_ES_RCVD) {
 		if (h2s->st == H2_SS_OPEN)
@@ -3463,10 +3463,10 @@
 		     h2c_read0_pending(h2c) ||
 		     h2s->st == H2_SS_CLOSED ||
 		     (h2s->flags & H2_SF_ES_RCVD) ||
-		     (h2s->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
+		     (h2s->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING|CS_EP_EOS)))) {
 			/* we may have to signal the upper layers */
 			TRACE_DEVEL("notifying stream before switching SID", H2_EV_RX_FRAME|H2_EV_STRM_WAKE, h2c->conn, h2s);
-			h2s->cs->flags |= CS_FL_RCV_MORE;
+			h2s->endp->flags |= CS_EP_RCV_MORE;
 			h2s_notify_recv(h2s);
 		}
 		h2s = tmp_h2s;
@@ -3634,10 +3634,10 @@
 	     h2c_read0_pending(h2c) ||
 	     h2s->st == H2_SS_CLOSED ||
 	     (h2s->flags & H2_SF_ES_RCVD) ||
-	     (h2s->cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING|CS_FL_EOS)))) {
+	     (h2s->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING|CS_EP_EOS)))) {
 		/* we may have to signal the upper layers */
 		TRACE_DEVEL("notifying stream before switching SID", H2_EV_RX_FRAME|H2_EV_H2S_WAKE, h2c->conn, h2s);
-		h2s->cs->flags |= CS_FL_RCV_MORE;
+		h2s->endp->flags |= CS_EP_RCV_MORE;
 		h2s_notify_recv(h2s);
 	}
 
@@ -5010,7 +5010,7 @@
 /* Transfer the payload of a DATA frame to the HTTP/1 side. The HTTP/2 frame
  * parser state is automatically updated. Returns > 0 if it could completely
  * send the current frame, 0 if it couldn't complete, in which case
- * CS_FL_RCV_MORE must be checked to know if some data remain pending (an empty
+ * CS_EP_RCV_MORE must be checked to know if some data remain pending (an empty
  * DATA frame can return 0 as a valid result). Stream errors are reported in
  * h2s->errcode and connection errors in h2c->errcode. The caller must already
  * have checked the frame header and ensured that the frame was complete or the
@@ -6470,7 +6470,7 @@
 	if (h2s_htx->flags & HTX_FL_PARSING_ERROR) {
 		buf_htx->flags |= HTX_FL_PARSING_ERROR;
 		if (htx_is_empty(buf_htx))
-			cs->flags |= CS_FL_EOI;
+			cs->endp->flags |= CS_EP_EOI;
 	}
 	else if (htx_is_empty(h2s_htx))
 		buf_htx->flags |= (h2s_htx->flags & HTX_FL_EOM);
@@ -6482,19 +6482,19 @@
 
   end:
 	if (b_data(&h2s->rxbuf))
-		cs->flags |= (CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags |= (CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 	else {
-		cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 		if (h2s->flags & H2_SF_ES_RCVD) {
-			cs->flags |= CS_FL_EOI;
+			cs->endp->flags |= CS_EP_EOI;
 			/* Add EOS flag for tunnel */
 			if (h2s->flags & H2_SF_BODY_TUNNEL)
-				cs->flags |= CS_FL_EOS;
+				cs->endp->flags |= CS_EP_EOS;
 		}
 		if (h2c_read0_pending(h2c) || h2s->st == H2_SS_CLOSED)
-			cs->flags |= CS_FL_EOS;
-		if (cs->flags & CS_FL_ERR_PENDING)
-			cs->flags |= CS_FL_ERROR;
+			cs->endp->flags |= CS_EP_EOS;
+		if (cs->endp->flags & CS_EP_ERR_PENDING)
+			cs->endp->flags |= CS_EP_ERROR;
 		if (b_size(&h2s->rxbuf)) {
 			b_free(&h2s->rxbuf);
 			offer_buffers(NULL, 1);
@@ -6546,7 +6546,7 @@
 	}
 
 	if (h2s->h2c->st0 >= H2_CS_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_DEVEL("connection is in error, leaving in error", H2_EV_H2S_SEND|H2_EV_H2S_BLK|H2_EV_H2S_ERR|H2_EV_STRM_ERR, h2s->h2c->conn, h2s);
 		return 0;
 	}
@@ -6560,7 +6560,7 @@
 		int32_t id = h2c_get_next_sid(h2s->h2c);
 
 		if (id < 0) {
-			cs->flags |= CS_FL_ERROR;
+			cs->endp->flags |= CS_EP_ERROR;
 			TRACE_DEVEL("couldn't get a stream ID, leaving in error", H2_EV_H2S_SEND|H2_EV_H2S_BLK|H2_EV_H2S_ERR|H2_EV_STRM_ERR, h2s->h2c->conn, h2s);
 			return 0;
 		}
@@ -6672,10 +6672,10 @@
 	    !b_data(&h2s->h2c->dbuf) &&
 	    (h2s->flags & (H2_SF_BLK_SFCTL | H2_SF_BLK_MFCTL))) {
 		TRACE_DEVEL("fctl with shutr, reporting error to app-layer", H2_EV_H2S_SEND|H2_EV_STRM_SEND|H2_EV_STRM_ERR, h2s->h2c->conn, h2s);
-		if (cs->flags & CS_FL_EOS)
-			cs->flags |= CS_FL_ERROR;
+		if (cs->endp->flags & CS_EP_EOS)
+			cs->endp->flags |= CS_EP_ERROR;
 		else
-			cs->flags |= CS_FL_ERR_PENDING;
+			cs->endp->flags |= CS_EP_ERR_PENDING;
 	}
 
 	if (total > 0 && !(h2s->flags & H2_SF_BLK_SFCTL) &&
diff --git a/src/mux_pt.c b/src/mux_pt.c
index 00cf542..7f9ce26 100644
--- a/src/mux_pt.c
+++ b/src/mux_pt.c
@@ -317,7 +317,7 @@
 	}
 	conn->ctx = ctx;
 	ctx->cs = cs;
-	cs->flags |= CS_FL_RCV_MORE;
+	cs->endp->flags |= CS_EP_RCV_MORE;
 	if (global.tune.options & GTUNE_USE_SPLICE)
 		cs->endp->flags |= CS_EP_MAY_SPLICE;
 
@@ -385,7 +385,7 @@
 		conn->xprt->unsubscribe(ctx->conn, conn->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
 	cs_attach_mux(cs, ctx, conn);
 	ctx->cs = cs;
-	cs->flags |= CS_FL_RCV_MORE;
+	cs->endp->flags |= CS_EP_RCV_MORE;
 
 	TRACE_LEAVE(PT_EV_STRM_NEW, conn, cs);
 	return 0;
@@ -464,7 +464,7 @@
 
 	if (cs->endp->flags & CS_EP_SHR)
 		return;
-	cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+	cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 	if (conn_xprt_ready(conn) && conn->xprt->shutr)
 		conn->xprt->shutr(conn, conn->xprt_ctx,
 		    (mode == CS_SHR_DRAIN));
@@ -516,19 +516,19 @@
 	TRACE_ENTER(PT_EV_RX_DATA, conn, cs, buf, (size_t[]){count});
 
 	if (!count) {
-		cs->flags |= (CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags |= (CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 		goto end;
 	}
 	b_realign_if_empty(buf);
 	ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, count, flags);
 	if (conn_xprt_read0_pending(conn)) {
-		cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
-		cs->flags |= CS_FL_EOS;
+		cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
+		cs->endp->flags |= CS_EP_EOS;
 		TRACE_DEVEL("read0 on connection", PT_EV_RX_DATA, conn, cs);
 	}
 	if (conn->flags & CO_FL_ERROR) {
-		cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_DEVEL("error on connection", PT_EV_RX_DATA|PT_EV_CONN_ERR, conn, cs);
 	}
   end:
@@ -550,7 +550,7 @@
 		b_del(buf, ret);
 
 	if (conn->flags & CO_FL_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_DEVEL("error on connection", PT_EV_TX_DATA|PT_EV_CONN_ERR, conn, cs);
 	}
 
@@ -594,11 +594,11 @@
 
 	ret = conn->xprt->rcv_pipe(conn, conn->xprt_ctx, pipe, count);
 	if (conn_xprt_read0_pending(conn))  {
-		cs->flags |= CS_FL_EOS;
+		cs->endp->flags |= CS_EP_EOS;
 		TRACE_DEVEL("read0 on connection", PT_EV_RX_DATA, conn, cs);
 	}
 	if (conn->flags & CO_FL_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_DEVEL("error on connection", PT_EV_RX_DATA|PT_EV_CONN_ERR, conn, cs);
 	}
 
@@ -616,7 +616,7 @@
 	ret = conn->xprt->snd_pipe(conn, conn->xprt_ctx, pipe);
 
 	if (conn->flags & CO_FL_ERROR) {
-		cs->flags |= CS_FL_ERROR;
+		cs->endp->flags |= CS_EP_ERROR;
 		TRACE_DEVEL("error on connection", PT_EV_TX_DATA|PT_EV_CONN_ERR, conn, cs);
 	}
 
diff --git a/src/mux_quic.c b/src/mux_quic.c
index c64f8d0..e207b3a 100644
--- a/src/mux_quic.c
+++ b/src/mux_quic.c
@@ -1144,15 +1144,15 @@
 
  end:
 	if (b_data(&qcs->rx.app_buf)) {
-		cs->flags |= (CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
+		cs->endp->flags |= (CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
 	}
 	else {
-		cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM);
-		if (cs->flags & CS_FL_ERR_PENDING)
-			cs->flags |= CS_FL_ERROR;
+		cs->endp->flags &= ~(CS_EP_RCV_MORE | CS_EP_WANT_ROOM);
+		if (cs->endp->flags & CS_EP_ERR_PENDING)
+			cs->endp->flags |= CS_EP_ERROR;
 
 		if (fin)
-			cs->flags |= (CS_FL_EOI|CS_FL_EOS);
+			cs->endp->flags |= (CS_EP_EOI|CS_EP_EOS);
 
 		if (b_size(&qcs->rx.app_buf)) {
 			b_free(&qcs->rx.app_buf);
@@ -1213,7 +1213,7 @@
 }
 
 /* Loop through all qcs from <qcc>. If CO_FL_ERROR is set on the connection,
- * report CS_FL_ERR_PENDING|CS_FL_ERROR on the attached conn-streams and wake
+ * report CS_EP_ERR_PENDING|CS_EP_ERROR on the attached conn-streams and wake
  * them.
  */
 static int qc_wake_some_streams(struct qcc *qcc)
@@ -1231,9 +1231,9 @@
 			continue;
 
 		if (qcc->conn->flags & CO_FL_ERROR) {
-			qcs->cs->flags |= CS_FL_ERR_PENDING;
-			if (qcs->cs->flags & CS_FL_EOS)
-				qcs->cs->flags |= CS_FL_ERROR;
+			qcs->endp->flags |= CS_EP_ERR_PENDING;
+			if (qcs->endp->flags & CS_EP_EOS)
+				qcs->endp->flags |= CS_EP_ERROR;
 
 			if (qcs->subs) {
 				qcs_notify_recv(qcs);
diff --git a/src/stats.c b/src/stats.c
index 2d1a33c..e18a516 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -4330,7 +4330,7 @@
 			channel_add_input(res, 1);
 		}
 		res_htx->flags |= HTX_FL_EOM;
-		si->cs->flags |= CS_FL_EOI;
+		si->cs->endp->flags |= CS_EP_EOI;
 		res->flags |= CF_EOI;
 		appctx->st0 = STAT_HTTP_END;
 	}
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 134dfcc..194c5ff 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -636,7 +636,7 @@
 	 */
 
 	if (si->state >= SI_ST_CON) {
-		if ((cs->flags & CS_FL_ERROR) || si_is_conn_error(si))
+		if ((cs->endp->flags & CS_EP_ERROR) || si_is_conn_error(si))
 			si->flags |= SI_FL_ERR;
 	}
 
@@ -666,7 +666,7 @@
 	 *       wake callback. Otherwise si_cs_recv()/si_cs_send() already take
 	 *       care of it.
 	 */
-	if (cs->flags & CS_FL_EOS && !(ic->flags & CF_SHUTR)) {
+	if (cs->endp->flags & CS_EP_EOS && !(ic->flags & CF_SHUTR)) {
 		/* we received a shutdown */
 		ic->flags |= CF_READ_NULL;
 		if (ic->flags & CF_AUTO_CLOSE)
@@ -681,7 +681,7 @@
 	 *       wake callback. Otherwise si_cs_recv()/si_cs_send() already take
 	 *       care of it.
 	 */
-	if ((cs->flags & CS_FL_EOI) && !(ic->flags & CF_EOI))
+	if ((cs->endp->flags & CS_EP_EOI) && !(ic->flags & CF_EOI))
 		ic->flags |= (CF_EOI|CF_READ_PARTIAL);
 
 	/* Second step : update the stream-int and channels, try to forward any
@@ -707,7 +707,7 @@
 	int ret;
 	int did_send = 0;
 
-	if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING) || si_is_conn_error(si)) {
+	if (cs->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING) || si_is_conn_error(si)) {
 		/* We're probably there because the tasklet was woken up,
 		 * but process_stream() ran before, detected there were an
 		 * error and put the si back to SI_ST_TAR. There's still
@@ -830,7 +830,7 @@
 		si_rx_room_rdy(si_opposite(si));
 	}
 
-	if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) {
+	if (cs->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING)) {
 		si->flags |= SI_FL_ERR;
 		return 1;
 	}
@@ -1213,7 +1213,7 @@
 	if (!(si->wait_event.events & SUB_RETRY_SEND) && !channel_is_empty(si_oc(si)))
 		si_cs_send(cs);
 
-	if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING) || si_is_conn_error(si)) {
+	if (cs->endp->flags & (CS_EP_ERROR|CS_EP_ERR_PENDING) || si_is_conn_error(si)) {
 		/* Write error on the file descriptor */
 		if (si->state >= SI_ST_CON)
 			si->flags |= SI_FL_ERR;
@@ -1316,7 +1316,7 @@
 		return 0;
 
 	/* stop here if we reached the end of data */
-	if (cs->flags & CS_FL_EOS)
+	if (cs->endp->flags & CS_EP_EOS)
 		goto end_recv;
 
 	/* stop immediately on errors. Note that we DON'T want to stop on
@@ -1325,15 +1325,15 @@
 	 * happens when we send too large a request to a backend server
 	 * which rejects it before reading it all.
 	 */
-	if (!(cs->flags & CS_FL_RCV_MORE)) {
+	if (!(cs->endp->flags & CS_EP_RCV_MORE)) {
 		if (!conn_xprt_ready(conn))
 			return 0;
-		if (cs->flags & CS_FL_ERROR)
+		if (cs->endp->flags & CS_EP_ERROR)
 			goto end_recv;
 	}
 
 	/* prepare to detect if the mux needs more room */
-	cs->flags &= ~CS_FL_WANT_ROOM;
+	cs->endp->flags &= ~CS_EP_WANT_ROOM;
 
 	if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(ic) &&
 	    global.tune.idle_timer &&
@@ -1385,7 +1385,7 @@
 			ic->flags |= CF_READ_PARTIAL;
 		}
 
-		if (cs->flags & (CS_FL_EOS|CS_FL_ERROR))
+		if (cs->endp->flags & (CS_EP_EOS|CS_EP_ERROR))
 			goto end_recv;
 
 		if (conn->flags & CO_FL_WAIT_ROOM) {
@@ -1440,9 +1440,9 @@
 	 * that if such an event is not handled above in splice, it will be handled here by
 	 * recv().
 	 */
-	while ((cs->flags & CS_FL_RCV_MORE) ||
+	while ((cs->endp->flags & CS_EP_RCV_MORE) ||
 	       (!(conn->flags & CO_FL_HANDSHAKE) &&
-	       (!(cs->flags & (CS_FL_ERROR|CS_FL_EOS))) && !(ic->flags & CF_SHUTR))) {
+	       (!(cs->endp->flags & (CS_EP_ERROR|CS_EP_EOS))) && !(ic->flags & CF_SHUTR))) {
 		int cur_flags = flags;
 
 		/* Compute transient CO_RFL_* flags */
@@ -1451,13 +1451,13 @@
 		}
 
 		/* <max> may be null. This is the mux responsibility to set
-		 * CS_FL_RCV_MORE on the CS if more space is needed.
+		 * CS_EP_RCV_MORE on the CS if more space is needed.
 		 */
 		max = channel_recv_max(ic);
 		ret = conn->mux->rcv_buf(cs, &ic->buf, max, cur_flags);
 
-		if (cs->flags & CS_FL_WANT_ROOM) {
-			/* CS_FL_WANT_ROOM must not be reported if the channel's
+		if (cs->endp->flags & CS_EP_WANT_ROOM) {
+			/* CS_EP_WANT_ROOM must not be reported if the channel's
 			 * buffer is empty.
 			 */
 			BUG_ON(c_empty(ic));
@@ -1501,7 +1501,7 @@
 		 * the channel's policies.This way, we are still able to receive
 		 * shutdowns.
 		 */
-		if (cs->flags & CS_FL_EOI)
+		if (cs->endp->flags & CS_EP_EOI)
 			break;
 
 		if ((ic->flags & CF_READ_DONTWAIT) || --read_poll <= 0) {
@@ -1587,16 +1587,16 @@
 
 	/* Report EOI on the channel if it was reached from the mux point of
 	 * view. */
-	if ((cs->flags & CS_FL_EOI) && !(ic->flags & CF_EOI)) {
+	if ((cs->endp->flags & CS_EP_EOI) && !(ic->flags & CF_EOI)) {
 		ic->flags |= (CF_EOI|CF_READ_PARTIAL);
 		ret = 1;
 	}
 
-	if (cs->flags & CS_FL_ERROR) {
+	if (cs->endp->flags & CS_EP_ERROR) {
 		si->flags |= SI_FL_ERR;
 		ret = 1;
 	}
-	else if (cs->flags & CS_FL_EOS) {
+	else if (cs->endp->flags & CS_EP_EOS) {
 		/* we received a shutdown */
 		ic->flags |= CF_READ_NULL;
 		if (ic->flags & CF_AUTO_CLOSE)
diff --git a/src/tcpcheck.c b/src/tcpcheck.c
index 53ee771..930735b 100644
--- a/src/tcpcheck.c
+++ b/src/tcpcheck.c
@@ -1483,7 +1483,7 @@
 	TRACE_DATA("send data", CHK_EV_TCPCHK_SND|CHK_EV_TX_DATA, check);
 	if (conn->mux->snd_buf(cs, &check->bo,
 			       (IS_HTX_CONN(conn) ? (htxbuf(&check->bo))->data: b_data(&check->bo)), 0) <= 0) {
-		if ((conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR)) {
+		if ((conn->flags & CO_FL_ERROR) || (cs->endp->flags & CS_EP_ERROR)) {
 			ret = TCPCHK_EVAL_STOP;
 			TRACE_DEVEL("connection error during send", CHK_EV_TCPCHK_SND|CHK_EV_TX_DATA|CHK_EV_TX_ERR, check);
 			goto out;
@@ -1547,7 +1547,7 @@
 		goto wait_more_data;
 	}
 
-	if (cs->flags & CS_FL_EOS)
+	if (cs->endp->flags & CS_EP_EOS)
 		goto end_recv;
 
 	if (check->state & CHK_ST_IN_ALLOC) {
@@ -1564,15 +1564,15 @@
 	/* errors on the connection and the conn-stream were already checked */
 
 	/* prepare to detect if the mux needs more room */
-	cs->flags &= ~CS_FL_WANT_ROOM;
+	cs->endp->flags &= ~CS_EP_WANT_ROOM;
 
-	while ((cs->flags & CS_FL_RCV_MORE) ||
-	       (!(conn->flags & CO_FL_ERROR) && !(cs->flags & (CS_FL_ERROR|CS_FL_EOS)))) {
+	while ((cs->endp->flags & CS_EP_RCV_MORE) ||
+	       (!(conn->flags & CO_FL_ERROR) && !(cs->endp->flags & (CS_EP_ERROR|CS_EP_EOS)))) {
 		max = (IS_HTX_CS(cs) ?  htx_free_space(htxbuf(&check->bi)) : b_room(&check->bi));
 		read = conn->mux->rcv_buf(cs, &check->bi, max, 0);
 		cur_read += read;
 		if (!read ||
-		    (cs->flags & CS_FL_WANT_ROOM) ||
+		    (cs->endp->flags & CS_EP_WANT_ROOM) ||
 		    (--read_poll <= 0) ||
 		    (read < max && read >= global.tune.recv_enough))
 			break;
@@ -1580,7 +1580,7 @@
 
   end_recv:
 	is_empty = (IS_HTX_CS(cs) ? htx_is_empty(htxbuf(&check->bi)) : !b_data(&check->bi));
-	if (is_empty && ((conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))) {
+	if (is_empty && ((conn->flags & CO_FL_ERROR) || (cs->endp->flags & CS_EP_ERROR))) {
 		/* Report network errors only if we got no other data. Otherwise
 		 * we'll let the upper layers decide whether the response is OK
 		 * or not. It is very common that an RST sent by the server is
@@ -1590,11 +1590,11 @@
 		goto stop;
 	}
 	if (!cur_read) {
-		if (cs->flags & CS_FL_EOI) {
+		if (cs->endp->flags & CS_EP_EOI) {
 			/* If EOI is set, it means there is a response or an error */
 			goto out;
 		}
-		if (!(cs->flags & (CS_FL_WANT_ROOM|CS_FL_ERROR|CS_FL_EOS))) {
+		if (!(cs->endp->flags & (CS_EP_WANT_ROOM|CS_EP_ERROR|CS_EP_EOS))) {
 			conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
 			TRACE_DEVEL("waiting for response", CHK_EV_RX_DATA, check);
 			goto wait_more_data;
@@ -2140,7 +2140,7 @@
 	 */
 
 	/* 1- check for connection error, if any */
-	if ((conn && conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))
+	if ((conn && conn->flags & CO_FL_ERROR) || (cs->endp->flags & CS_EP_ERROR))
 		goto out_end_tcpcheck;
 
 	/* 2- check if a rule must be resume. It happens if check->current_step
@@ -2222,7 +2222,7 @@
 					goto out_end_tcpcheck;
 				else if (eval_ret == TCPCHK_EVAL_WAIT)
 					goto out;
-				last_read = ((conn->flags & CO_FL_ERROR) || (cs->flags & (CS_FL_ERROR|CS_FL_EOS)));
+				last_read = ((conn->flags & CO_FL_ERROR) || (cs->endp->flags & (CS_EP_ERROR|CS_EP_EOS)));
 				must_read = 0;
 			}
 
@@ -2303,7 +2303,7 @@
 	TRACE_PROTO("tcp-check passed", CHK_EV_TCPCHK_EVAL, check);
 
   out_end_tcpcheck:
-	if ((conn && conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR)) {
+	if ((conn && conn->flags & CO_FL_ERROR) || (cs->endp->flags & CS_EP_ERROR)) {
 		TRACE_ERROR("report connection error", CHK_EV_TCPCHK_EVAL|CHK_EV_TCPCHK_ERR, check);
 		chk_report_conn_err(check, errno, 0);
 	}