MAJOR: channel: replace the struct buffer with a pointer to a buffer

With this commit, we now separate the channel from the buffer. This will
allow us to replace buffers on the fly without touching the channel. Since
nobody is supposed to keep a reference to a buffer anymore, doing so is not
a problem and will also permit some copy-less data manipulation.

Interestingly, these changes have shown a 2% performance increase on some
workloads, probably due to a better cache placement of data.
diff --git a/include/common/buffer.h b/include/common/buffer.h
index 6ad16c6..d46495c 100644
--- a/include/common/buffer.h
+++ b/include/common/buffer.h
@@ -28,6 +28,7 @@
 
 #include <common/chunk.h>
 #include <common/config.h>
+#include <common/memory.h>
 
 
 struct buffer {
@@ -38,7 +39,9 @@
 	char data[0];                   /* <size> bytes */
 };
 
+extern struct pool_head *pool2_buffer;
 
+int init_buffer();
 int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len);
 int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
 void buffer_dump(FILE *o, struct buffer *b, int from, int to);
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 37f5457..80bd39d 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -51,9 +51,9 @@
 /* Initialize all fields in the channel. */
 static inline void channel_init(struct channel *chn)
 {
-	chn->buf.o = 0;
-	chn->buf.i = 0;
-	chn->buf.p = chn->buf.data;
+	chn->buf->o = 0;
+	chn->buf->i = 0;
+	chn->buf->p = chn->buf->data;
 	chn->to_forward = 0;
 	chn->total = 0;
 	chn->pipe = NULL;
@@ -73,7 +73,7 @@
  */
 static inline unsigned int channel_is_empty(struct channel *c)
 {
-	return !(c->buf.o | (long)c->pipe);
+	return !(c->buf->o | (long)c->pipe);
 }
 
 /* Returns non-zero if the buffer input is considered full. The reserved space
@@ -83,20 +83,20 @@
  */
 static inline int channel_full(const struct channel *chn)
 {
-	int rem = chn->buf.size;
+	int rem = chn->buf->size;
 
-	rem -= chn->buf.o;
-	rem -= chn->buf.i;
+	rem -= chn->buf->o;
+	rem -= chn->buf->i;
 	if (!rem)
 		return 1; /* buffer already full */
 
-	if (chn->to_forward >= chn->buf.size ||
-	    (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf.size)) && // just there to ensure gcc
+	if (chn->to_forward >= chn->buf->size ||
+	    (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->size)) && // just there to ensure gcc
 	     chn->to_forward == CHN_INFINITE_FORWARD))                  // avoids the useless second
 		return 0;                                               // test whenever possible
 
 	rem -= global.tune.maxrewrite;
-	rem += chn->buf.o;
+	rem += chn->buf->o;
 	rem += chn->to_forward;
 	return rem <= 0;
 }
@@ -139,10 +139,10 @@
  */
 static inline void channel_erase(struct channel *chn)
 {
-	chn->buf.o = 0;
-	chn->buf.i = 0;
+	chn->buf->o = 0;
+	chn->buf->i = 0;
 	chn->to_forward = 0;
-	chn->buf.p = chn->buf.data;
+	chn->buf->p = chn->buf->data;
 }
 
 /* marks the channel as "shutdown" ASAP for reads */
@@ -236,7 +236,7 @@
  */
 static inline int buffer_reserved(const struct channel *chn)
 {
-	int ret = global.tune.maxrewrite - chn->to_forward - chn->buf.o;
+	int ret = global.tune.maxrewrite - chn->to_forward - chn->buf->o;
 
 	if (chn->to_forward == CHN_INFINITE_FORWARD)
 		return 0;
@@ -251,7 +251,7 @@
  */
 static inline int buffer_max_len(const struct channel *chn)
 {
-	return chn->buf.size - buffer_reserved(chn);
+	return chn->buf->size - buffer_reserved(chn);
 }
 
 /* Return the amount of bytes that can be written into the buffer at once,
@@ -259,7 +259,7 @@
  */
 static inline int buffer_contig_space_res(const struct channel *chn)
 {
-	return buffer_contig_space_with_res(&chn->buf, buffer_reserved(chn));
+	return buffer_contig_space_with_res(chn->buf, buffer_reserved(chn));
 }
 
 /* Returns the amount of space available at the input of the buffer, taking the
@@ -269,21 +269,21 @@
  */
 static inline int bi_avail(const struct channel *chn)
 {
-	int rem = chn->buf.size;
+	int rem = chn->buf->size;
 	int rem2;
 
-	rem -= chn->buf.o;
-	rem -= chn->buf.i;
+	rem -= chn->buf->o;
+	rem -= chn->buf->i;
 	if (!rem)
 		return rem; /* buffer already full */
 
-	if (chn->to_forward >= chn->buf.size ||
-	    (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf.size)) && // just there to ensure gcc
+	if (chn->to_forward >= chn->buf->size ||
+	    (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->size)) && // just there to ensure gcc
 	     chn->to_forward == CHN_INFINITE_FORWARD))                  // avoids the useless second
 		return rem;                                             // test whenever possible
 
 	rem2 = rem - global.tune.maxrewrite;
-	rem2 += chn->buf.o;
+	rem2 += chn->buf->o;
 	rem2 += chn->to_forward;
 
 	if (rem > rem2)
@@ -300,14 +300,14 @@
  */
 static inline void bi_erase(struct channel *chn)
 {
-	if (!chn->buf.o)
+	if (!chn->buf->o)
 		return channel_erase(chn);
 
 	chn->to_forward = 0;
-	if (!chn->buf.i)
+	if (!chn->buf->i)
 		return;
 
-	chn->buf.i = 0;
+	chn->buf->i = 0;
 }
 
 /*
@@ -319,10 +319,10 @@
  */
 static inline void bo_skip(struct channel *chn, int len)
 {
-	chn->buf.o -= len;
+	chn->buf->o -= len;
 
-	if (buffer_len(&chn->buf) == 0)
-		chn->buf.p = chn->buf.data;
+	if (buffer_len(chn->buf) == 0)
+		chn->buf->p = chn->buf->data;
 
 	/* notify that some data was written to the SI from the buffer */
 	chn->flags |= CF_WRITE_PARTIAL;
@@ -374,7 +374,7 @@
 			return -2;
 		return -1;
 	}
-	return *buffer_wrap_sub(&chn->buf, chn->buf.p - chn->buf.o);
+	return *buffer_wrap_sub(chn->buf, chn->buf->p - chn->buf->o);
 }
 
 
diff --git a/include/types/channel.h b/include/types/channel.h
index a21e13f..efd1a12 100644
--- a/include/types/channel.h
+++ b/include/types/channel.h
@@ -186,7 +186,7 @@
 	struct stream_interface *prod;  /* producer attached to this channel */
 	struct stream_interface *cons;  /* consumer attached to this channel */
 	struct pipe *pipe;		/* non-NULL only when data present */
-	struct buffer buf;		/* embedded buffer for now, will move */
+	struct buffer *buf;		/* buffer attached to the channel, always present but may move */
 };
 
 
diff --git a/src/acl.c b/src/acl.c
index d65447a..ba7c1f0 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -108,7 +108,7 @@
 		return 0;
 
 	smp->type = SMP_T_UINT;
-	smp->data.uint = l4->req->buf.i;
+	smp->data.uint = l4->req->buf->i;
 	smp->flags = SMP_F_VOLATILE | SMP_F_MAY_CHANGE;
 	return 1;
 }
@@ -128,8 +128,8 @@
 
 	chn = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? l4->rep : l4->req;
 
-	bleft = chn->buf.i;
-	data = (const unsigned char *)chn->buf.p;
+	bleft = chn->buf->i;
+	data = (const unsigned char *)chn->buf->p;
 
 	if (!bleft)
 		goto too_short;
@@ -194,11 +194,11 @@
 		return 0;
 
 	msg_len = 0;
-	bleft = l4->req->buf.i;
+	bleft = l4->req->buf->i;
 	if (!bleft)
 		goto too_short;
 
-	data = (const unsigned char *)l4->req->buf.p;
+	data = (const unsigned char *)l4->req->buf->p;
 	if ((*data >= 0x14 && *data <= 0x17) || (*data == 0xFF)) {
 		/* SSLv3 header format */
 		if (bleft < 5)
@@ -266,8 +266,8 @@
 	 * all the part of the request which fits in a buffer is already
 	 * there.
 	 */
-	if (msg_len > buffer_max_len(l4->req) + l4->req->buf.data - l4->req->buf.p)
-		msg_len = buffer_max_len(l4->req) + l4->req->buf.data - l4->req->buf.p;
+	if (msg_len > buffer_max_len(l4->req) + l4->req->buf->data - l4->req->buf->p)
+		msg_len = buffer_max_len(l4->req) + l4->req->buf->data - l4->req->buf->p;
 
 	if (bleft < msg_len)
 		goto too_short;
@@ -332,8 +332,8 @@
 
 	chn = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? l4->rep : l4->req;
 
-	bleft = chn->buf.i;
-	data = (unsigned char *)chn->buf.p;
+	bleft = chn->buf->i;
+	data = (unsigned char *)chn->buf->p;
 
 	/* Check for SSL/TLS Handshake */
 	if (!bleft)
diff --git a/src/backend.c b/src/backend.c
index bae62b5..4528d0e 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -258,11 +258,11 @@
 	struct proxy    *px   = s->be;
 	unsigned int     plen = px->url_param_len;
 	unsigned long    len  = msg->body_len;
-	const char      *params = b_ptr(&req->buf, (int)(msg->sov - req->buf.o));
+	const char      *params = b_ptr(req->buf, (int)(msg->sov - req->buf->o));
 	const char      *p    = params;
 
-	if (len > buffer_len(&req->buf) - msg->sov)
-		len = buffer_len(&req->buf) - msg->sov;
+	if (len > buffer_len(req->buf) - msg->sov)
+		len = buffer_len(req->buf) - msg->sov;
 
 	if (len == 0)
 		return NULL;
@@ -343,7 +343,7 @@
 	ctx.idx = 0;
 
 	/* if the message is chunked, we skip the chunk size, but use the value as len */
-	http_find_header2(px->hh_name, plen, b_ptr(&s->req->buf, (int)-s->req->buf.o), &txn->hdr_idx, &ctx);
+	http_find_header2(px->hh_name, plen, b_ptr(s->req->buf, (int)-s->req->buf->o), &txn->hdr_idx, &ctx);
 
 	/* if the header is not found or empty, let's fallback to round robin */
 	if (!ctx.idx || !ctx.vlen)
@@ -419,12 +419,12 @@
 	args[0].data.str.len = px->hh_len;
 	args[1].type = ARGT_STOP;
 
-	b_rew(&s->req->buf, rewind = s->req->buf.o);
+	b_rew(s->req->buf, rewind = s->req->buf->o);
 
 	ret = smp_fetch_rdp_cookie(px, s, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, args, &smp);
 	len = smp.data.str.len;
 
-	b_adv(&s->req->buf, rewind);
+	b_adv(s->req->buf, rewind);
 
 	if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0)
 		return NULL;
@@ -569,7 +569,7 @@
 				if (s->txn.req.msg_state < HTTP_MSG_BODY)
 					break;
 				srv = get_server_uh(s->be,
-						    b_ptr(&s->req->buf, (int)(s->txn.req.sl.rq.u - s->req->buf.o)),
+						    b_ptr(s->req->buf, (int)(s->txn.req.sl.rq.u - s->req->buf->o)),
 						    s->txn.req.sl.rq.u_l);
 				break;
 
@@ -579,7 +579,7 @@
 					break;
 
 				srv = get_server_ph(s->be,
-						    b_ptr(&s->req->buf, (int)(s->txn.req.sl.rq.u - s->req->buf.o)),
+						    b_ptr(s->req->buf, (int)(s->txn.req.sl.rq.u - s->req->buf->o)),
 						    s->txn.req.sl.rq.u_l);
 
 				if (!srv && s->txn.meth == HTTP_METH_POST)
@@ -905,13 +905,13 @@
 				((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);
+				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 =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
-				b_adv(&s->req->buf, rewind);
+				b_adv(s->req->buf, rewind);
 			}
 			break;
 		default:
@@ -939,13 +939,13 @@
 				((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);
+				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 =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
-				b_adv(&s->req->buf, rewind);
+				b_adv(s->req->buf, rewind);
 			}
 			break;
 		default:
