MEDIUM: stream: move the listener's pointer to the session

The listener is session-specific, move it there.
diff --git a/include/types/session.h b/include/types/session.h
index c07b46a..7ee7fb2 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -36,6 +36,7 @@
 #include <types/stick_table.h>
 
 struct session {
+	struct listener *listener;      /* the listener by which the request arrived */
 };
 
 #endif /* _TYPES_SESSION_H */
diff --git a/include/types/stream.h b/include/types/stream.h
index 469edc7..7e376db 100644
--- a/include/types/stream.h
+++ b/include/types/stream.h
@@ -122,7 +122,6 @@
 
 	struct session *sess;           /* the session this stream is attached to */
 
-	struct listener *listener;      /* the listener by which the request arrived */
 	struct server *srv_conn;        /* stream already has a slot on a server and is not in queue */
 	struct pendconn *pend_pos;      /* if not NULL, points to the position in the pending queue */
 
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 62f3dd9..47a009d 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -551,7 +551,7 @@
 
 	/* any other information should be dumped here */
 
-	if (target && s->listener->bind_conf->level < ACCESS_LVL_OPER)
+	if (target && strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_OPER)
 		chunk_appendf(msg, "# contents not dumped due to insufficient privileges\n");
 
 	if (bi_putchk(si_ic(si), msg) == -1) {
@@ -705,7 +705,7 @@
 	}
 
 	/* check permissions */
