REORG/MEDIUM: channel: only use chn_prod / chn_cons to find stream-interfaces

The purpose of these two macros will be to pass via the session to
find the relevant stream interfaces so that we don't need to store
the ->cons nor ->prod pointers anymore. Currently they're only defined
so that all references could be removed.

Note that many places need a second pass of clean up so that we don't
have any chn_prod(&s->req) anymore and only &s->si[0] instead, and
conversely for the 3 other cases.
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 79e5b78..28043f0 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -33,6 +33,7 @@
 
 #include <types/channel.h>
 #include <types/global.h>
+#include <types/stream_interface.h>
 
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_channel();
@@ -52,6 +53,18 @@
 int bo_getblk_nc(struct channel *chn, char **blk1, int *len1, char **blk2, int *len2);
 
 
+/* returns a pointer to the stream interface feeding the channel (producer) */
+static inline struct stream_interface *chn_prod(const struct channel *chn)
+{
+	return chn->prod;
+}
+
+/* returns a pointer to the stream interface consuming the channel (producer) */
+static inline struct stream_interface *chn_cons(const struct channel *chn)
+{
+	return chn->cons;
+}
+
 /* Initialize all fields in the channel. */
 static inline void channel_init(struct channel *chn)
 {
@@ -127,7 +140,7 @@
  */
 static inline int channel_may_send(const struct channel *chn)
 {
-	return chn->cons->state == SI_ST_EST;
+	return chn_cons(chn)->state == SI_ST_EST;
 }
 
 /* Returns the amount of bytes from the channel that are already scheduled for
diff --git a/src/backend.c b/src/backend.c
index a8178aa..9043eed 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -548,7 +548,7 @@
 
 	srv = NULL;
 	s->target = NULL;
-	conn = objt_conn(s->req.cons->end);
+	conn = objt_conn(chn_cons(&s->req)->end);
 
 	if (conn &&
 	    (conn->flags & CO_FL_CONNECTED) &&
@@ -607,7 +607,7 @@
 
 			switch (s->be->lbprm.algo & BE_LB_PARM) {
 			case BE_LB_HASH_SRC:
-				conn = objt_conn(s->req.prod->end);
+				conn = objt_conn(chn_prod(&s->req)->end);
 				if (conn && conn->addr.from.ss_family == AF_INET) {
 					srv = get_server_sh(s->be,
 							    (void *)&((struct sockaddr_in *)&conn->addr.from)->sin_addr,
@@ -698,7 +698,7 @@
 		s->target = &s->be->obj_type;
 	}
 	else if ((s->be->options & PR_O_HTTP_PROXY) &&
-		 (conn = objt_conn(s->req.cons->end)) &&
+		 (conn = objt_conn(chn_cons(&s->req)->end)) &&
 		 is_addr(&conn->addr.to)) {
 		/* in proxy mode, we need a valid destination address */
 		s->target = &s->be->obj_type;
@@ -746,8 +746,8 @@
  */
 int assign_server_address(struct session *s)
 {
-	struct connection *cli_conn = objt_conn(s->req.prod->end);
-	struct connection *srv_conn = objt_conn(s->req.cons->end);
+	struct connection *cli_conn = objt_conn(chn_prod(&s->req)->end);
+	struct connection *srv_conn = objt_conn(chn_cons(&s->req)->end);
 
 #ifdef DEBUG_FULL
 	fprintf(stderr,"assign_server_address : s=%p\n",s);
@@ -942,7 +942,7 @@
 /* If an explicit source binding is specified on the server and/or backend, and
  * this source makes use of the transparent proxy, then it is extracted now and
  * assigned to the session's pending connection. This function assumes that an
- * outgoing connection has already been assigned to s->req.cons->end.
+ * outgoing connection has already been assigned to chn_cons(&s->req)->end.
  */
 static void assign_tproxy_address(struct session *s)
 {
@@ -950,7 +950,7 @@
 	struct server *srv = objt_server(s->target);
 	struct conn_src *src;
 	struct connection *cli_conn;
-	struct connection *srv_conn = objt_conn(s->req.cons->end);
+	struct connection *srv_conn = objt_conn(chn_cons(&s->req)->end);
 
 	if (srv && srv->conn_src.opts & CO_SRC_BIND)
 		src = &srv->conn_src;
@@ -966,7 +966,7 @@
 	case CO_SRC_TPROXY_CLI:
 	case CO_SRC_TPROXY_CIP:
 		/* FIXME: what can we do if the client connects in IPv6 or unix socket ? */
-		cli_conn = objt_conn(s->req.prod->end);
+		cli_conn = objt_conn(chn_prod(&s->req)->end);
 		if (cli_conn)
 			srv_conn->addr.from = cli_conn->addr.from;
 		else
@@ -1001,7 +1001,7 @@
 
 /*
  * This function initiates a connection to the server assigned to this session
- * (s->target, s->req.cons->addr.to). It will assign a server if none
+ * (s->target, chn_cons(&s->req)->addr.to). It will assign a server if none
  * is assigned yet.
  * It can return one of :
  *  - SN_ERR_NONE if everything's OK
@@ -1012,7 +1012,7 @@
  *  - SN_ERR_INTERNAL for any other purely internal errors
  * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
  * The server-facing stream interface is expected to hold a pre-allocated connection
- * in s->req.cons->conn.
+ * in chn_cons(&s->req)->conn.
  */
 int connect_server(struct session *s)
 {
@@ -1022,7 +1022,7 @@
 	int reuse = 0;
 	int err;
 
-	srv_conn = objt_conn(s->req.cons->end);
+	srv_conn = objt_conn(chn_cons(&s->req)->end);
 	if (srv_conn)
 		reuse = s->target == srv_conn->target;
 
@@ -1043,7 +1043,7 @@
 		}
 	}
 
-	srv_conn = si_alloc_conn(s->req.cons, reuse);
+	srv_conn = si_alloc_conn(chn_cons(&s->req), reuse);
 	if (!srv_conn)
 		return SN_ERR_RESOURCE;
 
@@ -1064,7 +1064,7 @@
 		else if (obj_type(s->target) == OBJ_TYPE_PROXY) {
 			/* proxies exclusively run on raw_sock right now */
 			conn_prepare(srv_conn, protocol_by_family(srv_conn->addr.to.ss_family), &raw_sock);
-			if (!objt_conn(s->req.cons->end) || !objt_conn(s->req.cons->end)->ctrl)
+			if (!objt_conn(chn_cons(&s->req)->end) || !objt_conn(chn_cons(&s->req)->end)->ctrl)
 				return SN_ERR_INTERNAL;
 		}
 		else
@@ -1074,36 +1074,36 @@
 		srv_conn->send_proxy_ofs = 0;
 		if (objt_server(s->target) && objt_server(s->target)->pp_opts) {
 			srv_conn->send_proxy_ofs = 1; /* must compute size */
-			cli_conn = objt_conn(s->req.prod->end);
+			cli_conn = objt_conn(chn_prod(&s->req)->end);
 			if (cli_conn)
 				conn_get_to_addr(cli_conn);
 		}
 
-		si_attach_conn(s->req.cons, srv_conn);
+		si_attach_conn(chn_cons(&s->req), srv_conn);
 
 		assign_tproxy_address(s);
 	}
 	else {
 		/* the connection is being reused, just re-attach it */
-		si_attach_conn(s->req.cons, srv_conn);
+		si_attach_conn(chn_cons(&s->req), srv_conn);
 		s->flags |= SN_SRV_REUSED;
 	}
 
 	/* flag for logging source ip/port */
 	if (s->fe->options2 & PR_O2_SRC_ADDR)
-		s->req.cons->flags |= SI_FL_SRC_ADDR;
+		chn_cons(&s->req)->flags |= SI_FL_SRC_ADDR;
 
 	/* disable lingering */
 	if (s->be->options & PR_O_TCP_NOLING)
-		s->req.cons->flags |= SI_FL_NOLINGER;
+		chn_cons(&s->req)->flags |= SI_FL_NOLINGER;
 
-	err = si_connect(s->req.cons);
+	err = si_connect(chn_cons(&s->req));
 
 	if (err != SN_ERR_NONE)
 		return err;
 
 	/* set connect timeout */
-	s->req.cons->exp = tick_add_ifset(now_ms, s->be->timeout.connect);
+	chn_cons(&s->req)->exp = tick_add_ifset(now_ms, s->be->timeout.connect);
 
 	srv = objt_server(s->target);
 	if (srv) {
@@ -1157,8 +1157,8 @@
 			goto redispatch;
 		}
 
-		if (!s->req.cons->err_type) {
-			s->req.cons->err_type = SI_ET_QUEUE_ERR;
+		if (!chn_cons(&s->req)->err_type) {
+			chn_cons(&s->req)->err_type = SI_ET_QUEUE_ERR;
 		}
 
 		srv->counters.failed_conns++;
@@ -1167,23 +1167,23 @@
 
 	case SRV_STATUS_NOSRV:
 		/* note: it is guaranteed that srv == NULL here */
-		if (!s->req.cons->err_type) {
-			s->req.cons->err_type = SI_ET_CONN_ERR;
+		if (!chn_cons(&s->req)->err_type) {
+			chn_cons(&s->req)->err_type = SI_ET_CONN_ERR;
 		}
 
 		s->be->be_counters.failed_conns++;
 		return 1;
 
 	case SRV_STATUS_QUEUED:
-		s->req.cons->exp = tick_add_ifset(now_ms, s->be->timeout.queue);
-		s->req.cons->state = SI_ST_QUE;
+		chn_cons(&s->req)->exp = tick_add_ifset(now_ms, s->be->timeout.queue);
+		chn_cons(&s->req)->state = SI_ST_QUE;
 		/* do nothing else and do not wake any other session up */
 		return 1;
 
 	case SRV_STATUS_INTERNAL:
 	default:
-		if (!s->req.cons->err_type) {
-			s->req.cons->err_type = SI_ET_CONN_OTHER;
+		if (!chn_cons(&s->req)->err_type) {
+			chn_cons(&s->req)->err_type = SI_ET_CONN_OTHER;
 		}
 
 		if (srv)
diff --git a/src/hlua.c b/src/hlua.c
index 0aa92e9..570c9b4 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -1439,7 +1439,7 @@
 	 */
 	if (socket->s->req.buf->size == 0) {
 		if (!session_alloc_recv_buffer(socket->s, &socket->s->req.buf)) {
-			socket->s->req.prod->flags |= SI_FL_WAIT_ROOM;
+			chn_prod(&socket->s->req)->flags |= SI_FL_WAIT_ROOM;
 			goto hlua_socket_write_yield_return;
 		}
 	}
@@ -1734,7 +1734,7 @@
 	ip      = MAY_LJMP(luaL_checkstring(L, 2));
 	port    = MAY_LJMP(luaL_checkinteger(L, 3));
 
-	conn = si_alloc_conn(socket->s->req.cons, 0);
+	conn = si_alloc_conn(chn_cons(&socket->s->req), 0);
 	if (!conn)
 		WILL_LJMP(luaL_error(L, "connect: internal error"));
 
@@ -2328,7 +2328,7 @@
 	 */
 	if (chn->chn->buf->size == 0) {
 		if (!session_alloc_recv_buffer(chn->s, &chn->chn->buf)) {
-			chn->chn->prod->flags |= SI_FL_WAIT_ROOM;
+			chn_prod(chn->chn)->flags |= SI_FL_WAIT_ROOM;
 			WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
 		}
 	}
diff --git a/src/log.c b/src/log.c
index 77c7b71..a980bda 100644
--- a/src/log.c
+++ b/src/log.c
@@ -984,7 +984,7 @@
 				break;
 
 			case LOG_FMT_CLIENTIP:  // %ci
-				conn = objt_conn(s->req.prod->end);
+				conn = objt_conn(chn_prod(&s->req)->end);
 				if (conn)
 					ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
 				else
@@ -996,7 +996,7 @@
 				break;
 
 			case LOG_FMT_CLIENTPORT:  // %cp
-				conn = objt_conn(s->req.prod->end);
+				conn = objt_conn(chn_prod(&s->req)->end);
 				if (conn) {
 					if (conn->addr.from.ss_family == AF_UNIX) {
 						ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
@@ -1015,7 +1015,7 @@
 				break;
 
 			case LOG_FMT_FRONTENDIP: // %fi
-				conn = objt_conn(s->req.prod->end);
+				conn = objt_conn(chn_prod(&s->req)->end);
 				if (conn) {
 					conn_get_to_addr(conn);
 					ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
@@ -1030,7 +1030,7 @@
 				break;
 
 			case  LOG_FMT_FRONTENDPORT: // %fp
-				conn = objt_conn(s->req.prod->end);
+				conn = objt_conn(chn_prod(&s->req)->end);
 				if (conn) {
 					conn_get_to_addr(conn);
 					if (conn->addr.to.ss_family == AF_UNIX)
@@ -1048,7 +1048,7 @@
 				break;
 
 			case LOG_FMT_BACKENDIP:  // %bi
-				conn = objt_conn(s->req.cons->end);
+				conn = objt_conn(chn_cons(&s->req)->end);
 				if (conn)
 					ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
 				else
@@ -1061,7 +1061,7 @@
 				break;
 
 			case LOG_FMT_BACKENDPORT:  // %bp
-				conn = objt_conn(s->req.cons->end);
+				conn = objt_conn(chn_cons(&s->req)->end);
 				if (conn)
 					ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
 				else
@@ -1074,7 +1074,7 @@
 				break;
 
 			case LOG_FMT_SERVERIP: // %si
-				conn = objt_conn(s->req.cons->end);
+				conn = objt_conn(chn_cons(&s->req)->end);
 				if (conn)
 					ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
 				else
@@ -1087,7 +1087,7 @@
 				break;
 
 			case LOG_FMT_SERVERPORT: // %sp
-				conn = objt_conn(s->req.cons->end);
+				conn = objt_conn(chn_cons(&s->req)->end);
 				if (conn)
 					ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
 				else
@@ -1386,8 +1386,8 @@
 			case LOG_FMT_RETRIES:  // %rq
 				if (s->flags & SN_REDISP)
 					LOGCHAR('+');
-				ret = ltoa_o((s->req.cons->conn_retries>0) ?
-				                (be->conn_retries - s->req.cons->conn_retries) :
+				ret = ltoa_o((chn_cons(&s->req)->conn_retries>0) ?
+				                (be->conn_retries - chn_cons(&s->req)->conn_retries) :
 				                be->conn_retries, tmplog, dst + maxsize - tmplog);
 				if (ret == NULL)
 					goto out;
@@ -1611,7 +1611,7 @@
 	err = (s->flags & SN_REDISP) ||
               ((s->flags & SN_ERR_MASK) > SN_ERR_LOCAL) ||
 	      (((s->flags & SN_ERR_MASK) == SN_ERR_NONE) &&
-	       (s->req.cons->conn_retries != s->be->conn_retries)) ||
+	       (chn_cons(&s->req)->conn_retries != s->be->conn_retries)) ||
 	      ((s->fe->mode == PR_MODE_HTTP) && s->txn.status >= 500);
 
 	if (!err && (s->fe->options2 & PR_O2_NOLOGNORM))
diff --git a/src/proto_http.c b/src/proto_http.c
index 7bf80ca..a604773 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2692,7 +2692,7 @@
 			}
 
 			txn->status = 400;
-			stream_int_retnclose(req->prod, NULL);
+			stream_int_retnclose(chn_prod(req), NULL);
 			msg->msg_state = HTTP_MSG_ERROR;
 			req->analysers = 0;
 
@@ -2721,7 +2721,7 @@
 				session_inc_http_err_ctr(s);
 			}
 			txn->status = 408;
-			stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_408));
+			stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_408));
 			msg->msg_state = HTTP_MSG_ERROR;
 			req->analysers = 0;
 
@@ -2747,7 +2747,7 @@
 			if (msg->err_pos >= 0)
 				http_capture_bad_message(&s->fe->invalid_req, s, msg, msg->msg_state, s->fe);
 			txn->status = 400;
-			stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+			stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 			msg->msg_state = HTTP_MSG_ERROR;
 			req->analysers = 0;
 
@@ -2767,12 +2767,12 @@
 		req->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
 		s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
 #ifdef TCP_QUICKACK
-		if (s->listener->options & LI_O_NOQUICKACK && req->buf->i && objt_conn(s->req.prod->end) && conn_ctrl_ready(__objt_conn(s->req.prod->end))) {
+		if (s->listener->options & LI_O_NOQUICKACK && req->buf->i && objt_conn(chn_prod(&s->req)->end) && conn_ctrl_ready(__objt_conn(chn_prod(&s->req)->end))) {
 			/* We need more data, we have to re-enable quick-ack in case we
 			 * previously disabled it, otherwise we might cause the client
 			 * to delay next data.
 			 */
-			setsockopt(__objt_conn(s->req.prod->end)->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
+			setsockopt(__objt_conn(chn_prod(&s->req)->end)->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
 		}
 #endif
 
@@ -2809,7 +2809,7 @@
 		s->logs.logwait = 0;
 		s->logs.level = 0;
 		s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
-		stream_int_retnclose(req->prod, NULL);
+		stream_int_retnclose(chn_prod(req), NULL);
 		return 0;
 	}
 
@@ -2877,7 +2877,7 @@
 			if (ret) {
 				/* we fail this request, let's return 503 service unavail */
 				txn->status = 503;
-				stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_503));
+				stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_503));
 				if (!(s->flags & SN_ERR_MASK))
 					s->flags |= SN_ERR_LOCAL; /* we don't want a real error here */
 				goto return_prx_cond;
@@ -2886,7 +2886,7 @@
 
 		/* nothing to fail, let's reply normaly */
 		txn->status = 200;
-		stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_200));
+		stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_200));
 		if (!(s->flags & SN_ERR_MASK))
 			s->flags |= SN_ERR_LOCAL; /* we don't want a real error here */
 		goto return_prx_cond;
