MEDIUM: conn-stream: Be able to pass endpoint to create a conn-stream

It is a transient commit to prepare next changes. It is possible to pass a
pre-allocated endpoint to create a new conn-stream. If it is NULL, a new
endpoint is created, otherwise the existing one is used. There no more
change at the conn-stream level.

In the applets, all conn-stream are created with no pre-allocated
endpoint. But for multiplexers, an endpoint is systematically created before
creating the conn-stream.
diff --git a/src/check.c b/src/check.c
index 7e6430f..b26e7b9 100644
--- a/src/check.c
+++ b/src/check.c
@@ -1391,7 +1391,7 @@
 	if (check->type == PR_O2_EXT_CHK)
 		t = task_new_on(0);
 	else {
-		check->cs = cs_new();
+		check->cs = cs_new(NULL);
 		if (!check->cs)
 			goto fail_alloc_cs;
 		if (cs_attach_app(check->cs, &check->obj_type) < 0)
diff --git a/src/conn_stream.c b/src/conn_stream.c
index 0335cbb..5b81774 100644
--- a/src/conn_stream.c
+++ b/src/conn_stream.c
@@ -46,10 +46,9 @@
 /* Tries to allocate a new conn_stream and initialize its main fields. On
  * failure, nothing is allocated and NULL is returned.
  */
-struct conn_stream *cs_new()
+struct conn_stream *cs_new(struct cs_endpoint *endp)
 {
 	struct conn_stream *cs;
-	struct cs_endpoint *endp;
 
 	cs = pool_alloc(pool_head_connstream);
 
@@ -62,9 +61,11 @@
 	cs->si = NULL;
 	cs->data_cb = NULL;
 
-	endp = cs_endpoint_new();
-	if (unlikely(!endp))
-		goto alloc_error;
+	if (!endp) {
+		endp = cs_endpoint_new();
+		if (unlikely(!endp))
+			goto alloc_error;
+	}
 	cs->endp = endp;
 
 	return cs;
diff --git a/src/dns.c b/src/dns.c
index b13206d..461e3c7 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -891,7 +891,7 @@
 	struct stream *s;
 	struct applet *applet = &dns_session_applet;
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs) {
 		ha_alert("out of memory in dns_session_create().\n");
 		goto out_close;
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index a3713cf..e8daf1b 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -1991,7 +1991,7 @@
 	struct conn_stream *cs;
 	struct stream      *strm;
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs)
 		goto out_error;
 
diff --git a/src/hlua.c b/src/hlua.c
index 179b8f2..3f9b123 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -2944,7 +2944,7 @@
 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
 	lua_setmetatable(L, -2);
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs) {
 		hlua_pusherror(L, "socket: out of memory");
 		goto out_fail_conf;
diff --git a/src/http_client.c b/src/http_client.c
index 22a13b1..dd27482 100644
--- a/src/http_client.c
+++ b/src/http_client.c
@@ -476,7 +476,7 @@
 		goto out;
 	}
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs) {
 		ha_alert("httpclient: out of memory in %s:%d.\n", __FUNCTION__, __LINE__);
 		goto out;
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 82470bc..669b411 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -716,23 +716,31 @@
 static struct conn_stream *h1s_new_cs(struct h1s *h1s, struct buffer *input)
 {
 	struct h1c *h1c = h1s->h1c;
+	struct cs_endpoint *endp;
 	struct conn_stream *cs;
 
 	TRACE_ENTER(H1_EV_STRM_NEW, h1c->conn, h1s);
-	cs = cs_new();
+	endp = cs_endpoint_new();
+	if (!endp) {
+		TRACE_ERROR("CS endp allocation failure", H1_EV_STRM_NEW|H1_EV_STRM_END|H1_EV_STRM_ERR, h1c->conn, h1s);
+		goto err;
+	}
+	endp->target = h1s;
+	endp->ctx = h1c->conn;
+	if (h1s->flags & H1S_F_NOT_FIRST)
+		endp->flags |= CS_EP_NOT_FIRST;
+	if (h1s->req.flags & H1_MF_UPG_WEBSOCKET)
+		endp->flags |= CS_EP_WEBSOCKET;
+
+	cs = cs_new(endp);
 	if (!cs) {
 		TRACE_ERROR("CS allocation failure", H1_EV_STRM_NEW|H1_EV_STRM_END|H1_EV_STRM_ERR, h1c->conn, h1s);
+		cs_endpoint_free(endp);
 		goto err;
 	}
 	cs_attach_endp_mux(cs, h1s, h1c->conn);
 	h1s->cs = cs;
 
-	if (h1s->flags & H1S_F_NOT_FIRST)
-		cs->endp->flags |= CS_EP_NOT_FIRST;
-
-	if (h1s->req.flags & H1_MF_UPG_WEBSOCKET)
-		cs->endp->flags |= CS_EP_WEBSOCKET;
-
 	if (!stream_new(h1c->conn->owner, cs, input)) {
 		TRACE_DEVEL("leaving on stream creation failure", H1_EV_STRM_NEW|H1_EV_STRM_END|H1_EV_STRM_ERR, h1c->conn, h1s);
 		goto err_cs;
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 82196e9..98a837d 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -1590,6 +1590,7 @@
 static struct h2s *h2c_frt_stream_new(struct h2c *h2c, int id, struct buffer *input, uint32_t flags)
 {
 	struct session *sess = h2c->conn->owner;
+	struct cs_endpoint *endp;
 	struct conn_stream *cs;
 	struct h2s *h2s;
 
@@ -1602,19 +1603,26 @@
 	if (!h2s)
 		goto out;
 
-	cs = cs_new();
-	if (!cs)
+	endp = cs_endpoint_new();
+	if (!endp)
 		goto out_close;
-	cs->endp->flags |= CS_EP_NOT_FIRST;
-	cs_attach_endp_mux(cs, h2s, h2c->conn);
-	h2s->cs = cs;
-	h2c->nb_cs++;
-
+	endp->target = h2s;
+	endp->ctx = h2c->conn;
+	endp->flags |= CS_EP_NOT_FIRST;
 	/* FIXME wrong analogy between ext-connect and websocket, this need to
 	 * be refine.
 	 */
 	if (flags & H2_SF_EXT_CONNECT_RCVD)
-		cs->endp->flags |= CS_EP_WEBSOCKET;
+		endp->flags |= CS_EP_WEBSOCKET;
+
+	cs = cs_new(endp);
+	if (!cs) {
+		cs_endpoint_free(endp);
+		goto out_close;
+	}
+	cs_attach_endp_mux(cs, h2s, h2c->conn);
+	h2s->cs = cs;
+	h2c->nb_cs++;
 
 	/* The stream will record the request's accept date (which is either the
 	 * end of the connection's or the date immediately after the previous
diff --git a/src/mux_pt.c b/src/mux_pt.c
index 198c41a..e49898e 100644
--- a/src/mux_pt.c
+++ b/src/mux_pt.c
@@ -272,6 +272,7 @@
 static int mux_pt_init(struct connection *conn, struct proxy *prx, struct session *sess,
 		       struct buffer *input)
 {
+	struct cs_endpoint *endp;
 	struct conn_stream *cs = conn->ctx;
 	struct mux_pt_ctx *ctx = pool_alloc(pool_head_pt_ctx);
 
@@ -291,9 +292,15 @@
 	ctx->conn = conn;
 
 	if (!cs) {
-		cs = cs_new();
+		endp = cs_endpoint_new();
+		if (!endp)
+			goto fail_free_ctx;
+		endp->target = ctx;
+		endp->ctx = conn;
+		cs = cs_new(endp);
 		if (!cs) {
 			TRACE_ERROR("CS allocation failure", PT_EV_STRM_NEW|PT_EV_STRM_END|PT_EV_STRM_ERR, conn);
+			cs_endpoint_free(endp);
 			goto fail_free_ctx;
 		}
 		cs_attach_endp_mux(cs, ctx, conn);
diff --git a/src/peers.c b/src/peers.c
index d82e562..b88f4ec 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -3191,7 +3191,7 @@
 	peer->last_hdshk = now_ms;
 	s = NULL;
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs) {
 		ha_alert("out of memory in peer_session_create().\n");
 		goto out_close;
diff --git a/src/sink.c b/src/sink.c
index 87f076b..d704042 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -643,7 +643,7 @@
 	if (sft->srv->log_proto == SRV_LOG_PROTO_OCTET_COUNTING)
 		applet = &sink_forward_oc_applet;
 
-	cs = cs_new();
+	cs = cs_new(NULL);
 	if (!cs) {
 		ha_alert("out of memory in sink_forward_session_create");
 		goto out_close;
diff --git a/src/stream.c b/src/stream.c
index 868a3f0..e30027c 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -443,7 +443,7 @@
 		s->flags |= SF_HTX;
 
 	s->csf = cs;
-	s->csb = cs_new();
+	s->csb = cs_new(NULL);
 	if (!s->csb)
 		goto out_fail_alloc_csb;