-	if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
+	if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_OPER) {
 		appctx->ctx.cli.msg = stats_permission_denied_msg;
 		appctx->st0 = STAT_CLI_PRINT;
 		return;
@@ -905,7 +905,7 @@
 	struct appctx *appctx = __objt_appctx(si->end);
 	struct proxy *px;
 
-	if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+	if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 		appctx->ctx.cli.msg = stats_permission_denied_msg;
 		appctx->st0 = STAT_CLI_PRINT;
 		return NULL;
@@ -938,7 +938,7 @@
 	struct server *sv;
 	char *line;
 
-	if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+	if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 		appctx->ctx.cli.msg = stats_permission_denied_msg;
 		appctx->st0 = STAT_CLI_PRINT;
 		return NULL;
@@ -1111,7 +1111,7 @@
 		}
 		else if (strcmp(args[1], "sess") == 0) {
 			appctx->st2 = STAT_ST_INIT;
-			if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
+			if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_OPER) {
 				appctx->ctx.cli.msg = stats_permission_denied_msg;
 				appctx->st0 = STAT_CLI_PRINT;
 				return 1;
@@ -1127,7 +1127,7 @@
 			appctx->st0 = STAT_CLI_O_SESS; // stats_dump_sess_to_buffer
 		}
 		else if (strcmp(args[1], "errors") == 0) {
-			if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
+			if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_OPER) {
 				appctx->ctx.cli.msg = stats_permission_denied_msg;
 				appctx->st0 = STAT_CLI_PRINT;
 				return 1;
@@ -1188,8 +1188,8 @@
 				clrall = 1;
 
 			/* check permissions */
-			if (s->listener->bind_conf->level < ACCESS_LVL_OPER ||
-			    (clrall && s->listener->bind_conf->level < ACCESS_LVL_ADMIN)) {
+			if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_OPER ||
+			    (clrall && strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN)) {
 				appctx->ctx.cli.msg = stats_permission_denied_msg;
 				appctx->st0 = STAT_CLI_PRINT;
 				return 1;
@@ -1519,7 +1519,7 @@
 			else if (strcmp(args[2], "global") == 0) {
 				int v;
 
-				if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+				if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 					appctx->ctx.cli.msg = stats_permission_denied_msg;
 					appctx->st0 = STAT_CLI_PRINT;
 					return 1;
@@ -1561,7 +1561,7 @@
 				if (strcmp(args[3], "global") == 0) {
 					int v;
 
-					if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+					if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 						appctx->ctx.cli.msg = stats_permission_denied_msg;
 						appctx->st0 = STAT_CLI_PRINT;
 						return 1;
@@ -1598,7 +1598,7 @@
 				if (strcmp(args[3], "global") == 0) {
 					int v;
 
-					if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+					if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 						appctx->ctx.cli.msg = stats_permission_denied_msg;
 						appctx->st0 = STAT_CLI_PRINT;
 						return 1;
@@ -1636,7 +1636,7 @@
 				if (strcmp(args[3], "global") == 0) {
 					int v;
 
-					if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+					if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 						appctx->ctx.cli.msg = stats_permission_denied_msg;
 						appctx->st0 = STAT_CLI_PRINT;
 						return 1;
@@ -1981,7 +1981,7 @@
 		else if (strcmp(args[1], "session") == 0) {
 			struct stream *sess, *ptr;
 
-			if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
+			if (strm_sess(s)->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
 				appctx->ctx.cli.msg = stats_permission_denied_msg;
 				appctx->st0 = STAT_CLI_PRINT;
 				return 1;
@@ -5020,7 +5020,7 @@
 			     tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
 			     tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(sess->logs.accept_date.tv_usec),
 			     sess->uniq_id,
-			     sess->listener && sess->listener->proto->name ? sess->listener->proto->name : "?");
+			     strm_sess(sess)->listener && strm_sess(sess)->listener->proto->name ? strm_sess(sess)->listener->proto->name : "?");
 
 		conn = objt_conn(sess->si[0].end);
 		switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
@@ -5030,7 +5030,7 @@
 			              pn, get_host_port(&conn->addr.from));
 			break;
 		case AF_UNIX:
-			chunk_appendf(&trash, " source=unix:%d\n", sess->listener->luid);
+			chunk_appendf(&trash, " source=unix:%d\n", strm_sess(sess)->listener->luid);
 			break;
 		default:
 			/* no more information to print right now */
@@ -5045,8 +5045,8 @@
 		chunk_appendf(&trash,
 			     "  frontend=%s (id=%u mode=%s), listener=%s (id=%u)",
 			     sess->fe->id, sess->fe->uuid, sess->fe->mode ? "http" : "tcp",
-			     sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
-			     sess->listener ? sess->listener->luid : 0);
+			     strm_sess(sess)->listener ? strm_sess(sess)->listener->name ? strm_sess(sess)->listener->name : "?" : "?",
+			     strm_sess(sess)->listener ? strm_sess(sess)->listener->luid : 0);
 
 		if (conn)
 			conn_get_to_addr(conn);
@@ -5058,7 +5058,7 @@
 				     pn, get_host_port(&conn->addr.to));
 			break;
 		case AF_UNIX:
-			chunk_appendf(&trash, " addr=unix:%d\n", sess->listener->luid);
+			chunk_appendf(&trash, " addr=unix:%d\n", strm_sess(sess)->listener->luid);
 			break;
 		default:
 			/* no more information to print right now */
@@ -5601,7 +5601,7 @@
 			chunk_appendf(&trash,
 				     "%p: proto=%s",
 				     curr_sess,
-				     curr_sess->listener->proto->name);
+				     strm_sess(curr_sess)->listener->proto->name);
 
 
 			conn = objt_conn(curr_sess->si[0].end);
@@ -5620,7 +5620,7 @@
 			case AF_UNIX:
 				chunk_appendf(&trash,
 					     " src=unix:%d fe=%s be=%s srv=%s",
-					     curr_sess->listener->luid,
+					     strm_sess(curr_sess)->listener->luid,
 					     curr_sess->fe->id,
 					     (curr_sess->be->cap & PR_CAP_BE) ? curr_sess->be->id : "<NONE>",
 					     objt_server(curr_sess->target) ? objt_server(curr_sess->target)->id : "<none>"
@@ -5827,7 +5827,7 @@
 					return 0;
 
 				if (appctx->ctx.table.target &&
-				    s->listener->bind_conf->level >= ACCESS_LVL_OPER) {
+				    strm_sess(s)->listener->bind_conf->level >= ACCESS_LVL_OPER) {
 					/* dump entries only if table explicitly requested */
 					eb = ebmb_first(&appctx->ctx.table.proxy->table.keys);
 					if (eb) {
diff --git a/src/frontend.c b/src/frontend.c
index b793ff8..a64ff4f 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -55,6 +55,8 @@
 int frontend_accept(struct stream *s)
 {
 	struct connection *conn = __objt_conn(s->si[0].end);
+	struct listener *l = strm_sess(s)->listener;
+
 	int cfd = conn->t.sock.fd;
 
 	tv_zero(&s->logs.tv_request);
@@ -75,7 +77,7 @@
 	s->srv_error = default_srv_error;
 
 	/* Adjust some socket options */
-	if (s->listener->addr.ss_family == AF_INET || s->listener->addr.ss_family == AF_INET6) {
+	if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) {
 		if (setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY,
 			       (char *) &one, sizeof(one)) == -1)
 			goto out_return;
@@ -88,12 +90,12 @@
 			fdtab[cfd].linger_risk = 1;
 
 #if defined(TCP_MAXSEG)
-		if (s->listener->maxseg < 0) {
+		if (l->maxseg < 0) {
 			/* we just want to reduce the current MSS by that value */
 			int mss;
 			socklen_t mss_len = sizeof(mss);
 			if (getsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &mss_len) == 0) {
-				mss += s->listener->maxseg; /* remember, it's < 0 */
+				mss += l->maxseg; /* remember, it's < 0 */
 				setsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss));
 			}
 		}
@@ -158,7 +160,7 @@
 			case AF_UNIX:
 				/* UNIX socket, only the destination is known */
 				send_log(s->fe, LOG_INFO, "Connect to unix:%d (%s/%s)\n",
-					 s->listener->luid,
+					 l->luid,
 					 s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
 				break;
 			}
@@ -174,14 +176,14 @@
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
-			             s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
+			             s->uniq_id, s->fe->id, (unsigned short)l->fd, (unsigned short)cfd,
 			             pn, get_host_port(&conn->addr.from));
 			break;
 		case AF_UNIX:
 			/* UNIX socket, only the destination is known */
 			chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [unix:%d]\n",
-			             s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
-			             s->listener->luid);
+			             s->uniq_id, s->fe->id, (unsigned short)l->fd, (unsigned short)cfd,
+			             l->luid);
 			break;
 		}
 