@@ -3065,7 +3065,7 @@
 
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	txn->status = 400;
-	stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+	stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
 	if (s->listener->counters)
@@ -3094,7 +3094,7 @@
 int http_handle_stats(struct session *s, struct channel *req)
 {
 	struct stats_admin_rule *stats_admin_rule;
-	struct stream_interface *si = s->res.prod;
+	struct stream_interface *si = chn_prod(&s->res);
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->req;
 	struct uri_auth *uri_auth = s->be->uri_auth;
@@ -3440,13 +3440,13 @@
 			break;
 
 		case HTTP_REQ_ACT_SET_TOS:
-			if ((cli_conn = objt_conn(s->req.prod->end)) && conn_ctrl_ready(cli_conn))
+			if ((cli_conn = objt_conn(chn_prod(&s->req)->end)) && conn_ctrl_ready(cli_conn))
 				inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
 			break;
 
 		case HTTP_REQ_ACT_SET_MARK:
 #ifdef SO_MARK
-			if ((cli_conn = objt_conn(s->req.prod->end)) && conn_ctrl_ready(cli_conn))
+			if ((cli_conn = objt_conn(chn_prod(&s->req)->end)) && conn_ctrl_ready(cli_conn))
 				setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
 #endif
 			break;
@@ -3686,13 +3686,13 @@
 			break;
 
 		case HTTP_RES_ACT_SET_TOS:
-			if ((cli_conn = objt_conn(s->req.prod->end)) && conn_ctrl_ready(cli_conn))
+			if ((cli_conn = objt_conn(chn_prod(&s->req)->end)) && conn_ctrl_ready(cli_conn))
 				inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
 			break;
 
 		case HTTP_RES_ACT_SET_MARK:
 #ifdef SO_MARK
-			if ((cli_conn = objt_conn(s->req.prod->end)) && conn_ctrl_ready(cli_conn))
+			if ((cli_conn = objt_conn(chn_prod(&s->req)->end)) && conn_ctrl_ready(cli_conn))
 				setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
 #endif
 			break;
@@ -4084,7 +4084,7 @@
 			memcpy(trash.str + trash.len, "\r\nConnection: close\r\n\r\n", 23);
 			trash.len += 23;
 		}