@@ -1144,7 +1144,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	if (s->flags & SN_ASSIGNED)
diff --git a/src/buffer.c b/src/buffer.c
index f98da94..899f5f4 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -15,9 +15,20 @@
 
 #include <common/config.h>
 #include <common/buffer.h>
+#include <common/memory.h>
 
 #include <types/global.h>
 
+struct pool_head *pool2_buffer;
+
+
+/* perform minimal intializations, report 0 in case of error, 1 if OK. */
+int init_buffer()
+{
+	pool2_buffer = create_pool("buffer", sizeof (struct buffer) + global.tune.bufsize, MEM_F_SHARED);
+	return pool2_buffer != NULL;
+}
+
 /* This function writes the string <str> at position <pos> which must be in
  * buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
  * <l> and <r> are updated to be valid after the shift. The shift value
diff --git a/src/channel.c b/src/channel.c
index 7b0d44e..6e945d4 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -18,9 +18,8 @@
 #include <common/config.h>
 #include <common/memory.h>
 #include <common/buffer.h>
-#include <proto/channel.h>
-#include <types/global.h>
 
+#include <proto/channel.h>
 
 struct pool_head *pool2_channel;
 
@@ -28,7 +27,7 @@
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_channel()
 {
-	pool2_channel = create_pool("channel", sizeof(struct channel) + global.tune.bufsize, MEM_F_SHARED);
+	pool2_channel = create_pool("channel", sizeof(struct channel), MEM_F_SHARED);
 	return pool2_channel != NULL;
 }
 
@@ -53,17 +52,17 @@
 	 * once anyway.
 	 */
 	if (bytes <= ~0U) {
-		if (bytes32 <= chn->buf.i) {
+		if (bytes32 <= chn->buf->i) {
 			/* OK this amount of bytes might be forwarded at once */
 			if (!bytes32)
 				return 0;
-			b_adv(&chn->buf, bytes32);
+			b_adv(chn->buf, bytes32);
 			return bytes;
 		}
 	}
 
-	forwarded = chn->buf.i;
-	b_adv(&chn->buf, chn->buf.i);
+	forwarded = chn->buf->i;
+	b_adv(chn->buf, chn->buf->i);
 
 	/* Note: the case below is the only case where we may return
 	 * a byte count that does not fit into a 32-bit number.
@@ -105,7 +104,7 @@
 	if (len == 0)
 		return -1;
 
-	if (len > chn->buf.size) {
+	if (len > chn->buf->size) {
 		/* we can't write this chunk and will never be able to, because
 		 * it is larger than the buffer. This must be reported as an
 		 * error. Then we return -2 so that writers that don't care can
@@ -114,14 +113,14 @@
 		return -2;
 	}
 
-	max = buffer_realign(&chn->buf);
+	max = buffer_realign(chn->buf);
 
 	if (len > max)
 		return max;
 
-	memcpy(chn->buf.p, msg, len);
-	chn->buf.o += len;
-	chn->buf.p = b_ptr(&chn->buf, len);
+	memcpy(chn->buf->p, msg, len);
+	chn->buf->o += len;
+	chn->buf->p = b_ptr(chn->buf, len);
 	chn->total += len;
 	return -1;
 }
@@ -140,15 +139,15 @@
 	if (channel_full(chn))
 		return -1;
 
-	*bi_end(&chn->buf) = c;
+	*bi_end(chn->buf) = c;
 
-	chn->buf.i++;
+	chn->buf->i++;
 	chn->flags |= CF_READ_PARTIAL;
 
 	if (chn->to_forward >= 1) {
 		if (chn->to_forward != CHN_INFINITE_FORWARD)
 			chn->to_forward--;
-		b_adv(&chn->buf, 1);
+		b_adv(chn->buf, 1);
 	}
 
 	chn->total++;
@@ -171,7 +170,7 @@
 		return -2;
 
 	max = buffer_max_len(chn);
-	if (unlikely(len > max - buffer_len(&chn->buf))) {
+	if (unlikely(len > max - buffer_len(chn->buf))) {
 		/* we can't write this chunk right now because the buffer is
 		 * almost full or because the block is too large. Return the
 		 * available space or -2 if impossible.
@@ -186,12 +185,12 @@
 		return 0;
 
 	/* OK so the data fits in the buffer in one or two blocks */
-	max = buffer_contig_space_with_res(&chn->buf, chn->buf.size - max);
-	memcpy(bi_end(&chn->buf), blk, MIN(len, max));
+	max = buffer_contig_space_with_res(chn->buf, chn->buf->size - max);
+	memcpy(bi_end(chn->buf), blk, MIN(len, max));
 	if (len > max)
-		memcpy(chn->buf.data, blk + max, len - max);
+		memcpy(chn->buf->data, blk + max, len - max);
 
-	chn->buf.i += len;
+	chn->buf->i += len;
 	chn->total += len;
 	if (chn->to_forward) {
 		unsigned long fwd = len;
@@ -200,7 +199,7 @@
 				fwd = chn->to_forward;
 			chn->to_forward -= fwd;
 		}
-		b_adv(&chn->buf, fwd);
+		b_adv(chn->buf, fwd);
 	}
 
 	/* notify that some data was read from the SI into the buffer */
@@ -233,10 +232,10 @@
 		goto out;
 	}
 
-	p = bo_ptr(&chn->buf);
+	p = bo_ptr(chn->buf);
 
-	if (max > chn->buf.o) {
-		max = chn->buf.o;
+	if (max > chn->buf->o) {
+		max = chn->buf->o;
 		str[max-1] = 0;
 	}
 	while (max) {
@@ -246,9 +245,9 @@
 
 		if (*p == '\n')
 			break;
-		p = buffer_wrap_add(&chn->buf, p + 1);
+		p = buffer_wrap_add(chn->buf, p + 1);
 	}
-	if (ret > 0 && ret < len && ret < chn->buf.o &&
+	if (ret > 0 && ret < len && ret < chn->buf->o &&
 	    *(str-1) != '\n' &&
 	    !(chn->flags & (CF_SHUTW|CF_SHUTW_NOW)))
 		ret = 0;
@@ -273,25 +272,25 @@
 	if (chn->flags & CF_SHUTW)
 		return -1;
 
-	if (len + offset > chn->buf.o) {
+	if (len + offset > chn->buf->o) {
 		if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW))
 			return -1;
 		return 0;
 	}
 
-	firstblock = chn->buf.data + chn->buf.size - bo_ptr(&chn->buf);
+	firstblock = chn->buf->data + chn->buf->size - bo_ptr(chn->buf);
 	if (firstblock > offset) {
 		if (firstblock >= len + offset) {
-			memcpy(blk, bo_ptr(&chn->buf) + offset, len);
+			memcpy(blk, bo_ptr(chn->buf) + offset, len);
 			return len;
 		}
 
-		memcpy(blk, bo_ptr(&chn->buf) + offset, firstblock - offset);
-		memcpy(blk + firstblock - offset, chn->buf.data, len - firstblock + offset);
+		memcpy(blk, bo_ptr(chn->buf) + offset, firstblock - offset);
+		memcpy(blk + firstblock - offset, chn->buf->data, len - firstblock + offset);
 		return len;
 	}
 
-	memcpy(blk, chn->buf.data + offset - firstblock, len);
+	memcpy(blk, chn->buf->data + offset - firstblock, len);
 	return len;
 }
 
diff --git a/src/dumpstats.c b/src/dumpstats.c
index d11d380..fd7d422 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1462,7 +1462,7 @@
 			/* ensure we have some output room left in the event we
 			 * would want to return some info right after parsing.
 			 */
-			if (buffer_almost_full(&si->ib->buf))
+			if (buffer_almost_full(si->ib->buf))
 				break;
 
 			reql = bo_getline(si->ob, trash, trashlen);
@@ -1576,7 +1576,7 @@
 			 * buffer is empty. This still allows pipelined requests
 			 * to be sent in non-interactive mode.
 			 */