diff --git a/src/hlua.c b/src/hlua.c
index 4b56187..1a0b920 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -2133,7 +2133,7 @@
 	/* The stream dont have listener. The listener is used with real
 	 * proxies.
 	 */
-	socket->s->listener = NULL;
+	socket->s->sess->listener = NULL;
 
 	/* The flags are initialized to 0. Values are setted later. */
 	socket->s->flags = 0;
diff --git a/src/listener.c b/src/listener.c
index 6b5fc6a..af8a524 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -33,6 +33,7 @@
 #include <proto/freq_ctr.h>
 #include <proto/log.h>
 #include <proto/sample.h>
+#include <proto/stream.h>
 #include <proto/task.h>
 
 /* List head of all known bind keywords */
@@ -593,7 +594,7 @@
                 const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
 	smp->type = SMP_T_UINT;
-	smp->data.uint = l4->listener->nbconn;
+	smp->data.uint = strm_sess(l4)->listener->nbconn;
 	return 1;
 }
 
@@ -603,7 +604,7 @@
                 const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
 	smp->type = SMP_T_UINT;
-	smp->data.uint = l4->listener->luid;
+	smp->data.uint = strm_sess(l4)->listener->luid;
 	return 1;
 }
 
diff --git a/src/log.c b/src/log.c
index c4daa81..d2ae535 100644
--- a/src/log.c
+++ b/src/log.c
@@ -34,6 +34,7 @@
 #include <proto/frontend.h>
 #include <proto/log.h>
 #include <proto/sample.h>
+#include <proto/stream.h>
 #include <proto/stream_interface.h>
 #ifdef USE_OPENSSL
 #include <proto/ssl_sock.h>