-		stream_int_retnclose(txn->req.chn->prod, &trash);
+		stream_int_retnclose(chn_prod(txn->req.chn), &trash);
 		txn->req.chn->analysers = 0;
 	}
 
@@ -4162,12 +4162,12 @@
 	 * by a possible reqrep, while they are processed *after* so that a
 	 * reqdeny can still block them. This clearly needs to change in 1.6!
 	 */
-	if (stats_check_uri(s->res.prod, txn, px)) {
+	if (stats_check_uri(chn_prod(&s->res), txn, px)) {
 		s->target = &http_stats_applet.obj_type;
-		if (unlikely(!stream_int_register_handler(s->res.prod, objt_applet(s->target)))) {
+		if (unlikely(!stream_int_register_handler(chn_prod(&s->res), objt_applet(s->target)))) {
 			txn->status = 500;
 			s->logs.tv_request = now;
-			stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_500));
+			stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_500));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_RESOURCE;
@@ -4297,7 +4297,7 @@
 	txn->flags |= TX_CLDENY;
 	txn->status = 403;
 	s->logs.tv_request = now;
-	stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_403));
+	stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_403));
 	session_inc_http_err_ctr(s);
 	s->fe->fe_counters.denied_req++;
 	if (s->fe != s->be)
@@ -4317,7 +4317,7 @@
 
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	txn->status = 400;
-	stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+	stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
 	if (s->listener->counters)
