MAJOR: connection : Split struct connection into struct connection and struct conn_stream.

All the references to connections in the data path from streams and
stream_interfaces were changed to use conn_streams. Most functions named
"something_conn" were renamed to "something_cs" for this. Sometimes the
connection still is what matters (eg during a connection establishment)
and were not always renamed. The change is significant and minimal at the
same time, and was quite thoroughly tested now. As of this patch, all
accesses to the connection from upper layers go through the pass-through
mux.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index a2bcc97..e55ec8b 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -315,25 +315,25 @@
 	c->flags &= ~CO_FL_XPRT_RD_ENA;
 }
 
-static inline void __cs_data_want_recv(struct conn_stream *cs)
+static inline void __cs_want_recv(struct conn_stream *cs)
 {
 	cs->flags |= CS_FL_DATA_RD_ENA;
 }
 
-static inline void __cs_data_stop_recv(struct conn_stream *cs)
+static inline void __cs_stop_recv(struct conn_stream *cs)
 {
 	cs->flags &= ~CS_FL_DATA_RD_ENA;
 }
 
-static inline void cs_data_want_recv(struct conn_stream *cs)
+static inline void cs_want_recv(struct conn_stream *cs)
 {
-	__cs_data_want_recv(cs);
+	__cs_want_recv(cs);
 	cs_update_mux_polling(cs);
 }
 
-static inline void cs_data_stop_recv(struct conn_stream *cs)
+static inline void cs_stop_recv(struct conn_stream *cs)
 {
-	__cs_data_stop_recv(cs);
+	__cs_stop_recv(cs);
 	cs_update_mux_polling(cs);
 }
 
@@ -366,36 +366,36 @@
 	c->flags &= ~(CO_FL_XPRT_WR_ENA | CO_FL_XPRT_RD_ENA);
 }
 
-static inline void __cs_data_want_send(struct conn_stream *cs)
+static inline void __cs_want_send(struct conn_stream *cs)
 {
 	cs->flags |= CS_FL_DATA_WR_ENA;
 }
 
-static inline void __cs_data_stop_send(struct conn_stream *cs)
+static inline void __cs_stop_send(struct conn_stream *cs)
 {
 	cs->flags &= ~CS_FL_DATA_WR_ENA;
 }
 
-static inline void cs_data_stop_send(struct conn_stream *cs)
+static inline void cs_stop_send(struct conn_stream *cs)
 {
-	__cs_data_stop_send(cs);
+	__cs_stop_send(cs);
 	cs_update_mux_polling(cs);
 }
 
-static inline void cs_data_want_send(struct conn_stream *cs)
+static inline void cs_want_send(struct conn_stream *cs)
 {
-	__cs_data_want_send(cs);
+	__cs_want_send(cs);
 	cs_update_mux_polling(cs);
 }
 
-static inline void __cs_data_stop_both(struct conn_stream *cs)
+static inline void __cs_stop_both(struct conn_stream *cs)
 {
 	cs->flags &= ~(CS_FL_DATA_WR_ENA | CS_FL_DATA_RD_ENA);
 }
 
-static inline void cs_data_stop_both(struct conn_stream *cs)
+static inline void cs_stop_both(struct conn_stream *cs)
 {
-	__cs_data_stop_both(cs);
+	__cs_stop_both(cs);
 	cs_update_mux_polling(cs);
 }
 
@@ -537,6 +537,45 @@
 		c->xprt->shutw(c, 0);
 }
 
