MAJOR: session: detach the connections from the stream interfaces

We will need to be able to switch server connections on a session and
to keep idle connections. In order to achieve this, the preliminary
requirement is that the connections can survive the session and be
detached from them.

Right now they're still allocated at exactly the same place, so when
there is a session, there are always 2 connections. We could soon
improve on this by allocating the outgoing connection only during a
connect().

This current patch touches a lot of code and intentionally does not
change any functionnality. Performance tests show no regression (even
a very minor improvement). The doc has not yet been updated.
diff --git a/src/backend.c b/src/backend.c
index 4528d0e..82a88be 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -547,14 +547,14 @@
 
 			switch (s->be->lbprm.algo & BE_LB_PARM) {
 			case BE_LB_HASH_SRC:
-				if (s->req->prod->conn.addr.from.ss_family == AF_INET) {
+				if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
 					srv = get_server_sh(s->be,
-							    (void *)&((struct sockaddr_in *)&s->req->prod->conn.addr.from)->sin_addr,
+							    (void *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr,
 							    4);
 				}
-				else if (s->req->prod->conn.addr.from.ss_family == AF_INET6) {
+				else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
 					srv = get_server_sh(s->be,
-							    (void *)&((struct sockaddr_in6 *)&s->req->prod->conn.addr.from)->sin6_addr,
+							    (void *)&((struct sockaddr_in6 *)&s->req->prod->conn->addr.from)->sin6_addr,
 							    16);
 				}
 				else {
@@ -637,7 +637,7 @@
 		set_target_proxy(&s->target, s->be);
 	}
 	else if ((s->be->options & PR_O_HTTP_PROXY) &&
-		 is_addr(&s->req->cons->conn.addr.to)) {
+		 is_addr(&s->req->cons->conn->addr.to)) {
 		/* in proxy mode, we need a valid destination address */
 		set_target_proxy(&s->target, s->be);
 	}
@@ -691,20 +691,20 @@
 		if (!(s->flags & SN_ASSIGNED))
 			return SRV_STATUS_INTERNAL;
 
-		s->req->cons->conn.addr.to = target_srv(&s->target)->addr;
+		s->req->cons->conn->addr.to = target_srv(&s->target)->addr;
 
-		if (!is_addr(&s->req->cons->conn.addr.to)) {
+		if (!is_addr(&s->req->cons->conn->addr.to)) {
 			/* if the server has no address, we use the same address
 			 * the client asked, which is handy for remapping ports
 			 * locally on multiple addresses at once.
 			 */
 			if (!(s->be->options & PR_O_TRANSP))
-				conn_get_to_addr(&s->req->prod->conn);
+				conn_get_to_addr(s->req->prod->conn);
 
-			if (s->req->prod->conn.addr.to.ss_family == AF_INET) {
-				((struct sockaddr_in *)&s->req->cons->conn.addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->conn.addr.to)->sin_addr;
-			} else if (s->req->prod->conn.addr.to.ss_family == AF_INET6) {
-				((struct sockaddr_in6 *)&s->req->cons->conn.addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->conn.addr.to)->sin6_addr;
+			if (s->req->prod->conn->addr.to.ss_family == AF_INET) {
+				((struct sockaddr_in *)&s->req->cons->conn->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
+			} else if (s->req->prod->conn->addr.to.ss_family == AF_INET6) {
+				((struct sockaddr_in6 *)&s->req->cons->conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->conn->addr.to)->sin6_addr;
 			}
 		}
 
@@ -714,26 +714,26 @@
 			int base_port;
 
 			if (!(s->be->options & PR_O_TRANSP))
-				conn_get_to_addr(&s->req->prod->conn);
+				conn_get_to_addr(s->req->prod->conn);
 
 			/* First, retrieve the port from the incoming connection */
-			base_port = get_host_port(&s->req->prod->conn.addr.to);
+			base_port = get_host_port(&s->req->prod->conn->addr.to);
 
 			/* Second, assign the outgoing connection's port */
-			base_port += get_host_port(&s->req->cons->conn.addr.to);
-			set_host_port(&s->req->cons->conn.addr.to, base_port);
+			base_port += get_host_port(&s->req->cons->conn->addr.to);
+			set_host_port(&s->req->cons->conn->addr.to, base_port);
 		}
 	}
 	else if (s->be->options & PR_O_DISPATCH) {
 		/* connect to the defined dispatch addr */
-		s->req->cons->conn.addr.to = s->be->dispatch_addr;
+		s->req->cons->conn->addr.to = s->be->dispatch_addr;
 	}
 	else if (s->be->options & PR_O_TRANSP) {
 		/* in transparent mode, use the original dest addr if no dispatch specified */
-		conn_get_to_addr(&s->req->prod->conn);
+		conn_get_to_addr(s->req->prod->conn);
 
-		if (s->req->prod->conn.addr.to.ss_family == AF_INET || s->req->prod->conn.addr.to.ss_family == AF_INET6) {
-			memcpy(&s->req->cons->conn.addr.to, &s->req->prod->conn.addr.to, MIN(sizeof(s->req->cons->conn.addr.to), sizeof(s->req->prod->conn.addr.to)));
+		if (s->req->prod->conn->addr.to.ss_family == AF_INET || s->req->prod->conn->addr.to.ss_family == AF_INET6) {
+			memcpy(&s->req->cons->conn->addr.to, &s->req->prod->conn->addr.to, MIN(sizeof(s->req->cons->conn->addr.to), sizeof(s->req->prod->conn->addr.to)));
 		}
 		/* when we support IPv6 on the backend, we may add other tests */
 		//qfprintf(stderr, "Cannot get original server address.\n");
@@ -887,12 +887,12 @@
 	if (srv && srv->state & SRV_BIND_SRC) {
 		switch (srv->state & SRV_TPROXY_MASK) {
 		case SRV_TPROXY_ADDR:
-			s->req->cons->conn.addr.from = srv->tproxy_addr;
+			s->req->cons->conn->addr.from = srv->tproxy_addr;
 			break;
 		case SRV_TPROXY_CLI:
 		case SRV_TPROXY_CIP:
 			/* FIXME: what can we do if the client connects in IPv6 or unix socket ? */
-			s->req->cons->conn.addr.from = s->req->prod->conn.addr.from;
+			s->req->cons->conn->addr.from = s->req->prod->conn->addr.from;
 			break;
 		case SRV_TPROXY_DYN:
 			if (srv->bind_hdr_occ) {
@@ -901,32 +901,32 @@
 				int rewind;
 
 				/* bind to the IP in a header */
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_family = AF_INET;
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_port = 0;
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr = 0;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_family = AF_INET;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_port = 0;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr = 0;
 
 				b_rew(s->req->buf, rewind = s->req->buf->o);
 				if (http_get_hdr(&s->txn.req, srv->bind_hdr_name, srv->bind_hdr_len,
 						 &s->txn.hdr_idx, srv->bind_hdr_occ, NULL, &vptr, &vlen)) {
-					((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr =
+					((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
 				b_adv(s->req->buf, rewind);
 			}
 			break;
 		default:
-			memset(&s->req->cons->conn.addr.from, 0, sizeof(s->req->cons->conn.addr.from));
+			memset(&s->req->cons->conn->addr.from, 0, sizeof(s->req->cons->conn->addr.from));
 		}
 	}
 	else if (s->be->options & PR_O_BIND_SRC) {
 		switch (s->be->options & PR_O_TPXY_MASK) {
 		case PR_O_TPXY_ADDR:
-			s->req->cons->conn.addr.from = s->be->tproxy_addr;
+			s->req->cons->conn->addr.from = s->be->tproxy_addr;
 			break;
 		case PR_O_TPXY_CLI:
 		case PR_O_TPXY_CIP:
 			/* FIXME: what can we do if the client connects in IPv6 or socket unix? */
-			s->req->cons->conn.addr.from = s->req->prod->conn.addr.from;
+			s->req->cons->conn->addr.from = s->req->prod->conn->addr.from;
 			break;
 		case PR_O_TPXY_DYN:
 			if (s->be->bind_hdr_occ) {
@@ -935,21 +935,21 @@
 				int rewind;
 
 				/* bind to the IP in a header */
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_family = AF_INET;
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_port = 0;
-				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr = 0;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_family = AF_INET;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_port = 0;
+				((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr = 0;
 
 				b_rew(s->req->buf, rewind = s->req->buf->o);
 				if (http_get_hdr(&s->txn.req, s->be->bind_hdr_name, s->be->bind_hdr_len,
 						 &s->txn.hdr_idx, s->be->bind_hdr_occ, NULL, &vptr, &vlen)) {
-					((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr =
+					((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
 				b_adv(s->req->buf, rewind);
 			}
 			break;
 		default:
-			memset(&s->req->cons->conn.addr.from, 0, sizeof(s->req->cons->conn.addr.from));
+			memset(&s->req->cons->conn->addr.from, 0, sizeof(s->req->cons->conn->addr.from));
 		}
 	}
 #endif
@@ -981,7 +981,7 @@
 	}
 
 	/* the target was only on the session, assign it to the SI now */
-	copy_target(&s->req->cons->conn.target, &s->target);
+	copy_target(&s->req->cons->conn->target, &s->target);
 
 	/* set the correct protocol on the output stream interface */
 	if (s->target.type == TARG_TYPE_SERVER) {
@@ -989,7 +989,7 @@
 	}
 	else if (s->target.type == TARG_TYPE_PROXY) {
 		/* proxies exclusively run on raw_sock right now */
-		si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->conn.addr.to.ss_family), &raw_sock);
+		si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->conn->addr.to.ss_family), &raw_sock);
 		if (!si_ctrl(s->req->cons))
 			return SN_ERR_INTERNAL;
 	}
@@ -1000,7 +1000,7 @@
 	s->req->cons->send_proxy_ofs = 0;
 	if (s->target.type == TARG_TYPE_SERVER && (s->target.ptr.s->state & SRV_SEND_PROXY)) {
 		s->req->cons->send_proxy_ofs = 1; /* must compute size */
-		conn_get_to_addr(&s->req->prod->conn);
+		conn_get_to_addr(s->req->prod->conn);
 	}
 
 	assign_tproxy_address(s);
diff --git a/src/connection.c b/src/connection.c
index 310e0da..9ccebbc 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -26,6 +26,15 @@
 #include <proto/ssl_sock.h>
 #endif
 
+struct pool_head *pool2_connection;
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_connection()
+{
+	pool2_connection = create_pool("connection", sizeof (struct connection), MEM_F_SHARED);
+	return pool2_connection != NULL;
+}
+
 /* I/O callback for fd-based connections. It calls the read/write handlers
  * provided by the connection's sock_ops, which must be valid. It returns 0.
  */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 21517be..0732e2a 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -125,8 +125,8 @@
 {
 	/* we have a dedicated I/O handler for the stats */
 	stream_int_register_handler(&s->si[1], &cli_applet);
-	copy_target(&s->target, &s->si[1].conn.target); // for logging only
-	s->si[1].conn.xprt_ctx = s;
+	copy_target(&s->target, &s->si[1].conn->target); // for logging only
+	s->si[1].conn->xprt_ctx = s;
 	s->si[1].applet.st1 = 0;
 	s->si[1].applet.st0 = STAT_CLI_INIT;
 
@@ -431,7 +431,7 @@
 static int stats_dump_table_head_to_buffer(struct chunk *msg, struct stream_interface *si,
 					   struct proxy *proxy, struct proxy *target)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 
 	chunk_printf(msg, "# table: %s, type: %s, size:%d, used:%d\n",
 		     proxy->id, stktable_types[proxy->table.type].kw, proxy->table.size, proxy->table.current);
@@ -520,7 +520,7 @@
 
 static void stats_sock_table_key_request(struct stream_interface *si, char **args, int action)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct proxy *px = si->applet.ctx.table.target;
 	struct stksess *ts;
 	uint32_t uint32_key;
@@ -723,7 +723,7 @@
 static void stats_sock_table_request(struct stream_interface *si, char **args, int action)
 {
 	si->applet.ctx.table.data_type = -1;
-	si->conn.xprt_st = STAT_ST_INIT;
+	si->conn->xprt_st = STAT_ST_INIT;
 	si->applet.ctx.table.target = NULL;
 	si->applet.ctx.table.proxy = NULL;
 	si->applet.ctx.table.entry = NULL;
@@ -849,7 +849,7 @@
  */
 static int stats_sock_parse_request(struct stream_interface *si, char *line)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	char *args[MAX_STATS_ARGS + 1];
 	int arg;
 
@@ -888,17 +888,17 @@
 
 			si->applet.ctx.stats.flags |= STAT_SHOW_STAT;
 			si->applet.ctx.stats.flags |= STAT_FMT_CSV;
-			si->conn.xprt_st = STAT_ST_INIT;
+			si->conn->xprt_st = STAT_ST_INIT;
 			si->applet.st0 = STAT_CLI_O_INFO; // stats_dump_raw_to_buffer
 		}
 		else if (strcmp(args[1], "info") == 0) {
 			si->applet.ctx.stats.flags |= STAT_SHOW_INFO;
 			si->applet.ctx.stats.flags |= STAT_FMT_CSV;
-			si->conn.xprt_st = STAT_ST_INIT;
+			si->conn->xprt_st = STAT_ST_INIT;
 			si->applet.st0 = STAT_CLI_O_INFO; // stats_dump_raw_to_buffer
 		}
 		else if (strcmp(args[1], "sess") == 0) {
-			si->conn.xprt_st = STAT_ST_INIT;
+			si->conn->xprt_st = STAT_ST_INIT;
 			if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
 				si->applet.ctx.cli.msg = stats_permission_denied_msg;
 				si->applet.st0 = STAT_CLI_PRINT;
@@ -923,7 +923,7 @@
 			else
 				si->applet.ctx.errors.iid	= -1;
 			si->applet.ctx.errors.px = NULL;
-			si->conn.xprt_st = STAT_ST_INIT;
+			si->conn->xprt_st = STAT_ST_INIT;
 			si->applet.st0 = STAT_CLI_O_ERR; // stats_dump_errors_to_buffer
 		}
 		else if (strcmp(args[1], "table") == 0) {
@@ -1670,10 +1670,10 @@
 
 	chunk_init(&msg, trash, global.tune.bufsize);
 
-	switch (si->conn.xprt_st) {
+	switch (si->conn->xprt_st) {
 	case STAT_ST_INIT:
 		/* the function had not been called yet */
-		si->conn.xprt_st = STAT_ST_HEAD;
+		si->conn->xprt_st = STAT_ST_HEAD;
 		/* fall through */
 
 	case STAT_ST_HEAD:
@@ -1683,7 +1683,7 @@
 				return 0;
 		}
 
-		si->conn.xprt_st = STAT_ST_INFO;
+		si->conn->xprt_st = STAT_ST_INFO;
 		/* fall through */
 
 	case STAT_ST_INFO:
@@ -1736,7 +1736,7 @@
 		si->applet.ctx.stats.px = proxy;
 		si->applet.ctx.stats.px_st = STAT_PX_ST_INIT;
 		si->applet.ctx.stats.sv = NULL;
-		si->conn.xprt_st = STAT_ST_LIST;
+		si->conn->xprt_st = STAT_ST_LIST;
 		/* fall through */
 
 	case STAT_ST_LIST:
@@ -1757,11 +1757,11 @@
 			/* here, we just have reached the last proxy */
 		}
 
-		si->conn.xprt_st = STAT_ST_END;
+		si->conn->xprt_st = STAT_ST_END;
 		/* fall through */
 
 	case STAT_ST_END:
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		/* fall through */
 
 	case STAT_ST_FIN:
@@ -1769,7 +1769,7 @@
 
 	default:
 		/* unknown state ! */
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		return 1;
 	}
 }
@@ -1781,12 +1781,12 @@
  */
 static int stats_http_redir(struct stream_interface *si, struct uri_auth *uri)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct chunk msg;
 
 	chunk_init(&msg, trash, global.tune.bufsize);
 
-	switch (si->conn.xprt_st) {
+	switch (si->conn->xprt_st) {
 	case STAT_ST_INIT:
 		chunk_printf(&msg,
 			"HTTP/1.0 303 See Other\r\n"
@@ -1812,7 +1812,7 @@
 		if (!(s->flags & SN_FINST_MASK))
 			s->flags |= SN_FINST_R;
 
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		return 1;
 	}
 	return 1;
@@ -1826,7 +1826,7 @@
  */
 static void http_stats_io_handler(struct stream_interface *si)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct channel *req = si->ob;
 	struct channel *res = si->ib;
 
@@ -1882,7 +1882,7 @@
  */
 static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct channel *rep = si->ib;
 	struct proxy *px;
 	struct chunk msg;
@@ -1890,7 +1890,7 @@
 
 	chunk_init(&msg, trash, global.tune.bufsize);
 
-	switch (si->conn.xprt_st) {
+	switch (si->conn->xprt_st) {
 	case STAT_ST_INIT:
 		chunk_printf(&msg,
 			     "HTTP/1.0 200 OK\r\n"
@@ -1916,11 +1916,11 @@
 
 		if (s->txn.meth == HTTP_METH_HEAD) {
 			/* that's all we return in case of HEAD request */
-			si->conn.xprt_st = STAT_ST_FIN;
+			si->conn->xprt_st = STAT_ST_FIN;
 			return 1;
 		}
 
-		si->conn.xprt_st = STAT_ST_HEAD; /* let's start producing data */
+		si->conn->xprt_st = STAT_ST_HEAD; /* let's start producing data */
 		/* fall through */
 
 	case STAT_ST_HEAD:
@@ -2024,7 +2024,7 @@
 		if (bi_putchk(rep, &msg) == -1)
 			return 0;
 
-		si->conn.xprt_st = STAT_ST_INFO;
+		si->conn->xprt_st = STAT_ST_INFO;
 		/* fall through */
 
 	case STAT_ST_INFO:
@@ -2202,7 +2202,7 @@
 
 		si->applet.ctx.stats.px = proxy;
 		si->applet.ctx.stats.px_st = STAT_PX_ST_INIT;
-		si->conn.xprt_st = STAT_ST_LIST;
+		si->conn->xprt_st = STAT_ST_LIST;
 		/* fall through */
 
 	case STAT_ST_LIST:
@@ -2221,7 +2221,7 @@
 		}
 		/* here, we just have reached the last proxy */
 
-		si->conn.xprt_st = STAT_ST_END;
+		si->conn->xprt_st = STAT_ST_END;
 		/* fall through */
 
 	case STAT_ST_END:
@@ -2231,7 +2231,7 @@
 				return 0;
 		}
 
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		/* fall through */
 
 	case STAT_ST_FIN:
@@ -2239,7 +2239,7 @@
 
 	default:
 		/* unknown state ! */
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		return -1;
 	}
 }
@@ -2252,7 +2252,7 @@
  */
 static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct channel *rep = si->ib;
 	struct server *sv, *svs;	/* server and server-state, server-state=server or server->track */
 	struct listener *l;
@@ -3341,11 +3341,11 @@
 			     sess->uniq_id,
 			     sess->listener->proto->name);
 
-		switch (addr_to_str(&sess->si[0].conn.addr.from, pn, sizeof(pn))) {
+		switch (addr_to_str(&sess->si[0].conn->addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " source=%s:%d\n",
-				     pn, get_host_port(&sess->si[0].conn.addr.from));
+				     pn, get_host_port(&sess->si[0].conn->addr.from));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " source=unix:%d\n", sess->listener->luid);
@@ -3366,12 +3366,12 @@
 			     sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
 			     sess->listener ? sess->listener->luid : 0);
 
-		conn_get_to_addr(&sess->si[0].conn);
-		switch (addr_to_str(&sess->si[0].conn.addr.to, pn, sizeof(pn))) {
+		conn_get_to_addr(sess->si[0].conn);
+		switch (addr_to_str(&sess->si[0].conn->addr.to, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[0].conn.addr.to));
+				     pn, get_host_port(&sess->si[0].conn->addr.to));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix:%d\n", sess->listener->luid);
@@ -3390,12 +3390,12 @@
 		else
 			chunk_printf(&msg, "  backend=<NONE> (id=-1 mode=-)");
 
-		conn_get_from_addr(&sess->si[1].conn);
-		switch (addr_to_str(&sess->si[1].conn.addr.from, pn, sizeof(pn))) {
+		conn_get_from_addr(sess->si[1].conn);
+		switch (addr_to_str(&sess->si[1].conn->addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[1].conn.addr.from));
+				     pn, get_host_port(&sess->si[1].conn->addr.from));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix\n");
@@ -3414,12 +3414,12 @@
 		else
 			chunk_printf(&msg, "  server=<NONE> (id=-1)");
 
-		conn_get_to_addr(&sess->si[1].conn);
-		switch (addr_to_str(&sess->si[1].conn.addr.to, pn, sizeof(pn))) {
+		conn_get_to_addr(sess->si[1].conn);
+		switch (addr_to_str(&sess->si[1].conn->addr.to, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[1].conn.addr.to));
+				     pn, get_host_port(&sess->si[1].conn->addr.to));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix\n");
@@ -3560,7 +3560,7 @@
 		/* If we're forced to shut down, we might have to remove our
 		 * reference to the last session being dumped.
 		 */
-		if (si->conn.xprt_st == STAT_ST_LIST) {
+		if (si->conn->xprt_st == STAT_ST_LIST) {
 			if (!LIST_ISEMPTY(&si->applet.ctx.sess.bref.users)) {
 				LIST_DEL(&si->applet.ctx.sess.bref.users);
 				LIST_INIT(&si->applet.ctx.sess.bref.users);
@@ -3571,7 +3571,7 @@
 
 	chunk_init(&msg, trash, global.tune.bufsize);
 
-	switch (si->conn.xprt_st) {
+	switch (si->conn->xprt_st) {
 	case STAT_ST_INIT:
 		/* the function had not been called yet, let's prepare the
 		 * buffer for a response. We initialize the current session
@@ -3582,7 +3582,7 @@
 		 */
 		LIST_INIT(&si->applet.ctx.sess.bref.users);
 		si->applet.ctx.sess.bref.ref = sessions.n;
-		si->conn.xprt_st = STAT_ST_LIST;
+		si->conn->xprt_st = STAT_ST_LIST;
 		/* fall through */
 
 	case STAT_ST_LIST:
@@ -3621,13 +3621,13 @@
 				     curr_sess->listener->proto->name);
 
 
-			switch (addr_to_str(&curr_sess->si[0].conn.addr.from, pn, sizeof(pn))) {
+			switch (addr_to_str(&curr_sess->si[0].conn->addr.from, pn, sizeof(pn))) {
 			case AF_INET:
 			case AF_INET6:
 				chunk_printf(&msg,
 					     " src=%s:%d fe=%s be=%s srv=%s",
 					     pn,
-					     get_host_port(&curr_sess->si[0].conn.addr.from),
+					     get_host_port(&curr_sess->si[0].conn->addr.from),
 					     curr_sess->fe->id,
 					     (curr_sess->be->cap & PR_CAP_BE) ? curr_sess->be->id : "<NONE>",
 					     target_srv(&curr_sess->target) ? target_srv(&curr_sess->target)->id : "<none>"
@@ -3747,11 +3747,11 @@
 			return 1;
 		}
 
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		/* fall through */
 
 	default:
-		si->conn.xprt_st = STAT_ST_FIN;
+		si->conn->xprt_st = STAT_ST_FIN;
 		return 1;
 	}
 }
@@ -3763,14 +3763,14 @@
  */
 static int stats_table_request(struct stream_interface *si, bool show)
 {
-	struct session *s = si->conn.xprt_ctx;
+	struct session *s = si->conn->xprt_ctx;
 	struct chunk msg;
 	struct ebmb_node *eb;
 	int dt;
 	bool skip_entry;
 
 	/*
-	 * We have 3 possible states in si->conn.xprt_st :
+	 * We have 3 possible states in si->conn->xprt_st :
 	 *   - STAT_ST_INIT : the first call
 	 *   - STAT_ST_INFO : the proxy pointer points to the next table to
 	 *     dump, the entry pointer is NULL ;
@@ -3783,7 +3783,7 @@
 
 	if (unlikely(si->ib->flags & (CF_WRITE_ERROR|CF_SHUTW))) {
 		/* in case of abort, remove any refcount we might have set on an entry */
-		if (si->conn.xprt_st == STAT_ST_LIST) {
+		if (si->conn->xprt_st == STAT_ST_LIST) {
 			si->applet.ctx.table.entry->ref_cnt--;
 			stksess_kill_if_expired(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry);
 		}
@@ -3792,22 +3792,22 @@
 
 	chunk_init(&msg, trash, global.tune.bufsize);
 
-	while (si->conn.xprt_st != STAT_ST_FIN) {
-		switch (si->conn.xprt_st) {
+	while (si->conn->xprt_st != STAT_ST_FIN) {
+		switch (si->conn->xprt_st) {
 		case STAT_ST_INIT:
 			si->applet.ctx.table.proxy = si->applet.ctx.table.target;
 			if (!si->applet.ctx.table.proxy)
 				si->applet.ctx.table.proxy = proxy;
 
 			si->applet.ctx.table.entry = NULL;
-			si->conn.xprt_st = STAT_ST_INFO;
+			si->conn->xprt_st = STAT_ST_INFO;
 			break;
 
 		case STAT_ST_INFO:
 			if (!si->applet.ctx.table.proxy ||
 			    (si->applet.ctx.table.target &&
 			     si->applet.ctx.table.proxy != si->applet.ctx.table.target)) {
-				si->conn.xprt_st = STAT_ST_END;
+				si->conn->xprt_st = STAT_ST_END;
 				break;
 			}
 
@@ -3823,7 +3823,7 @@
 					if (eb) {
 						si->applet.ctx.table.entry = ebmb_entry(eb, struct stksess, key);
 						si->applet.ctx.table.entry->ref_cnt++;
-						si->conn.xprt_st = STAT_ST_LIST;
+						si->conn->xprt_st = STAT_ST_LIST;
 						break;
 					}
 				}
@@ -3903,11 +3903,11 @@
 				stksess_kill(&si->applet.ctx.table.proxy->table, si->applet.ctx.table.entry);
 
 			si->applet.ctx.table.proxy = si->applet.ctx.table.proxy->next;
-			si->conn.xprt_st = STAT_ST_INFO;
+			si->conn->xprt_st = STAT_ST_INFO;
 			break;
 
 		case STAT_ST_END:
-			si->conn.xprt_st = STAT_ST_FIN;
+			si->conn->xprt_st = STAT_ST_FIN;
 			break;
 		}
 	}
diff --git a/src/frontend.c b/src/frontend.c
index d4b60db..0adbf8d 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -139,16 +139,16 @@
 		else {
 			char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
 
-			conn_get_from_addr(&s->req->prod->conn);
-			conn_get_to_addr(&s->req->prod->conn);
+			conn_get_from_addr(s->req->prod->conn);
+			conn_get_to_addr(s->req->prod->conn);
 
-			switch (addr_to_str(&s->req->prod->conn.addr.from, pn, sizeof(pn))) {
+			switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
 			case AF_INET:
 			case AF_INET6:
-				addr_to_str(&s->req->prod->conn.addr.to, sn, sizeof(sn));
+				addr_to_str(&s->req->prod->conn->addr.to, sn, sizeof(sn));
 				send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
-					 pn, get_host_port(&s->req->prod->conn.addr.from),
-					 sn, get_host_port(&s->req->prod->conn.addr.to),
+					 pn, get_host_port(&s->req->prod->conn->addr.from),
+					 sn, get_host_port(&s->req->prod->conn->addr.to),
 					 s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
 				break;
 			case AF_UNIX:
@@ -165,14 +165,14 @@
 		char pn[INET6_ADDRSTRLEN];
 		int len = 0;
 
-		conn_get_from_addr(&s->req->prod->conn);
+		conn_get_from_addr(s->req->prod->conn);
 
-		switch (addr_to_str(&s->req->prod->conn.addr.from, pn, sizeof(pn))) {
+		switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			len = sprintf(trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
 				      s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
-				      pn, get_host_port(&s->req->prod->conn.addr.from));
+				      pn, get_host_port(&s->req->prod->conn->addr.from));
 			break;
 		case AF_UNIX:
 			/* UNIX socket, only the destination is known */
diff --git a/src/haproxy.c b/src/haproxy.c
index 6d00438..bfbcb32 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -77,6 +77,7 @@
 #include <proto/backend.h>
 #include <proto/channel.h>
 #include <proto/checks.h>
+#include <proto/connection.h>
 #include <proto/fd.h>
 #include <proto/hdr_idx.h>
 #include <proto/listener.h>
@@ -430,6 +431,7 @@
 	signal_init();
 	init_task();
 	init_session();
+	init_connection();
 	/* warning, we init buffers later */
 	init_pendconn();
 	init_proto_http();
@@ -1122,6 +1124,7 @@
 	}
 
 	pool_destroy2(pool2_session);
+	pool_destroy2(pool2_connection);
 	pool_destroy2(pool2_buffer);
 	pool_destroy2(pool2_channel);
 	pool_destroy2(pool2_requri);
diff --git a/src/log.c b/src/log.c
index 130c378..752f275 100644
--- a/src/log.c
+++ b/src/log.c
@@ -842,7 +842,7 @@
 				break;
 
 			case LOG_FMT_CLIENTIP:  // %Ci
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.from,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -851,10 +851,10 @@
 				break;
 
 			case LOG_FMT_CLIENTPORT:  // %Cp
-				if (s->req->prod->conn.addr.from.ss_family == AF_UNIX) {
+				if (s->req->prod->conn->addr.from.ss_family == AF_UNIX) {
 					ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
 				} else {
-					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.from,
+					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
 						      dst + maxsize - tmplog, tmp);
 				}
 				if (ret == NULL)
@@ -864,8 +864,8 @@
 				break;
 
 			case LOG_FMT_FRONTENDIP: // %Fi
-				conn_get_to_addr(&s->req->prod->conn);
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.to,
+				conn_get_to_addr(s->req->prod->conn);
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -874,12 +874,12 @@
 				break;
 
 			case  LOG_FMT_FRONTENDPORT: // %Fp
-				conn_get_to_addr(&s->req->prod->conn);
-				if (s->req->prod->conn.addr.to.ss_family == AF_UNIX) {
+				conn_get_to_addr(s->req->prod->conn);
+				if (s->req->prod->conn->addr.to.ss_family == AF_UNIX) {
 					ret = ltoa_o(s->listener->luid,
 						     tmplog, dst + maxsize - tmplog);
 				} else {
-					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.to,
+					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
 						      dst + maxsize - tmplog, tmp);
 				}
 				if (ret == NULL)
@@ -889,7 +889,7 @@
 				break;
 
 			case LOG_FMT_BACKENDIP:  // %Bi
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.from,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -898,7 +898,7 @@
 				break;
 
 			case LOG_FMT_BACKENDPORT:  // %Bp
-				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.from,
+				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
 					      dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -907,7 +907,7 @@
 				break;
 
 			case LOG_FMT_SERVERIP: // %Si
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.to,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -916,7 +916,7 @@
 				break;
 
 			case LOG_FMT_SERVERPORT: // %Sp
-				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.to,
+				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
 					      dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -1007,7 +1007,7 @@
 			case LOG_FMT_SSL_CIPHER: // %sslc
 				src = NULL;
 				if (s->listener->xprt == &ssl_sock)
-					src = ssl_sock_get_cipher_name(&s->si[0].conn);
+					src = ssl_sock_get_cipher_name(s->si[0].conn);
 				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -1018,7 +1018,7 @@
 			case LOG_FMT_SSL_VERSION: // %sslv
 				src = NULL;
 				if (s->listener->xprt == &ssl_sock)
-					src = ssl_sock_get_proto_version(&s->si[0].conn);
+					src = ssl_sock_get_proto_version(s->si[0].conn);
 				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
diff --git a/src/peers.c b/src/peers.c
index 05baa02..a84aba4 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -184,9 +184,9 @@
 {
 	struct task *t = (struct task *)si->owner;
 	struct session *s = (struct session *)t->context;
-	struct peer_session *ps = (struct peer_session *)si->conn.xprt_ctx;
+	struct peer_session *ps = (struct peer_session *)si->conn->xprt_ctx;
 
-	/* si->conn.xprt_ctx is not a peer session */
+	/* si->conn->xprt_ctx is not a peer session */
 	if (si->applet.st0 < PEER_SESSION_SENDSUCCESS)
 		return;
 
@@ -226,7 +226,7 @@
 switchstate:
 		switch(si->applet.st0) {
 			case PEER_SESSION_ACCEPT:
-				si->conn.xprt_ctx = NULL;
+				si->conn->xprt_ctx = NULL;
 				si->applet.st0 = PEER_SESSION_GETVERSION;
 				/* fall through */
 			case PEER_SESSION_GETVERSION:
@@ -332,12 +332,12 @@
 					goto switchstate;
 				}
 
-				si->conn.xprt_ctx = curpeer;
+				si->conn->xprt_ctx = curpeer;
 				si->applet.st0 = PEER_SESSION_GETTABLE;
 				/* fall through */
 			}
 			case PEER_SESSION_GETTABLE: {
-				struct peer *curpeer = (struct peer *)si->conn.xprt_ctx;
+				struct peer *curpeer = (struct peer *)si->conn->xprt_ctx;
 				struct shared_table *st;
 				struct peer_session *ps = NULL;
 				unsigned long key_type;
@@ -348,12 +348,12 @@
 				if (reql <= 0) { /* closed or EOL not found */
 					if (reql == 0)
 						goto out;
-					si->conn.xprt_ctx = NULL;
+					si->conn->xprt_ctx = NULL;
 					si->applet.st0 = PEER_SESSION_END;
 					goto switchstate;
 				}
-				/* Re init si->conn.xprt_ctx to null, to handle correctly a release case */
-				si->conn.xprt_ctx = NULL;
+				/* Re init si->conn->xprt_ctx to null, to handle correctly a release case */
+				si->conn->xprt_ctx = NULL;
 
 				if (trash[reql-1] != '\n') {
 					/* Incomplete line, we quit */
@@ -379,7 +379,7 @@
 
 				p = strchr(p+1, ' ');
 				if (!p) {
-					si->conn.xprt_ctx = NULL;
+					si->conn->xprt_ctx = NULL;
 					si->applet.st0 = PEER_SESSION_EXIT;
 					si->applet.st1 = PEER_SESSION_ERRPROTO;
 					goto switchstate;
@@ -438,12 +438,12 @@
 					goto switchstate;
 				}
 
-				si->conn.xprt_ctx = ps;
+				si->conn->xprt_ctx = ps;
 				si->applet.st0 = PEER_SESSION_SENDSUCCESS;
 				/* fall through */
 			}
 			case PEER_SESSION_SENDSUCCESS:{
-				struct peer_session *ps = (struct peer_session *)si->conn.xprt_ctx;
+				struct peer_session *ps = (struct peer_session *)si->conn->xprt_ctx;
 
 				repl = snprintf(trash, global.tune.bufsize, "%d\n", PEER_SESSION_SUCCESSCODE);
 				repl = bi_putblk(si->ib, trash, repl);
@@ -493,7 +493,7 @@
 				goto switchstate;
 			}
 			case PEER_SESSION_CONNECT: {
-				struct peer_session *ps = (struct peer_session *)si->conn.xprt_ctx;
+				struct peer_session *ps = (struct peer_session *)si->conn->xprt_ctx;
 
 				/* Send headers */
 				repl = snprintf(trash, global.tune.bufsize,
@@ -523,7 +523,7 @@
 				/* fall through */
 			}
 			case PEER_SESSION_GETSTATUS: {
-				struct peer_session *ps = (struct peer_session *)si->conn.xprt_ctx;
+				struct peer_session *ps = (struct peer_session *)si->conn->xprt_ctx;
 
 				if (si->ib->flags & CF_WRITE_PARTIAL)
 					ps->statuscode = PEER_SESSION_CONNECTEDCODE;
@@ -594,7 +594,7 @@
 				/* fall through */
 			}
 			case PEER_SESSION_WAITMSG: {
-				struct peer_session *ps = (struct peer_session *)si->conn.xprt_ctx;
+				struct peer_session *ps = (struct peer_session *)si->conn->xprt_ctx;
 				char c;
 				int totl = 0;
 
@@ -1052,8 +1052,8 @@
 {
 	struct stream_interface *oldsi;
 
-	if (session->si[0].conn.target.type == TARG_TYPE_APPLET &&
-	    session->si[0].conn.target.ptr.a == &peer_applet) {
+	if (session->si[0].conn->target.type == TARG_TYPE_APPLET &&
+	    session->si[0].conn->target.ptr.a == &peer_applet) {
 		oldsi = &session->si[0];
 	}
 	else {
@@ -1063,7 +1063,7 @@
 	/* call release to reinit resync states if needed */
 	peer_session_release(oldsi);
 	oldsi->applet.st0 = PEER_SESSION_END;
-	oldsi->conn.xprt_ctx = NULL;
+	oldsi->conn->xprt_ctx = NULL;
 	task_wakeup(session->task, TASK_WOKEN_MSG);
 }
 
@@ -1077,8 +1077,8 @@
 {
 	 /* we have a dedicated I/O handler for the stats */
 	stream_int_register_handler(&s->si[1], &peer_applet);
-	copy_target(&s->target, &s->si[1].conn.target); // for logging only
-	s->si[1].conn.xprt_ctx = s;
+	copy_target(&s->target, &s->si[1].conn->target); // for logging only
+	s->si[1].conn->xprt_ctx = s;
 	s->si[1].applet.st0 = PEER_SESSION_ACCEPT;
 
 	tv_zero(&s->logs.tv_request);
@@ -1115,6 +1115,12 @@
 		goto out_close;
 	}
 
+	if (unlikely((s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
+		goto out_fail_conn0;
+
+	if (unlikely((s->si[1].conn = pool_alloc2(pool2_connection)) == NULL))
+		goto out_fail_conn1;
+
 	LIST_ADDQ(&sessions, &s->list);
 	LIST_INIT(&s->back_refs);
 
@@ -1135,7 +1141,7 @@
 	t->context = s;
 	t->nice = l->nice;
 
-	memcpy(&s->si[1].conn.addr.to, &peer->addr, sizeof(s->si[1].conn.addr.to));
+	memcpy(&s->si[1].conn->addr.to, &peer->addr, sizeof(s->si[1].conn->addr.to));
 	s->task = t;
 	s->listener = l;
 
@@ -1147,15 +1153,15 @@
 
 	s->req = s->rep = NULL; /* will be allocated later */
 
-	s->si[0].conn.t.sock.fd = -1;
-	s->si[0].conn.flags = CO_FL_NONE;
+	s->si[0].conn->t.sock.fd = -1;
+	s->si[0].conn->flags = CO_FL_NONE;
 	s->si[0].owner = t;
 	s->si[0].state = s->si[0].prev_state = SI_ST_EST;
 	s->si[0].err_type = SI_ET_NONE;
 	s->si[0].err_loc = NULL;
 	s->si[0].release = NULL;
 	s->si[0].send_proxy_ofs = 0;
-	set_target_client(&s->si[0].conn.target, l);
+	set_target_client(&s->si[0].conn->target, l);
 	s->si[0].exp = TICK_ETERNITY;
 	s->si[0].flags = SI_FL_NONE;
 	if (s->fe->options2 & PR_O2_INDEPSTR)
@@ -1163,10 +1169,10 @@
 
 	stream_int_register_handler(&s->si[0], &peer_applet);
 	s->si[0].applet.st0 = PEER_SESSION_CONNECT;
-	s->si[0].conn.xprt_ctx = (void *)ps;
+	s->si[0].conn->xprt_ctx = (void *)ps;
 
-	s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
-	s->si[1].conn.flags = CO_FL_NONE;
+	s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
+	s->si[1].conn->flags = CO_FL_NONE;
 	s->si[1].owner = t;
 	s->si[1].state = s->si[1].prev_state = SI_ST_ASS;
 	s->si[1].conn_retries = p->conn_retries;
@@ -1174,7 +1180,7 @@
 	s->si[1].err_loc = NULL;
 	s->si[1].release = NULL;
 	s->si[1].send_proxy_ofs = 0;
-	set_target_proxy(&s->si[1].conn.target, s->be);
+	set_target_proxy(&s->si[1].conn->target, s->be);
 	si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
 	s->si[1].exp = TICK_ETERNITY;
 	s->si[1].flags = SI_FL_NONE;
@@ -1293,6 +1299,10 @@
 	task_free(t);
  out_free_session:
 	LIST_DEL(&s->list);
+	pool_free2(pool2_connection, s->si[1].conn);
+ out_fail_conn1:
+	pool_free2(pool2_connection, s->si[0].conn);
+ out_fail_conn0:
 	pool_free2(pool2_session, s);
  out_close:
 	return s;
diff --git a/src/proto_http.c b/src/proto_http.c
index 817ef8c..31d49f9 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3184,8 +3184,8 @@
 		s->logs.tv_request = now;
 		s->task->nice = -32; /* small boost for HTTP statistics */
 		stream_int_register_handler(s->rep->prod, &http_stats_applet);
-		copy_target(&s->target, &s->rep->prod->conn.target); // for logging only
-		s->rep->prod->conn.xprt_ctx = s;
+		copy_target(&s->target, &s->rep->prod->conn->target); // for logging only
+		s->rep->prod->conn->xprt_ctx = s;
 		s->rep->prod->applet.st0 = s->rep->prod->applet.st1 = 0;
 		req->analysers = 0;
 		if (s->fe == s->be) /* report it if the request was intercepted by the frontend */
@@ -3493,7 +3493,7 @@
 	 * parsing incoming request.
 	 */
 	if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
-		url2sa(req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->conn.addr.to);
+		url2sa(req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->conn->addr.to);
 	}
 
 	/*
@@ -3543,19 +3543,19 @@
 			 * and we found it, so don't do anything.
 			 */
 		}
-		else if (s->req->prod->conn.addr.from.ss_family == AF_INET) {
+		else if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
 			/* Add an X-Forwarded-For header unless the source IP is
 			 * in the 'except' network range.
 			 */
 			if ((!s->fe->except_mask.s_addr ||
-			     (((struct sockaddr_in *)&s->req->prod->conn.addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
 			     != s->fe->except_net.s_addr) &&
 			    (!s->be->except_mask.s_addr ||
-			     (((struct sockaddr_in *)&s->req->prod->conn.addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
 			     != s->be->except_net.s_addr)) {
 				int len;
 				unsigned char *pn;
-				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn.addr.from)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr;
 
 				/* Note: we rely on the backend to get the header name to be used for
 				 * x-forwarded-for, because the header is really meant for the backends.
@@ -3575,14 +3575,14 @@
 					goto return_bad_req;
 			}
 		}
-		else if (s->req->prod->conn.addr.from.ss_family == AF_INET6) {
+		else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
 			/* FIXME: for the sake of completeness, we should also support
 			 * 'except' here, although it is mostly useless in this case.
 			 */
 			int len;
 			char pn[INET6_ADDRSTRLEN];
 			inet_ntop(AF_INET6,
-				  (const void *)&((struct sockaddr_in6 *)(&s->req->prod->conn.addr.from))->sin6_addr,
+				  (const void *)&((struct sockaddr_in6 *)(&s->req->prod->conn->addr.from))->sin6_addr,
 				  pn, sizeof(pn));
 
 			/* Note: we rely on the backend to get the header name to be used for
@@ -3611,22 +3611,22 @@
 	if ((s->fe->options | s->be->options) & PR_O_ORGTO) {
 
 		/* FIXME: don't know if IPv6 can handle that case too. */
-		if (s->req->prod->conn.addr.from.ss_family == AF_INET) {
+		if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
 			/* Add an X-Original-To header unless the destination IP is
 			 * in the 'except' network range.
 			 */
-			conn_get_to_addr(&s->req->prod->conn);
+			conn_get_to_addr(s->req->prod->conn);
 
-			if (s->req->prod->conn.addr.to.ss_family == AF_INET &&
+			if (s->req->prod->conn->addr.to.ss_family == AF_INET &&
 			    ((!s->fe->except_mask_to.s_addr ||
-			      (((struct sockaddr_in *)&s->req->prod->conn.addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
 			      != s->fe->except_to.s_addr) &&
 			     (!s->be->except_mask_to.s_addr ||
-			      (((struct sockaddr_in *)&s->req->prod->conn.addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
 			      != s->be->except_to.s_addr))) {
 				int len;
 				unsigned char *pn;
-				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn.addr.to)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
 
 				/* Note: we rely on the backend to get the header name to be used for
 				 * x-original-to, because the header is really meant for the backends.
@@ -4046,8 +4046,8 @@
 	clear_target(&s->target);
 
 	s->req->cons->state     = s->req->cons->prev_state = SI_ST_INI;
-	s->req->cons->conn.t.sock.fd = -1; /* just to help with debugging */
-	s->req->cons->conn.flags = CO_FL_NONE;
+	s->req->cons->conn->t.sock.fd = -1; /* just to help with debugging */
+	s->req->cons->conn->flags = CO_FL_NONE;
 	s->req->cons->err_type  = SI_ET_NONE;
 	s->req->cons->conn_retries = 0;  /* used for logging too */
 	s->req->cons->err_loc   = NULL;
@@ -7562,7 +7562,7 @@
 	es->sid  = s->uniq_id;
 	es->srv  = target_srv(&s->target);
 	es->oe   = other_end;
-	es->src  = s->req->prod->conn.addr.from;
+	es->src  = s->req->prod->conn->addr.from;
 	es->state = state;
 	es->ev_id = error_snapshot_id++;
 	es->b_flags = chn->flags;
@@ -8145,11 +8145,11 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	/* Parse HTTP request */
-	url2sa(txn->req.chn->buf->p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn.addr.to);
-	if (((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_family != AF_INET)
+	url2sa(txn->req.chn->buf->p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn->addr.to);
+	if (((struct sockaddr_in *)&l4->req->cons->conn->addr.to)->sin_family != AF_INET)
 		return 0;
 	smp->type = SMP_T_IPV4;
-	smp->data.ipv4 = ((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_addr;
+	smp->data.ipv4 = ((struct sockaddr_in *)&l4->req->cons->conn->addr.to)->sin_addr;
 
 	/*
 	 * If we are parsing url in frontend space, we prepare backend stage
@@ -8171,9 +8171,9 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	/* Same optimization as url_ip */
-	url2sa(txn->req.chn->buf->p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn.addr.to);
+	url2sa(txn->req.chn->buf->p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn->addr.to);
 	smp->type = SMP_T_UINT;
-	smp->data.uint = ntohs(((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_port);
+	smp->data.uint = ntohs(((struct sockaddr_in *)&l4->req->cons->conn->addr.to)->sin_port);
 
 	if (px->options & PR_O_HTTP_PROXY)
 		l4->flags |= SN_ADDR_SET;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index b94f9b2..28df64b 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -863,7 +863,7 @@
 					 * to consider rule->act_prm->trk_ctr.type.
 					 */
 					t = rule->act_prm.trk_ctr.table.t;
-					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn.addr.from));
+					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn->addr.from));
 					if (ts) {
 						session_track_stkctr1(s, t, ts);
 						if (s->fe != s->be)
@@ -879,7 +879,7 @@
 					 * to consider rule->act_prm->trk_ctr.type.
 					 */
 					t = rule->act_prm.trk_ctr.table.t;
-					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn.addr.from));
+					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn->addr.from));
 					if (ts) {
 						session_track_stkctr2(s, t, ts);
 						if (s->fe != s->be)
@@ -1033,7 +1033,7 @@
 					 * to consider rule->act_prm->trk_ctr.type.
 					 */
 					t = rule->act_prm.trk_ctr.table.t;
-					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn.addr.from));
+					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn->addr.from));
 					if (ts)
 						session_track_stkctr1(s, t, ts);
 				}
@@ -1046,7 +1046,7 @@
 					 * to consider rule->act_prm->trk_ctr.type.
 					 */
 					t = rule->act_prm.trk_ctr.table.t;
-					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn.addr.from));
+					ts = stktable_get_entry(t, addr_to_stktable_key(&s->si[0].conn->addr.from));
 					if (ts)
 						session_track_stkctr2(s, t, ts);
 				}
@@ -1511,13 +1511,13 @@
 smp_fetch_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
-	switch (l4->si[0].conn.addr.from.ss_family) {
+	switch (l4->si[0].conn->addr.from.ss_family) {
 	case AF_INET:
-		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn.addr.from)->sin_addr;
+		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr;
 		smp->type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn.addr.from))->sin6_addr;
+		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr;
 		smp->type = SMP_T_IPV6;
 		break;
 	default:
@@ -1534,7 +1534,7 @@
                 const struct arg *args, struct sample *smp)
 {
 	smp->type = SMP_T_UINT;
-	if (!(smp->data.uint = get_host_port(&l4->si[0].conn.addr.from)))
+	if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.from)))
 		return 0;
 
 	smp->flags = 0;
@@ -1546,15 +1546,15 @@
 smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
-	conn_get_to_addr(&l4->si[0].conn);
+	conn_get_to_addr(l4->si[0].conn);
 
-	switch (l4->si[0].conn.addr.to.ss_family) {
+	switch (l4->si[0].conn->addr.to.ss_family) {
 	case AF_INET:
-		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn.addr.to)->sin_addr;
+		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.to)->sin_addr;
 		smp->type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn.addr.to))->sin6_addr;
+		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.to))->sin6_addr;
 		smp->type = SMP_T_IPV6;
 		break;
 	default:
@@ -1570,10 +1570,10 @@
 smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                 const struct arg *args, struct sample *smp)
 {
-	conn_get_to_addr(&l4->si[0].conn);
+	conn_get_to_addr(l4->si[0].conn);
 
 	smp->type = SMP_T_UINT;
-	if (!(smp->data.uint = get_host_port(&l4->si[0].conn.addr.to)))
+	if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.to)))
 		return 0;
 
 	smp->flags = 0;
diff --git a/src/session.c b/src/session.c
index 1ac0cad..60c8426 100644
--- a/src/session.c
+++ b/src/session.c
@@ -83,6 +83,12 @@
 	if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
 		goto out_close;
 
+	if (unlikely((s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
+		goto out_fail_conn0;
+
+	if (unlikely((s->si[1].conn = pool_alloc2(pool2_connection)) == NULL))
+		goto out_fail_conn1;
+
 	/* minimum session initialization required for an embryonic session is
 	 * fairly low. We need very little to execute L4 ACLs, then we need a
 	 * task to make the client-side connection live on its own.
@@ -100,11 +106,11 @@
 	s->fe  = p;
 
 	/* OK, we're keeping the session, so let's properly initialize the session */
-	s->si[0].conn.t.sock.fd = cfd;
-	s->si[0].conn.ctrl = l->proto;
-	s->si[0].conn.flags = CO_FL_NONE;
-	s->si[0].conn.addr.from = *addr;
-	set_target_client(&s->si[0].conn.target, l);
+	s->si[0].conn->t.sock.fd = cfd;
+	s->si[0].conn->ctrl = l->proto;
+	s->si[0].conn->flags = CO_FL_NONE;
+	s->si[0].conn->addr.from = *addr;
+	set_target_client(&s->si[0].conn->target, l);
 
 	s->logs.accept_date = date; /* user-visible date for logging */
 	s->logs.tv_accept = now;  /* corrected date for internal use */
@@ -165,8 +171,8 @@
 
 	/* wait for a PROXY protocol header */
 	if (l->options & LI_O_ACC_PROXY) {
-		s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
-		conn_sock_want_recv(&s->si[0].conn);
+		s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY;
+		conn_sock_want_recv(s->si[0].conn);
 	}
 
 	if (unlikely((t = task_new()) == NULL))
@@ -180,14 +186,14 @@
 	 * but not initialized. Also note we need to be careful as the stream
 	 * int is not initialized yet.
 	 */
-	conn_prepare(&s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
+	conn_prepare(s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
 
 	/* finish initialization of the accepted file descriptor */
 	fd_insert(cfd);
-	fdtab[cfd].owner = &s->si[0].conn;
+	fdtab[cfd].owner = s->si[0].conn;
 	fdtab[cfd].iocb = conn_fd_handler;
-	conn_data_want_recv(&s->si[0].conn);
-	if (conn_xprt_init(&s->si[0].conn) < 0)
+	conn_data_want_recv(s->si[0].conn);
+	if (conn_xprt_init(s->si[0].conn) < 0)
 		goto out_free_task;
 
 	/* OK, now either we have a pending handshake to execute with and
@@ -196,11 +202,11 @@
 	 * set the I/O timeout to the frontend's client timeout.
 	 */
 
-	if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
+	if (s->si[0].conn->flags & CO_FL_HANDSHAKE) {
 		t->process = expire_mini_session;
 		t->expire = tick_add_ifset(now_ms, p->timeout.client);
 		task_queue(t);
-		s->si[0].conn.flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
+		s->si[0].conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
 		return 1;
 	}
 
@@ -216,6 +222,10 @@
 	p->feconn--;
 	if (s->stkctr1_entry || s->stkctr2_entry)
 		session_store_counters(s);
+	pool_free2(pool2_connection, s->si[1].conn);
+ out_fail_conn1:
+	pool_free2(pool2_connection, s->si[0].conn);
+ out_fail_conn0:
 	pool_free2(pool2_session, s);
  out_close:
 	if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) {
@@ -238,7 +248,7 @@
 static void kill_mini_session(struct session *s)
 {
 	/* kill the connection now */
-	conn_xprt_close(&s->si[0].conn);
+	conn_xprt_close(s->si[0].conn);
 
 	s->fe->feconn--;
 	if (s->stkctr1_entry || s->stkctr2_entry)
@@ -262,11 +272,13 @@
 	task_delete(s->task);
 	task_free(s->task);
 
-	if (fdtab[s->si[0].conn.t.sock.fd].owner)
-		fd_delete(s->si[0].conn.t.sock.fd);
+	if (fdtab[s->si[0].conn->t.sock.fd].owner)
+		fd_delete(s->si[0].conn->t.sock.fd);
 	else
-		close(s->si[0].conn.t.sock.fd);
+		close(s->si[0].conn->t.sock.fd);
 
+	pool_free2(pool2_connection, s->si[1].conn);
+	pool_free2(pool2_connection, s->si[0].conn);
 	pool_free2(pool2_session, s);
 }
 
@@ -393,8 +405,8 @@
 	/* pre-initialize the other side's stream interface to an INIT state. The
 	 * callbacks will be initialized before attempting to connect.
 	 */
-	s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
-	s->si[1].conn.flags = CO_FL_NONE;
+	s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
+	s->si[1].conn->flags = CO_FL_NONE;
 	s->si[1].owner     = t;
 	s->si[1].state     = s->si[1].prev_state = SI_ST_INI;
 	s->si[1].err_type  = SI_ET_NONE;
@@ -402,7 +414,7 @@
 	s->si[1].err_loc   = NULL;
 	s->si[1].release   = NULL;
 	s->si[1].send_proxy_ofs = 0;
-	clear_target(&s->si[1].conn.target);
+	clear_target(&s->si[1].conn->target);
 	si_prepare_embedded(&s->si[1]);
 	s->si[1].exp       = TICK_ETERNITY;
 	s->si[1].flags     = SI_FL_NONE;
@@ -485,7 +497,7 @@
 	txn->rsp.chn = s->rep;
 
 	/* finish initialization of the accepted file descriptor */
-	conn_data_want_recv(&s->si[0].conn);
+	conn_data_want_recv(s->si[0].conn);
 
 	if (p->accept && (ret = p->accept(s)) <= 0) {
 		/* Either we had an unrecoverable error (<0) or work is
@@ -497,10 +509,10 @@
 
 	/* if logs require transport layer information, note it on the connection */
 	if (s->logs.logwait & LW_XPRT)
-		s->si[0].conn.flags |= CO_FL_XPRT_TRACKED;
+		s->si[0].conn->flags |= CO_FL_XPRT_TRACKED;
 
 	/* we want the connection handler to notify the stream interface about updates. */
-	s->si[0].conn.flags |= CO_FL_WAKE_DATA;
+	s->si[0].conn->flags |= CO_FL_WAKE_DATA;
 
 	/* it is important not to call the wakeup function directly but to
 	 * pass through task_wakeup(), because this one knows how to apply
@@ -572,8 +584,8 @@
 	http_end_txn(s);
 
 	/* ensure the client-side transport layer is destroyed */
-	s->si[0].conn.flags &= ~CO_FL_XPRT_TRACKED;
-	conn_xprt_close(&s->si[0].conn);
+	s->si[0].conn->flags &= ~CO_FL_XPRT_TRACKED;
+	conn_xprt_close(s->si[0].conn);
 
 	for (i = 0; i < s->store_count; i++) {
 		if (!s->store[i].ts)
@@ -602,6 +614,8 @@
 		bref->ref = s->list.n;
 	}
 	LIST_DEL(&s->list);
+	pool_free2(pool2_connection, s->si[1].conn);
+	pool_free2(pool2_connection, s->si[0].conn);
 	pool_free2(pool2_session, s);
 
 	/* We may want to free the maximum amount of pools if the proxy is stopping */
@@ -752,7 +766,7 @@
 		si->state = SI_ST_CER;
 		fd_delete(si_fd(si));
 
-		conn_xprt_close(&si->conn);
+		conn_xprt_close(si->conn);
 		if (si->release)
 			si->release(si);
 
@@ -2069,8 +2083,8 @@
 	if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
 	    s->req->to_forward &&
 	    (global.tune.options & GTUNE_USE_SPLICE) &&
-	    (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
-	    (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
+	    (s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
+	    (s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
 	    (pipes_used < global.maxpipes) &&
 	    (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
 	     (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
@@ -2124,7 +2138,7 @@
 				 */
 				s->req->cons->state = SI_ST_REQ; /* new connection requested */
 				s->req->cons->conn_retries = s->be->conn_retries;
-				if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
+				if (unlikely(s->req->cons->conn->target.type == TARG_TYPE_APPLET &&
 					     !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
 					s->req->cons->state = SI_ST_EST; /* connection established */
 					s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
@@ -2215,8 +2229,8 @@
 	if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
 	    s->rep->to_forward &&
 	    (global.tune.options & GTUNE_USE_SPLICE) &&
-	    (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
-	    (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
+	    (s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
+	    (s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
 	    (pipes_used < global.maxpipes) &&
 	    (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
 	     (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
@@ -2305,10 +2319,10 @@
 		if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
 			session_process_counters(s);
 
-		if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
+		if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn->target.type != TARG_TYPE_APPLET)
 			si_update(s->rep->cons);
 
-		if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
+		if (s->req->cons->state == SI_ST_EST && s->req->cons->conn->target.type != TARG_TYPE_APPLET)
 			si_update(s->req->cons);
 
 		s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
@@ -2335,12 +2349,12 @@
 		/* Call the stream interfaces' I/O handlers when embedded.
 		 * Note that this one may wake the task up again.
 		 */
-		if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
-		    s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
-			if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
-				s->req->cons->conn.target.ptr.a->fct(s->req->cons);
-			if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
-				s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
+		if (s->req->cons->conn->target.type == TARG_TYPE_APPLET ||
+		    s->rep->cons->conn->target.type == TARG_TYPE_APPLET) {
+			if (s->req->cons->conn->target.type == TARG_TYPE_APPLET)
+				s->req->cons->conn->target.ptr.a->fct(s->req->cons);
+			if (s->rep->cons->conn->target.type == TARG_TYPE_APPLET)
+				s->rep->cons->conn->target.ptr.a->fct(s->rep->cons);
 			if (task_in_rq(t)) {
 				/* If we woke up, we don't want to requeue the
 				 * task to the wait queue, but rather requeue
@@ -2577,7 +2591,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2637,7 +2651,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2698,7 +2712,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2754,7 +2768,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2815,7 +2829,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2835,7 +2849,7 @@
 	struct stktable_key *key;
 	void *ptr;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2904,7 +2918,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -2960,7 +2974,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3021,7 +3035,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3077,7 +3091,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3138,7 +3152,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3194,7 +3208,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3255,7 +3269,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3316,7 +3330,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3379,7 +3393,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3440,7 +3454,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
@@ -3503,7 +3517,7 @@
 {
 	struct stktable_key *key;
 
-	key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
+	key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
 	if (!key)
 		return 0;
 
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 1c2c72d..8c05126 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1281,17 +1281,17 @@
 smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                          const struct arg *args, struct sample *smp)
 {
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	smp->flags = 0;
 	smp->type = SMP_T_BOOL;
-	smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn.xprt_st ? 1 : 0;
+	smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
 
 	return 1;
 }
@@ -1305,16 +1305,16 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate, it increase X509 * ref count */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1340,16 +1340,16 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate, it increase X509 * ref count */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1376,16 +1376,16 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate, it increase X509 * ref count */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1426,16 +1426,16 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate, it increase X509 * ref count */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1462,16 +1462,16 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate, it increase X509 * ref count */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1509,16 +1509,16 @@
 {
 	X509 *crt;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1537,16 +1537,16 @@
 	X509 *crt;
 	int nid;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate increase X509 * ref count  */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1571,16 +1571,16 @@
 	X509 *crt;
 	int nid;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_peer_certificate increase X509 * ref count  */
-	crt = SSL_get_peer_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1603,7 +1603,7 @@
                  const struct arg *args, struct sample *smp)
 {
 	smp->type = SMP_T_BOOL;
-	smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock);
+	smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
 	return 1;
 }
 
@@ -1614,9 +1614,9 @@
 {
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	smp->type = SMP_T_BOOL;
-	smp->data.uint = (l4->si[0].conn.xprt == &ssl_sock) &&
-		l4->si[0].conn.xprt_ctx &&
-		SSL_get_servername(l4->si[0].conn.xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
+	smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
+		l4->si[0].conn->xprt_ctx &&
+		SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
 	return 1;
 #else
 	return 0;
@@ -1632,15 +1632,15 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1663,15 +1663,15 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1695,15 +1695,15 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1725,16 +1725,16 @@
 {
 	X509 *crt;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	/* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1752,15 +1752,15 @@
 	X509 *crt;
 	int nid;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1784,15 +1784,15 @@
 	X509 *crt;
 	int nid;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		return 0;
 
@@ -1818,15 +1818,15 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1866,15 +1866,15 @@
 	int ret = 0;
 	struct chunk *smp_trash;
 
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags |= SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
+	crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
 	if (!crt)
 		goto out;
 
@@ -1910,10 +1910,10 @@
 {
 	smp->flags = 0;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn.xprt_ctx);
+	smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
 	if (!smp->data.str.str)
 		return 0;
 
@@ -1929,10 +1929,10 @@
 {
 	smp->flags = 0;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, (int *)&smp->data.uint))
+	if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
 		return 0;
 
 	smp->type = SMP_T_UINT;
@@ -1946,10 +1946,10 @@
 {
 	smp->flags = 0;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn.xprt_ctx, NULL);
+	smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
 	if (!smp->data.uint)
 		return 0;
 
@@ -1966,11 +1966,11 @@
 	smp->flags = 0;
 	smp->type = SMP_T_CSTR;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
 	smp->data.str.str = NULL;
-	SSL_get0_next_proto_negotiated(l4->si[0].conn.xprt_ctx,
+	SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
 	                                (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
 
 	if (!smp->data.str.str)
@@ -1986,10 +1986,10 @@
 {
 	smp->flags = 0;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn.xprt_ctx);
+	smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
 	if (!smp->data.str.str)
 		return 0;
 
@@ -2009,10 +2009,10 @@
 	smp->flags = 0;
 	smp->type = SMP_T_CBIN;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	sess = SSL_get_session(l4->si[0].conn.xprt_ctx);
+	sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
 	if (!sess)
 		return 0;
 
@@ -2034,10 +2034,10 @@
 	smp->flags = 0;
 	smp->type = SMP_T_CSTR;
 
-	if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn.xprt_ctx, TLSEXT_NAMETYPE_host_name);
+	smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
 	if (!smp->data.str.str)
 		return 0;
 
@@ -2053,16 +2053,16 @@
 smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags = SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	smp->type = SMP_T_UINT;
-	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn.xprt_st);
+	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
 	smp->flags = 0;
 
 	return 1;
@@ -2073,16 +2073,16 @@
 smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                              const struct arg *args, struct sample *smp)
 {
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags = SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	smp->type = SMP_T_UINT;
-	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn.xprt_st);
+	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
 	smp->flags = 0;
 
 	return 1;
@@ -2093,16 +2093,16 @@
 smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                     const struct arg *args, struct sample *smp)
 {
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags = SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
 	smp->type = SMP_T_UINT;
-	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn.xprt_st);
+	smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
 	smp->flags = 0;
 
 	return 1;
@@ -2113,19 +2113,19 @@
 smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-	if (!l4 || l4->si[0].conn.xprt != &ssl_sock)
+	if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
 		return 0;
 
-	if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+	if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
 		smp->flags = SMP_F_MAY_CHANGE;
 		return 0;
 	}
 
-	if (!l4->si[0].conn.xprt_ctx)
+	if (!l4->si[0].conn->xprt_ctx)
 		return 0;
 
 	smp->type = SMP_T_UINT;
-	smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn.xprt_ctx);
+	smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
 	smp->flags = 0;
 
 	return 1;
diff --git a/src/stream_interface.c b/src/stream_interface.c
index b3b095a..b075065 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -233,7 +233,7 @@
  */
 int stream_int_shutr(struct stream_interface *si)
 {
-	struct connection *conn = &si->conn;
+	struct connection *conn = si->conn;
 
 	si->ib->flags &= ~CF_SHUTR_NOW;
 	if (si->ib->flags & CF_SHUTR)
@@ -246,7 +246,7 @@
 		return 0;
 
 	if (si->ob->flags & CF_SHUTW) {
-		conn_xprt_close(&si->conn);
+		conn_xprt_close(si->conn);
 		if (conn->ctrl)
 			fd_delete(si_fd(si));
 		si->state = SI_ST_DIS;
@@ -284,7 +284,7 @@
  */
 int stream_int_shutw(struct stream_interface *si)
 {
-	struct connection *conn = &si->conn;
+	struct connection *conn = si->conn;
 
 	si->ob->flags &= ~CF_SHUTW_NOW;
 	if (si->ob->flags & CF_SHUTW)
@@ -337,7 +337,7 @@
 		/* we may have to close a pending connection, and mark the
 		 * response buffer as shutr
 		 */
-		conn_xprt_close(&si->conn);
+		conn_xprt_close(si->conn);
 		if (conn->ctrl)
 			fd_delete(si_fd(si));
 		/* fall through */
@@ -425,7 +425,7 @@
 	DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", app, si, si->owner);
 
 	si_prepare_embedded(si);
-	set_target_applet(&si->conn.target, app);
+	set_target_applet(&si->conn->target, app);
 	si->release   = app->release;
 	si->flags |= SI_FL_WAIT_DATA;
 	return si->owner;
@@ -446,7 +446,7 @@
 	DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", fct, si, si->owner);
 
 	si_prepare_task(si);
-	clear_target(&si->conn.target);
+	clear_target(&si->conn->target);
 	si->release   = NULL;
 	si->flags |= SI_FL_WAIT_DATA;
 
@@ -455,7 +455,7 @@
 	if (!t)
 		return t;
 
-	set_target_task(&si->conn.target, t);
+	set_target_task(&si->conn->target, t);
 
 	t->process = fct;
 	t->context = si;
@@ -470,14 +470,14 @@
  */
 void stream_int_unregister_handler(struct stream_interface *si)
 {
-	if (si->conn.target.type == TARG_TYPE_TASK) {
+	if (si->conn->target.type == TARG_TYPE_TASK) {
 		/* external handler : kill the task */
-		task_delete(si->conn.target.ptr.t);
-		task_free(si->conn.target.ptr.t);
+		task_delete(si->conn->target.ptr.t);
+		task_free(si->conn->target.ptr.t);
 	}
 	si->release   = NULL;
 	si->owner = NULL;
-	clear_target(&si->conn.target);
+	clear_target(&si->conn->target);
 }
 
 /* This callback is used to send a valid PROXY protocol line to a socket being
@@ -507,7 +507,7 @@
 		 * (which is recomputed every time since it's constant). If
 		 * it is positive, it means we have to send from the start.
 		 */
-		ret = make_proxy_line(trash, global.tune.bufsize, &si->ob->prod->conn.addr.from, &si->ob->prod->conn.addr.to);
+		ret = make_proxy_line(trash, global.tune.bufsize, &si->ob->prod->conn->addr.from, &si->ob->prod->conn->addr.to);
 		if (!ret)
 			goto out_error;
 
@@ -759,7 +759,7 @@
 			if (!(si->flags & SI_FL_WAIT_ROOM)) {
 				if (!(ib->flags & (CF_HIJACK|CF_DONT_READ))) /* full */
 					si->flags |= SI_FL_WAIT_ROOM;
-				conn_data_stop_recv(&si->conn);
+				conn_data_stop_recv(si->conn);
 				ib->rex = TICK_ETERNITY;
 			}
 		}
@@ -770,7 +770,7 @@
 			 * have updated it if there has been a completed I/O.
 			 */
 			si->flags &= ~SI_FL_WAIT_ROOM;
-			conn_data_want_recv(&si->conn);
+			conn_data_want_recv(si->conn);
 			if (!(ib->flags & (CF_READ_NOEXP|CF_DONT_READ)) && !tick_isset(ib->rex))
 				ib->rex = tick_add_ifset(now_ms, ib->rto);
 		}
@@ -784,7 +784,7 @@
 			if (!(si->flags & SI_FL_WAIT_DATA)) {
 				if ((ob->flags & (CF_HIJACK|CF_SHUTW_NOW)) == 0)
 					si->flags |= SI_FL_WAIT_DATA;
-				conn_data_stop_send(&si->conn);
+				conn_data_stop_send(si->conn);
 				ob->wex = TICK_ETERNITY;
 			}
 		}
@@ -795,7 +795,7 @@
 			 * have updated it if there has been a completed I/O.
 			 */
 			si->flags &= ~SI_FL_WAIT_DATA;
-			conn_data_want_send(&si->conn);
+			conn_data_want_send(si->conn);
 			if (!tick_isset(ob->wex)) {
 				ob->wex = tick_add_ifset(now_ms, ob->wto);
 				if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
@@ -829,12 +829,12 @@
 		/* stop reading */
 		if (!(ib->flags & (CF_HIJACK|CF_DONT_READ))) /* full */
 			si->flags |= SI_FL_WAIT_ROOM;
-		conn_data_stop_recv(&si->conn);
+		conn_data_stop_recv(si->conn);
 	}
 	else {
 		/* (re)start reading */
 		si->flags &= ~SI_FL_WAIT_ROOM;
-		conn_data_want_recv(&si->conn);
+		conn_data_want_recv(si->conn);
 	}
 }
 
@@ -859,14 +859,14 @@
 	     (fdtab[si_fd(si)].ev & FD_POLL_OUT)))   /* we'll be called anyway */
 		return;
 
-	if (!(si->conn.flags & CO_FL_HANDSHAKE) && si_conn_send_loop(&si->conn) < 0) {
+	if (!(si->conn->flags & CO_FL_HANDSHAKE) && si_conn_send_loop(si->conn) < 0) {
 		/* Write error on the file descriptor. We mark the FD as STERROR so
 		 * that we don't use it anymore and we notify the task.
 		 */
 		fdtab[si_fd(si)].ev &= ~FD_POLL_STICKY;
-		__conn_data_stop_both(&si->conn);
+		__conn_data_stop_both(si->conn);
 		si->flags |= SI_FL_ERR;
-		si->conn.flags |= CO_FL_ERROR;
+		si->conn->flags |= CO_FL_ERROR;
 		goto out_wakeup;
 	}
 
@@ -894,7 +894,7 @@
 		/* Otherwise there are remaining data to be sent in the buffer,
 		 * which means we have to poll before doing so.
 		 */
-		__conn_data_want_send(&si->conn);
+		__conn_data_want_send(si->conn);
 		si->flags &= ~SI_FL_WAIT_DATA;
 		if (!tick_isset(ob->wex))
 			ob->wex = tick_add_ifset(now_ms, ob->wto);
@@ -931,7 +931,7 @@
 	}
 
 	/* commit possible polling changes */
-	conn_cond_update_polling(&si->conn);
+	conn_cond_update_polling(si->conn);
 }
 
 /*
@@ -1158,7 +1158,7 @@
 	if (conn->flags & CO_FL_ERROR)
 		goto out_error;
 
-	if (si->conn.flags & CO_FL_HANDSHAKE)
+	if (si->conn->flags & CO_FL_HANDSHAKE)
 		/* a handshake was requested */
 		return;
 
@@ -1208,17 +1208,17 @@
 				   (struct linger *) &nolinger, sizeof(struct linger));
 		}
 		/* force flag on ssl to keep session in cache */
-		if (si->conn.xprt->shutw)
-			si->conn.xprt->shutw(&si->conn, 0);
+		if (si->conn->xprt->shutw)
+			si->conn->xprt->shutw(si->conn, 0);
 		goto do_close;
 	}
 
 	/* otherwise that's just a normal read shutdown */
-	__conn_data_stop_recv(&si->conn);
+	__conn_data_stop_recv(si->conn);
 	return;
 
  do_close:
-	conn_xprt_close(&si->conn);
+	conn_xprt_close(si->conn);
 	fd_delete(si_fd(si));
 	si->state = SI_ST_DIS;
 	si->exp = TICK_ETERNITY;