@@ -4347,7 +4347,7 @@
 {
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->req;
-	struct connection *cli_conn = objt_conn(req->prod->end);
+	struct connection *cli_conn = objt_conn(chn_prod(req)->end);
 
 	if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
 		/* we need more data */
@@ -4384,11 +4384,11 @@
 		char *path;
 
 		/* Note that for now we don't reuse existing proxy connections */
-		if (unlikely((conn = si_alloc_conn(req->cons, 0)) == NULL)) {
+		if (unlikely((conn = si_alloc_conn(chn_cons(req), 0)) == NULL)) {
 			txn->req.msg_state = HTTP_MSG_ERROR;
 			txn->status = 500;
 			req->analysers = 0;
-			stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_500));
+			stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_500));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_RESOURCE;
@@ -4656,7 +4656,7 @@
 	 * and close the socket to save packets and syscalls.
 	 */
 	if (!(req->analysers & AN_REQ_HTTP_XFER_BODY))
-		req->cons->flags |= SI_FL_NOHALF;
+		chn_cons(req)->flags |= SI_FL_NOHALF;
 
 	s->logs.tv_request = now;
 	/* OK let's go on with the BODY now */
@@ -4673,7 +4673,7 @@
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	txn->status = 400;
 	req->analysers = 0;
-	stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+	stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
 	if (s->listener->counters)
@@ -4714,7 +4714,7 @@
 
 	txn->status = 500;
 	if (!(req->flags & CF_READ_ERROR))
-		stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_500));
+		stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_500));
 
 	req->analysers = 0;
 	req->analyse_exp = TICK_ETERNITY;
@@ -4825,7 +4825,7 @@
 
 	if ((req->flags & CF_READ_TIMEOUT) || tick_is_expired(req->analyse_exp, now_ms)) {
 		txn->status = 408;
-		stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_408));
+		stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_408));
 
 		if (!(s->flags & SN_ERR_MASK))
 			s->flags |= SN_ERR_CLITO;