+/* shut read after draining possibly pending data */
+static inline void cs_shutr(struct conn_stream *cs)
+{
+	__cs_stop_recv(cs);
+
+	/* clean data-layer shutdown */
+	if (cs->conn->mux && cs->conn->mux->shutr)
+		cs->conn->mux->shutr(cs, 1);
+}
+
+/* shut read after disabling lingering */
+static inline void cs_shutr_hard(struct conn_stream *cs)
+{
+	__cs_stop_recv(cs);
+
+	/* clean data-layer shutdown */
+	if (cs->conn->mux && cs->conn->mux->shutr)
+		cs->conn->mux->shutr(cs, 0);
+}
+
+static inline void cs_shutw(struct conn_stream *cs)
+{
+	__cs_stop_send(cs);
+
+	/* clean data-layer shutdown */
+	if (cs->conn->mux && cs->conn->mux->shutw)
+		cs->conn->mux->shutw(cs, 1);
+}
+
+static inline void cs_shutw_hard(struct conn_stream *cs)
+{
+	__cs_stop_send(cs);
+
+	/* unclean data-layer shutdown */
+	if (cs->conn->mux && cs->conn->mux->shutw)
+		cs->conn->mux->shutw(cs, 0);
+}
+
+
 /* detect sock->data read0 transition */
 static inline int conn_xprt_read0_pending(struct connection *c)
 {
@@ -576,7 +615,6 @@
 {
 	conn->obj_type = OBJ_TYPE_CONN;
 	conn->flags = CO_FL_NONE;
-	conn->data = NULL;
 	conn->tmp_early_data = -1;
 	conn->mux = NULL;
 	conn->mux_ctx = NULL;
@@ -622,31 +660,43 @@
 	return conn;
 }
 
-/* Tries to allocate a new conn_stream and initialize its main fields. The
- * connection is returned on success, NULL on failure. The connection must
- * be released using pool_free2() or conn_free().
+/* Releases a conn_stream previously allocated by cs_new() */
+static inline void cs_free(struct conn_stream *cs)
+{
+	pool_free2(pool2_connstream, cs);
+}
+
+/* Tries to allocate a new conn_stream and initialize its main fields. If
+ * <conn> is NULL, then a new connection is allocated on the fly, initialized,
+ * and assigned to cs->conn ; this connection will then have to be released
+ * using pool_free2() or conn_free(). The conn_stream is initialized and added
+ * to the mux's stream list on success, then returned. On failure, nothing is
+ * allocated and NULL is returned.
  */
 static inline struct conn_stream *cs_new(struct connection *conn)
 {
 	struct conn_stream *cs;
 
 	cs = pool_alloc2(pool2_connstream);
-	if (likely(cs != NULL))
-		cs_init(cs, conn);
-	return cs;
-}
+	if (!likely(cs))
+		return NULL;
 
-/* Releases a conn_stream previously allocated by cs_new() */
-static inline void cs_free(struct conn_stream *cs)
-{
-	pool_free2(pool2_connstream, cs);
+	if (!conn) {
+		conn = conn_new();
+		if (!likely(conn)) {
+			cs_free(cs);
+			return NULL;
+		}
+		conn_init(conn);
+	}
+
+	cs_init(cs, conn);
+	return cs;
 }
 
 /* Releases a connection previously allocated by conn_new() */
 static inline void conn_free(struct connection *conn)
 {
-	if (conn->mux && conn->mux->release)
-		conn->mux->release(conn);
 	pool_free2(pool2_connection, conn);
 }
 
@@ -700,11 +750,11 @@
 	conn->flags |= CO_FL_ADDR_TO_SET;
 }
 
-/* Attaches a connection to an owner and assigns a data layer */
-static inline void conn_attach(struct connection *conn, void *owner, const struct data_cb *data)
+/* Attaches a conn_stream to a data layer and sets the relevant callbacks */
+static inline void cs_attach(struct conn_stream *cs, void *data, const struct data_cb *data_cb)
 {
-	conn->data = data;
-	conn->owner = owner;
+	cs->data_cb = data_cb;
+	cs->data = data;
 }
 
 /* Installs the connection's mux layer for upper context <ctx>.
@@ -789,11 +839,11 @@
 	return conn->mux->name;
 }
 
-static inline const char *conn_get_data_name(const struct connection *conn)
+static inline const char *cs_get_data_name(const struct conn_stream *cs)
 {
-	if (!conn->data)
+	if (!cs->data_cb)
 		return "NONE";
-	return conn->data->name;
+	return cs->data_cb->name;
 }
 
 /* registers pointer to transport layer <id> (XPRT_*) */
diff --git a/include/proto/stream.h b/include/proto/stream.h
index 3efb42b..f0edc2e 100644
--- a/include/proto/stream.h
+++ b/include/proto/stream.h
@@ -36,7 +36,7 @@
 extern struct data_cb sess_conn_cb;
 
 struct stream *stream_new(struct session *sess, enum obj_type *origin);
