MAJOR: conn-stream: Share endpoint struct between the CS and the mux/applet

The conn-stream endpoint is now shared between the conn-stream and the
applet or the multiplexer. If the mux or the applet is created first, it is
responsible to also create the endpoint and share it with the conn-stream.
If the conn-stream is created first, it is the opposite.

When the endpoint is only owned by an applet or a mux, it is called an
orphan endpoint (there is no conn-stream). When it is only owned by a
conn-stream, it is called a detached endpoint (there is no mux/applet).

The last entity that owns an endpoint is responsible to release it. When a
mux or an applet is detached from a conn-stream, the conn-stream
relinquishes the endpoint to recreate a new one. This way, the endpoint
state is never lost for the mux or the applet.
diff --git a/src/peers.c b/src/peers.c
index 9701963..c31aa81 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -3181,7 +3181,6 @@
 	struct proxy *p = peers->peers_fe; /* attached frontend */
 	struct appctx *appctx;
 	struct session *sess;
-	struct cs_endpoint *endp;
 	struct conn_stream *cs;
 	struct stream *s;
 	struct sockaddr_storage *addr = NULL;
@@ -3193,7 +3192,7 @@
 	peer->last_hdshk = now_ms;
 	s = NULL;
 
-	appctx = appctx_new(&peer_applet);
+	appctx = appctx_new(&peer_applet, NULL);
 	if (!appctx)
 		goto out_close;
 
@@ -3209,17 +3208,9 @@
 	if (!sockaddr_alloc(&addr, &peer->addr, sizeof(peer->addr)))
 		goto out_free_sess;
 
-	endp = cs_endpoint_new();
-	if (!endp)
-		goto out_free_addr;
-	endp->target = appctx;
-	endp->ctx = appctx;
-	endp->flags |= CS_EP_T_APPLET;
-
-	cs = cs_new_from_applet(endp, sess, &BUF_NULL);
+	cs = cs_new_from_applet(appctx->endp, sess, &BUF_NULL);
 	if (!cs) {
 		ha_alert("Failed to initialize stream in peer_session_create().\n");
-		cs_endpoint_free(endp);
 		goto out_free_addr;
 	}