@@ -4858,7 +4858,7 @@
  return_bad_req: /* let's centralize all bad requests */
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	txn->status = 400;
-	stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+	stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 
 	if (!(s->flags & SN_ERR_MASK))
 		s->flags |= SN_ERR_PRXCOND;
@@ -4945,10 +4945,10 @@
 	 * to the server.
 	 */
 	if (((s->txn.flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
-	    !si_conn_ready(s->req.cons)) {
-		s->req.cons->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
-		si_shutr(s->req.cons);
-		si_shutw(s->req.cons);
+	    !si_conn_ready(chn_cons(&s->req))) {
+		chn_cons(&s->req)->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
+		si_shutr(chn_cons(&s->req));
+		si_shutw(chn_cons(&s->req));
 	}
 
 	if (s->flags & SN_BE_ASSIGNED) {
@@ -5027,15 +5027,15 @@
 	 * connection.
 	 */
 	if (((s->txn.flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
-	    !si_conn_ready(s->req.cons)) {
-		si_release_endpoint(s->req.cons);
+	    !si_conn_ready(chn_cons(&s->req))) {
+		si_release_endpoint(chn_cons(&s->req));
 	}
 
-	s->req.cons->state     = s->req.cons->prev_state = SI_ST_INI;
-	s->req.cons->err_type  = SI_ET_NONE;
-	s->req.cons->conn_retries = 0;  /* used for logging too */
-	s->req.cons->exp       = TICK_ETERNITY;
-	s->req.cons->flags    &= SI_FL_ISBACK | SI_FL_DONT_WAKE; /* we're in the context of process_session */
+	chn_cons(&s->req)->state     = chn_cons(&s->req)->prev_state = SI_ST_INI;
+	chn_cons(&s->req)->err_type  = SI_ET_NONE;
+	chn_cons(&s->req)->conn_retries = 0;  /* used for logging too */
+	chn_cons(&s->req)->exp       = TICK_ETERNITY;
+	chn_cons(&s->req)->flags    &= SI_FL_ISBACK | SI_FL_DONT_WAKE; /* we're in the context of process_session */
 	s->req.flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_WRITE_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WAKE_CONNECT|CF_WROTE_DATA);
 	s->res.flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_READ_ATTACHED|CF_READ_ERROR|CF_READ_NOEXP|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_PARTIAL|CF_NEVER_WAIT|CF_WROTE_DATA);
 	s->flags &= ~(SN_DIRECT|SN_ASSIGNED|SN_ADDR_SET|SN_BE_ASSIGNED|SN_FORCE_PRST|SN_IGNORE_PRST);
@@ -5058,7 +5058,7 @@
 	}
 
 	if (s->fe->options2 & PR_O2_INDEPSTR)
-		s->req.cons->flags |= SI_FL_INDEP_STR;
+		chn_cons(&s->req)->flags |= SI_FL_INDEP_STR;
 
 	if (s->fe->options2 & PR_O2_NODELAY) {
 		s->req.flags |= CF_NEVER_WAIT;
@@ -5086,7 +5086,7 @@
 	channel_auto_close(&s->res);
 
 	/* we're in keep-alive with an idle connection, monitor it */
-	si_idle_conn(s->req.cons);
+	si_idle_conn(chn_cons(&s->req));
 
 	s->req.analysers = s->listener->analysers;
 	s->res.analysers = 0;
@@ -5132,7 +5132,7 @@
 		/* if the server closes the connection, we want to immediately react
 		 * and close the socket to save packets and syscalls.
 		 */
-		chn->cons->flags |= SI_FL_NOHALF;
+		chn_cons(chn)->flags |= SI_FL_NOHALF;
 
 		if (txn->rsp.msg_state == HTTP_MSG_ERROR)
 			goto wait_other_side;
@@ -5187,7 +5187,7 @@
 
 		if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) {
 			/* if we've just closed an output, let's switch */
-			chn->cons->flags |= SI_FL_NOLINGER;  /* we want to close ASAP */
+			chn_cons(chn)->flags |= SI_FL_NOLINGER;  /* we want to close ASAP */
 
 			if (!channel_is_empty(chn)) {
 				txn->req.msg_state = HTTP_MSG_CLOSING;
@@ -5694,10 +5694,10 @@
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	if (txn->status) {
 		/* Note: we don't send any error if some data were already sent */
-		stream_int_retnclose(req->prod, NULL);
+		stream_int_retnclose(chn_prod(req), NULL);
 	} else {
 		txn->status = 400;
-		stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_400));
+		stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_400));
 	}
 	req->analysers = 0;
 	s->res.analysers = 0; /* we're in data phase, we want to abort both directions */
@@ -5716,10 +5716,10 @@
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	if (txn->status) {
 		/* Note: we don't send any error if some data were already sent */
-		stream_int_retnclose(req->prod, NULL);
+		stream_int_retnclose(chn_prod(req), NULL);
 	} else {
 		txn->status = 502;
-		stream_int_retnclose(req->prod, http_error_message(s, HTTP_ERR_502));
+		stream_int_retnclose(chn_prod(req), http_error_message(s, HTTP_ERR_502));
 	}
 	req->analysers = 0;
 	s->res.analysers = 0; /* we're in data phase, we want to abort both directions */
@@ -5859,9 +5859,9 @@
 			channel_auto_close(rep);
 			rep->analysers = 0;
 			txn->status = 502;
-			rep->prod->flags |= SI_FL_NOLINGER;
+			chn_prod(rep)->flags |= SI_FL_NOLINGER;
 			channel_truncate(rep);
-			stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_502));
+			stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_502));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_PRXCOND;
@@ -5894,9 +5894,9 @@
 			channel_auto_close(rep);
 			rep->analysers = 0;
 			txn->status = 502;
-			rep->prod->flags |= SI_FL_NOLINGER;
+			chn_prod(rep)->flags |= SI_FL_NOLINGER;
 			channel_truncate(rep);
-			stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_502));
+			stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_502));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_SRVCL;
@@ -5921,9 +5921,9 @@
 			channel_auto_close(rep);
 			rep->analysers = 0;
 			txn->status = 504;