@@ -918,6 +919,7 @@
  */
 int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list_format)
 {
+	struct session *sess = strm_sess(s);
 	struct proxy *fe = s->fe;
 	struct proxy *be = s->be;
 	struct http_txn *txn = &s->txn;
@@ -999,7 +1001,7 @@
 				conn = objt_conn(s->si[0].end);
 				if (conn) {
 					if (conn->addr.from.ss_family == AF_UNIX) {
-						ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
+						ret = ltoa_o(sess->listener->luid, tmplog, dst + maxsize - tmplog);
 					} else {
 						ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from,
 						              dst + maxsize - tmplog, tmp);
@@ -1034,7 +1036,7 @@
 				if (conn) {
 					conn_get_to_addr(conn);
 					if (conn->addr.to.ss_family == AF_UNIX)
-						ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
+						ret = ltoa_o(sess->listener->luid, tmplog, dst + maxsize - tmplog);
 					else
 						ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
 				}
@@ -1181,7 +1183,7 @@
 					goto out;
 				tmplog += iret;
 #ifdef USE_OPENSSL
-				if (s->listener->xprt == &ssl_sock)
+				if (sess->listener->xprt == &ssl_sock)
 					LOGCHAR('~');
 #endif
 				if (tmp->options & LOG_OPT_QUOTE)
@@ -1193,7 +1195,7 @@
 				src = NULL;
 				conn = objt_conn(s->si[0].end);
 				if (conn) {
-					if (s->listener->xprt == &ssl_sock)
+					if (sess->listener->xprt == &ssl_sock)
 						src = ssl_sock_get_cipher_name(conn);
 				}
 				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
@@ -1207,7 +1209,7 @@
 				src = NULL;
 				conn = objt_conn(s->si[0].end);
 				if (conn) {
-					if (s->listener->xprt == &ssl_sock)
+					if (sess->listener->xprt == &ssl_sock)
 						src = ssl_sock_get_proto_version(conn);
 				}
 				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
diff --git a/src/peers.c b/src/peers.c
index 2801320..98ce8bf 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1144,13 +1144,14 @@
 	t->nice = l->nice;
 
 	s->task = t;
-	s->listener = l;
 	s->sess = pool_alloc2(pool2_session);
 	if (!s->sess) {
 		Alert("out of memory in peer_session_create().\n");
 		goto out_free_task;
 	}
 
+	s->sess->listener = l;
+
 	/* Note: initially, the stream's backend points to the frontend.
 	 * This changes later when switching rules are executed or
 	 * when the default backend is assigned.
@@ -1272,7 +1273,7 @@
 	l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
 	p->feconn++;/* beconn will be increased later */
 	jobs++;
-	if (!(s->listener->options & LI_O_UNLIMITED))
+	if (!(s->sess->listener->options & LI_O_UNLIMITED))
 		actconn++;
 	totalconn++;
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 0abba2f..4af1b80 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2546,6 +2546,7 @@
 
 	int cur_idx;
 	int use_close_only;
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->req;
 	struct hdr_ctx ctx;
@@ -2702,8 +2703,8 @@
 			stream_inc_http_req_ctr(s);
 			proxy_inc_fe_req_ctr(s->fe);
 			s->fe->fe_counters.failed_req++;
-			if (s->listener->counters)
-				s->listener->counters->failed_req++;
+			if (sess->listener->counters)
+				sess->listener->counters->failed_req++;
 
 			if (!(s->flags & SF_FINST_MASK))
 				s->flags |= SF_FINST_R;
@@ -2731,8 +2732,8 @@
 			stream_inc_http_req_ctr(s);
 			proxy_inc_fe_req_ctr(s->fe);
 			s->fe->fe_counters.failed_req++;
-			if (s->listener->counters)
-				s->listener->counters->failed_req++;
+			if (sess->listener->counters)
+				sess->listener->counters->failed_req++;
 
 			if (!(s->flags & SF_FINST_MASK))
 				s->flags |= SF_FINST_R;
@@ -2758,8 +2759,8 @@
 			stream_inc_http_req_ctr(s);
 			proxy_inc_fe_req_ctr(s->fe);
 			s->fe->fe_counters.failed_req++;
-			if (s->listener->counters)
-				s->listener->counters->failed_req++;
+			if (sess->listener->counters)
+				sess->listener->counters->failed_req++;
 
 			if (!(s->flags & SF_FINST_MASK))
 				s->flags |= SF_FINST_R;
@@ -2770,7 +2771,7 @@
 		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->si[0].end) && conn_ctrl_ready(__objt_conn(s->si[0].end))) {
+		if (sess->listener->options & LI_O_NOQUICKACK && req->buf->i && objt_conn(s->si[0].end) && conn_ctrl_ready(__objt_conn(s->si[0].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.
@@ -3071,8 +3072,8 @@
 	stream_int_retnclose(&s->si[0], http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
-	if (s->listener->counters)
-		s->listener->counters->failed_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->failed_req++;
 
  return_prx_cond:
 	if (!(s->flags & SF_ERR_MASK))
@@ -4065,6 +4066,7 @@
  */
 int http_process_req_common(struct stream *s, struct channel *req, int an_bit, struct proxy *px)
 {
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->req;
 	struct redirect_rule *rule;
@@ -4249,8 +4251,8 @@
 	s->fe->fe_counters.denied_req++;
 	if (s->fe != s->be)
 		s->be->be_counters.denied_req++;
-	if (s->listener->counters)
-		s->listener->counters->denied_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->denied_req++;
 	goto done_without_exp;
 
  deny:	/* this request was blocked (denied) */
@@ -4262,8 +4264,8 @@
 	s->fe->fe_counters.denied_req++;
 	if (s->fe != s->be)
 		s->be->be_counters.denied_req++;
-	if (s->listener->counters)
-		s->listener->counters->denied_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->denied_req++;
 	goto return_prx_cond;
 
  return_bad_req:
@@ -4280,8 +4282,8 @@
 	stream_int_retnclose(&s->si[0], http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
-	if (s->listener->counters)
-		s->listener->counters->failed_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->failed_req++;
 
  return_prx_cond:
 	if (!(s->flags & SF_ERR_MASK))
@@ -4305,6 +4307,7 @@
  */
 int http_process_request(struct stream *s, struct channel *req, int an_bit)
 {
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->req;
 	struct connection *cli_conn = objt_conn(s->si[1].end);
@@ -4597,7 +4600,7 @@
 		 * in case we previously disabled it, otherwise we might cause
 		 * the client to delay further data.
 		 */
-		if ((s->listener->options & LI_O_NOQUICKACK) &&
+		if ((sess->listener->options & LI_O_NOQUICKACK) &&
 		    cli_conn && conn_ctrl_ready(cli_conn) &&
 		    ((msg->flags & HTTP_MSGF_TE_CHNK) ||
 		     (msg->body_len > req->buf->i - txn->req.eoh - 2)))
@@ -4636,8 +4639,8 @@
 	stream_int_retnclose(&s->si[0], http_error_message(s, HTTP_ERR_400));
 
 	s->fe->fe_counters.failed_req++;
-	if (s->listener->counters)
-		s->listener->counters->failed_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->failed_req++;
 
 	if (!(s->flags & SF_ERR_MASK))
 		s->flags |= SF_ERR_PRXCOND;
@@ -4697,6 +4700,7 @@
  */
 int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit)
 {
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &s->txn.req;
 
@@ -4828,8 +4832,8 @@
  return_err_msg:
 	req->analysers = 0;
 	s->fe->fe_counters.failed_req++;
-	if (s->listener->counters)
-		s->listener->counters->failed_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->failed_req++;
 	return 0;
 }
 
@@ -5048,7 +5052,7 @@
 	/* we're in keep-alive with an idle connection, monitor it */
 	si_idle_conn(&s->si[1]);
 
-	s->req.analysers = s->listener->analysers;
+	s->req.analysers = strm_sess(s)->listener->analysers;
 	s->res.analysers = 0;
 }
 
@@ -5405,6 +5409,7 @@
  */
 int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
 {
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &s->txn.req;
 
@@ -5643,8 +5648,8 @@
 
  return_bad_req: /* let's centralize all bad requests */
 	s->fe->fe_counters.failed_req++;
-	if (s->listener->counters)
-		s->listener->counters->failed_req++;
+	if (sess->listener->counters)
+		sess->listener->counters->failed_req++;
 
  return_bad_req_stats_ok:
 	/* we may have some pending data starting at req->buf->p */
@@ -6276,6 +6281,7 @@
  */
 int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, struct proxy *px)
 {
+	struct session *sess = s->sess;
 	struct http_txn *txn = &s->txn;
 	struct http_msg *msg = &txn->rsp;
 	struct proxy *cur_proxy;
@@ -6369,8 +6375,8 @@
 
 			s->be->be_counters.denied_resp++;
 			s->fe->fe_counters.denied_resp++;
-			if (s->listener->counters)
-				s->listener->counters->denied_resp++;
+			if (sess->listener->counters)
+				sess->listener->counters->denied_resp++;
 
 			goto return_srv_prx_502;
 		}
@@ -6520,8 +6526,8 @@
 
 		s->be->be_counters.denied_resp++;
 		s->fe->fe_counters.denied_resp++;
-		if (s->listener->counters)
-			s->listener->counters->denied_resp++;
+		if (sess->listener->counters)
+			sess->listener->counters->denied_resp++;
 
 		Alert("Blocking cacheable cookie in response from instance %s, server %s.\n",
 		      s->be->id, objt_server(s->target) ? objt_server(s->target)->id : "<dispatch>");
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 1c2cb8a..338a0d2 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1089,6 +1089,7 @@
  */
 int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
 {
+	struct session *sess = s->sess;
 	struct tcp_rule *rule;
 	struct stksess *ts;
 	struct stktable *t;
@@ -1154,8 +1155,8 @@
 
 				s->be->be_counters.denied_req++;
 				s->fe->fe_counters.denied_req++;
-				if (s->listener->counters)
-					s->listener->counters->denied_req++;
+				if (sess->listener->counters)
+					sess->listener->counters->denied_req++;
 
 				if (!(s->flags & SF_ERR_MASK))
 					s->flags |= SF_ERR_PRXCOND;
@@ -1249,6 +1250,7 @@
  */
 int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
 {
+	struct session *sess = s->sess;
 	struct tcp_rule *rule;
 	int partial;
 
@@ -1315,8 +1317,8 @@
 
 				s->be->be_counters.denied_resp++;
 				s->fe->fe_counters.denied_resp++;
-				if (s->listener->counters)
-					s->listener->counters->denied_resp++;
+				if (sess->listener->counters)
+					sess->listener->counters->denied_resp++;
 
 				if (!(s->flags & SF_ERR_MASK))
 					s->flags |= SF_ERR_PRXCOND;
@@ -1360,6 +1362,7 @@
  */
 int tcp_exec_req_rules(struct stream *s)
 {
+	struct session *sess = s->sess;
 	struct tcp_rule *rule;
 	struct stksess *ts;
 	struct stktable *t = NULL;
@@ -1384,8 +1387,8 @@
 			/* we have a matching rule. */
 			if (rule->action == TCP_ACT_REJECT) {
 				s->fe->fe_counters.denied_conn++;
-				if (s->listener->counters)
-					s->listener->counters->denied_conn++;
+				if (sess->listener->counters)
+					sess->listener->counters->denied_conn++;
 
 				if (!(s->flags & SF_ERR_MASK))
 					s->flags |= SF_ERR_PRXCOND;
diff --git a/src/proxy.c b/src/proxy.c
index dfe01ff..85d7562 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -41,6 +41,7 @@
 #include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/signal.h>
+#include <proto/stream.h>
 #include <proto/task.h>
 
 
@@ -982,7 +983,7 @@
 	 * be more reliable to store the list of analysers that have been run,
 	 * but what we do here is OK for now.
 	 */
-	s->req.analysers |= be->be_req_ana & ~(s->listener->analysers);
+	s->req.analysers |= be->be_req_ana & ~strm_sess(s)->listener->analysers;
 
 	return 1;
 }
diff --git a/src/stream.c b/src/stream.c
index e81de2a..290c565 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -121,7 +121,7 @@
 	if (!s->sess)
 		goto out_free_stream;
 
-	s->listener = l;
+	s->sess->listener = l;
 	s->fe  = p;
 
 	s->si[0].flags = SI_FL_NONE;
@@ -275,23 +275,24 @@
 	char pn[INET6_ADDRSTRLEN];
 	int ret;
 	char *end;
+	struct session *sess = s->sess;
 	struct connection *cli_conn = __objt_conn(s->target);
 
 	ret = addr_to_str(&cli_conn->addr.from, pn, sizeof(pn));
 	if (ret <= 0)
 		chunk_printf(&trash, "unknown [");
 	else if (ret == AF_UNIX)
-		chunk_printf(&trash, "%s:%d [", pn, s->listener->luid);
+		chunk_printf(&trash, "%s:%d [", pn, sess->listener->luid);
 	else
 		chunk_printf(&trash, "%s:%d [", pn, get_host_port(&cli_conn->addr.from));
 
 	get_localtime(s->logs.accept_date.tv_sec, &tm);
 	end = date2str_log(trash.str + trash.len, &tm, &(s->logs.accept_date), trash.size - trash.len);
 	trash.len = end - trash.str;
-	if (s->listener->name)
-		chunk_appendf(&trash, "] %s/%s", s->fe->id, s->listener->name);
+	if (sess->listener->name)
+		chunk_appendf(&trash, "] %s/%s", s->fe->id, sess->listener->name);
 	else
-		chunk_appendf(&trash, "] %s/%d", s->fe->id, s->listener->luid);
+		chunk_appendf(&trash, "] %s/%d", s->fe->id, sess->listener->luid);
 }
 
 /* This function kills an existing embryonic stream. It stops the connection's
@@ -302,6 +303,7 @@
 static void kill_mini_session(struct stream *s)
 {
 	int level = LOG_INFO;
+	struct session *sess = s->sess;
 	struct connection *conn = __objt_conn(s->target);
 	unsigned int log = s->logs.logwait;
 	const char *err_msg;
@@ -341,12 +343,12 @@
 	s->fe->feconn--;
 	stream_store_counters(s);
 
-	if (!(s->listener->options & LI_O_UNLIMITED))
+	if (!(sess->listener->options & LI_O_UNLIMITED))
 		actconn--;
 	jobs--;
-	s->listener->nbconn--;
-	if (s->listener->state == LI_FULL)
-		resume_listener(s->listener);
+	sess->listener->nbconn--;
+	if (sess->listener->state == LI_FULL)
+		resume_listener(sess->listener);
 
 	/* Dequeues all of the listeners waiting for a resource */
 	if (!LIST_ISEMPTY(&global_listener_queue))
@@ -419,7 +421,8 @@
  */
 int stream_complete(struct stream *s)
 {
-	struct listener *l = s->listener;
+	struct session *sess = s->sess;
+	struct listener *l = sess->listener;
 	struct proxy *p = s->fe;
 	struct http_txn *txn;
 	struct task *t = s->task;
@@ -804,6 +807,7 @@
 
 void stream_process_counters(struct stream *s)
 {
+	struct session *sess = s->sess;
 	unsigned long long bytes;
 	void *ptr;
 	int i;
@@ -818,8 +822,8 @@
 		if (objt_server(s->target))
 			objt_server(s->target)->counters.bytes_in += bytes;
 
-		if (s->listener && s->listener->counters)
-			s->listener->counters->bytes_in += bytes;
+		if (sess->listener && sess->listener->counters)
+			sess->listener->counters->bytes_in += bytes;
 
 		for (i = 0; i < MAX_SESS_STKCTR; i++) {
 			if (!stkctr_entry(&s->stkctr[i]))
@@ -850,8 +854,8 @@
 		if (objt_server(s->target))
 			objt_server(s->target)->counters.bytes_out += bytes;
 
-		if (s->listener && s->listener->counters)
-			s->listener->counters->bytes_out += bytes;
+		if (sess->listener && sess->listener->counters)
+			sess->listener->counters->bytes_out += bytes;
 
 		for (i = 0; i < MAX_SESS_STKCTR; i++) {
 			if (!stkctr_entry(&s->stkctr[i]))
@@ -1271,8 +1275,8 @@
 		if (s->si[1].state < SI_ST_REQ) {
 
 			s->fe->fe_counters.failed_req++;
-			if (s->listener->counters)
-				s->listener->counters->failed_req++;
+			if (strm_sess(s)->listener->counters)
+				strm_sess(s)->listener->counters->failed_req++;
 
 			s->flags |= SF_FINST_R;
 		}
@@ -1754,6 +1758,7 @@
 {
 	struct server *srv;
 	struct stream *s = t->context;
+	struct session *sess = s->sess;
 	unsigned int rqf_last, rpf_last;
 	unsigned int rq_prod_last, rq_cons_last;
 	unsigned int rp_cons_last, rp_prod_last;
@@ -2685,12 +2690,12 @@
 	if (s->flags & SF_BE_ASSIGNED)
 		s->be->beconn--;
 	jobs--;
-	if (s->listener) {
-		if (!(s->listener->options & LI_O_UNLIMITED))
+	if (sess->listener) {
+		if (!(sess->listener->options & LI_O_UNLIMITED))
 			actconn--;
-		s->listener->nbconn--;
-		if (s->listener->state == LI_FULL)
-			resume_listener(s->listener);
+		sess->listener->nbconn--;
+		if (sess->listener->state == LI_FULL)
+			resume_listener(sess->listener);
 
 		/* Dequeues all of the listeners waiting for a resource */
 		if (!LIST_ISEMPTY(&global_listener_queue))