-int stream_create_from_conn(struct connection *conn);
+int stream_create_from_cs(struct conn_stream *cs);
 
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_stream();
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index c6578ef..ee1fa12 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.h
@@ -152,18 +152,14 @@
  */
 static inline void si_release_endpoint(struct stream_interface *si)
 {
-	struct connection *conn;
+	struct conn_stream *cs;
 	struct appctx *appctx;
 
 	if (!si->end)
 		return;
 
-	if ((conn = objt_conn(si->end))) {
-		LIST_DEL(&conn->list);
-		conn_stop_tracking(conn);
-		conn_full_close(conn);
-		conn_free(conn);
-	}
+	if ((cs = objt_cs(si->end)))
+		cs_destroy(cs);
 	else if ((appctx = objt_appctx(si->end))) {
 		if (appctx->applet->release && si->state < SI_ST_DIS)
 			appctx->applet->release(appctx);
@@ -178,26 +174,27 @@
  * connection will also be added at the head of this list. This connection
  * remains assigned to the stream interface it is currently attached to.
  */
-static inline void si_idle_conn(struct stream_interface *si, struct list *pool)
+static inline void si_idle_cs(struct stream_interface *si, struct list *pool)
 {
-	struct connection *conn = __objt_conn(si->end);
+	struct conn_stream *cs = __objt_cs(si->end);
+	struct connection *conn = cs->conn;
 
 	if (pool)
 		LIST_ADD(pool, &conn->list);
 
-	conn_attach(conn, si, &si_idle_conn_cb);
-	conn_xprt_want_recv(conn);
+	cs_attach(cs, si, &si_idle_conn_cb);
+	cs_want_recv(cs);
 }
 
-/* Attach connection <conn> to the stream interface <si>. The stream interface
+/* Attach conn_stream <cs> to the stream interface <si>. The stream interface
  * is configured to work with a connection and the connection it configured
  * with a stream interface data layer.
  */
-static inline void si_attach_conn(struct stream_interface *si, struct connection *conn)
+static inline void si_attach_cs(struct stream_interface *si, struct conn_stream *cs)
 {
 	si->ops = &si_conn_ops;
-	si->end = &conn->obj_type;
-	conn_attach(conn, si, &si_conn_cb);
+	si->end = &cs->obj_type;
+	cs_attach(cs, si, &si_conn_cb);
 }
 
 /* Returns true if a connection is attached to the stream interface <si> and
@@ -205,7 +202,7 @@
  */
 static inline int si_conn_ready(struct stream_interface *si)
 {
-	struct connection *conn = objt_conn(si->end);
+	struct connection *conn = cs_conn(objt_cs(si->end));
 
 	return conn && conn_ctrl_ready(conn) && conn_xprt_ready(conn);
 }
@@ -276,22 +273,22 @@
 	si->flags &= ~SI_FL_WANT_GET;
 }
 
-/* Try to allocate a new connection and assign it to the interface. If
+/* Try to allocate a new conn_stream and assign it to the interface. If
  * an endpoint was previously allocated, it is released first. The newly
- * allocated connection is initialized, assigned to the stream interface,
+ * allocated conn_stream is initialized, assigned to the stream interface,
  * and returned.
  */
-static inline struct connection *si_alloc_conn(struct stream_interface *si)
+static inline struct conn_stream *si_alloc_cs(struct stream_interface *si, struct connection *conn)
 {
-	struct connection *conn;
+	struct conn_stream *cs;
 
 	si_release_endpoint(si);
 
-	conn = conn_new();
-	if (conn)
-		si_attach_conn(si, conn);
+	cs = cs_new(conn);
+	if (cs)
+		si_attach_cs(si, cs);
 
-	return conn;
+	return cs;
 }
 
 /* Release the interface's existing endpoint (connection or appctx) and
@@ -346,7 +343,8 @@
 /* Calls chk_snd on the connection using the ctrl layer */
 static inline int si_connect(struct stream_interface *si)
 {
-	struct connection *conn = objt_conn(si->end);
+	struct conn_stream *cs = objt_cs(si->end);
+	struct connection *conn = cs_conn(cs);
 	int ret = SF_ERR_NONE;
 
 	if (unlikely(!conn || !conn->ctrl || !conn->ctrl->connect))
@@ -364,7 +362,7 @@
 		/* reuse the existing connection */
 		if (!channel_is_empty(si_oc(si))) {
 			/* we'll have to send a request there. */
-			conn_xprt_want_send(conn);
+			cs_want_send(cs);
 		}
 
 		/* the connection is established */