-			rep->prod->flags |= SI_FL_NOLINGER;
+			chn_prod(rep)->flags |= SI_FL_NOLINGER;
 			channel_truncate(rep);
-			stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_504));
+			stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_504));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_SRVTO;
@@ -5944,7 +5944,7 @@
 
 			txn->status = 400;
 			channel_truncate(rep);
-			stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_400));
+			stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_400));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_CLICL;
@@ -5971,9 +5971,9 @@
 			channel_auto_close(rep);
 			rep->analysers = 0;
 			txn->status = 502;
-			rep->prod->flags |= SI_FL_NOLINGER;
+			chn_prod(rep)->flags |= SI_FL_NOLINGER;
 			channel_truncate(rep);
-			stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_502));
+			stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_502));
 
 			if (!(s->flags & SN_ERR_MASK))
 				s->flags |= SN_ERR_SRVCL;
@@ -6305,7 +6305,7 @@
 	s->logs.level = 0;
 	s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
 	channel_truncate(rep);
-	stream_int_retnclose(rep->cons, NULL);
+	stream_int_retnclose(chn_cons(rep), NULL);
 	return 0;
 }
 
@@ -6391,9 +6391,9 @@
 				rep->analysers = 0;
 				txn->status = 502;
 				s->logs.t_data = -1; /* was not a valid response */
-				rep->prod->flags |= SI_FL_NOLINGER;
+				chn_prod(rep)->flags |= SI_FL_NOLINGER;
 				channel_truncate(rep);
-				stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_502));
+				stream_int_retnclose(chn_cons(rep), http_error_message(s, HTTP_ERR_502));
 				if (!(s->flags & SN_ERR_MASK))
 					s->flags |= SN_ERR_PRXCOND;
 				if (!(s->flags & SN_FINST_MASK))
@@ -6927,7 +6927,7 @@
 
 	txn->rsp.msg_state = HTTP_MSG_ERROR;
 	/* don't send any error message as we're in the body */
-	stream_int_retnclose(res->cons, NULL);
+	stream_int_retnclose(chn_cons(res), NULL);
 	res->analysers = 0;
 	s->req.analysers = 0; /* we're in data phase, we want to abort both directions */
 	if (objt_server(s->target))
@@ -6947,7 +6947,7 @@
 
 	txn->rsp.msg_state = HTTP_MSG_ERROR;
 	/* don't send any error message as we're in the body */
-	stream_int_retnclose(res->cons, NULL);
+	stream_int_retnclose(chn_cons(res), NULL);
 	res->analysers = 0;
 	s->req.analysers = 0; /* we're in data phase, we want to abort both directions */
 
@@ -8638,8 +8638,8 @@
 	es->sid  = s->uniq_id;
 	es->srv  = objt_server(s->target);
 	es->oe   = other_end;
-	if (objt_conn(s->req.prod->end))
-		es->src  = __objt_conn(s->req.prod->end)->addr.from;
+	if (objt_conn(chn_prod(&s->req)->end))
+		es->src  = __objt_conn(chn_prod(&s->req)->end)->addr.from;
 	else
 		memset(&es->src, 0, sizeof(es->src));
 
@@ -8796,8 +8796,8 @@
 	int max;
 	chunk_printf(&trash, "%08x:%s.%s[%04x:%04x]: ", s->uniq_id, s->be->id,
 		      dir,
-		     objt_conn(s->req.prod->end) ? (unsigned short)objt_conn(s->req.prod->end)->t.sock.fd : -1,
-		     objt_conn(s->req.cons->end) ? (unsigned short)objt_conn(s->req.cons->end)->t.sock.fd : -1);
+		     objt_conn(chn_prod(&s->req)->end) ? (unsigned short)objt_conn(chn_prod(&s->req)->end)->t.sock.fd : -1,
+		     objt_conn(chn_cons(&s->req)->end) ? (unsigned short)objt_conn(chn_cons(&s->req)->end)->t.sock.fd : -1);
 
 	for (max = 0; start + max < end; max++)
 		if (start[max] == '\r' || start[max] == '\n')
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 086c6ce..b1ce8b6 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1325,9 +1325,9 @@
 				return 0;
 			}
 			else if (rule->action == TCP_ACT_CLOSE) {
-				rep->prod->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
-				si_shutr(rep->prod);
-				si_shutw(rep->prod);
+				chn_prod(rep)->flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
+				si_shutr(chn_prod(rep));
+				si_shutw(chn_prod(rep));
 				break;
 			}
 			else {
diff --git a/src/session.c b/src/session.c
index ca8efca..a924e8c 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1087,7 +1087,7 @@
 		s->req, s->rep,
 		s->req.rex, s->res.wex,
 		s->req.flags, s->res.flags,
-		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, s->res.cons->state, s->req.cons->state);
+		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, chn_cons(&s->res)->state, s->req.cons->state);
 
 	if (si->state == SI_ST_ASS) {
 		/* Server assigned to connection request, we have to try to connect now */
@@ -1279,7 +1279,7 @@
 		s->req, s->rep,
 		s->req.rex, s->res.wex,
 		s->req.flags, s->res.flags,
-		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, s->res.cons->state, s->req.cons->state);
+		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, chn_cons(&s->res)->state, s->req.cons->state);
 
 	if (si->state != SI_ST_REQ)
 		return;
@@ -1750,8 +1750,8 @@
 	rpf_last = s->res.flags & ~CF_MASK_ANALYSER;
 
 	/* we don't want the stream interface functions to recursively wake us up */