-			if ((res->flags & (CF_SHUTW|CF_SHUTW_NOW)) || (!si->applet.st1 && !req->buf.o)) {
+			if ((res->flags & (CF_SHUTW|CF_SHUTW_NOW)) || (!si->applet.st1 && !req->buf->o)) {
 				si->applet.st0 = STAT_CLI_END;
 				continue;
 			}
@@ -1618,7 +1618,7 @@
  out:
 	DPRINTF(stderr, "%s@%d: st=%d, rqf=%x, rpf=%x, rqh=%d, rqs=%d, rh=%d, rs=%d\n",
 		__FUNCTION__, __LINE__,
-		si->state, req->flags, res->flags, req->buf.i, req->buf.o, res->buf.i, res->buf.o);
+		si->state, req->flags, res->flags, req->buf->i, req->buf->o, res->buf->i, res->buf->o);
 
 	if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO)) {
 		/* check that we have released everything then unregister */
@@ -2178,7 +2178,7 @@
 	case STAT_ST_LIST:
 		/* dump proxies */
 		while (si->applet.ctx.stats.px) {
-			if (buffer_almost_full(&rep->buf))
+			if (buffer_almost_full(rep->buf))
 				return 0;
 			px = si->applet.ctx.stats.px;
 			/* skip the disabled proxies, global frontend and non-networked ones */
@@ -2494,7 +2494,7 @@
 	case STAT_PX_ST_LI:
 		/* stats.l has been initialized above */
 		for (; si->applet.ctx.stats.l != &px->conf.listeners; si->applet.ctx.stats.l = l->by_fe.n) {
-			if (buffer_almost_full(&rep->buf))
+			if (buffer_almost_full(rep->buf))
 				return 0;
 
 			l = LIST_ELEM(si->applet.ctx.stats.l, struct listener *, by_fe);
@@ -2632,7 +2632,7 @@
 		for (; si->applet.ctx.stats.sv != NULL; si->applet.ctx.stats.sv = sv->next) {
 			int sv_state; /* 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB, 6=unchecked */
 
-			if (buffer_almost_full(&rep->buf))
+			if (buffer_almost_full(rep->buf))
 				return 0;
 
 			sv = si->applet.ctx.stats.sv;
@@ -3453,7 +3453,7 @@
 			     "      an_exp=%s",
 			     sess->req,
 			     sess->req->flags, sess->req->analysers,
-			     sess->req->buf.i, sess->req->buf.o,
+			     sess->req->buf->i, sess->req->buf->o,
 			     sess->req->pipe ? sess->req->pipe->data : 0,
 			     sess->req->to_forward,
 			     sess->req->analyse_exp ?
@@ -3472,8 +3472,8 @@
 			     sess->req->wex ?
 			     human_time(TICKS_TO_MS(sess->req->wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
-			     sess->req->buf.data,
-			     (int)(sess->req->buf.p - sess->req->buf.data),
+			     sess->req->buf->data,
+			     (int)(sess->req->buf->p - sess->req->buf->data),
 			     sess->txn.req.next,
 			     sess->req->total);
 
@@ -3482,7 +3482,7 @@
 			     "      an_exp=%s",
 			     sess->rep,
 			     sess->rep->flags, sess->rep->analysers,
-			     sess->rep->buf.i, sess->rep->buf.o,
+			     sess->rep->buf->i, sess->rep->buf->o,
 			     sess->rep->pipe ? sess->rep->pipe->data : 0,
 			     sess->rep->to_forward,
 			     sess->rep->analyse_exp ?
@@ -3501,8 +3501,8 @@
 			     sess->rep->wex ?
 			     human_time(TICKS_TO_MS(sess->rep->wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
-			     sess->rep->buf.data,
-			     (int)(sess->rep->buf.p - sess->rep->buf.data),
+			     sess->rep->buf->data,
+			     (int)(sess->rep->buf->p - sess->rep->buf->data),
 			     sess->txn.rsp.next,
 			     sess->rep->total);
 
@@ -3623,7 +3623,7 @@
 			chunk_printf(&msg,
 				     " rq[f=%06xh,i=%d,an=%02xh,rx=%s",
 				     curr_sess->req->flags,
-				     curr_sess->req->buf.i,
+				     curr_sess->req->buf->i,
 				     curr_sess->req->analysers,
 				     curr_sess->req->rex ?
 				     human_time(TICKS_TO_MS(curr_sess->req->rex - now_ms),
@@ -3644,7 +3644,7 @@
 			chunk_printf(&msg,
 				     " rp[f=%06xh,i=%d,an=%02xh,rx=%s",
 				     curr_sess->rep->flags,
-				     curr_sess->rep->buf.i,
+				     curr_sess->rep->buf->i,
 				     curr_sess->rep->analysers,
 				     curr_sess->rep->rex ?
 				     human_time(TICKS_TO_MS(curr_sess->rep->rex - now_ms),
diff --git a/src/haproxy.c b/src/haproxy.c
index 1cad8e4..6c80f6b 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -628,6 +628,7 @@
 
 	/* now we know the buffer size, we can initialize the channels and buffers */
 	init_channel();
+	init_buffer();
 
 	if (have_appsession)
 		appsession_init();
@@ -1112,6 +1113,7 @@
 	}
 
 	pool_destroy2(pool2_session);
+	pool_destroy2(pool2_buffer);
 	pool_destroy2(pool2_channel);
 	pool_destroy2(pool2_requri);
 	pool_destroy2(pool2_task);
diff --git a/src/peers.c b/src/peers.c
index f030613..f3ca6f7 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1221,7 +1221,10 @@
 	if ((s->req = pool_alloc2(pool2_channel)) == NULL)
 		goto out_fail_req; /* no memory */
 
-	s->req->buf.size = global.tune.bufsize;
+	if ((s->req->buf = pool_alloc2(pool2_buffer)) == NULL)
+		goto out_fail_req_buf; /* no memory */
+
+	s->req->buf->size = global.tune.bufsize;
 	channel_init(s->req);
 	s->req->prod = &s->si[0];
 	s->req->cons = &s->si[1];
@@ -1244,7 +1247,10 @@
 	if ((s->rep = pool_alloc2(pool2_channel)) == NULL)
 		goto out_fail_rep; /* no memory */
 
-	s->rep->buf.size = global.tune.bufsize;
+	if ((s->rep->buf = pool_alloc2(pool2_buffer)) == NULL)
+		goto out_fail_rep_buf; /* no memory */
+
+	s->rep->buf->size = global.tune.bufsize;
 	channel_init(s->rep);
 	s->rep->prod = &s->si[1];
 	s->rep->cons = &s->si[0];
@@ -1278,7 +1284,11 @@
 	return s;
 
 	/* Error unrolling */
+ out_fail_rep_buf:
+	pool_free2(pool2_channel, s->rep);
  out_fail_rep:
+	pool_free2(pool2_buffer, s->req->buf);
+ out_fail_req_buf:
 	pool_free2(pool2_channel, s->req);
  out_fail_req:
 	task_free(t);
diff --git a/src/proto_http.c b/src/proto_http.c
index 1b52c51..66dc87d 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -394,14 +394,14 @@
 			 "[%04d] req: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p o=%p sm=%d fw=%ld tf=%08x\n",
 			 line,
 			 s->si[0].state, s->si[0].fd, s->txn.req.msg_state, s->req->flags, s->req->analysers,
-			 s->req->buf.data, s->req->buf.size, s->req->l, s->req->w, s->req->r, s->req->buf.p, s->req->buf.o, s->req->to_forward, s->txn.flags);
+			 s->req->buf->data, s->req->buf->size, s->req->l, s->req->w, s->req->r, s->req->buf->p, s->req->buf->o, s->req->to_forward, s->txn.flags);
 	write(-1, trash, size);
 	size = 0;
 	size += snprintf(trash + size, trashlen - size,
 			 " %04d  rep: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p o=%p sm=%d fw=%ld\n",
 			 line,
 			 s->si[1].state, s->si[1].fd, s->txn.rsp.msg_state, s->rep->flags, s->rep->analysers,
-			 s->rep->buf.data, s->rep->buf.size, s->rep->l, s->rep->w, s->rep->r, s->rep->buf.p, s->rep->buf.o, s->rep->to_forward);
+			 s->rep->buf->data, s->rep->buf->size, s->rep->l, s->rep->w, s->rep->r, s->rep->buf->p, s->rep->buf->o, s->rep->to_forward);
 
 	write(-1, trash, size);
 }
@@ -421,7 +421,7 @@
 	int bytes, len;
 
 	len = strlen(text);
-	bytes = buffer_insert_line2(&msg->chn->buf, msg->chn->buf.p + msg->eoh, text, len);
+	bytes = buffer_insert_line2(msg->chn->buf, msg->chn->buf->p + msg->eoh, text, len);
 	if (!bytes)
 		return -1;
 	http_msg_move_end(msg, bytes);
@@ -441,7 +441,7 @@
 {
 	int bytes;
 
-	bytes = buffer_insert_line2(&msg->chn->buf, msg->chn->buf.p + msg->eoh, text, len);
+	bytes = buffer_insert_line2(msg->chn->buf, msg->chn->buf->p + msg->eoh, text, len);
 	if (!bytes)
 		return -1;
 	http_msg_move_end(msg, bytes);
@@ -610,7 +610,7 @@
 	hdr = &idx->v[cur_idx];
 	if (sol[ctx->del] == ':' && ctx->val + ctx->vlen + ctx->tws == hdr->len) {
 		/* This was the only value of the header, we must now remove it entirely. */
-		delta = buffer_replace2(&msg->chn->buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
+		delta = buffer_replace2(msg->chn->buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
 		http_msg_move_end(msg, delta);
 		idx->used--;
 		hdr->len = 0;   /* unused entry */
@@ -630,7 +630,7 @@
 	 */
 
 	skip_comma = (ctx->val + ctx->vlen + ctx->tws == hdr->len) ? 0 : 1;
-	delta = buffer_replace2(&msg->chn->buf, sol + ctx->del + skip_comma,
+	delta = buffer_replace2(msg->chn->buf, sol + ctx->del + skip_comma,
 				sol + ctx->val + ctx->vlen + ctx->tws + skip_comma,
 				NULL, 0);
 	hdr->len += delta;
@@ -712,7 +712,7 @@
 {
 	char *ptr, *end;
 
-	ptr = txn->req.chn->buf.p + txn->req.sl.rq.u;
+	ptr = txn->req.chn->buf->p + txn->req.sl.rq.u;
 	end = ptr + txn->req.sl.rq.u_l;
 
 	if (ptr >= end)
@@ -787,12 +787,12 @@
 	 * to temporarily rewind the buffer.
 	 */
 	txn = &s->txn;
-	b_rew(&s->req->buf, rewind = s->req->buf.o);
+	b_rew(s->req->buf, rewind = s->req->buf->o);
 
 	path = http_get_path(txn);
-	len = buffer_count(&s->req->buf, path, b_ptr(&s->req->buf, txn->req.sl.rq.u + txn->req.sl.rq.u_l));
+	len = buffer_count(s->req->buf, path, b_ptr(s->req->buf, txn->req.sl.rq.u + txn->req.sl.rq.u_l));
 
-	b_adv(&s->req->buf, rewind);
+	b_adv(s->req->buf, rewind);
 
 	if (!path)
 		return;
@@ -962,7 +962,7 @@
 			       unsigned int state, const char *ptr, const char *end,
 			       unsigned int *ret_ptr, unsigned int *ret_state)
 {
-	const char *msg_start = msg->chn->buf.p;
+	const char *msg_start = msg->chn->buf->p;
 
 	switch (state)	{
 	case HTTP_MSG_RPVER:
@@ -1072,7 +1072,7 @@
 			       unsigned int state, const char *ptr, const char *end,
 			       unsigned int *ret_ptr, unsigned int *ret_state)
 {
-	const char *msg_start = msg->chn->buf.p;
+	const char *msg_start = msg->chn->buf->p;
 
 	switch (state)	{
 	case HTTP_MSG_RQMETH:
@@ -1234,7 +1234,7 @@
 		len = strlen(h);
 	}
 
-	if (!http_find_header2(h, len, s->req->buf.p, &txn->hdr_idx, &ctx))
+	if (!http_find_header2(h, len, s->req->buf->p, &txn->hdr_idx, &ctx))
 		return 0;
 
 	h = ctx.line + ctx.val;
@@ -1293,7 +1293,7 @@
 	struct buffer *buf;
 
 	state = msg->msg_state;
-	buf = &msg->chn->buf;
+	buf = msg->chn->buf;
 	ptr = buf->p + msg->next;
 	end = buf->p + buf->i;
 
@@ -1603,22 +1603,22 @@
 	if (msg->sl.rq.v_l != 0)
 		return 1;
 
-	cur_end = msg->chn->buf.p + msg->sl.rq.l;
+	cur_end = msg->chn->buf->p + msg->sl.rq.l;
 	delta = 0;
 
 	if (msg->sl.rq.u_l == 0) {
 		/* if no URI was set, add "/" */
-		delta = buffer_replace2(&msg->chn->buf, cur_end, cur_end, " /", 2);
+		delta = buffer_replace2(msg->chn->buf, cur_end, cur_end, " /", 2);
 		cur_end += delta;
 		http_msg_move_end(msg, delta);
 	}
 	/* add HTTP version */
-	delta = buffer_replace2(&msg->chn->buf, cur_end, cur_end, " HTTP/1.0\r\n", 11);
+	delta = buffer_replace2(msg->chn->buf, cur_end, cur_end, " HTTP/1.0\r\n", 11);
 	http_msg_move_end(msg, delta);
 	cur_end += delta;
 	cur_end = (char *)http_parse_reqline(msg,
 					     HTTP_MSG_RQMETH,
-					     msg->chn->buf.p, cur_end + 1,
+					     msg->chn->buf->p, cur_end + 1,
 					     NULL, NULL);
 	if (unlikely(!cur_end))
 		return 0;
@@ -1656,7 +1656,7 @@
 
 	ctx.idx = 0;
 	txn->flags &= ~(TX_CON_KAL_SET|TX_CON_CLO_SET);
-	while (http_find_header2(hdr_val, hdr_len, msg->chn->buf.p, &txn->hdr_idx, &ctx)) {
+	while (http_find_header2(hdr_val, hdr_len, msg->chn->buf->p, &txn->hdr_idx, &ctx)) {
 		if (ctx.vlen >= 10 && word_match(ctx.line + ctx.val, ctx.vlen, "keep-alive", 10)) {
 			txn->flags |= TX_HDR_CONN_KAL;
 			if (to_del & 2)
@@ -1697,7 +1697,7 @@
 	}
 
 	txn->flags &= ~(TX_CON_CLO_SET | TX_CON_KAL_SET);
-	while (http_find_header2(hdr_val, hdr_len, msg->chn->buf.p, &txn->hdr_idx, &ctx)) {
+	while (http_find_header2(hdr_val, hdr_len, msg->chn->buf->p, &txn->hdr_idx, &ctx)) {
 		if (ctx.vlen >= 10 && word_match(ctx.line + ctx.val, ctx.vlen, "keep-alive", 10)) {
 			if (wanted & TX_CON_KAL_SET)
 				txn->flags |= TX_CON_KAL_SET;
@@ -1747,7 +1747,7 @@
  */
 int http_parse_chunk_size(struct http_msg *msg)
 {
-	const struct buffer *buf = &msg->chn->buf;
+	const struct buffer *buf = msg->chn->buf;
 	const char *ptr = b_ptr(buf, msg->next);
 	const char *ptr_old = ptr;
 	const char *end = buf->data + buf->size;
@@ -1857,7 +1857,7 @@
  */
 int http_forward_trailers(struct http_msg *msg)
 {
-	const struct buffer *buf = &msg->chn->buf;
+	const struct buffer *buf = msg->chn->buf;
 
 	/* we have msg->next which points to next line. Look for CRLF. */
 	while (1) {
@@ -1931,7 +1931,7 @@
  */
 int http_skip_chunk_crlf(struct http_msg *msg)
 {
-	const struct buffer *buf = &msg->chn->buf;
+	const struct buffer *buf = msg->chn->buf;
 	const char *ptr;
 	int bytes;
 
@@ -1984,9 +1984,9 @@
 	 * For the parsing, we use a 28 states FSM.
 	 *
 	 * Here is the information we currently have :
-	 *   req->buf.p             = beginning of request
-	 *   req->buf.p + msg->eoh  = end of processed headers / start of current one
-	 *   req->buf.p + req->buf.i    = end of input data
+	 *   req->buf->p             = beginning of request
+	 *   req->buf->p + msg->eoh  = end of processed headers / start of current one
+	 *   req->buf->p + req->buf->i    = end of input data
 	 *   msg->eol           = end of current header or line (LF or CRLF)
 	 *   msg->next          = first non-visited byte
 	 *
@@ -2008,7 +2008,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	/* we're speaking HTTP here, so let's speak HTTP to the client */
@@ -2019,12 +2019,12 @@
 	 * protected area is affected, because we may have to move processed
 	 * data later, which is much more complicated.
 	 */
-	if (buffer_not_empty(&req->buf) && msg->msg_state < HTTP_MSG_ERROR) {
+	if (buffer_not_empty(req->buf) && msg->msg_state < HTTP_MSG_ERROR) {
 		if ((txn->flags & TX_NOT_FIRST) &&
 		    unlikely(channel_full(req) ||
-			     bi_end(&req->buf) < b_ptr(&req->buf, msg->next) ||
-			     bi_end(&req->buf) > req->buf.data + req->buf.size - global.tune.maxrewrite)) {
-			if (req->buf.o) {
+			     bi_end(req->buf) < b_ptr(req->buf, msg->next) ||
+			     bi_end(req->buf) > req->buf->data + req->buf->size - global.tune.maxrewrite)) {
+			if (req->buf->o) {
 				if (req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT))
 					goto failed_keep_alive;
 				/* some data has still not left the buffer, wake us once that's done */
@@ -2032,9 +2032,9 @@
 				req->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
 				return 0;
 			}
-			if (bi_end(&req->buf) < b_ptr(&req->buf, msg->next) ||
-			    bi_end(&req->buf) > req->buf.data + req->buf.size - global.tune.maxrewrite)
-				buffer_slow_realign(&msg->chn->buf);
+			if (bi_end(req->buf) < b_ptr(req->buf, msg->next) ||
+			    bi_end(req->buf) > req->buf->data + req->buf->size - global.tune.maxrewrite)
+				buffer_slow_realign(msg->chn->buf);
 		}
 
 		/* Note that we have the same problem with the response ; we
@@ -2046,9 +2046,9 @@
 		 */
 		if ((txn->flags & TX_NOT_FIRST) &&
 		    unlikely(channel_full(s->rep) ||
-			     bi_end(&s->rep->buf) < b_ptr(&s->rep->buf, txn->rsp.next) ||
-			     bi_end(&s->rep->buf) > s->rep->buf.data + s->rep->buf.size - global.tune.maxrewrite)) {
-			if (s->rep->buf.o) {
+			     bi_end(s->rep->buf) < b_ptr(s->rep->buf, txn->rsp.next) ||
+			     bi_end(s->rep->buf) > s->rep->buf->data + s->rep->buf->size - global.tune.maxrewrite)) {
+			if (s->rep->buf->o) {
 				if (s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT))
 					goto failed_keep_alive;
 				/* don't let a connection request be initiated */
@@ -2059,7 +2059,7 @@
 			}
 		}
 
-		if (likely(msg->next < req->buf.i)) /* some unparsed data are available */
+		if (likely(msg->next < req->buf->i)) /* some unparsed data are available */
 			http_msg_analyzer(msg, &txn->hdr_idx);
 	}
 
@@ -2069,12 +2069,12 @@
 		     (msg->msg_state >= HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
 		char *eol, *sol;
 
-		sol = req->buf.p;
+		sol = req->buf->p;
 		/* this is a bit complex : in case of error on the request line,
 		 * we know that rq.l is still zero, so we display only the part
 		 * up to the end of the line (truncated by debug_hdr).
 		 */
-		eol = sol + (msg->sl.rq.l ? msg->sl.rq.l : req->buf.i);
+		eol = sol + (msg->sl.rq.l ? msg->sl.rq.l : req->buf->i);
 		debug_hdr("clireq", s, sol, eol);
 
 		sol += hdr_idx_first_pos(&txn->hdr_idx);
@@ -2121,7 +2121,7 @@
 		 *    later, so the session will never terminate. We
 		 *    must terminate it now.
 		 */
-		if (unlikely(buffer_full(&req->buf, global.tune.maxrewrite))) {
+		if (unlikely(buffer_full(req->buf, global.tune.maxrewrite))) {
 			/* FIXME: check if URI is set and return Status
 			 * 414 Request URI too long instead.
 			 */
@@ -2129,7 +2129,7 @@
 			session_inc_http_err_ctr(s);
 			proxy_inc_fe_req_ctr(s->fe);
 			if (msg->err_pos < 0)
-				msg->err_pos = req->buf.i;
+				msg->err_pos = req->buf->i;
 			goto return_bad_req;
 		}
 
@@ -2221,7 +2221,7 @@
 		req->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
 		s->rep->flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
 #ifdef TCP_QUICKACK
-		if (s->listener->options & LI_O_NOQUICKACK && req->buf.i) {
+		if (s->listener->options & LI_O_NOQUICKACK && req->buf->i) {
 			/* 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.
@@ -2268,7 +2268,7 @@
 
 	/* OK now we have a complete HTTP request with indexed headers. Let's
 	 * complete the request parsing by setting a few fields we will need
-	 * later. At this point, we have the last CRLF at req->buf.data + msg->eoh.
+	 * later. At this point, we have the last CRLF at req->buf->data + msg->eoh.
 	 * If the request is in HTTP/0.9 form, the rule is still true, and eoh
 	 * points to the CRLF of the request line. msg->next points to the first
 	 * byte after the last LF. msg->sov points to the first byte of data.
@@ -2295,7 +2295,7 @@
 	/*
 	 * 1: identify the method
 	 */
-	txn->meth = find_http_meth(req->buf.p, msg->sl.rq.m_l);
+	txn->meth = find_http_meth(req->buf->p, msg->sl.rq.m_l);
 
 	/* we can make use of server redirect on GET and HEAD */
 	if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
@@ -2308,7 +2308,7 @@
 	 */
 	if (unlikely((s->fe->monitor_uri_len != 0) &&
 		     (s->fe->monitor_uri_len == msg->sl.rq.u_l) &&
-		     !memcmp(req->buf.p + msg->sl.rq.u,
+		     !memcmp(req->buf->p + msg->sl.rq.u,
 			     s->fe->monitor_uri,
 			     s->fe->monitor_uri_len))) {
 		/*
@@ -2353,7 +2353,7 @@
 
 			if (urilen >= REQURI_LEN)
 				urilen = REQURI_LEN - 1;
-			memcpy(txn->uri, req->buf.p, urilen);
+			memcpy(txn->uri, req->buf->p, urilen);
 			txn->uri[urilen] = 0;
 
 			if (!(s->logs.logwait &= ~LW_REQ))
@@ -2373,9 +2373,9 @@
 
 	/* ... and check if the request is HTTP/1.1 or above */
 	if ((msg->sl.rq.v_l == 8) &&
-	    ((req->buf.p[msg->sl.rq.v + 5] > '1') ||
-	     ((req->buf.p[msg->sl.rq.v + 5] == '1') &&
-	      (req->buf.p[msg->sl.rq.v + 7] >= '1'))))
+	    ((req->buf->p[msg->sl.rq.v + 5] > '1') ||
+	     ((req->buf->p[msg->sl.rq.v + 5] == '1') &&
+	      (req->buf->p[msg->sl.rq.v + 7] >= '1'))))
 		msg->flags |= HTTP_MSGF_VER_11;
 
 	/* "connection" has not been parsed yet */
@@ -2391,7 +2391,7 @@
 	 * CONNECT ip:port.
 	 */
 	if ((s->fe->options2 & PR_O2_USE_PXHDR) &&
-	    req->buf.p[msg->sl.rq.u] != '/' && req->buf.p[msg->sl.rq.u] != '*')
+	    req->buf->p[msg->sl.rq.u] != '/' && req->buf->p[msg->sl.rq.u] != '*')
 		txn->flags |= TX_USE_PX_CONN;
 
 	/* transfer length unknown*/
@@ -2399,7 +2399,7 @@
 
 	/* 5: we may need to capture headers */
 	if (unlikely((s->logs.logwait & LW_REQHDR) && txn->req.cap))
-		capture_headers(req->buf.p, &txn->hdr_idx,
+		capture_headers(req->buf->p, &txn->hdr_idx,
 				txn->req.cap, s->fe->req_cap);
 
 	/* 6: determine the transfer-length.
@@ -2444,7 +2444,7 @@
 	ctx.idx = 0;
 	/* set TE_CHNK and XFER_LEN only if "chunked" is seen last */
 	while ((msg->flags & HTTP_MSGF_VER_11) &&
-	       http_find_header2("Transfer-Encoding", 17, req->buf.p, &txn->hdr_idx, &ctx)) {
+	       http_find_header2("Transfer-Encoding", 17, req->buf->p, &txn->hdr_idx, &ctx)) {
 		if (ctx.vlen == 7 && strncasecmp(ctx.line + ctx.val, "chunked", 7) == 0)
 			msg->flags |= (HTTP_MSGF_TE_CHNK | HTTP_MSGF_XFER_LEN);
 		else if (msg->flags & HTTP_MSGF_TE_CHNK) {
@@ -2457,26 +2457,26 @@
 
 	ctx.idx = 0;
 	while (!(msg->flags & HTTP_MSGF_TE_CHNK) && !use_close_only &&
-	       http_find_header2("Content-Length", 14, req->buf.p, &txn->hdr_idx, &ctx)) {
+	       http_find_header2("Content-Length", 14, req->buf->p, &txn->hdr_idx, &ctx)) {
 		signed long long cl;
 
 		if (!ctx.vlen) {
-			msg->err_pos = ctx.line + ctx.val - req->buf.p;
+			msg->err_pos = ctx.line + ctx.val - req->buf->p;
 			goto return_bad_req;
 		}
 
 		if (strl2llrc(ctx.line + ctx.val, ctx.vlen, &cl)) {
-			msg->err_pos = ctx.line + ctx.val - req->buf.p;
+			msg->err_pos = ctx.line + ctx.val - req->buf->p;
 			goto return_bad_req; /* parse failure */
 		}
 
 		if (cl < 0) {
-			msg->err_pos = ctx.line + ctx.val - req->buf.p;
+			msg->err_pos = ctx.line + ctx.val - req->buf->p;
 			goto return_bad_req;
 		}
 
 		if ((msg->flags & HTTP_MSGF_CNT_LEN) && (msg->chunk_len != cl)) {
-			msg->err_pos = ctx.line + ctx.val - req->buf.p;
+			msg->err_pos = ctx.line + ctx.val - req->buf->p;
 			goto return_bad_req; /* already specified, was different */
 		}
 
@@ -2541,17 +2541,17 @@
 	char *st_cur_param = NULL;
 	char *st_next_param = NULL;
 
-	first_param = req->buf.p + txn->req.eoh + 2;
+	first_param = req->buf->p + txn->req.eoh + 2;
 	end_params  = first_param + txn->req.body_len;
 
 	cur_param = next_param = end_params;
 
-	if (end_params >= req->buf.data + req->buf.size - global.tune.maxrewrite) {
+	if (end_params >= req->buf->data + req->buf->size - global.tune.maxrewrite) {
 		/* Prevent buffer overflow */
 		si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
 		return 1;
 	}
-	else if (end_params > req->buf.p + req->buf.i) {
+	else if (end_params > req->buf->p + req->buf->i) {
 		/* we need more data */
 		si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
 		return 0;
@@ -2803,7 +2803,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	/* first check whether we have some ACLs set to block this request */
@@ -3012,7 +3012,7 @@
 						struct hdr_ctx ctx;
 						ctx.idx = 0;
 						/* Expect is allowed in 1.1, look for it */
-						if (http_find_header2("Expect", 6, req->buf.p, &txn->hdr_idx, &ctx) &&
+						if (http_find_header2("Expect", 6, req->buf->p, &txn->hdr_idx, &ctx) &&
 						    unlikely(ctx.vlen == 12 && strncasecmp(ctx.line+ctx.val, "100-continue", 12) == 0)) {
 							bo_inject(s->rep, http_100_chunk.str, http_100_chunk.len);
 						}
@@ -3088,7 +3088,7 @@
 				host = "";
 				hostlen = 0;
 				ctx.idx = 0;
-				if (http_find_header2("Host", 4, txn->req.chn->buf.p + txn->req.sol, &txn->hdr_idx, &ctx)) {
+				if (http_find_header2("Host", 4, txn->req.chn->buf->p + txn->req.sol, &txn->hdr_idx, &ctx)) {
 					host = ctx.line + ctx.val;
 					hostlen = ctx.vlen;
 				}
@@ -3096,7 +3096,7 @@
 				path = http_get_path(txn);
 				/* build message using path */
 				if (path) {
-					pathlen = txn->req.sl.rq.u_l + (req->buf.p + txn->req.sl.rq.u) - path;
+					pathlen = txn->req.sl.rq.u_l + (req->buf->p + txn->req.sl.rq.u) - path;
 					if (rule->flags & REDIRECT_FLAG_DROP_QS) {
 						int qs = 0;
 						while (qs < pathlen) {
@@ -3150,7 +3150,7 @@
 				path = http_get_path(txn);
 				/* build message using path */
 				if (path) {
-					pathlen = txn->req.sl.rq.u_l + (req->buf.p + txn->req.sl.rq.u) - path;
+					pathlen = txn->req.sl.rq.u_l + (req->buf->p + txn->req.sl.rq.u) - path;
 					if (rule->flags & REDIRECT_FLAG_DROP_QS) {
 						int qs = 0;
 						while (qs < pathlen) {
@@ -3241,7 +3241,7 @@
 				rdr.len += 4;
 				bo_inject(req->prod->ob, rdr.str, rdr.len);
 				/* "eat" the request */
-				bi_fast_delete(&req->buf, msg->sov);
+				bi_fast_delete(req->buf, msg->sov);
 				msg->sov = 0;
 				req->analysers = AN_REQ_HTTP_XFER_BODY;
 				s->rep->analysers = AN_RES_HTTP_XFER_BODY;
@@ -3325,7 +3325,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	/*
@@ -3340,7 +3340,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);
 	}
 
 	/*
@@ -3360,7 +3360,7 @@
 
 	/* It needs to look into the URI unless persistence must be ignored */
 	if ((txn->sessid == NULL) && s->be->appsession_name && !(s->flags & SN_IGNORE_PRST)) {
-		get_srv_from_appsession(s, req->buf.p + msg->sl.rq.u, msg->sl.rq.u_l);
+		get_srv_from_appsession(s, req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l);
 	}
 
 	/* add unique-id if "header-unique-id" is specified */
@@ -3385,7 +3385,7 @@
 		if (!((s->fe->options | s->be->options) & PR_O_FF_ALWAYS) &&
 			http_find_header2(s->be->fwdfor_hdr_len ? s->be->fwdfor_hdr_name : s->fe->fwdfor_hdr_name,
 			                  s->be->fwdfor_hdr_len ? s->be->fwdfor_hdr_len : s->fe->fwdfor_hdr_len,
-			                  req->buf.p, &txn->hdr_idx, &ctx)) {
+			                  req->buf->p, &txn->hdr_idx, &ctx)) {
 			/* The header is set to be added only if none is present
 			 * and we found it, so don't do anything.
 			 */
@@ -3539,7 +3539,7 @@
 		 */
 		if ((s->listener->options & LI_O_NOQUICKACK) &&
 		    ((msg->flags & HTTP_MSGF_TE_CHNK) ||
-		     (msg->body_len > req->buf.i - txn->req.eoh - 2)))
+		     (msg->body_len > req->buf->i - txn->req.eoh - 2)))
 			setsockopt(si_fd(&s->si[0]), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
 #endif
 	}
@@ -3657,7 +3657,7 @@
 			struct hdr_ctx ctx;
 			ctx.idx = 0;
 			/* Expect is allowed in 1.1, look for it */
-			if (http_find_header2("Expect", 6, req->buf.p, &txn->hdr_idx, &ctx) &&
+			if (http_find_header2("Expect", 6, req->buf->p, &txn->hdr_idx, &ctx) &&
 			    unlikely(ctx.vlen == 12 && strncasecmp(ctx.line+ctx.val, "100-continue", 12) == 0)) {
 				bo_inject(s->rep, http_100_chunk.str, http_100_chunk.len);
 			}
@@ -3667,7 +3667,7 @@
 
 	if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) {
 		/* we have msg->sov which points to the first byte of message body.
-		 * req->buf.p still points to the beginning of the message and msg->sol
+		 * req->buf->p still points to the beginning of the message and msg->sol
 		 * is still null. We must save the body in msg->next because it
 		 * survives buffer re-alignments.
 		 */
@@ -3702,12 +3702,12 @@
 	if (msg->body_len < limit)
 		limit = msg->body_len;
 
-	if (req->buf.i - msg->sov >= limit)    /* we have enough bytes now */
+	if (req->buf->i - msg->sov >= limit)    /* we have enough bytes now */
 		goto http_end;
 
  missing_data:
 	/* we get here if we need to wait for more data */
-	if (buffer_full(&req->buf, global.tune.maxrewrite)) {
+	if (buffer_full(req->buf, global.tune.maxrewrite)) {
 		session_inc_http_err_ctr(s);
 		goto return_bad_req;
 	}
@@ -3724,7 +3724,7 @@
 	}
 
 	/* we get here if we need to wait for more data */
-	if (!(req->flags & (CF_SHUTR | CF_READ_ERROR)) && !buffer_full(&req->buf, global.tune.maxrewrite)) {
+	if (!(req->flags & (CF_SHUTR | CF_READ_ERROR)) && !buffer_full(req->buf, global.tune.maxrewrite)) {
 		/* Not enough data. We'll re-use the http-request
 		 * timeout here. Ideally, we should set the timeout
 		 * relative to the accept() date. We just set the
@@ -3779,14 +3779,14 @@
 
 	ctx.idx = 0;
 
-	old_o = chn->buf.o;
+	old_o = chn->buf->o;
 	if (old_o) {
 		/* The request was already skipped, let's restore it */
-		b_rew(&chn->buf, old_o);
+		b_rew(chn->buf, old_o);
 	}
 
-	old_i = chn->buf.i;
-	while (http_find_header2(hdr_name, hdr_name_len, txn->req.chn->buf.p, &txn->hdr_idx, &ctx)) {
+	old_i = chn->buf->i;
+	while (http_find_header2(hdr_name, hdr_name_len, txn->req.chn->buf->p, &txn->hdr_idx, &ctx)) {
 		/* remove any existing values from the header */
 	        http_remove_header2(&txn->req, &txn->hdr_idx, &ctx);
 	}
@@ -3805,7 +3805,7 @@
 		 * data to be forwarded in order to take into account the size
 		 * variations.
 		 */
-		b_adv(&chn->buf, old_o + chn->buf.i - old_i);
+		b_adv(chn->buf, old_o + chn->buf->i - old_i);
 	}
 
 	return 0;
@@ -3855,8 +3855,8 @@
 	}
 
 	/* don't count other requests' data */
-	s->logs.bytes_in  -= s->req->buf.i;
-	s->logs.bytes_out -= s->rep->buf.i;
+	s->logs.bytes_in  -= s->req->buf->i;
+	s->logs.bytes_out -= s->rep->buf->i;
 
 	/* let's do a final log if we need it */
 	if (s->logs.logwait &&
@@ -3875,8 +3875,8 @@
 	s->logs.prx_queue_size = 0;  /* we get the number of pending conns before us */
 	s->logs.srv_queue_size = 0; /* we will get this number soon */
 
-	s->logs.bytes_in = s->req->total = s->req->buf.i;
-	s->logs.bytes_out = s->rep->total = s->rep->buf.i;
+	s->logs.bytes_in = s->req->total = s->req->buf->i;
+	s->logs.bytes_out = s->rep->total = s->rep->buf->i;
 
 	if (s->pend_pos)
 		pendconn_free(s->pend_pos);
@@ -3922,10 +3922,10 @@
 	 * because the request will wait for it to flush a little
 	 * bit before proceeding.
 	 */
-	if (s->req->buf.i) {
-		if (s->rep->buf.o &&
-		    !buffer_full(&s->rep->buf, global.tune.maxrewrite) &&
-		    bi_end(&s->rep->buf) <= s->rep->buf.data + s->rep->buf.size - global.tune.maxrewrite)
+	if (s->req->buf->i) {
+		if (s->rep->buf->o &&
+		    !buffer_full(s->rep->buf, global.tune.maxrewrite) &&
+		    bi_end(s->rep->buf) <= s->rep->buf->data + s->rep->buf->size - global.tune.maxrewrite)
 			s->rep->flags |= CF_EXPECT_MORE;
 	}
 
@@ -4281,7 +4281,7 @@
 		return 0;
 
 	if ((req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) ||
-	    ((req->flags & CF_SHUTW) && (req->to_forward || req->buf.o))) {
+	    ((req->flags & CF_SHUTW) && (req->to_forward || req->buf->o))) {
 		/* Output closed while we were sending data. We must abort and
 		 * wake the other side up.
 		 */
@@ -4301,7 +4301,7 @@
 
 	if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) {
 		/* we have msg->sov which points to the first byte of message body.
-		 * req->buf.p still points to the beginning of the message and msg->sol
+		 * req->buf->p still points to the beginning of the message and msg->sol
 		 * is still null. We must save the body in msg->next because it
 		 * survives buffer re-alignments.
 		 */
@@ -4553,7 +4553,7 @@
 		rep,
 		rep->rex, rep->wex,
 		rep->flags,
-		rep->buf.i,
+		rep->buf->i,
 		rep->analysers);
 
 	/*
@@ -4565,9 +4565,9 @@
 	 * For the parsing, we use a 28 states FSM.
 	 *
 	 * Here is the information we currently have :
-	 *   rep->buf.p             = beginning of response
-	 *   rep->buf.p + msg->eoh  = end of processed headers / start of current one
-	 *   rep->buf.p + rep->buf.i    = end of input data
+	 *   rep->buf->p             = beginning of response
+	 *   rep->buf->p + msg->eoh  = end of processed headers / start of current one
+	 *   rep->buf->p + rep->buf->i    = end of input data
 	 *   msg->eol           = end of current header or line (LF or CRLF)
 	 *   msg->next          = first non-visited byte
 	 */
@@ -4577,11 +4577,11 @@
 	 * protected area is affected, because we may have to move processed
 	 * data later, which is much more complicated.
 	 */
-	if (buffer_not_empty(&rep->buf) && msg->msg_state < HTTP_MSG_ERROR) {
+	if (buffer_not_empty(rep->buf) && msg->msg_state < HTTP_MSG_ERROR) {
 		if (unlikely(channel_full(rep) ||
-			     bi_end(&rep->buf) < b_ptr(&rep->buf, msg->next) ||
-			     bi_end(&rep->buf) > rep->buf.data + rep->buf.size - global.tune.maxrewrite)) {
-			if (rep->buf.o) {
+			     bi_end(rep->buf) < b_ptr(rep->buf, msg->next) ||
+			     bi_end(rep->buf) > rep->buf->data + rep->buf->size - global.tune.maxrewrite)) {
+			if (rep->buf->o) {
 				/* some data has still not left the buffer, wake us once that's done */
 				if (rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_WRITE_ERROR|CF_WRITE_TIMEOUT))
 					goto abort_response;
@@ -4589,11 +4589,11 @@
 				rep->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
 				return 0;
 			}
-			if (rep->buf.i <= rep->buf.size - global.tune.maxrewrite)
-				buffer_slow_realign(&msg->chn->buf);
+			if (rep->buf->i <= rep->buf->size - global.tune.maxrewrite)
+				buffer_slow_realign(msg->chn->buf);
 		}
 
-		if (likely(msg->next < rep->buf.i))
+		if (likely(msg->next < rep->buf->i))
 			http_msg_analyzer(msg, &txn->hdr_idx);
 	}
 
@@ -4603,8 +4603,8 @@
 		     (msg->msg_state >= HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
 		char *eol, *sol;
 
-		sol = rep->buf.p;
-		eol = sol + (msg->sl.st.l ? msg->sl.st.l : rep->buf.i);
+		sol = rep->buf->p;
+		eol = sol + (msg->sl.st.l ? msg->sl.st.l : rep->buf->i);
 		debug_hdr("srvrep", s, sol, eol);
 
 		sol += hdr_idx_first_pos(&txn->hdr_idx);
@@ -4663,9 +4663,9 @@
 		}
 
 		/* too large response does not fit in buffer. */
-		else if (buffer_full(&rep->buf, global.tune.maxrewrite)) {
+		else if (buffer_full(rep->buf, global.tune.maxrewrite)) {
 			if (msg->err_pos < 0)
-				msg->err_pos = rep->buf.i;
+				msg->err_pos = rep->buf->i;
 			goto hdr_response_bad;
 		}
 
@@ -4777,7 +4777,7 @@
 	/*
 	 * 1: get the status code
 	 */
-	n = rep->buf.p[msg->sl.st.c] - '0';
+	n = rep->buf->p[msg->sl.st.c] - '0';
 	if (n < 1 || n > 5)
 		n = 0;
 	/* when the client triggers a 4xx from the server, it's most often due
@@ -4793,8 +4793,8 @@
 
 	/* check if the response is HTTP/1.1 or above */
 	if ((msg->sl.st.v_l == 8) &&
-	    ((rep->buf.p[5] > '1') ||
-	     ((rep->buf.p[5] == '1') && (rep->buf.p[7] >= '1'))))
+	    ((rep->buf->p[5] > '1') ||
+	     ((rep->buf->p[5] == '1') && (rep->buf->p[7] >= '1'))))
 		msg->flags |= HTTP_MSGF_VER_11;
 
 	/* "connection" has not been parsed yet */
@@ -4803,7 +4803,7 @@
 	/* transfer length unknown*/
 	msg->flags &= ~HTTP_MSGF_XFER_LEN;
 
-	txn->status = strl2ui(rep->buf.p + msg->sl.st.c, msg->sl.st.c_l);
+	txn->status = strl2ui(rep->buf->p + msg->sl.st.c, msg->sl.st.c_l);
 
 	/* Adjust server's health based on status code. Note: status codes 501
 	 * and 505 are triggered on demand by client request, so we must not
@@ -4851,7 +4851,7 @@
 	 */
 	s->logs.logwait &= ~LW_RESP;
 	if (unlikely((s->logs.logwait & LW_RSPHDR) && txn->rsp.cap))
-		capture_headers(rep->buf.p, &txn->hdr_idx,
+		capture_headers(rep->buf->p, &txn->hdr_idx,
 				txn->rsp.cap, s->fe->rsp_cap);
 
 	/* 4: determine the transfer-length.
@@ -4909,7 +4909,7 @@
 	use_close_only = 0;
 	ctx.idx = 0;
 	while ((msg->flags & HTTP_MSGF_VER_11) &&
-	       http_find_header2("Transfer-Encoding", 17, rep->buf.p, &txn->hdr_idx, &ctx)) {
+	       http_find_header2("Transfer-Encoding", 17, rep->buf->p, &txn->hdr_idx, &ctx)) {
 		if (ctx.vlen == 7 && strncasecmp(ctx.line + ctx.val, "chunked", 7) == 0)
 			msg->flags |= (HTTP_MSGF_TE_CHNK | HTTP_MSGF_XFER_LEN);
 		else if (msg->flags & HTTP_MSGF_TE_CHNK) {
@@ -4923,26 +4923,26 @@
 	/* FIXME: below we should remove the content-length header(s) in case of chunked encoding */
 	ctx.idx = 0;
 	while (!(msg->flags & HTTP_MSGF_TE_CHNK) && !use_close_only &&
-	       http_find_header2("Content-Length", 14, rep->buf.p, &txn->hdr_idx, &ctx)) {
+	       http_find_header2("Content-Length", 14, rep->buf->p, &txn->hdr_idx, &ctx)) {
 		signed long long cl;
 
 		if (!ctx.vlen) {
-			msg->err_pos = ctx.line + ctx.val - rep->buf.p;
+			msg->err_pos = ctx.line + ctx.val - rep->buf->p;
 			goto hdr_response_bad;
 		}
 
 		if (strl2llrc(ctx.line + ctx.val, ctx.vlen, &cl)) {
-			msg->err_pos = ctx.line + ctx.val - rep->buf.p;
+			msg->err_pos = ctx.line + ctx.val - rep->buf->p;
 			goto hdr_response_bad; /* parse failure */
 		}
 
 		if (cl < 0) {
-			msg->err_pos = ctx.line + ctx.val - rep->buf.p;
+			msg->err_pos = ctx.line + ctx.val - rep->buf->p;
 			goto hdr_response_bad;
 		}
 
 		if ((msg->flags & HTTP_MSGF_CNT_LEN) && (msg->chunk_len != cl)) {
-			msg->err_pos = ctx.line + ctx.val - rep->buf.p;
+			msg->err_pos = ctx.line + ctx.val - rep->buf->p;
 			goto hdr_response_bad; /* already specified, was different */
 		}
 
@@ -4980,7 +4980,7 @@
 		rep,
 		rep->rex, rep->wex,
 		rep->flags,
-		rep->buf.i,
+		rep->buf->i,
 		rep->analysers);
 
 	if (unlikely(msg->msg_state < HTTP_MSG_BODY))	/* we need more data */
@@ -5349,7 +5349,7 @@
 		return 0;
 
 	if ((res->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) ||
-	    ((res->flags & CF_SHUTW) && (res->to_forward || res->buf.o)) ||
+	    ((res->flags & CF_SHUTW) && (res->to_forward || res->buf->o)) ||
 	    !s->req->analysers) {
 		/* Output closed while we were sending data. We must abort and
 		 * wake the other side up.
@@ -5364,7 +5364,7 @@
 
 	if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) {
 		/* we have msg->sov which points to the first byte of message body.
-		 * rep->buf.p still points to the beginning of the message and msg->sol
+		 * rep->buf->p still points to the beginning of the message and msg->sol
 		 * is still null. We must save the body in msg->next because it
 		 * survives buffer re-alignments.
 		 */
@@ -5579,7 +5579,7 @@
 
 	last_hdr = 0;
 
-	cur_next = req->buf.p + hdr_idx_first_pos(&txn->hdr_idx);
+	cur_next = req->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
 	old_idx = 0;
 
 	while (!last_hdr) {
@@ -5658,7 +5658,7 @@
 
 			case ACT_REPLACE:
 				len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
-				delta = buffer_replace2(&req->buf, cur_ptr, cur_end, trash, len);
+				delta = buffer_replace2(req->buf, cur_ptr, cur_end, trash, len);
 				/* FIXME: if the user adds a newline in the replacement, the
 				 * index will not be recalculated for now, and the new line
 				 * will not be counted as a new header.
@@ -5671,7 +5671,7 @@
 				break;
 
 			case ACT_REMOVE:
-				delta = buffer_replace2(&req->buf, cur_ptr, cur_next, NULL, 0);
+				delta = buffer_replace2(req->buf, cur_ptr, cur_next, NULL, 0);
 				cur_next += delta;
 
 				http_msg_move_end(&txn->req, delta);
@@ -5723,7 +5723,7 @@
 
 	done = 0;
 
-	cur_ptr = req->buf.p;
+	cur_ptr = req->buf->p;
 	cur_end = cur_ptr + txn->req.sl.rq.l;
 
 	/* Now we have the request line between cur_ptr and cur_end */
@@ -5783,7 +5783,7 @@
 		case ACT_REPLACE:
 			*cur_end = term; /* restore the string terminator */
 			len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
-			delta = buffer_replace2(&req->buf, cur_ptr, cur_end, trash, len);
+			delta = buffer_replace2(req->buf, cur_ptr, cur_end, trash, len);
 			/* FIXME: if the user adds a newline in the replacement, the
 			 * index will not be recalculated for now, and the new line
 			 * will not be counted as a new header.
@@ -6036,7 +6036,7 @@
 
 	/* Iterate through the headers, we start with the start line. */
 	old_idx = 0;
-	hdr_next = req->buf.p + hdr_idx_first_pos(&txn->hdr_idx);
+	hdr_next = req->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
 
 	while ((cur_idx = txn->hdr_idx.v[old_idx].next)) {
 		struct hdr_idx_elem *cur_hdr;
@@ -6164,7 +6164,7 @@
 				 */
 				preserve_hdr = 1;
 				if (del_from != NULL) {
-					int delta = del_hdr_value(&req->buf, &del_from, prev);
+					int delta = del_hdr_value(req->buf, &del_from, prev);
 					val_end  += delta;
 					next     += delta;
 					hdr_end  += delta;
@@ -6187,13 +6187,13 @@
 				int stripped_after = 0;
 
 				if (att_end != equal) {
-					stripped_before = buffer_replace2(&req->buf, att_end, equal, NULL, 0);
+					stripped_before = buffer_replace2(req->buf, att_end, equal, NULL, 0);
 					equal   += stripped_before;
 					val_beg += stripped_before;
 				}
 
 				if (val_beg > equal + 1) {
-					stripped_after = buffer_replace2(&req->buf, equal + 1, val_beg, NULL, 0);
+					stripped_after = buffer_replace2(req->buf, equal + 1, val_beg, NULL, 0);
 					val_beg += stripped_after;
 					stripped_before += stripped_after;
 				}
@@ -6374,7 +6374,7 @@
 				if ((t->be->ck_opts & PR_CK_PFX) && (delim != val_end)) {
 					int delta; /* negative */
 
-					delta = buffer_replace2(&req->buf, val_beg, delim + 1, NULL, 0);
+					delta = buffer_replace2(req->buf, val_beg, delim + 1, NULL, 0);
 					val_end  += delta;
 					next     += delta;
 					hdr_end  += delta;
@@ -6397,7 +6397,7 @@
 				preserve_hdr = 1;
 
 				if (del_from != NULL) {
-					int delta = del_hdr_value(&req->buf, &del_from, prev);
+					int delta = del_hdr_value(req->buf, &del_from, prev);
 					if (att_beg >= del_from)
 						att_beg += delta;
 					if (att_end >= del_from)
@@ -6450,11 +6450,11 @@
 		if (del_from) {
 			int delta;
 			if (preserve_hdr) {
-				delta = del_hdr_value(&req->buf, &del_from, hdr_end);
+				delta = del_hdr_value(req->buf, &del_from, hdr_end);
 				hdr_end = del_from;
 				cur_hdr->len += delta;
 			} else {
-				delta = buffer_replace2(&req->buf, hdr_beg, hdr_next, NULL, 0);
+				delta = buffer_replace2(req->buf, hdr_beg, hdr_next, NULL, 0);
 
 				/* FIXME: this should be a separate function */
 				txn->hdr_idx.v[old_idx].next = cur_hdr->next;
@@ -6486,7 +6486,7 @@
 
 	last_hdr = 0;
 
-	cur_next = rtr->buf.p + hdr_idx_first_pos(&txn->hdr_idx);
+	cur_next = rtr->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
 	old_idx = 0;
 
 	while (!last_hdr) {
@@ -6532,7 +6532,7 @@
 
 			case ACT_REPLACE:
 				len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
-				delta = buffer_replace2(&rtr->buf, cur_ptr, cur_end, trash, len);
+				delta = buffer_replace2(rtr->buf, cur_ptr, cur_end, trash, len);
 				/* FIXME: if the user adds a newline in the replacement, the
 				 * index will not be recalculated for now, and the new line
 				 * will not be counted as a new header.
@@ -6545,7 +6545,7 @@
 				break;
 
 			case ACT_REMOVE:
-				delta = buffer_replace2(&rtr->buf, cur_ptr, cur_next, NULL, 0);
+				delta = buffer_replace2(rtr->buf, cur_ptr, cur_next, NULL, 0);
 				cur_next += delta;
 
 				http_msg_move_end(&txn->rsp, delta);
@@ -6594,7 +6594,7 @@
 
 	done = 0;
 
-	cur_ptr = rtr->buf.p;
+	cur_ptr = rtr->buf->p;
 	cur_end = cur_ptr + txn->rsp.sl.st.l;
 
 	/* Now we have the status line between cur_ptr and cur_end */
@@ -6622,7 +6622,7 @@
 		case ACT_REPLACE:
 			*cur_end = term; /* restore the string terminator */
 			len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
-			delta = buffer_replace2(&rtr->buf, cur_ptr, cur_end, trash, len);
+			delta = buffer_replace2(rtr->buf, cur_ptr, cur_end, trash, len);
 			/* FIXME: if the user adds a newline in the replacement, the
 			 * index will not be recalculated for now, and the new line
 			 * will not be counted as a new header.
@@ -6640,7 +6640,7 @@
 			/* we have a full respnse and we know that we have either a CR
 			 * or an LF at <ptr>.
 			 */
-			txn->status = strl2ui(rtr->buf.p + txn->rsp.sl.st.c, txn->rsp.sl.st.c_l);
+			txn->status = strl2ui(rtr->buf->p + txn->rsp.sl.st.c, txn->rsp.sl.st.c_l);
 			hdr_idx_set_start(&txn->hdr_idx, txn->rsp.sl.st.l, *cur_end == '\r');
 			/* there is no point trying this regex on headers */
 			return 1;
@@ -6727,7 +6727,7 @@
 	 * we start with the start line.
 	 */
 	old_idx = 0;
-	hdr_next = res->buf.p + hdr_idx_first_pos(&txn->hdr_idx);
+	hdr_next = res->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
 
 	while ((cur_idx = txn->hdr_idx.v[old_idx].next)) {
 		struct hdr_idx_elem *cur_hdr;
@@ -6877,13 +6877,13 @@
 				int stripped_after = 0;
 
 				if (att_end != equal) {
-					stripped_before = buffer_replace2(&res->buf, att_end, equal, NULL, 0);
+					stripped_before = buffer_replace2(res->buf, att_end, equal, NULL, 0);
 					equal   += stripped_before;
 					val_beg += stripped_before;
 				}
 
 				if (val_beg > equal + 1) {
-					stripped_after = buffer_replace2(&res->buf, equal + 1, val_beg, NULL, 0);
+					stripped_after = buffer_replace2(res->buf, equal + 1, val_beg, NULL, 0);
 					val_beg += stripped_after;
 					stripped_before += stripped_after;
 				}
@@ -6941,7 +6941,7 @@
 					/* this cookie must be deleted */
 					if (*prev == ':' && next == hdr_end) {
 						/* whole header */
-						delta = buffer_replace2(&res->buf, hdr_beg, hdr_next, NULL, 0);
+						delta = buffer_replace2(res->buf, hdr_beg, hdr_next, NULL, 0);
 						txn->hdr_idx.v[old_idx].next = cur_hdr->next;
 						txn->hdr_idx.used--;
 						cur_hdr->len = 0;
@@ -6953,7 +6953,7 @@
 						 */
 					} else {
 						/* just remove the value */
-						int delta = del_hdr_value(&res->buf, &prev, next);
+						int delta = del_hdr_value(res->buf, &prev, next);
 						next      = prev;
 						hdr_end  += delta;
 						hdr_next += delta;
@@ -6968,7 +6968,7 @@
 					/* replace bytes val_beg->val_end with the cookie name associated
 					 * with this server since we know it.
 					 */
-					delta = buffer_replace2(&res->buf, val_beg, val_end, srv->cookie, srv->cklen);
+					delta = buffer_replace2(res->buf, val_beg, val_end, srv->cookie, srv->cklen);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
@@ -6982,7 +6982,7 @@
 					/* insert the cookie name associated with this server
 					 * before existing cookie, and insert a delimiter between them..
 					 */
-					delta = buffer_replace2(&res->buf, val_beg, val_beg, srv->cookie, srv->cklen + 1);
+					delta = buffer_replace2(res->buf, val_beg, val_beg, srv->cookie, srv->cklen + 1);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
@@ -7092,7 +7092,7 @@
 	 * we start with the start line.
 	 */
 	cur_idx = 0;
-	cur_next = rtr->buf.p + hdr_idx_first_pos(&txn->hdr_idx);
+	cur_next = rtr->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
 
 	while ((cur_idx = txn->hdr_idx.v[cur_idx].next)) {
 		struct hdr_idx_elem *cur_hdr;
@@ -7246,7 +7246,7 @@
 {
 	struct uri_auth *uri_auth = backend->uri_auth;
 	struct http_msg *msg = &txn->req;
-	const char *uri = msg->chn->buf.p+ msg->sl.rq.u;
+	const char *uri = msg->chn->buf->p+ msg->sl.rq.u;
 	const char *h;
 
 	if (!uri_auth)
@@ -7331,14 +7331,14 @@
 	struct channel *chn = msg->chn;
 	int len1, len2;
 
-	es->len = MIN(chn->buf.i, sizeof(es->buf));
-	len1 = chn->buf.data + chn->buf.size - chn->buf.p;
+	es->len = MIN(chn->buf->i, sizeof(es->buf));
+	len1 = chn->buf->data + chn->buf->size - chn->buf->p;
 	len1 = MIN(len1, es->len);
 	len2 = es->len - len1; /* remaining data if buffer wraps */
 
-	memcpy(es->buf, chn->buf.p, len1);
+	memcpy(es->buf, chn->buf->p, len1);
 	if (len2)
-		memcpy(es->buf + len1, chn->buf.data, len2);
+		memcpy(es->buf + len1, chn->buf->data, len2);
 
 	if (msg->err_pos >= 0)
 		es->pos = msg->err_pos;
@@ -7356,8 +7356,8 @@
 	es->s_flags = s->flags;
 	es->t_flags = s->txn.flags;
 	es->m_flags = msg->flags;
-	es->b_out = chn->buf.o;
-	es->b_wrap = chn->buf.data + chn->buf.size - chn->buf.p;
+	es->b_out = chn->buf->o;
+	es->b_wrap = chn->buf->data + chn->buf->size - chn->buf->p;
 	es->b_tot = chn->total;
 	es->m_clen = msg->chunk_len;
 	es->m_blen = msg->body_len;
@@ -7390,7 +7390,7 @@
 
 	if (occ >= 0) {
 		/* search from the beginning */
-		while (http_find_header2(hname, hlen, msg->chn->buf.p, idx, ctx)) {
+		while (http_find_header2(hname, hlen, msg->chn->buf->p, idx, ctx)) {
 			occ--;
 			if (occ <= 0) {
 				*vptr = ctx->line + ctx->val;
@@ -7406,7 +7406,7 @@
 		return 0;
 
 	found = hist_ptr = 0;
-	while (http_find_header2(hname, hlen, msg->chn->buf.p, idx, ctx)) {
+	while (http_find_header2(hname, hlen, msg->chn->buf->p, idx, ctx)) {
 		ptr_hist[hist_ptr] = ctx->line + ctx->val;
 		len_hist[hist_ptr] = ctx->vlen;
 		if (++hist_ptr >= MAX_HDR_HISTORY)
@@ -7555,8 +7555,8 @@
 	 * a HEAD with some data, or sending more than the advertised
 	 * content-length.
 	 */
-	if (unlikely(s->rep->buf.i))
-		s->rep->buf.i = 0;
+	if (unlikely(s->rep->buf->i))
+		s->rep->buf->i = 0;
 
 	s->req->rto = s->fe->timeout.client;
 	s->req->wto = TICK_ETERNITY;
@@ -7683,19 +7683,19 @@
 
 		if (unlikely(txn->req.msg_state < HTTP_MSG_BODY)) {
 			if ((msg->msg_state == HTTP_MSG_ERROR) ||
-			    buffer_full(&s->req->buf, global.tune.maxrewrite)) {
+			    buffer_full(s->req->buf, global.tune.maxrewrite)) {
 				smp->data.uint = 0;
 				return -1;
 			}
 
 			/* Try to decode HTTP request */
-			if (likely(msg->next < s->req->buf.i))
+			if (likely(msg->next < s->req->buf->i))
 				http_msg_analyzer(msg, &txn->hdr_idx);
 
 			/* Still no valid request ? */
 			if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
 				if ((msg->msg_state == HTTP_MSG_ERROR) ||
-				    buffer_full(&s->req->buf, global.tune.maxrewrite)) {
+				    buffer_full(s->req->buf, global.tune.maxrewrite)) {
 					smp->data.uint = 0;
 					return -1;
 				}
@@ -7708,7 +7708,7 @@
 			 * preparation to perform so that further checks can rely
 			 * on HTTP tests.
 			 */
-			txn->meth = find_http_meth(msg->chn->buf.p, msg->sl.rq.m_l);
+			txn->meth = find_http_meth(msg->chn->buf->p, msg->sl.rq.m_l);
 			if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
 				s->flags |= SN_REDIRECTABLE;
 
@@ -7789,7 +7789,7 @@
 			return 0;
 		smp->type = SMP_T_CSTR;
 		smp->data.str.len = txn->req.sl.rq.m_l;
-		smp->data.str.str = txn->req.chn->buf.p;
+		smp->data.str.str = txn->req.chn->buf->p;
 	}
 	smp->flags = SMP_F_VOL_1ST;
 	return 1;
@@ -7848,7 +7848,7 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	len = txn->req.sl.rq.v_l;
-	ptr = txn->req.chn->buf.p + txn->req.sl.rq.v;
+	ptr = txn->req.chn->buf->p + txn->req.sl.rq.v;
 
 	while ((len-- > 0) && (*ptr++ != '/'));
 	if (len <= 0)
@@ -7873,7 +7873,7 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	len = txn->rsp.sl.st.v_l;
-	ptr = txn->rsp.chn->buf.p;
+	ptr = txn->rsp.chn->buf->p;
 
 	while ((len-- > 0) && (*ptr++ != '/'));
 	if (len <= 0)
@@ -7899,7 +7899,7 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	len = txn->rsp.sl.st.c_l;
-	ptr = txn->rsp.chn->buf.p + txn->rsp.sl.st.c;
+	ptr = txn->rsp.chn->buf->p + txn->rsp.sl.st.c;
 
 	smp->type = SMP_T_UINT;
 	smp->data.uint = __strl2ui(ptr, len);
@@ -7918,7 +7918,7 @@
 
 	smp->type = SMP_T_CSTR;
 	smp->data.str.len = txn->req.sl.rq.u_l;
-	smp->data.str.str = txn->req.chn->buf.p + txn->req.sl.rq.u;
+	smp->data.str.str = txn->req.chn->buf->p + txn->req.sl.rq.u;
 	smp->flags = SMP_F_VOL_1ST;
 	return 1;
 }
@@ -7932,7 +7932,7 @@
 	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);
+	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;
@@ -7958,7 +7958,7 @@
 	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);
 
@@ -8040,7 +8040,7 @@
 
 	ctx.idx = 0;
 	cnt = 0;
-	while (http_find_header2(args->data.str.str, args->data.str.len, msg->chn->buf.p, idx, &ctx))
+	while (http_find_header2(args->data.str.str, args->data.str.len, msg->chn->buf->p, idx, &ctx))
 		cnt++;
 
 	smp->type = SMP_T_UINT;
@@ -8101,7 +8101,7 @@
 
 	CHECK_HTTP_MESSAGE_FIRST();
 
-	end = txn->req.chn->buf.p + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
+	end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
 	ptr = http_get_path(txn);
 	if (!ptr)
 		return 0;
@@ -8135,7 +8135,7 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	ctx.idx = 0;
-	if (!http_find_header2("Host", 4, txn->req.chn->buf.p + txn->req.sol, &txn->hdr_idx, &ctx) ||
+	if (!http_find_header2("Host", 4, txn->req.chn->buf->p + txn->req.sol, &txn->hdr_idx, &ctx) ||
 	    !ctx.vlen)
 		return smp_fetch_path(px, l4, l7, opt, args, smp);
 
@@ -8146,7 +8146,7 @@
 	smp->data.str.len = ctx.vlen;
 
 	/* now retrieve the path */
-	end = txn->req.chn->buf.p + txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
+	end = txn->req.chn->buf->p + txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
 	beg = http_get_path(txn);
 	if (!beg)
 		beg = end;
@@ -8382,7 +8382,7 @@
 	 * next one.
 	 */
 
-	sol = msg->chn->buf.p;
+	sol = msg->chn->buf->p;
 	if (!(smp->flags & SMP_F_NOT_LAST)) {
 		/* search for the header from the beginning, we must first initialize
 		 * the search parameters.
@@ -8464,7 +8464,7 @@
 		hdr_name_len = 10;
 	}
 
-	sol = msg->chn->buf.p;
+	sol = msg->chn->buf->p;
 	val_end = val_beg = NULL;
 	ctx.idx = 0;
 	cnt = 0;
@@ -8622,7 +8622,7 @@
 	if (args[1].type)
 		delim = *args[1].data.str.str;
 
-	if (!find_url_param_value(msg->chn->buf.p + msg->sl.rq.u, msg->sl.rq.u_l,
+	if (!find_url_param_value(msg->chn->buf->p + msg->sl.rq.u, msg->sl.rq.u_l,
                                  args->data.str.str, args->data.str.len,
                                  &smp->data.str.str, &smp->data.str.len,
                                  delim))
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 7185a0a..d0424d9 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -792,7 +792,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	/* We don't know whether we have enough data, so must proceed
@@ -805,7 +805,7 @@
 	 * - if one rule returns KO, then return KO
 	 */
 
-	if ((req->flags & CF_SHUTR) || buffer_full(&req->buf, global.tune.maxrewrite) ||
+	if ((req->flags & CF_SHUTR) || buffer_full(req->buf, global.tune.maxrewrite) ||
 	    !s->be->tcp_req.inspect_delay || tick_is_expired(req->analyse_exp, now_ms))
 		partial = SMP_OPT_FINAL;
 	else
@@ -911,7 +911,7 @@
 		rep,
 		rep->rex, rep->wex,
 		rep->flags,
-		rep->buf.i,
+		rep->buf->i,
 		rep->analysers);
 
 	/* We don't know whether we have enough data, so must proceed
@@ -1400,11 +1400,11 @@
 	smp->flags = 0;
 	smp->type = SMP_T_CSTR;
 
-	bleft = l4->req->buf.i;
+	bleft = l4->req->buf->i;
 	if (bleft <= 11)
 		goto too_short;
 
-	data = (const unsigned char *)l4->req->buf.p + 11;
+	data = (const unsigned char *)l4->req->buf->p + 11;
 	bleft -= 11;
 
 	if (bleft <= 7)
@@ -1595,11 +1595,11 @@
 	if (!chn)
 		return 0;
 
-	if (len_offset + len_size > chn->buf.i)
+	if (len_offset + len_size > chn->buf->i)
 		goto too_short;
 
 	for (i = 0; i < len_size; i++) {
-		buf_size = (buf_size << 8) + ((unsigned char *)chn->buf.p)[i + len_offset];
+		buf_size = (buf_size << 8) + ((unsigned char *)chn->buf->p)[i + len_offset];
 	}
 
 	/* buf offset may be implicit, absolute or relative */
@@ -1609,18 +1609,18 @@
 	else if (arg_p[2].type == ARGT_SINT)
 		buf_offset += arg_p[2].data.sint;
 
-	if (!buf_size || buf_size > chn->buf.size || buf_offset + buf_size > chn->buf.size) {
+	if (!buf_size || buf_size > chn->buf->size || buf_offset + buf_size > chn->buf->size) {
 		/* will never match */
 		smp->flags = 0;
 		return 0;
 	}
 
-	if (buf_offset + buf_size > chn->buf.i)
+	if (buf_offset + buf_size > chn->buf->i)
 		goto too_short;
 
 	/* init chunk as read only */
 	smp->type = SMP_T_CBIN;
-	chunk_initlen(&smp->data.str, chn->buf.p + buf_offset, 0, buf_size);
+	chunk_initlen(&smp->data.str, chn->buf->p + buf_offset, 0, buf_size);
 	smp->flags = SMP_F_VOLATILE;
 	return 1;
 
@@ -1645,18 +1645,18 @@
 	if (!chn)
 		return 0;
 
-	if (!buf_size || buf_size > chn->buf.size || buf_offset + buf_size > chn->buf.size) {
+	if (!buf_size || buf_size > chn->buf->size || buf_offset + buf_size > chn->buf->size) {
 		/* will never match */
 		smp->flags = 0;
 		return 0;
 	}
 
-	if (buf_offset + buf_size > chn->buf.i)
+	if (buf_offset + buf_size > chn->buf->i)
 		goto too_short;
 
 	/* init chunk as read only */
 	smp->type = SMP_T_CBIN;
-	chunk_initlen(&smp->data.str, chn->buf.p + buf_offset, 0, buf_size);
+	chunk_initlen(&smp->data.str, chn->buf->p + buf_offset, 0, buf_size);
 	smp->flags = SMP_F_VOLATILE;
 	return 1;
 
diff --git a/src/session.c b/src/session.c
index b154407..ce99e78 100644
--- a/src/session.c
+++ b/src/session.c
@@ -15,6 +15,7 @@
 #include <fcntl.h>
 
 #include <common/config.h>
+#include <common/buffer.h>
 #include <common/debug.h>
 #include <common/memory.h>
 
@@ -419,11 +420,17 @@
 	if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
 		goto out_free_task; /* no memory */
 
-	if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
+	if (unlikely((s->req->buf = pool_alloc2(pool2_buffer)) == NULL))
 		goto out_free_req; /* no memory */
 
+	if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
+		goto out_free_req_buf; /* no memory */
+
+	if (unlikely((s->rep->buf = pool_alloc2(pool2_buffer)) == NULL))
+		goto out_free_rep; /* no memory */
+
 	/* initialize the request buffer */
-	s->req->buf.size = global.tune.bufsize;
+	s->req->buf->size = global.tune.bufsize;
 	channel_init(s->req);
 	s->req->prod = &s->si[0];
 	s->req->cons = &s->si[1];
@@ -440,7 +447,7 @@
 	s->req->analyse_exp = TICK_ETERNITY;
 
 	/* initialize response buffer */
-	s->rep->buf.size = global.tune.bufsize;
+	s->rep->buf->size = global.tune.bufsize;
 	channel_init(s->rep);
 	s->rep->prod = &s->si[1];
 	s->rep->cons = &s->si[0];
@@ -485,7 +492,7 @@
 		 * finished (=0, eg: monitoring), in both situations,
 		 * we can release everything and close.
 		 */
-		goto out_free_rep;
+		goto out_free_rep_buf;
 	}
 
 	/* if logs require transport layer information, note it on the connection */
@@ -503,8 +510,12 @@
 	return 1;
 
 	/* Error unrolling */
+ out_free_rep_buf:
+	pool_free2(pool2_buffer, s->rep->buf);
  out_free_rep:
 	pool_free2(pool2_channel, s->rep);
+ out_free_req_buf:
+	pool_free2(pool2_buffer, s->req->buf);
  out_free_req:
 	pool_free2(pool2_channel, s->req);
  out_free_task:
@@ -547,6 +558,9 @@
 	if (s->rep->pipe)
 		put_pipe(s->rep->pipe);
 
+	pool_free2(pool2_buffer, s->req->buf);
+	pool_free2(pool2_buffer, s->rep->buf);
+
 	pool_free2(pool2_channel, s->req);
 	pool_free2(pool2_channel, s->rep);
 
@@ -587,6 +601,7 @@
 
 	/* We may want to free the maximum amount of pools if the proxy is stopping */
 	if (fe && unlikely(fe->state == PR_STSTOPPED)) {
+		pool_flush2(pool2_buffer);
 		pool_flush2(pool2_channel);
 		pool_flush2(pool2_hdr_idx);
 		pool_flush2(pool2_requri);
@@ -915,7 +930,7 @@
 		s->req, s->rep,
 		s->req->rex, s->rep->wex,
 		s->req->flags, s->rep->flags,
-		s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state);
+		s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state);
 
 	if (si->state == SI_ST_ASS) {
 		/* Server assigned to connection request, we have to try to connect now */
@@ -1103,7 +1118,7 @@
 		s->req, s->rep,
 		s->req->rex, s->rep->wex,
 		s->req->flags, s->rep->flags,
-		s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state);
+		s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state);
 
 	if (si->state != SI_ST_REQ)
 		return;
@@ -1152,7 +1167,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	/* now check whether we have some switching rules for this request */
@@ -1247,7 +1262,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i + req->buf.o,
+		req->buf->i + req->buf->o,
 		req->analysers);
 
 	if (!(s->flags & SN_ASSIGNED)) {
@@ -1296,7 +1311,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf.i,
+		req->buf->i,
 		req->analysers);
 
 	list_for_each_entry(rule, &px->sticking_rules, list) {
@@ -1386,7 +1401,7 @@
 		rep,
 		rep->rex, rep->wex,
 		rep->flags,
-		rep->buf.i,
+		rep->buf->i,
 		rep->analysers);
 
 	list_for_each_entry(rule, &px->storersp_rules, list) {
@@ -1633,7 +1648,7 @@
 		s->req, s->rep,
 		s->req->rex, s->rep->wex,
 		s->req->flags, s->rep->flags,
-		s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state,
+		s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state,
 		s->rep->cons->err_type, s->req->cons->err_type,
 		s->req->cons->conn_retries);
 
@@ -2036,7 +2051,7 @@
 		channel_auto_read(s->req);
 		channel_auto_connect(s->req);
 		channel_auto_close(s->req);
-		buffer_flush(&s->req->buf);
+		buffer_flush(s->req->buf);
 
 		/* We'll let data flow between the producer (if still connected)
 		 * to the consumer (which might possibly not be connected yet).
@@ -2172,7 +2187,7 @@
 		 */
 		channel_auto_read(s->rep);
 		channel_auto_close(s->rep);
-		buffer_flush(&s->rep->buf);
+		buffer_flush(s->rep->buf);
 
 		/* We'll let data flow between the producer (if still connected)
 		 * to the consumer.
diff --git a/src/stream_interface.c b/src/stream_interface.c
index fd427b3..c74f453 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -617,7 +617,7 @@
 	 */
 	if (((si->ib->flags & CF_READ_PARTIAL) && !channel_is_empty(si->ib)) &&
 	    (si->ib->pipe /* always try to send spliced data */ ||
-	     (si->ib->buf.i == 0 && (si->ib->cons->flags & SI_FL_WAIT_DATA)))) {
+	     (si->ib->buf->i == 0 && (si->ib->cons->flags & SI_FL_WAIT_DATA)))) {
 		int last_len = si->ib->pipe ? si->ib->pipe->data : 0;
 
 		si_chk_snd(si->ib->cons);
@@ -691,7 +691,7 @@
 	/* At this point, the pipe is empty, but we may still have data pending
 	 * in the normal buffer.
 	 */
-	if (!chn->buf.o)
+	if (!chn->buf->o)
 		return 0;
 
 	/* when we're in this loop, we already know that there is no spliced
@@ -716,13 +716,13 @@
 		    ((chn->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK)) == CF_SHUTW_NOW))
 			send_flag |= MSG_MORE;
 
-		ret = conn->xprt->snd_buf(conn, &chn->buf, send_flag);
+		ret = conn->xprt->snd_buf(conn, chn->buf, send_flag);
 		if (ret <= 0)
 			break;
 
 		chn->flags |= CF_WRITE_PARTIAL;
 
-		if (!chn->buf.o) {
+		if (!chn->buf->o) {
 			/* Always clear both flags once everything has been sent, they're one-shot */
 			chn->flags &= ~(CF_EXPECT_MORE | CF_SEND_DONTWAIT);
 			break;
@@ -970,7 +970,7 @@
 	 */
 	if (conn->xprt->rcv_pipe &&
 	    chn->to_forward >= MIN_SPLICE_FORWARD && chn->flags & CF_KERN_SPLICING) {
-		if (buffer_not_empty(&chn->buf)) {
+		if (buffer_not_empty(chn->buf)) {
 			/* We're embarrassed, there are already data pending in
 			 * the buffer and we don't want to have them at two
 			 * locations at a time. Let's indicate we need some
@@ -1028,7 +1028,7 @@
 			break;
 		}
 
-		ret = conn->xprt->rcv_buf(conn, &chn->buf, max);
+		ret = conn->xprt->rcv_buf(conn, chn->buf, max);
 		if (ret <= 0)
 			break;
 
@@ -1042,7 +1042,7 @@
 					fwd = chn->to_forward;
 				chn->to_forward -= fwd;
 			}
-			b_adv(&chn->buf, fwd);
+			b_adv(chn->buf, fwd);
 		}
 
 		chn->flags |= CF_READ_PARTIAL;
@@ -1052,7 +1052,7 @@
 			/* The buffer is now full, there's no point in going through
 			 * the loop again.
 			 */
-			if (!(chn->flags & CF_STREAMER_FAST) && (cur_read == buffer_len(&chn->buf))) {
+			if (!(chn->flags & CF_STREAMER_FAST) && (cur_read == buffer_len(chn->buf))) {
 				chn->xfer_small = 0;
 				chn->xfer_large++;
 				if (chn->xfer_large >= 3) {
@@ -1064,7 +1064,7 @@
 				}
 			}
 			else if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) &&
-				 (cur_read <= chn->buf.size / 2)) {
+				 (cur_read <= chn->buf->size / 2)) {
 				chn->xfer_large = 0;
 				chn->xfer_small++;
 				if (chn->xfer_small >= 2) {
@@ -1094,7 +1094,7 @@
 		 */
 		if (ret < max) {
 			if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) &&
-			    (cur_read <= chn->buf.size / 2)) {
+			    (cur_read <= chn->buf->size / 2)) {
 				chn->xfer_large = 0;
 				chn->xfer_small++;
 				if (chn->xfer_small >= 3) {