-	s->req.prod->flags |= SI_FL_DONT_WAKE;
-	s->req.cons->flags |= SI_FL_DONT_WAKE;
+	s->si[0].flags |= SI_FL_DONT_WAKE;
+	s->si[1].flags |= SI_FL_DONT_WAKE;
 
 	/* 1a: Check for low level timeouts if needed. We just set a flag on
 	 * stream interfaces when their timeouts have expired.
@@ -1769,27 +1769,27 @@
 		channel_check_timeouts(&s->req);
 
 		if (unlikely((s->req.flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
-			s->req.cons->flags |= SI_FL_NOLINGER;
-			si_shutw(s->req.cons);
+			chn_cons(&s->req)->flags |= SI_FL_NOLINGER;
+			si_shutw(chn_cons(&s->req));
 		}
 
 		if (unlikely((s->req.flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
-			if (s->req.prod->flags & SI_FL_NOHALF)
-				s->req.prod->flags |= SI_FL_NOLINGER;
-			si_shutr(s->req.prod);
+			if (chn_prod(&s->req)->flags & SI_FL_NOHALF)
+				chn_prod(&s->req)->flags |= SI_FL_NOLINGER;
+			si_shutr(chn_prod(&s->req));
 		}
 
 		channel_check_timeouts(&s->res);
 
 		if (unlikely((s->res.flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
-			s->res.cons->flags |= SI_FL_NOLINGER;
-			si_shutw(s->res.cons);
+			chn_cons(&s->res)->flags |= SI_FL_NOLINGER;
+			si_shutw(chn_cons(&s->res));
 		}
 
 		if (unlikely((s->res.flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
-			if (s->res.prod->flags & SI_FL_NOHALF)
-				s->res.prod->flags |= SI_FL_NOLINGER;
-			si_shutr(s->res.prod);
+			if (chn_prod(&s->res)->flags & SI_FL_NOHALF)
+				chn_prod(&s->res)->flags |= SI_FL_NOLINGER;
+			si_shutr(chn_prod(&s->res));
 		}
 
 		/* Once in a while we're woken up because the task expires. But
@@ -1894,19 +1894,19 @@
 		s->req, s->rep,
 		s->req.rex, s->res.wex,
 		s->req.flags, s->res.flags,
-		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, s->res.cons->state, s->req.cons->state,
-		s->res.cons->err_type, s->req.cons->err_type,
-		s->req.cons->conn_retries);
+		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, chn_cons(&s->res)->state, chn_cons(&s->req)->state,
+		chn_cons(&s->res)->err_type, chn_cons(&s->req)->err_type,
+		chn_cons(&s->req)->conn_retries);
 
 	/* nothing special to be done on client side */
-	if (unlikely(s->req.prod->state == SI_ST_DIS))
-		s->req.prod->state = SI_ST_CLO;
+	if (unlikely(chn_prod(&s->req)->state == SI_ST_DIS))
+		chn_prod(&s->req)->state = SI_ST_CLO;
 
 	/* When a server-side connection is released, we have to count it and
 	 * check for pending connections on this server.
 	 */
-	if (unlikely(s->req.cons->state == SI_ST_DIS)) {
-		s->req.cons->state = SI_ST_CLO;
+	if (unlikely(chn_cons(&s->req)->state == SI_ST_DIS)) {
+		chn_cons(&s->req)->state = SI_ST_CLO;
 		srv = objt_server(s->target);
 		if (srv) {
 			if (s->flags & SN_CURR_SESS) {
@@ -1933,7 +1933,7 @@
 	    s->task->state & TASK_WOKEN_MSG) {
 		unsigned int flags = s->req.flags;
 
-		if (s->req.prod->state >= SI_ST_EST) {
+		if (chn_prod(&s->req)->state >= SI_ST_EST) {
 			int max_loops = global.tune.maxpollevents;
 			unsigned int ana_list;
 			unsigned int ana_back;
@@ -2104,7 +2104,7 @@
 			s->req.flags |= CF_WAKE_ONCE;
 		}
 
-		if (s->res.prod->state >= SI_ST_EST) {
+		if (chn_prod(&s->res)->state >= SI_ST_EST) {
 			int max_loops = global.tune.maxpollevents;
 			unsigned int ana_list;
 			unsigned int ana_back;
@@ -2274,7 +2274,7 @@
 	 */
 	if (unlikely(!s->req.analysers &&
 	    !(s->req.flags & (CF_SHUTW|CF_SHUTR_NOW)) &&
-	    (s->req.prod->state >= SI_ST_EST) &&
+	    (chn_prod(&s->req)->state >= SI_ST_EST) &&
 	    (s->req.to_forward != CHN_INFINITE_FORWARD))) {
 		/* This buffer is freewheeling, there's no analyser
 		 * attached to it. If any data are left in, we'll permit them to
@@ -2330,8 +2330,8 @@
 	if (unlikely((s->req.flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
 		     channel_is_empty(&s->req))) {
 		if (s->req.flags & CF_READ_ERROR)
-			s->req.cons->flags |= SI_FL_NOLINGER;
-		si_shutw(s->req.cons);
+			chn_cons(&s->req)->flags |= SI_FL_NOLINGER;
+		si_shutw(chn_cons(&s->req));
 		if (tick_isset(s->be->timeout.serverfin)) {
 			s->res.rto = s->be->timeout.serverfin;
 			s->res.rex = tick_add(now_ms, s->res.rto);
@@ -2345,9 +2345,9 @@
 
 	/* shutdown(read) pending */
 	if (unlikely((s->req.flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
-		if (s->req.prod->flags & SI_FL_NOHALF)
-			s->req.prod->flags |= SI_FL_NOLINGER;
-		si_shutr(s->req.prod);
+		if (chn_prod(&s->req)->flags & SI_FL_NOHALF)
+			chn_prod(&s->req)->flags |= SI_FL_NOLINGER;
+		si_shutr(chn_prod(&s->req));
 		if (tick_isset(s->fe->timeout.clientfin)) {
 			s->res.wto = s->fe->timeout.clientfin;
 			s->res.wex = tick_add(now_ms, s->res.wto);
@@ -2359,19 +2359,19 @@
 	 *  - there are data scheduled for emission in the buffer
 	 *  - the CF_AUTO_CONNECT flag is set (active connection)
 	 */
-	if (s->req.cons->state == SI_ST_INI) {
+	if (chn_cons(&s->req)->state == SI_ST_INI) {
 		if (!(s->req.flags & CF_SHUTW)) {
 			if ((s->req.flags & CF_AUTO_CONNECT) || !channel_is_empty(&s->req)) {
 				/* If we have an appctx, there is no connect method, so we
 				 * immediately switch to the connected state, otherwise we
 				 * perform a connection request.
 				 */
-				s->req.cons->state = SI_ST_REQ; /* new connection requested */
-				s->req.cons->conn_retries = s->be->conn_retries;
+				chn_cons(&s->req)->state = SI_ST_REQ; /* new connection requested */
+				chn_cons(&s->req)->conn_retries = s->be->conn_retries;
 			}
 		}
 		else {
-			s->req.cons->state = SI_ST_CLO; /* shutw+ini = abort */
+			chn_cons(&s->req)->state = SI_ST_CLO; /* shutw+ini = abort */
 			channel_shutw_now(&s->req);        /* fix buffer flags upon abort */
 			channel_shutr_now(&s->res);
 		}
@@ -2414,7 +2414,7 @@
 	}
 
 	/* Benchmarks have shown that it's optimal to do a full resync now */
-	if (s->req.prod->state == SI_ST_DIS || s->req.cons->state == SI_ST_DIS)
+	if (chn_prod(&s->req)->state == SI_ST_DIS || chn_cons(&s->req)->state == SI_ST_DIS)
 		goto resync_stream_interface;
 
 	/* otherwise we want to check if we need to resync the req buffer or not */
@@ -2430,7 +2430,7 @@
 	 */
 	if (unlikely(!s->res.analysers &&
 	    !(s->res.flags & (CF_SHUTW|CF_SHUTR_NOW)) &&
-	    (s->res.prod->state >= SI_ST_EST) &&
+	    (chn_prod(&s->res)->state >= SI_ST_EST) &&
 	    (s->res.to_forward != CHN_INFINITE_FORWARD))) {
 		/* This buffer is freewheeling, there's no analyser
 		 * attached to it. If any data are left in, we'll permit them to
@@ -2507,7 +2507,7 @@
 	/* shutdown(write) pending */
 	if (unlikely((s->res.flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
 		     channel_is_empty(&s->res))) {
-		si_shutw(s->res.cons);
+		si_shutw(chn_cons(&s->res));
 		if (tick_isset(s->fe->timeout.clientfin)) {
 			s->req.rto = s->fe->timeout.clientfin;
 			s->req.rex = tick_add(now_ms, s->req.rto);
@@ -2521,16 +2521,16 @@
 
 	/* shutdown(read) pending */
 	if (unlikely((s->res.flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
-		if (s->res.prod->flags & SI_FL_NOHALF)
-			s->res.prod->flags |= SI_FL_NOLINGER;
-		si_shutr(s->res.prod);
+		if (chn_prod(&s->res)->flags & SI_FL_NOHALF)
+			chn_prod(&s->res)->flags |= SI_FL_NOLINGER;
+		si_shutr(chn_prod(&s->res));
 		if (tick_isset(s->be->timeout.serverfin)) {
 			s->req.wto = s->be->timeout.serverfin;
 			s->req.wex = tick_add(now_ms, s->req.wto);
 		}
 	}
 
-	if (s->req.prod->state == SI_ST_DIS || s->req.cons->state == SI_ST_DIS)
+	if (chn_prod(&s->req)->state == SI_ST_DIS || chn_cons(&s->req)->state == SI_ST_DIS)
 		goto resync_stream_interface;
 
 	if (s->req.flags != rqf_last)
@@ -2540,8 +2540,8 @@
 		goto resync_response;
 
 	/* we're interested in getting wakeups again */
-	s->req.prod->flags &= ~SI_FL_DONT_WAKE;
-	s->req.cons->flags &= ~SI_FL_DONT_WAKE;
+	chn_prod(&s->req)->flags &= ~SI_FL_DONT_WAKE;
+	chn_cons(&s->req)->flags &= ~SI_FL_DONT_WAKE;
 
 	/* This is needed only when debugging is enabled, to indicate
 	 * client-side or server-side close. Please note that in the unlikely
@@ -2570,17 +2570,17 @@
 		}
 	}
 
-	if (likely((s->res.cons->state != SI_ST_CLO) ||
-		   (s->req.cons->state > SI_ST_INI && s->req.cons->state < SI_ST_CLO))) {
+	if (likely((chn_cons(&s->res)->state != SI_ST_CLO) ||
+		   (chn_cons(&s->req)->state > SI_ST_INI && chn_cons(&s->req)->state < SI_ST_CLO))) {
 
 		if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
 			session_process_counters(s);
 
-		if (s->res.cons->state == SI_ST_EST && obj_type(s->res.cons->end) != OBJ_TYPE_APPCTX)
-			si_update(s->res.cons);
+		if (chn_cons(&s->res)->state == SI_ST_EST && obj_type(chn_cons(&s->res)->end) != OBJ_TYPE_APPCTX)
+			si_update(chn_cons(&s->res));
 
-		if (s->req.cons->state == SI_ST_EST && obj_type(s->req.cons->end) != OBJ_TYPE_APPCTX)
-			si_update(s->req.cons);
+		if (chn_cons(&s->req)->state == SI_ST_EST && obj_type(chn_cons(&s->req)->end) != OBJ_TYPE_APPCTX)
+			si_update(chn_cons(&s->req));
 
 		s->req.flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
 		s->res.flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
@@ -2612,7 +2612,7 @@
 		 * both functions are always called and that we wake up if at
 		 * least one did something.
 		 */
-		if ((si_applet_call(s->req.cons) | si_applet_call(s->res.cons)) != 0) {
+		if ((si_applet_call(chn_cons(&s->req)) | si_applet_call(chn_cons(&s->res))) != 0) {
 			if (task_in_rq(t)) {
 				t->expire = TICK_ETERNITY;
 				session_release_buffers(s);