MAJOR: buffer: finalize buffer detachment

Now the buffers only contain the header and a pointer to the storage
area which can be anywhere. This will significantly simplify buffer
swapping and will make it possible to map chunks on buffers as well.

The buf_empty variable was removed, as now it's enough to have size==0
and area==NULL to designate the empty buffer (thus a non-allocated head
is the empty buffer by default). buf_wanted for now is indicated by
size==0 and area==(void *)1.

The channels and the checks now embed the buffer's head, and the only
pointer is to the storage area. This slightly increases the unallocated
buffer size (3 extra ints for the empty buffer) but considerably
simplifies dynamic buffer management. It will also later permit to
detach unused checks.

The way the struct buffer is arranged has proven quite efficient on a
number of tests, which makes sense given that size is always accessed
and often first, followed by the othe ones.
diff --git a/src/backend.c b/src/backend.c
index 66fd605..b82ecbb 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -329,8 +329,8 @@
 	if (len == 0)
 		return NULL;
 
-	if (len > b_wrap(req->buf) - p)
-		len = b_wrap(req->buf) - p;
+	if (len > b_wrap(&req->buf) - p)
+		len = b_wrap(&req->buf) - p;
 
 	if (px->lbprm.tot_weight == 0)
 		return NULL;
diff --git a/src/buffer.c b/src/buffer.c
index 6f4c494..d6bd242 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -22,15 +22,6 @@
 
 struct pool_head *pool_head_buffer;
 
-/* These buffers are used to always have a valid pointer to an empty buffer in
- * channels. The first buffer is set once a buffer is empty. The second one is
- * set when a buffer is desired but no more are available. It helps knowing
- * what channel wants a buffer. They can reliably be exchanged, the split
- * between the two is only an optimization.
- */
-struct buffer buf_empty  = {  };
-struct buffer buf_wanted = {  };
-
 /* list of objects waiting for at least one buffer */
 struct list buffer_wq = LIST_HEAD_INIT(buffer_wq);
 __decl_hathreads(HA_SPINLOCK_T __attribute__((aligned(64))) buffer_wq_lock);
@@ -40,7 +31,7 @@
 {
 	void *buffer;
 
-	pool_head_buffer = create_pool("buffer", sizeof (struct buffer) + global.tune.bufsize, MEM_F_SHARED|MEM_F_EXACT);
+	pool_head_buffer = create_pool("buffer", global.tune.bufsize, MEM_F_SHARED|MEM_F_EXACT);
 	if (!pool_head_buffer)
 		return 0;
 
diff --git a/src/cache.c b/src/cache.c
index 581c408..6e7a87a 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -541,7 +541,7 @@
 		goto out;
 
 	/* Check if the input buffer is avalaible. */
-	if (res->buf->size == 0) {
+	if (res->buf.size == 0) {
 		si_applet_cant_put(si);
 		goto out;
 	}
@@ -560,7 +560,7 @@
 			si_applet_cant_put(si);
 			goto out;
 		}
-		b_add(res->buf, len);
+		b_add(&res->buf, len);
 		res->total += len;
 		appctx->st0 = HTTP_CACHE_FWD;
 	}
diff --git a/src/channel.c b/src/channel.c
index bb5e144..13184ec 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -92,12 +92,12 @@
 	}
 
 	c_realign_if_empty(chn);
-	max = b_contig_space(chn->buf);
+	max = b_contig_space(&chn->buf);
 	if (len > max)
 		return max;
 
 	memcpy(ci_tail(chn), msg, len);
-	b_add(chn->buf, len);
+	b_add(&chn->buf, len);
 	c_adv(chn, len);
 	chn->total += len;
 	return -1;
@@ -119,7 +119,7 @@
 
 	*ci_tail(chn) = c;
 
-	b_add(chn->buf, 1);
+	b_add(&chn->buf, 1);
 	chn->flags |= CF_READ_PARTIAL;
 
 	if (chn->to_forward >= 1) {
@@ -166,12 +166,12 @@
 		return 0;
 
 	/* OK so the data fits in the buffer in one or two blocks */
-	max = b_contig_space(chn->buf);
+	max = b_contig_space(&chn->buf);
 	memcpy(ci_tail(chn), blk, MIN(len, max));
 	if (len > max)
 		memcpy(c_orig(chn), blk + max, len - max);
 
-	b_add(chn->buf, len);
+	b_add(&chn->buf, len);
 	chn->total += len;
 	if (chn->to_forward) {
 		unsigned long fwd = len;
@@ -226,7 +226,7 @@
 
 		if (*p == '\n')
 			break;
-		p = b_next(chn->buf, p);
+		p = b_next(&chn->buf, p);
 	}
 	if (ret > 0 && ret < len &&
 	    (ret < co_data(chn) || channel_may_recv(chn)) &&
@@ -258,7 +258,7 @@
 		return 0;
 	}
 
-	return b_getblk(chn->buf, blk, len, offset);
+	return b_getblk(&chn->buf, blk, len, offset);
 }
 
 /* Gets one or two blocks of data at once from a channel's output buffer.
@@ -277,7 +277,7 @@
 		return 0;
 	}
 
-	return b_getblk_nc(chn->buf, blk1, len1, blk2, len2, 0, co_data(chn));
+	return b_getblk_nc(&chn->buf, blk1, len1, blk2, len2, 0, co_data(chn));
 }
 
 /* Gets one text line out of a channel's output buffer from a stream interface.
@@ -411,7 +411,7 @@
  */
 int ci_insert_line2(struct channel *c, int pos, const char *str, int len)
 {
-	struct buffer *b = c->buf;
+	struct buffer *b = &c->buf;
 	char *dst = c_ptr(c, pos);
 	int delta;
 
diff --git a/src/checks.c b/src/checks.c
index bf4c78f..6db077a 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -745,16 +745,16 @@
 	if (check->type == PR_O2_TCPCHK_CHK)
 		goto out_unlock;
 
-	if (b_data(check->bo)) {
-		b_del(check->bo, conn->mux->snd_buf(cs, check->bo, b_data(check->bo), 0));
-		b_realign_if_empty(check->bo);
+	if (b_data(&check->bo)) {
+		b_del(&check->bo, conn->mux->snd_buf(cs, &check->bo, b_data(&check->bo), 0));
+		b_realign_if_empty(&check->bo);
 
 		if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
 			chk_report_conn_err(check, errno, 0);
 			__cs_stop_both(cs);
 			goto out_wakeup;
 		}
-		if (b_data(check->bo))
+		if (b_data(&check->bo))
 			goto out_unlock;
 	}
 
@@ -824,10 +824,10 @@
 
 	done = 0;
 
-	conn->mux->rcv_buf(cs, check->bi, check->bi->size, 0);
+	conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0);
 	if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) {
 		done = 1;
-		if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(check->bi)) {
+		if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) {
 			/* Report network errors only if we got no other data. Otherwise
 			 * we'll let the upper layers decide whether the response is OK
 			 * or not. It is very common that an RST sent by the server is
@@ -840,35 +840,35 @@
 
 
 	/* Intermediate or complete response received.
-	 * Terminate string in b_head(check->bi) buffer.
+	 * Terminate string in b_head(&check->bi) buffer.
 	 */
-	if (b_data(check->bi) < check->bi->size)
-		b_head(check->bi)[b_data(check->bi)] = '\0';
+	if (b_data(&check->bi) < b_size(&check->bi))
+		b_head(&check->bi)[b_data(&check->bi)] = '\0';
 	else {
-		b_head(check->bi)[b_data(check->bi) - 1] = '\0';
+		b_head(&check->bi)[b_data(&check->bi) - 1] = '\0';
 		done = 1; /* buffer full, don't wait for more data */
 	}
 
 	/* Run the checks... */
 	switch (check->type) {
 	case PR_O2_HTTP_CHK:
-		if (!done && b_data(check->bi) < strlen("HTTP/1.0 000\r"))
+		if (!done && b_data(&check->bi) < strlen("HTTP/1.0 000\r"))
 			goto wait_more_data;
 
 		/* Check if the server speaks HTTP 1.X */
-		if ((b_data(check->bi) < strlen("HTTP/1.0 000\r")) ||
-		    (memcmp(b_head(check->bi), "HTTP/1.", 7) != 0 ||
-		    (*(b_head(check->bi) + 12) != ' ' && *(b_head(check->bi) + 12) != '\r')) ||
-		    !isdigit((unsigned char) *(b_head(check->bi) + 9)) || !isdigit((unsigned char) *(b_head(check->bi) + 10)) ||
-		    !isdigit((unsigned char) *(b_head(check->bi) + 11))) {
-			cut_crlf(b_head(check->bi));
-			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(check->bi));
+		if ((b_data(&check->bi) < strlen("HTTP/1.0 000\r")) ||
+		    (memcmp(b_head(&check->bi), "HTTP/1.", 7) != 0 ||
+		    (*(b_head(&check->bi) + 12) != ' ' && *(b_head(&check->bi) + 12) != '\r')) ||
+		    !isdigit((unsigned char) *(b_head(&check->bi) + 9)) || !isdigit((unsigned char) *(b_head(&check->bi) + 10)) ||
+		    !isdigit((unsigned char) *(b_head(&check->bi) + 11))) {
+			cut_crlf(b_head(&check->bi));
+			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
 
 			goto out_wakeup;
 		}
 
-		check->code = str2uic(b_head(check->bi) + 9);
-		desc = ltrim(b_head(check->bi) + 12, ' ');
+		check->code = str2uic(b_head(&check->bi) + 9);
+		desc = ltrim(b_head(&check->bi) + 12, ' ');
 
 		if ((s->proxy->options & PR_O_DISABLE404) &&
 			 (s->next_state != SRV_ST_STOPPED) && (check->code == 404)) {
@@ -882,7 +882,7 @@
 				goto wait_more_data;
 		}
 		/* check the reply : HTTP/1.X 2xx and 3xx are OK */
-		else if (*(b_head(check->bi) + 9) == '2' || *(b_head(check->bi) + 9) == '3') {
+		else if (*(b_head(&check->bi) + 9) == '2' || *(b_head(&check->bi) + 9) == '3') {
 			cut_crlf(desc);
 			set_server_check_status(check,  HCHK_STATUS_L7OKD, desc);
 		}
@@ -893,37 +893,37 @@
 		break;
 
 	case PR_O2_SSL3_CHK:
-		if (!done && b_data(check->bi) < 5)
+		if (!done && b_data(&check->bi) < 5)
 			goto wait_more_data;
 
 		/* Check for SSLv3 alert or handshake */
-		if ((b_data(check->bi) >= 5) && (*b_head(check->bi) == 0x15 || *b_head(check->bi) == 0x16))
+		if ((b_data(&check->bi) >= 5) && (*b_head(&check->bi) == 0x15 || *b_head(&check->bi) == 0x16))
 			set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
 		else
 			set_server_check_status(check, HCHK_STATUS_L6RSP, NULL);
 		break;
 
 	case PR_O2_SMTP_CHK:
-		if (!done && b_data(check->bi) < strlen("000\r"))
+		if (!done && b_data(&check->bi) < strlen("000\r"))
 			goto wait_more_data;
 
 		/* Check if the server speaks SMTP */
-		if ((b_data(check->bi) < strlen("000\r")) ||
-		    (*(b_head(check->bi) + 3) != ' ' && *(b_head(check->bi) + 3) != '\r') ||
-		    !isdigit((unsigned char) *b_head(check->bi)) || !isdigit((unsigned char) *(b_head(check->bi) + 1)) ||
-		    !isdigit((unsigned char) *(b_head(check->bi) + 2))) {
-			cut_crlf(b_head(check->bi));
-			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(check->bi));
+		if ((b_data(&check->bi) < strlen("000\r")) ||
+		    (*(b_head(&check->bi) + 3) != ' ' && *(b_head(&check->bi) + 3) != '\r') ||
+		    !isdigit((unsigned char) *b_head(&check->bi)) || !isdigit((unsigned char) *(b_head(&check->bi) + 1)) ||
+		    !isdigit((unsigned char) *(b_head(&check->bi) + 2))) {
+			cut_crlf(b_head(&check->bi));
+			set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
 			goto out_wakeup;
 		}
 
-		check->code = str2uic(b_head(check->bi));
+		check->code = str2uic(b_head(&check->bi));
 
-		desc = ltrim(b_head(check->bi) + 3, ' ');
+		desc = ltrim(b_head(&check->bi) + 3, ' ');
 		cut_crlf(desc);
 
 		/* Check for SMTP code 2xx (should be 250) */
-		if (*b_head(check->bi) == '2')
+		if (*b_head(&check->bi) == '2')
 			set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
 		else
 			set_server_check_status(check, HCHK_STATUS_L7STS, desc);
@@ -963,7 +963,7 @@
 		 * same category appear, the last one wins.
 		 */
 
-		p = b_head(check->bi);
+		p = b_head(&check->bi);
 		while (*p && *p != '\n' && *p != '\r')
 			p++;
 
@@ -977,7 +977,7 @@
 		}
 
 		*p = 0;
-		cmd = b_head(check->bi);
+		cmd = b_head(&check->bi);
 
 		while (*cmd) {
 			/* look for next word */
@@ -1135,15 +1135,15 @@
 	}
 
 	case PR_O2_PGSQL_CHK:
-		if (!done && b_data(check->bi) < 9)
+		if (!done && b_data(&check->bi) < 9)
 			goto wait_more_data;
 
-		if (b_head(check->bi)[0] == 'R') {
+		if (b_head(&check->bi)[0] == 'R') {
 			set_server_check_status(check, HCHK_STATUS_L7OKD, "PostgreSQL server is ok");
 		}
 		else {
-			if ((b_head(check->bi)[0] == 'E') && (b_head(check->bi)[5]!=0) && (b_head(check->bi)[6]!=0))
-				desc = &b_head(check->bi)[6];
+			if ((b_head(&check->bi)[0] == 'E') && (b_head(&check->bi)[5]!=0) && (b_head(&check->bi)[6]!=0))
+				desc = &b_head(&check->bi)[6];
 			else
 				desc = "PostgreSQL unknown error";
 
@@ -1152,29 +1152,29 @@
 		break;
 
 	case PR_O2_REDIS_CHK:
-		if (!done && b_data(check->bi) < 7)
+		if (!done && b_data(&check->bi) < 7)
 			goto wait_more_data;
 
-		if (strcmp(b_head(check->bi), "+PONG\r\n") == 0) {
+		if (strcmp(b_head(&check->bi), "+PONG\r\n") == 0) {
 			set_server_check_status(check, HCHK_STATUS_L7OKD, "Redis server is ok");
 		}
 		else {
-			set_server_check_status(check, HCHK_STATUS_L7STS, b_head(check->bi));
+			set_server_check_status(check, HCHK_STATUS_L7STS, b_head(&check->bi));
 		}
 		break;
 
 	case PR_O2_MYSQL_CHK:
-		if (!done && b_data(check->bi) < 5)
+		if (!done && b_data(&check->bi) < 5)
 			goto wait_more_data;
 
 		if (s->proxy->check_len == 0) { // old mode
-			if (*(b_head(check->bi) + 4) != '\xff') {
+			if (*(b_head(&check->bi) + 4) != '\xff') {
 				/* We set the MySQL Version in description for information purpose
 				 * FIXME : it can be cool to use MySQL Version for other purpose,
 				 * like mark as down old MySQL server.
 				 */
-				if (b_data(check->bi) > 51) {
-					desc = ltrim(b_head(check->bi) + 5, ' ');
+				if (b_data(&check->bi) > 51) {
+					desc = ltrim(b_head(&check->bi) + 5, ' ');
 					set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
 				}
 				else {
@@ -1184,48 +1184,48 @@
 					/* it seems we have a OK packet but without a valid length,
 					 * it must be a protocol error
 					 */
-					set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(check->bi));
+					set_server_check_status(check, HCHK_STATUS_L7RSP, b_head(&check->bi));
 				}
 			}
 			else {
 				/* An error message is attached in the Error packet */
-				desc = ltrim(b_head(check->bi) + 7, ' ');
+				desc = ltrim(b_head(&check->bi) + 7, ' ');
 				set_server_check_status(check, HCHK_STATUS_L7STS, desc);
 			}
 		} else {
-			unsigned int first_packet_len = ((unsigned int) *b_head(check->bi)) +
-			                                (((unsigned int) *(b_head(check->bi) + 1)) << 8) +
-			                                (((unsigned int) *(b_head(check->bi) + 2)) << 16);
+			unsigned int first_packet_len = ((unsigned int) *b_head(&check->bi)) +
+			                                (((unsigned int) *(b_head(&check->bi) + 1)) << 8) +
+			                                (((unsigned int) *(b_head(&check->bi) + 2)) << 16);
 
-			if (b_data(check->bi) == first_packet_len + 4) {
+			if (b_data(&check->bi) == first_packet_len + 4) {
 				/* MySQL Error packet always begin with field_count = 0xff */
-				if (*(b_head(check->bi) + 4) != '\xff') {
+				if (*(b_head(&check->bi) + 4) != '\xff') {
 					/* We have only one MySQL packet and it is a Handshake Initialization packet
 					* but we need to have a second packet to know if it is alright
 					*/
-					if (!done && b_data(check->bi) < first_packet_len + 5)
+					if (!done && b_data(&check->bi) < first_packet_len + 5)
 						goto wait_more_data;
 				}
 				else {
 					/* We have only one packet and it is an Error packet,
 					* an error message is attached, so we can display it
 					*/
-					desc = &b_head(check->bi)[7];
+					desc = &b_head(&check->bi)[7];
 					//ha_warning("onlyoneERR: %s\n", desc);
 					set_server_check_status(check, HCHK_STATUS_L7STS, desc);
 				}
-			} else if (b_data(check->bi) > first_packet_len + 4) {
-				unsigned int second_packet_len = ((unsigned int) *(b_head(check->bi) + first_packet_len + 4)) +
-				                                 (((unsigned int) *(b_head(check->bi) + first_packet_len + 5)) << 8) +
-				                                 (((unsigned int) *(b_head(check->bi) + first_packet_len + 6)) << 16);
+			} else if (b_data(&check->bi) > first_packet_len + 4) {
+				unsigned int second_packet_len = ((unsigned int) *(b_head(&check->bi) + first_packet_len + 4)) +
+				                                 (((unsigned int) *(b_head(&check->bi) + first_packet_len + 5)) << 8) +
+				                                 (((unsigned int) *(b_head(&check->bi) + first_packet_len + 6)) << 16);
 
-				if (b_data(check->bi) == first_packet_len + 4 + second_packet_len + 4 ) {
+				if (b_data(&check->bi) == first_packet_len + 4 + second_packet_len + 4 ) {
 					/* We have 2 packets and that's good */
 					/* Check if the second packet is a MySQL Error packet or not */
-					if (*(b_head(check->bi) + first_packet_len + 8) != '\xff') {
+					if (*(b_head(&check->bi) + first_packet_len + 8) != '\xff') {
 						/* No error packet */
 						/* We set the MySQL Version in description for information purpose */
-						desc = &b_head(check->bi)[5];
+						desc = &b_head(&check->bi)[5];
 						//ha_warning("2packetOK: %s\n", desc);
 						set_server_check_status(check, HCHK_STATUS_L7OKD, desc);
 					}
@@ -1233,7 +1233,7 @@
 						/* An error message is attached in the Error packet
 						* so we can display it ! :)
 						*/
-						desc = &b_head(check->bi)[first_packet_len+11];
+						desc = &b_head(&check->bi)[first_packet_len+11];
 						//ha_warning("2packetERR: %s\n", desc);
 						set_server_check_status(check, HCHK_STATUS_L7STS, desc);
 					}
@@ -1246,7 +1246,7 @@
 				/* it seems we have a Handshake Initialization packet but without a valid length,
 				 * it must be a protocol error
 				 */
-				desc = &b_head(check->bi)[5];
+				desc = &b_head(&check->bi)[5];
 				//ha_warning("protoerr: %s\n", desc);
 				set_server_check_status(check, HCHK_STATUS_L7RSP, desc);
 			}
@@ -1254,7 +1254,7 @@
 		break;
 
 	case PR_O2_LDAP_CHK:
-		if (!done && b_data(check->bi) < 14)
+		if (!done && b_data(&check->bi) < 14)
 			goto wait_more_data;
 
 		/* Check if the server speaks LDAP (ASN.1/BER)
@@ -1265,31 +1265,31 @@
 		/* http://tools.ietf.org/html/rfc4511#section-4.1.1
 		 *   LDAPMessage: 0x30: SEQUENCE
 		 */
-		if ((b_data(check->bi) < 14) || (*(b_head(check->bi)) != '\x30')) {
+		if ((b_data(&check->bi) < 14) || (*(b_head(&check->bi)) != '\x30')) {
 			set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 		}
 		else {
 			 /* size of LDAPMessage */
-			msglen = (*(b_head(check->bi) + 1) & 0x80) ? (*(b_head(check->bi) + 1) & 0x7f) : 0;
+			msglen = (*(b_head(&check->bi) + 1) & 0x80) ? (*(b_head(&check->bi) + 1) & 0x7f) : 0;
 
 			/* http://tools.ietf.org/html/rfc4511#section-4.2.2
 			 *   messageID: 0x02 0x01 0x01: INTEGER 1
 			 *   protocolOp: 0x61: bindResponse
 			 */
 			if ((msglen > 2) ||
-			    (memcmp(b_head(check->bi) + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
+			    (memcmp(b_head(&check->bi) + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
 				set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 				goto out_wakeup;
 			}
 
 			/* size of bindResponse */
-			msglen += (*(b_head(check->bi) + msglen + 6) & 0x80) ? (*(b_head(check->bi) + msglen + 6) & 0x7f) : 0;
+			msglen += (*(b_head(&check->bi) + msglen + 6) & 0x80) ? (*(b_head(&check->bi) + msglen + 6) & 0x7f) : 0;
 
 			/* http://tools.ietf.org/html/rfc4511#section-4.1.9
 			 *   ldapResult: 0x0a 0x01: ENUMERATION
 			 */
 			if ((msglen > 4) ||
-			    (memcmp(b_head(check->bi) + 7 + msglen, "\x0a\x01", 2) != 0)) {
+			    (memcmp(b_head(&check->bi) + 7 + msglen, "\x0a\x01", 2) != 0)) {
 				set_server_check_status(check, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
 				goto out_wakeup;
 			}
@@ -1297,7 +1297,7 @@
 			/* http://tools.ietf.org/html/rfc4511#section-4.1.9
 			 *   resultCode
 			 */
-			check->code = *(b_head(check->bi) + msglen + 9);
+			check->code = *(b_head(&check->bi) + msglen + 9);
 			if (check->code) {
 				set_server_check_status(check, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
 			} else {
@@ -1310,16 +1310,16 @@
 		unsigned int framesz;
 		char	     err[HCHK_DESC_LEN];
 
-		if (!done && b_data(check->bi) < 4)
+		if (!done && b_data(&check->bi) < 4)
 			goto wait_more_data;
 
-		memcpy(&framesz, b_head(check->bi), 4);
+		memcpy(&framesz, b_head(&check->bi), 4);
 		framesz = ntohl(framesz);
 
-		if (!done && b_data(check->bi) < (4+framesz))
+		if (!done && b_data(&check->bi) < (4+framesz))
 		    goto wait_more_data;
 
-		if (!spoe_handle_healthcheck_response(b_head(check->bi)+4, framesz, err, HCHK_DESC_LEN-1))
+		if (!spoe_handle_healthcheck_response(b_head(&check->bi)+4, framesz, err, HCHK_DESC_LEN-1))
 			set_server_check_status(check, HCHK_STATUS_L7OKD, "SPOA server is ok");
 		else
 			set_server_check_status(check, HCHK_STATUS_L7STS, err);
@@ -1337,8 +1337,8 @@
 		chk_report_conn_err(check, 0, 0);
 
 	/* Reset the check buffer... */
-	*b_head(check->bi) = '\0';
-	b_reset(check->bi);
+	*b_head(&check->bi) = '\0';
+	b_reset(&check->bi);
 
 	/* Close the connection... We still attempt to nicely close if,
 	 * for instance, SSL needs to send a "close notify." Later, we perform
@@ -1518,7 +1518,7 @@
 	 * its own strings.
 	 */
 	if (check->type && check->type != PR_O2_TCPCHK_CHK && !(check->state & CHK_ST_AGENT)) {
-		b_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
+		b_putblk(&check->bo, s->proxy->check_req, s->proxy->check_len);
 
 		/* we want to check if this host replies to HTTP or SSLv3 requests
 		 * so we'll send the request, and won't wake the checker up now.
@@ -1526,21 +1526,21 @@
 		if ((check->type) == PR_O2_SSL3_CHK) {
 			/* SSL requires that we put Unix time in the request */
 			int gmt_time = htonl(date.tv_sec);
-			memcpy(b_head(check->bo) + 11, &gmt_time, 4);
+			memcpy(b_head(&check->bo) + 11, &gmt_time, 4);
 		}
 		else if ((check->type) == PR_O2_HTTP_CHK) {
 			if (s->proxy->options2 & PR_O2_CHK_SNDST)
-				b_putblk(check->bo, trash.str, httpchk_build_status_header(s, trash.str, trash.size));
+				b_putblk(&check->bo, trash.str, httpchk_build_status_header(s, trash.str, trash.size));
 			/* prevent HTTP keep-alive when "http-check expect" is used */
 			if (s->proxy->options2 & PR_O2_EXP_TYPE)
-				b_putist(check->bo, ist("Connection: close\r\n"));
-			b_putist(check->bo, ist("\r\n"));
-			*b_tail(check->bo) = '\0'; /* to make gdb output easier to read */
+				b_putist(&check->bo, ist("Connection: close\r\n"));
+			b_putist(&check->bo, ist("\r\n"));
+			*b_tail(&check->bo) = '\0'; /* to make gdb output easier to read */
 		}
 	}
 
 	if ((check->type & PR_O2_LB_AGENT_CHK) && check->send_string_len) {
-		b_putblk(check->bo, check->send_string, check->send_string_len);
+		b_putblk(&check->bo, check->send_string, check->send_string_len);
 	}
 
 	/* for tcp-checks, the initial connection setup is handled separately as
@@ -2129,8 +2129,8 @@
 		set_server_check_status(check, HCHK_STATUS_START, NULL);
 
 		check->state |= CHK_ST_INPROGRESS;
-		b_reset(check->bi);
-		b_reset(check->bo);
+		b_reset(&check->bi);
+		b_reset(&check->bo);
 
 		ret = connect_conn_chk(t);
 		cs = check->cs;
@@ -2424,8 +2424,8 @@
 	switch (s->proxy->options2 & PR_O2_EXP_TYPE) {
 	case PR_O2_EXP_STS:
 	case PR_O2_EXP_RSTS:
-		memcpy(status_code, b_head(s->check.bi) + 9, 3);
-		memcpy(status_msg + strlen(status_msg) - 4, b_head(s->check.bi) + 9, 3);
+		memcpy(status_code, b_head(&s->check.bi) + 9, 3);
+		memcpy(status_msg + strlen(status_msg) - 4, b_head(&s->check.bi) + 9, 3);
 
 		if ((s->proxy->options2 & PR_O2_EXP_TYPE) == PR_O2_EXP_STS)
 			ret = strncmp(s->proxy->expect_str, status_code, 3) == 0;
@@ -2446,7 +2446,7 @@
 		 * to '\0' if crlf < 2.
 		 */
 		crlf = 0;
-		for (contentptr = b_head(s->check.bi); *contentptr; contentptr++) {
+		for (contentptr = b_head(&s->check.bi); *contentptr; contentptr++) {
 			if (crlf >= 2)
 				break;
 			if (*contentptr == '\r')
@@ -2645,8 +2645,8 @@
 	/* no step means first step initialisation */
 	if (check->current_step == NULL) {
 		check->last_started_step = NULL;
-		b_reset(check->bo);
-		b_reset(check->bi);
+		b_reset(&check->bo);
+		b_reset(&check->bi);
 		check->current_step = next;
 		t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
 		if (s->proxy->timeout.check)
@@ -2663,16 +2663,16 @@
 		 * in the remaining space. That explains why we break out of the
 		 * loop after this control. If we have data, conn is valid.
 		 */
-		if (b_data(check->bo) &&
+		if (b_data(&check->bo) &&
 		    (&check->current_step->list == head ||
 		     check->current_step->action != TCPCHK_ACT_SEND ||
-		     check->current_step->string_len >= b_room(check->bo))) {
+		     check->current_step->string_len >= b_room(&check->bo))) {
 			int ret;
 
 			__cs_want_send(cs);
-			ret = conn->mux->snd_buf(cs, check->bo, b_data(check->bo), 0);
-			b_del(check->bo, ret);
-			b_realign_if_empty(check->bo);
+			ret = conn->mux->snd_buf(cs, &check->bo, b_data(&check->bo), 0);
+			b_del(&check->bo, ret);
+			b_realign_if_empty(&check->bo);
 
 			if (ret <= 0) {
 				if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) {
@@ -2845,9 +2845,9 @@
 			check->last_started_step = check->current_step;
 
 			/* reset the read buffer */
-			if (*b_head(check->bi) != '\0') {
-				*b_head(check->bi) = '\0';
-				b_reset(check->bi);
+			if (*b_head(&check->bi) != '\0') {
+				*b_head(&check->bi) = '\0';
+				b_reset(&check->bi);
 			}
 
 			if (conn->flags & CO_FL_SOCK_WR_SH) {
@@ -2856,20 +2856,20 @@
 				goto out_end_tcpcheck;
 			}
 
-			if (check->current_step->string_len >= check->bo->size) {
+			if (check->current_step->string_len >= b_size(&check->bo)) {
 				chunk_printf(&trash, "tcp-check send : string too large (%d) for buffer size (%u) at step %d",
-					     check->current_step->string_len, (unsigned int)check->bo->size,
+					     check->current_step->string_len, (unsigned int)b_size(&check->bo),
 					     tcpcheck_get_step_id(check));
 				set_server_check_status(check, HCHK_STATUS_L7RSP, trash.str);
 				goto out_end_tcpcheck;
 			}
 
 			/* do not try to send if there is no space */
-			if (check->current_step->string_len >= b_room(check->bo))
+			if (check->current_step->string_len >= b_room(&check->bo))
 				continue;
 
-			b_putblk(check->bo, check->current_step->string, check->current_step->string_len);
-			*b_tail(check->bo) = '\0'; /* to make gdb output easier to read */
+			b_putblk(&check->bo, check->current_step->string, check->current_step->string_len);
+			*b_tail(&check->bo) = '\0'; /* to make gdb output easier to read */
 
 			/* go to next rule and try to send */
 			check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
@@ -2885,10 +2885,10 @@
 				goto out_end_tcpcheck;
 
 			__cs_want_recv(cs);
-			if (conn->mux->rcv_buf(cs, check->bi, check->bi->size, 0) <= 0) {
+			if (conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0) <= 0) {
 				if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) {
 					done = 1;
-					if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(check->bi)) {
+					if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) {
 						/* Report network errors only if we got no other data. Otherwise
 						 * we'll let the upper layers decide whether the response is OK
 						 * or not. It is very common that an RST sent by the server is
@@ -2907,20 +2907,20 @@
 
 
 			/* Intermediate or complete response received.
-			 * Terminate string in b_head(check->bi) buffer.
+			 * Terminate string in b_head(&check->bi) buffer.
 			 */
-			if (b_data(check->bi) < check->bi->size) {
-				b_head(check->bi)[b_data(check->bi)] = '\0';
+			if (b_data(&check->bi) < b_size(&check->bi)) {
+				b_head(&check->bi)[b_data(&check->bi)] = '\0';
 			}
 			else {
-				b_head(check->bi)[b_data(check->bi) - 1] = '\0';
+				b_head(&check->bi)[b_data(&check->bi) - 1] = '\0';
 				done = 1; /* buffer full, don't wait for more data */
 			}
 
-			contentptr = b_head(check->bi);
+			contentptr = b_head(&check->bi);
 
 			/* Check that response body is not empty... */
-			if (!b_data(check->bi)) {
+			if (!b_data(&check->bi)) {
 				if (!done)
 					continue;
 
@@ -2935,12 +2935,12 @@
 				goto out_end_tcpcheck;
 			}
 
-			if (!done && (check->current_step->string != NULL) && (b_data(check->bi) < check->current_step->string_len) )
+			if (!done && (check->current_step->string != NULL) && (b_data(&check->bi) < check->current_step->string_len) )
 				continue; /* try to read more */
 
 		tcpcheck_expect:
 			if (check->current_step->string != NULL)
-				ret = my_memmem(contentptr, b_data(check->bi), check->current_step->string, check->current_step->string_len) != NULL;
+				ret = my_memmem(contentptr, b_data(&check->bi), check->current_step->string, check->current_step->string_len) != NULL;
 			else if (check->current_step->expect_regex != NULL)
 				ret = regex_exec(check->current_step->expect_regex, contentptr);
 
@@ -3048,13 +3048,13 @@
 	/* We're waiting for some I/O to complete, we've reached the end of the
 	 * rules, or both. Do what we have to do, otherwise we're done.
 	 */
-	if (&check->current_step->list == head && !b_data(check->bo)) {
+	if (&check->current_step->list == head && !b_data(&check->bo)) {
 		set_server_check_status(check, HCHK_STATUS_L7OKD, "(tcp-check)");
 		goto out_end_tcpcheck;
 	}
 
 	/* warning, current_step may now point to the head */
-	if (b_data(check->bo))
+	if (b_data(&check->bo))
 		__cs_want_send(cs);
 
 	if (&check->current_step->list != head &&
@@ -3083,26 +3083,22 @@
 {
 	check->type = type;
 
-	/* Allocate buffer for requests... */
-	if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
-		return "out of memory while allocating check buffer";
-	}
-	check->bi->size = global.tune.chksize;
+	b_reset(&check->bi); check->bi.size = global.tune.chksize;
+	b_reset(&check->bo); check->bo.size = global.tune.chksize;
 
-	/* Allocate buffer for responses... */
-	if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
+	check->bi.area = calloc(check->bi.size, sizeof(char));
+	check->bo.area = calloc(check->bo.size, sizeof(char));
+
+	if (!check->bi.area || !check->bo.area)
 		return "out of memory while allocating check buffer";
-	}
-	check->bo->size = global.tune.chksize;
+
 	return NULL;
 }
 
 void free_check(struct check *check)
 {
-	free(check->bi);
-	check->bi = NULL;
-	free(check->bo);
-	check->bo = NULL;
+	free(check->bi.area);
+	free(check->bo.area);
 	if (check->cs) {
 		free(check->cs->conn);
 		check->cs->conn = NULL;
diff --git a/src/cli.c b/src/cli.c
index c656e4b..0bc4722 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -524,7 +524,7 @@
 		goto out;
 
 	/* Check if the input buffer is avalaible. */
-	if (res->buf->size == 0) {
+	if (res->buf.size == 0) {
 		si_applet_cant_put(si);
 		goto out;
 	}
diff --git a/src/compression.c b/src/compression.c
index eb74661..3e98402 100644
--- a/src/compression.c
+++ b/src/compression.c
@@ -172,7 +172,7 @@
 #if defined(USE_SLZ)
 	(*comp_ctx)->direct_ptr = NULL;
 	(*comp_ctx)->direct_len = 0;
-	(*comp_ctx)->queued = NULL;
+	(*comp_ctx)->queued = BUF_NULL;
 #elif defined(USE_ZLIB)
 	HA_ATOMIC_ADD(&zlib_used_memory, sizeof(struct comp_ctx));
 
@@ -291,34 +291,34 @@
  */
 static int rfc195x_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
 {
-	static THREAD_LOCAL struct buffer *tmpbuf = &buf_empty;
+	static THREAD_LOCAL struct buffer tmpbuf = BUF_NULL;
 
 	if (in_len <= 0)
 		return 0;
 
-	if (comp_ctx->direct_ptr && !comp_ctx->queued) {
+	if (comp_ctx->direct_ptr && b_is_null(&comp_ctx->queued)) {
 		/* data already being pointed to, we're in front of fragmented
 		 * data and need a buffer now. We reuse the same buffer, as it's
 		 * not used out of the scope of a series of add_data()*, end().
 		 */
-		if (unlikely(!tmpbuf->size)) {
+		if (unlikely(!tmpbuf.size)) {
 			/* this is the first time we need the compression buffer */
 			if (b_alloc(&tmpbuf) == NULL)
 				return -1; /* no memory */
 		}
-		b_reset(tmpbuf);
-		memcpy(b_tail(tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
-		b_add(tmpbuf, comp_ctx->direct_len);
+		b_reset(&tmpbuf);
+		memcpy(b_tail(&tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
+		b_add(&tmpbuf, comp_ctx->direct_len);
 		comp_ctx->direct_ptr = NULL;
 		comp_ctx->direct_len = 0;
 		comp_ctx->queued = tmpbuf;
 		/* fall through buffer copy */
 	}
 
-	if (comp_ctx->queued) {
+	if (!b_is_null(&comp_ctx->queued)) {
 		/* data already pending */
-		memcpy(b_tail(comp_ctx->queued), in_data, in_len);
-		b_add(comp_ctx->queued, in_len);
+		memcpy(b_tail(&comp_ctx->queued), in_data, in_len);
+		b_add(&comp_ctx->queued, in_len);
 		return in_len;
 	}
 
@@ -342,9 +342,9 @@
 	in_ptr = comp_ctx->direct_ptr;
 	in_len = comp_ctx->direct_len;
 
-	if (comp_ctx->queued) {
-		in_ptr = b_head(comp_ctx->queued);
-		in_len = b_data(comp_ctx->queued);
+	if (!b_is_null(&comp_ctx->queued)) {
+		in_ptr = b_head(&comp_ctx->queued);
+		in_len = b_data(&comp_ctx->queued);
 	}
 
 	out_len = b_data(out);
@@ -360,7 +360,7 @@
 	/* very important, we must wipe the data we've just flushed */
 	comp_ctx->direct_len = 0;
 	comp_ctx->direct_ptr = NULL;
-	comp_ctx->queued     = NULL;
+	comp_ctx->queued     = BUF_NULL;
 
 	/* Verify compression rate limiting and CPU usage */
 	if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) ||    /* rate */
diff --git a/src/filters.c b/src/filters.c
index 03534f7..a4005ed 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -569,7 +569,7 @@
 			/* And set this value as the bound for the next
 			 * filter. It will not able to parse more data than this
 			 * one. */
-			b_set_data(msg->chn->buf, co_data(msg->chn) + *nxt);
+			b_set_data(&msg->chn->buf, co_data(msg->chn) + *nxt);
 		}
 		else {
 			/* Consume all available data and update the next offset
@@ -580,7 +580,7 @@
 	}
 
 	/* Restore the original buffer state */
-	b_set_data(msg->chn->buf, co_data(msg->chn) + buf_i + delta);
+	b_set_data(&msg->chn->buf, co_data(msg->chn) + buf_i + delta);
 
 	return ret;
 }
@@ -981,7 +981,7 @@
 			/* And set this value as the bound for the next
 			 * filter. It will not able to parse more data than the
 			 * current one. */
-			b_set_data(chn->buf, co_data(chn) + *nxt);
+			b_set_data(&chn->buf, co_data(chn) + *nxt);
 		}
 		else {
 			/* Consume all available data */
@@ -995,7 +995,7 @@
 	}
 
 	/* Restore the original buffer state */
-	b_set_data(chn->buf, co_data(chn) + buf_i + delta);
+	b_set_data(&chn->buf, co_data(chn) + buf_i + delta);
 
 	return ret;
 }
diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
index f54feb2..86d0866 100644
--- a/src/flt_http_comp.c
+++ b/src/flt_http_comp.c
@@ -36,8 +36,8 @@
 /* Pools used to allocate comp_state structs */
 static struct pool_head *pool_head_comp_state = NULL;
 
-static THREAD_LOCAL struct buffer *tmpbuf = &buf_empty;
-static THREAD_LOCAL struct buffer *zbuf   = &buf_empty;
+static THREAD_LOCAL struct buffer tmpbuf;
+static THREAD_LOCAL struct buffer zbuf;
 static THREAD_LOCAL unsigned int buf_output;
 
 struct comp_state {
@@ -63,16 +63,16 @@
 					    int in_out,
 					    struct buffer *out, int sz);
 static int http_compression_buffer_end(struct comp_state *st, struct stream *s,
-				       struct channel *chn, struct buffer **out,
+				       struct channel *chn, struct buffer *out,
 				       unsigned int *out_len, int end);
 
 /***********************************************************************/
 static int
 comp_flt_init_per_thread(struct proxy *px, struct flt_conf *fconf)
 {
-	if (!tmpbuf->size && b_alloc(&tmpbuf) == NULL)
+	if (!tmpbuf.size && b_alloc(&tmpbuf) == NULL)
 		return -1;
-	if (!zbuf->size && b_alloc(&zbuf) == NULL)
+	if (!zbuf.size && b_alloc(&zbuf) == NULL)
 		return -1;
 	return 0;
 }
@@ -80,9 +80,9 @@
 static void
 comp_flt_deinit_per_thread(struct proxy *px, struct flt_conf *fconf)
 {
-	if (tmpbuf->size)
+	if (tmpbuf.size)
 		b_free(&tmpbuf);
-	if (zbuf->size)
+	if (zbuf.size)
 		b_free(&zbuf);
 }
 
@@ -191,9 +191,9 @@
 	if (!st->initialized) {
 		unsigned int fwd = flt_rsp_fwd(filter) + st->hdrs_len;
 
-		b_reset(tmpbuf);
+		b_reset(&tmpbuf);
 		c_adv(chn, fwd);
-		ret = http_compression_buffer_init(chn, zbuf, &buf_output);
+		ret = http_compression_buffer_init(chn, &zbuf, &buf_output);
 		c_rew(chn, fwd);
 		if (ret < 0) {
 			msg->chn->flags |= CF_WAKE_WRITE;
@@ -204,21 +204,21 @@
 	if (msg->flags & HTTP_MSGF_TE_CHNK) {
 		int block;
 
-		len = MIN(b_room(tmpbuf), len);
+		len = MIN(b_room(&tmpbuf), len);
 
 		c_adv(chn, *nxt);
 		block = ci_contig_data(chn);
-		memcpy(b_tail(tmpbuf), ci_head(chn), block);
+		memcpy(b_tail(&tmpbuf), ci_head(chn), block);
 		if (len > block)
-			memcpy(b_tail(tmpbuf)+block, b_orig(chn->buf), len-block);
+			memcpy(b_tail(&tmpbuf)+block, b_orig(&chn->buf), len-block);
 		c_rew(chn, *nxt);
 
-		b_add(tmpbuf, len);
+		b_add(&tmpbuf, len);
 		ret        = len;
 	}
 	else {
 		c_adv(chn, *nxt);
-		ret = http_compression_buffer_add_data(st, chn->buf, co_data(chn), zbuf, len);
+		ret = http_compression_buffer_add_data(st, &chn->buf, co_data(chn), &zbuf, len);
 		c_rew(chn, *nxt);
 		if (ret < 0)
 			return ret;
@@ -242,9 +242,9 @@
 			struct channel *chn = msg->chn;
 			unsigned int   fwd = flt_rsp_fwd(filter) + st->hdrs_len;
 
-			b_reset(tmpbuf);
+			b_reset(&tmpbuf);
 			c_adv(chn, fwd);
-			http_compression_buffer_init(chn, zbuf, &buf_output);
+			http_compression_buffer_init(chn, &zbuf, &buf_output);
 			c_rew(chn, fwd);
 			st->initialized = 1;
 		}
@@ -298,11 +298,11 @@
 	}
 
 	if (msg->flags & HTTP_MSGF_TE_CHNK) {
-		ret = http_compression_buffer_add_data(st, tmpbuf, 0,
-		    zbuf, b_data(tmpbuf));
-		if (ret != b_data(tmpbuf)) {
+		ret = http_compression_buffer_add_data(st, &tmpbuf, 0,
+		    &zbuf, b_data(&tmpbuf));
+		if (ret != b_data(&tmpbuf)) {
 			ha_warning("HTTP compression failed: Must consume %u bytes but only %d bytes consumed\n",
-				   (unsigned int)b_data(tmpbuf), ret);
+				   (unsigned int)b_data(&tmpbuf), ret);
 			return -1;
 		}
 	}
@@ -668,10 +668,10 @@
  */
 static int
 http_compression_buffer_end(struct comp_state *st, struct stream *s,
-			    struct channel *chn, struct buffer **out,
+			    struct channel *chn, struct buffer *out,
 			    unsigned int *buf_out, int end)
 {
-	struct buffer *ob = *out;
+	struct buffer tmp_buf;
 	char *tail;
 	int   to_forward, left;
 	unsigned int tmp_out;
@@ -681,22 +681,22 @@
 
 	/* flush data here */
 	if (end)
-		ret = st->comp_algo->finish(st->comp_ctx, ob); /* end of data */
+		ret = st->comp_algo->finish(st->comp_ctx, out); /* end of data */
 	else
-		ret = st->comp_algo->flush(st->comp_ctx, ob); /* end of buffer */
+		ret = st->comp_algo->flush(st->comp_ctx, out); /* end of buffer */
 
 	if (ret < 0)
 		return -1; /* flush failed */
 
 #endif /* USE_ZLIB */
-	if (b_data(ob) == 0) {
+	if (b_data(out) == 0) {
 		/* No data were appended, let's drop the output buffer and
 		 * keep the input buffer unchanged.
 		 */
 		return 0;
 	}
 
-	/* OK so at this stage, we have an output buffer <ob> looking like this :
+	/* OK so at this stage, we have an output buffer <out> looking like this :
 	 *
 	 *        <-- o --> <------ i ----->
 	 *       +---------+---+------------+-----------+
@@ -705,7 +705,7 @@
 	 *     data        p                           size
 	 *
 	 * <out> is the room reserved to copy the channel output. It starts at
-	 * ob->area and has not yet been filled. <c> is the room reserved to
+	 * out->area and has not yet been filled. <c> is the room reserved to
 	 * write the chunk size (10 bytes). <comp_in> is the compressed
 	 * equivalent of the data part of ib->len. <empty> is the amount of
 	 * empty bytes at the end of  the buffer, into which we may have to
@@ -714,28 +714,28 @@
 	 */
 
 	/* Write real size at the begining of the chunk, no need of wrapping.
-	 * We write the chunk using a dynamic length and adjust ob->p and ob->i
+	 * We write the chunk using a dynamic length and adjust out->p and out->i
 	 * accordingly afterwards. That will move <out> away from <data>.
 	 */
-	left = http_emit_chunk_size(b_head(ob), b_data(ob));
-	b_add(ob, left);
-	ob->head -= *buf_out + (left);
-	/* Copy previous data from chn into ob */
+	left = http_emit_chunk_size(b_head(out), b_data(out));
+	b_add(out, left);
+	out->head -= *buf_out + (left);
+	/* Copy previous data from chn into out */
 	if (co_data(chn) > 0) {
-		left = b_contig_data(chn->buf, 0);
+		left = b_contig_data(&chn->buf, 0);
 		if (left > *buf_out)
 			left = *buf_out;
 
-		memcpy(b_head(ob), co_head(chn), left);
-		b_add(ob, left);
+		memcpy(b_head(out), co_head(chn), left);
+		b_add(out, left);
 		if (co_data(chn) - left) {/* second part of the buffer */
-			memcpy(b_head(ob) + left, b_orig(chn->buf), co_data(chn) - left);
-			b_add(ob, co_data(chn) - left);
+			memcpy(b_head(out) + left, b_orig(&chn->buf), co_data(chn) - left);
+			b_add(out, co_data(chn) - left);
 		}
 	}
 
 	/* chunked encoding requires CRLF after data */
-	tail = b_tail(ob);
+	tail = b_tail(out);
 	*tail++ = '\r';
 	*tail++ = '\n';
 
@@ -757,8 +757,8 @@
 		}
 	}
 
-	b_add(ob, tail - b_tail(ob));
-	to_forward = b_data(ob) - *buf_out;
+	b_add(out, tail - b_tail(out));
+	to_forward = b_data(out) - *buf_out;
 
 	/* update input rate */
 	if (st->comp_ctx && st->comp_ctx->cur_lvl > 0) {
@@ -772,18 +772,20 @@
 
 	/* copy the remaining data in the tmp buffer. */
 	c_adv(chn, st->consumed);
-	if (b_data(chn->buf) - co_data(chn) > 0) {
+	if (b_data(&chn->buf) - co_data(chn) > 0) {
 		left = ci_contig_data(chn);
-		memcpy(b_tail(ob), ci_head(chn), left);
-		b_add(ob, left);
-		if (b_data(chn->buf) - (co_data(chn) + left)) {
-			memcpy(b_tail(ob), b_orig(chn->buf), b_data(chn->buf) - left);
-			b_add(ob, b_data(chn->buf) - left);
+		memcpy(b_tail(out), ci_head(chn), left);
+		b_add(out, left);
+		if (b_data(&chn->buf) - (co_data(chn) + left)) {
+			memcpy(b_tail(out), b_orig(&chn->buf), b_data(&chn->buf) - left);
+			b_add(out, b_data(&chn->buf) - left);
 		}
 	}
 	/* swap the buffers */
-	*out = chn->buf;
-	chn->buf = ob;
+	tmp_buf = chn->buf;
+	chn->buf = *out;
+	*out = tmp_buf;
+
 	tmp_out = chn->output;
 	chn->output = *buf_out;
 	*buf_out = tmp_out;
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index 2a4f05e..b0f25fa 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -105,8 +105,8 @@
 struct flt_ops spoe_ops;
 
 static int  spoe_queue_context(struct spoe_context *ctx);
-static int  spoe_acquire_buffer(struct buffer **buf, struct buffer_wait *buffer_wait);
-static void spoe_release_buffer(struct buffer **buf, struct buffer_wait *buffer_wait);
+static int  spoe_acquire_buffer(struct buffer *buf, struct buffer_wait *buffer_wait);
+static void spoe_release_buffer(struct buffer *buf, struct buffer_wait *buffer_wait);
 
 /********************************************************************
  * helper functions/globals
@@ -573,10 +573,10 @@
 		goto too_big;
 
 	/* Copy encoded messages, if possible */
-	sz = b_data(ctx->buffer);
+	sz = b_data(&ctx->buffer);
 	if (p + sz >= end)
 		goto too_big;
-	memcpy(p, b_head(ctx->buffer), sz);
+	memcpy(p, b_head(&ctx->buffer), sz);
 	p += sz;
 
 	return (p - frame);
@@ -633,10 +633,10 @@
 		goto end;
 
 	/* Copy encoded messages, if possible */
-	sz = b_data(ctx->buffer);
+	sz = b_data(&ctx->buffer);
 	if (p + sz >= end)
 		goto too_big;
-	memcpy(p, b_head(ctx->buffer), sz);
+	memcpy(p, b_head(&ctx->buffer), sz);
 	p += sz;
 
   end:
@@ -1044,13 +1044,13 @@
 
 	/* Copy encoded actions */
 	len = (end - p);
-	memcpy(b_head(SPOE_APPCTX(appctx)->buffer), p, len);
-	b_set_data(SPOE_APPCTX(appctx)->buffer, len);
+	memcpy(b_head(&SPOE_APPCTX(appctx)->buffer), p, len);
+	b_set_data(&SPOE_APPCTX(appctx)->buffer, len);
 	p += len;
 
 	/* Transfer the buffer ownership to the SPOE context */
 	(*ctx)->buffer = SPOE_APPCTX(appctx)->buffer;
-	SPOE_APPCTX(appctx)->buffer = &buf_empty;
+	SPOE_APPCTX(appctx)->buffer = BUF_NULL;
 
 	(*ctx)->state = SPOE_CTX_ST_DONE;
 
@@ -1154,7 +1154,7 @@
 	memcpy(buf, (char *)&netint, 4);
 	ret = ci_putblk(si_ic(si), buf, framesz+4);
 	if (ret <= 0) {
-		if ((ret == -3 && si_ic(si)->buf == &buf_empty) || ret == -1) {
+		if ((ret == -3 && b_is_null(&si_ic(si)->buf)) || ret == -1) {
 			si_applet_cant_put(si);
 			return 1; /* retry */
 		}
@@ -1976,7 +1976,7 @@
 	SPOE_APPCTX(appctx)->max_frame_size  = conf->agent->max_frame_size;
 	SPOE_APPCTX(appctx)->flags           = 0;
 	SPOE_APPCTX(appctx)->status_code     = SPOE_FRM_ERR_NONE;
-	SPOE_APPCTX(appctx)->buffer          = &buf_empty;
+	SPOE_APPCTX(appctx)->buffer          = BUF_NULL;
 	SPOE_APPCTX(appctx)->cur_fpa         = 0;
 
 	LIST_INIT(&SPOE_APPCTX(appctx)->buffer_wait.list);
@@ -2212,7 +2212,7 @@
 	struct spoe_message *msg;
 	char   *p, *end;
 
-	p   = b_head(ctx->buffer);
+	p   = b_head(&ctx->buffer);
 	end =  p + agent->rt[tid].frame_size - FRAME_HDR_SIZE;
 
 	if (type == SPOE_MSGS_BY_EVENT) { /* Loop on messages by event */
@@ -2254,7 +2254,7 @@
 
 
 	/* nothing has been encoded for an unfragmented payload */
-	if (!(ctx->flags & SPOE_CTX_FL_FRAGMENTED) && p == b_head(ctx->buffer))
+	if (!(ctx->flags & SPOE_CTX_FL_FRAGMENTED) && p == b_head(&ctx->buffer))
 		goto skip;
 
 	SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p"
@@ -2266,7 +2266,7 @@
 		    ctx->spoe_appctx, (agent->rt[tid].frame_size - FRAME_HDR_SIZE),
 		    p - ctx->buffer->p);
 
-	b_set_data(ctx->buffer, p - b_head(ctx->buffer));
+	b_set_data(&ctx->buffer, p - b_head(&ctx->buffer));
 	ctx->frag_ctx.curmsg = NULL;
 	ctx->frag_ctx.curarg = NULL;
 	ctx->frag_ctx.curoff = 0;
@@ -2287,9 +2287,9 @@
 		    (int)now.tv_sec, (int)now.tv_usec,
 		    agent->id, __FUNCTION__, s, ctx->spoe_appctx,
 		    ctx->frag_ctx.curmsg, ctx->frag_ctx.curarg, ctx->frag_ctx.curoff,
-		    (agent->rt[tid].frame_size - FRAME_HDR_SIZE), p - b_head(ctx->buffer));
+		    (agent->rt[tid].frame_size - FRAME_HDR_SIZE), p - b_head(&ctx->buffer));
 
-	b_set_data(ctx->buffer, p - b_head(ctx->buffer));
+	b_set_data(&ctx->buffer, p - b_head(&ctx->buffer));
 	ctx->flags |= SPOE_CTX_FL_FRAGMENTED;
 	ctx->frag_ctx.flags &= ~SPOE_FRM_FL_FIN;
 	return 1;
@@ -2445,8 +2445,8 @@
 	char *p, *end;
 	int   ret;
 
-	p   = b_head(ctx->buffer);
-	end = p + b_data(ctx->buffer);
+	p   = b_head(&ctx->buffer);
+	end = p + b_data(&ctx->buffer);
 
 	while (p < end)  {
 		enum spoe_action_type type;
@@ -2809,9 +2809,9 @@
  * Functions that create/destroy SPOE contexts
  **************************************************************************/
 static int
-spoe_acquire_buffer(struct buffer **buf, struct buffer_wait *buffer_wait)
+spoe_acquire_buffer(struct buffer *buf, struct buffer_wait *buffer_wait)
 {
-	if ((*buf)->size)
+	if (buf->size)
 		return 1;
 
 	if (!LIST_ISEMPTY(&buffer_wait->list)) {
@@ -2831,7 +2831,7 @@
 }
 
 static void
-spoe_release_buffer(struct buffer **buf, struct buffer_wait *buffer_wait)
+spoe_release_buffer(struct buffer *buf, struct buffer_wait *buffer_wait)
 {
 	if (!LIST_ISEMPTY(&buffer_wait->list)) {
 		HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
@@ -2841,7 +2841,7 @@
 	}
 
 	/* Release the buffer if needed */
-	if ((*buf)->size) {
+	if (buf->size) {
 		b_free(buf);
 		offer_buffers(buffer_wait->target, tasks_run_queue);
 	}
@@ -2871,7 +2871,7 @@
 	ctx->flags       = 0;
 	ctx->events      = conf->agent->events;
 	ctx->groups      = &conf->agent->groups;
-	ctx->buffer      = &buf_empty;
+	ctx->buffer      = BUF_NULL;
 	LIST_INIT(&ctx->buffer_wait.list);
 	ctx->buffer_wait.target = ctx;
 	ctx->buffer_wait.wakeup_cb = (int (*)(void *))spoe_wakeup_context;
diff --git a/src/flt_trace.c b/src/flt_trace.c
index 0115129..5d24a41 100644
--- a/src/flt_trace.c
+++ b/src/flt_trace.c
@@ -466,7 +466,7 @@
 
 	if (conf->hexdump) {
 		c_adv(msg->chn, FLT_FWD(filter, msg->chn));
-		trace_hexdump(msg->chn->buf, ret, co_data(msg->chn));
+		trace_hexdump(&msg->chn->buf, ret, co_data(msg->chn));
 		c_rew(msg->chn, FLT_FWD(filter, msg->chn));
 	}
 
@@ -516,7 +516,7 @@
 
 	if (conf->hexdump) {
 		c_adv(chn, FLT_FWD(filter, chn));
-		trace_hexdump(chn->buf, ret, co_data(chn));
+		trace_hexdump(&chn->buf, ret, co_data(chn));
 		c_rew(chn, FLT_FWD(filter, chn));
 	}
 
diff --git a/src/h1.c b/src/h1.c
index 7e19679..0d41d0b 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -461,7 +461,7 @@
 	struct buffer *buf;
 
 	state = msg->msg_state;
-	buf = msg->chn->buf;
+	buf = &msg->chn->buf;
 	ptr = input + msg->next;
 	end = b_stop(buf);
 
@@ -1276,7 +1276,7 @@
  */
 int http_forward_trailers(struct http_msg *msg)
 {
-	const struct buffer *buf = msg->chn->buf;
+	const struct buffer *buf = &msg->chn->buf;
 	const char *parse = ci_head(msg->chn);
 	const char *stop  = b_tail(buf);
 
diff --git a/src/haproxy.c b/src/haproxy.c
index e19d89a..768034a 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2204,10 +2204,10 @@
 
 			free(s->id);
 			free(s->cookie);
-			free(s->check.bi);
-			free(s->check.bo);
-			free(s->agent.bi);
-			free(s->agent.bo);
+			free(s->check.bi.area);
+			free(s->check.bo.area);
+			free(s->agent.bi.area);
+			free(s->agent.bo.area);
 			free(s->agent.send_string);
 			free(s->hostname_dn);
 			free((char*)s->conf.file);
diff --git a/src/hlua.c b/src/hlua.c
index 3fd4d15..32cb66d 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -2019,13 +2019,13 @@
 	/* Check if the buffer is avalaible because HAProxy doesn't allocate
 	 * the request buffer if its not required.
 	 */
-	if (s->req.buf->size == 0) {
+	if (s->req.buf.size == 0) {
 		if (!channel_alloc_buffer(&s->req, &appctx->buffer_wait))
 			goto hlua_socket_write_yield_return;
 	}
 
 	/* Check for avalaible space. */
-	len = b_room(s->req.buf);
+	len = b_room(&s->req.buf);
 	if (len <= 0) {
 		goto hlua_socket_write_yield_return;
 	}
@@ -2840,7 +2840,7 @@
 	if (unlikely(ret == -1))
 		return 1;
 
-	b_sub(chn->buf, ret);
+	b_sub(&chn->buf, ret);
 	hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
 	return 1;
 }
@@ -2888,7 +2888,7 @@
 		len += len2;
 	}
 	luaL_pushresult(&b);
-	b_rep_blk(chn->buf, ci_head(chn), ci_head(chn) + len,  NULL, 0);
+	b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn) + len,  NULL, 0);
 	hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
 	return 1;
 }
@@ -2920,12 +2920,12 @@
 	/* Check if the buffer is avalaible because HAProxy doesn't allocate
 	 * the request buffer if its not required.
 	 */
-	if (chn->buf->size == 0) {
+	if (chn->buf.size == 0) {
 		si_applet_cant_put(chn_prod(chn));
 		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
 	}
 
-	max = channel_recv_limit(chn) - b_data(chn->buf);
+	max = channel_recv_limit(chn) - b_data(&chn->buf);
 	if (max > len - l)
 		max = len - l;
 
@@ -2943,7 +2943,7 @@
 	lua_pushinteger(L, l);
 	hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
 
-	max = channel_recv_limit(chn) - b_data(chn->buf);
+	max = channel_recv_limit(chn) - b_data(&chn->buf);
 	if (max == 0 && co_data(chn) == 0) {
 		/* There are no space avalaible, and the output buffer is empty.
 		 * in this case, we cannot add more data, so we cannot yield,
@@ -2987,7 +2987,7 @@
 	chn = MAY_LJMP(hlua_checkchannel(L, 1));
 	lua_pushinteger(L, 0);
 
-	b_set_data(chn->buf, co_data(chn));
+	b_set_data(&chn->buf, co_data(chn));
 
 	return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
 }
@@ -3014,7 +3014,7 @@
 	/* Check if the buffer is avalaible because HAProxy doesn't allocate
 	 * the request buffer if its not required.
 	 */
-	if (chn->buf->size == 0) {
+	if (chn->buf.size == 0) {
 		si_applet_cant_put(chn_prod(chn));
 		WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
 	}
@@ -3024,7 +3024,7 @@
 	 * The reserve is guaranted for the processing of incoming
 	 * data, because the buffer will be flushed.
 	 */
-	max = b_room(chn->buf);
+	max = b_room(&chn->buf);
 
 	/* If there are no space avalaible, and the output buffer is empty.
 	 * in this case, we cannot add more data, so we cannot yield,
@@ -3044,7 +3044,7 @@
 		channel_slow_realign(chn, trash.str);
 
 	/* Copy input data in the buffer. */
-	max = b_rep_blk(chn->buf, ci_head(chn), ci_head(chn), str + l, max);
+	max = b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn), str + l, max);
 
 	/* buffer replace considers that the input part is filled.
 	 * so, I must forward these new data in the output part.
@@ -3059,7 +3059,7 @@
 	 * in this case, we cannot add more data, so we cannot yield,
 	 * we return the amount of copyied data.
 	 */
-	max = b_room(chn->buf);
+	max = b_room(&chn->buf);
 	if (max == 0 && co_data(chn) == 0)
 		return 1;
 
@@ -3177,7 +3177,7 @@
 	MAY_LJMP(check_args(L, 1, "is_full"));
 	chn = MAY_LJMP(hlua_checkchannel(L, 1));
 
-	rem = b_room(chn->buf);
+	rem = b_room(&chn->buf);
 	rem -= global.tune.maxrewrite; /* Rewrite reserved size */
 
 	lua_pushboolean(L, rem <= 0);
@@ -5405,7 +5405,7 @@
 
 	if (htxn->s->txn) {
 		/* HTTP mode, let's stay in sync with the stream */
-		b_del(ic->buf, htxn->s->txn->req.sov);
+		b_del(&ic->buf, htxn->s->txn->req.sov);
 		htxn->s->txn->req.next -= htxn->s->txn->req.sov;
 		htxn->s->txn->req.sov = 0;
 		ic->analysers &= AN_REQ_HTTP_XFER_BODY;
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 8bb6c6c..35c7865 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -90,7 +90,7 @@
 
 	/* states for the demux direction */
 	struct hpack_dht *ddht; /* demux dynamic header table */
-	struct buffer *dbuf;    /* demux buffer */
+	struct buffer dbuf;    /* demux buffer */
 
 	int32_t dsi; /* demux stream ID (<0 = idle) */
 	int32_t dfl; /* demux frame length (if dsi >= 0) */
@@ -101,7 +101,7 @@
 	int32_t last_sid; /* last processed stream ID for GOAWAY, <0 before preface */
 
 	/* states for the mux direction */
-	struct buffer *mbuf;    /* mux buffer */
+	struct buffer mbuf;    /* mux buffer */
 	int32_t msi; /* mux stream ID (<0 = idle) */
 	int32_t mfl; /* mux frame length (if dsi >= 0) */
 	int8_t  mft; /* mux frame type   (if dsi >= 0) */
@@ -239,7 +239,7 @@
  */
 static inline int h2_recv_allowed(const struct h2c *h2c)
 {
-	if (b_data(h2c->dbuf) == 0 &&
+	if (b_data(&h2c->dbuf) == 0 &&
 	    (h2c->st0 >= H2_CS_ERROR ||
 	     h2c->conn->flags & CO_FL_ERROR ||
 	     conn_xprt_read0_pending(h2c->conn)))
@@ -289,7 +289,7 @@
 	return 0;
 }
 
-static inline struct buffer *h2_get_buf(struct h2c *h2c, struct buffer **bptr)
+static inline struct buffer *h2_get_buf(struct h2c *h2c, struct buffer *bptr)
 {
 	struct buffer *buf = NULL;
 
@@ -305,9 +305,9 @@
 	return buf;
 }
 
-static inline void h2_release_buf(struct h2c *h2c, struct buffer **bptr)
+static inline void h2_release_buf(struct h2c *h2c, struct buffer *bptr)
 {
-	if ((*bptr)->size) {
+	if (bptr->size) {
 		b_free(bptr);
 		offer_buffers(h2c->buf_wait.target, tasks_run_queue);
 	}
@@ -361,12 +361,12 @@
 	h2c->nb_streams = 0;
 	h2c->nb_cs = 0;
 
-	h2c->dbuf = &buf_empty;
+	h2c->dbuf = BUF_NULL;
 	h2c->dsi = -1;
 	h2c->msi = -1;
 	h2c->last_sid = -1;
 
-	h2c->mbuf = &buf_empty;
+	h2c->mbuf = BUF_NULL;
 	h2c->miw = 65535; /* mux initial window size */
 	h2c->mws = 65535; /* mux window size */
 	h2c->mfs = 16384; /* initial max frame size */
@@ -752,7 +752,7 @@
 	int ret1;
 	int ret2;
 
-	ret1 = b_isteq(h2c->dbuf, 0, b_data(h2c->dbuf), ist(H2_CONN_PREFACE));
+	ret1 = b_isteq(&h2c->dbuf, 0, b_data(&h2c->dbuf), ist(H2_CONN_PREFACE));
 
 	if (unlikely(ret1 <= 0)) {
 		if (ret1 < 0 || conn_xprt_read0_pending(h2c->conn))
@@ -762,7 +762,7 @@
 
 	ret2 = h2c_snd_settings(h2c);
 	if (ret2 > 0)
-		b_del(h2c->dbuf, ret1);
+		b_del(&h2c->dbuf, ret1);
 
 	return ret2;
 }
@@ -1109,13 +1109,13 @@
 	}
 
 	/* process full frame only */
-	if (b_data(h2c->dbuf) < h2c->dfl)
+	if (b_data(&h2c->dbuf) < h2c->dfl)
 		return 0;
 
 	/* parse the frame */
 	for (offset = 0; offset < h2c->dfl; offset += 6) {
-		uint16_t type = h2_get_n16(h2c->dbuf, offset);
-		int32_t  arg  = h2_get_n32(h2c->dbuf, offset + 2);
+		uint16_t type = h2_get_n16(&h2c->dbuf, offset);
+		int32_t  arg  = h2_get_n32(&h2c->dbuf, offset + 2);
 
 		switch (type) {
 		case H2_SETTINGS_INITIAL_WINDOW_SIZE:
@@ -1302,7 +1302,7 @@
 	char str[17];
 	int ret = -1;
 
-	if (b_data(h2c->dbuf) < 8)
+	if (b_data(&h2c->dbuf) < 8)
 		return 0;
 
 	if (h2c_mux_busy(h2c, NULL)) {
@@ -1323,7 +1323,7 @@
 	       "\x00\x00\x00\x00" /* stream ID */, 9);
 
 	/* copy the original payload */
-	h2_get_buf_bytes(str + 9, 8, h2c->dbuf, 0);
+	h2_get_buf_bytes(str + 9, 8, &h2c->dbuf, 0);
 
 	ret = b_istput(res, ist2(str, 17));
 	if (unlikely(ret <= 0)) {
@@ -1355,10 +1355,10 @@
 	}
 
 	/* process full frame only */
-	if (b_data(h2c->dbuf) < h2c->dfl)
+	if (b_data(&h2c->dbuf) < h2c->dfl)
 		return 0;
 
-	inc = h2_get_n32(h2c->dbuf, 0);
+	inc = h2_get_n32(&h2c->dbuf, 0);
 
 	if (h2c->dsi != 0) {
 		/* stream window update */
@@ -1441,11 +1441,11 @@
 	}
 
 	/* process full frame only */
-	if (b_data(h2c->dbuf) < h2c->dfl)
+	if (b_data(&h2c->dbuf) < h2c->dfl)
 		return 0;
 
-	last = h2_get_n32(h2c->dbuf, 0);
-	h2c->errcode = h2_get_n32(h2c->dbuf, 4);
+	last = h2_get_n32(&h2c->dbuf, 0);
+	h2c->errcode = h2_get_n32(&h2c->dbuf, 4);
 	h2_wake_some_streams(h2c, last, CS_FL_ERROR);
 	if (h2c->last_sid < 0)
 		h2c->last_sid = last;
@@ -1475,10 +1475,10 @@
 	}
 
 	/* process full frame only */
-	if (b_data(h2c->dbuf) < h2c->dfl)
+	if (b_data(&h2c->dbuf) < h2c->dfl)
 		return 0;
 
-	if (h2_get_n32(h2c->dbuf, 0) == h2c->dsi) {
+	if (h2_get_n32(&h2c->dbuf, 0) == h2c->dsi) {
 		/* 7540#5.3 : can't depend on itself */
 		error = H2_ERR_PROTOCOL_ERROR;
 		goto conn_err;
@@ -1509,14 +1509,14 @@
 	}
 
 	/* process full frame only */
-	if (b_data(h2c->dbuf) < h2c->dfl)
+	if (b_data(&h2c->dbuf) < h2c->dfl)
 		return 0;
 
 	/* late RST, already handled */
 	if (h2s->st == H2_SS_CLOSED)
 		return 1;
 
-	h2s->errcode = h2_get_n32(h2c->dbuf, 0);
+	h2s->errcode = h2_get_n32(&h2c->dbuf, 0);
 	h2s_close(h2s);
 
 	if (h2s->cs) {
@@ -1550,10 +1550,10 @@
 		goto strm_err;
 	}
 
-	if (!b_size(h2c->dbuf))
+	if (!b_size(&h2c->dbuf))
 		return 0; // empty buffer
 
-	if (b_data(h2c->dbuf) < h2c->dfl && !b_full(h2c->dbuf))
+	if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
 		return 0; // incomplete frame
 
 	if (h2c->flags & H2_CF_DEM_TOOMANY)
@@ -1636,10 +1636,10 @@
 	 * to signal an end of stream (with the ES flag).
 	 */
 
-	if (!b_size(h2c->dbuf) && h2c->dfl)
+	if (!b_size(&h2c->dbuf) && h2c->dfl)
 		return 0; // empty buffer
 
-	if (b_data(h2c->dbuf) < h2c->dfl && !b_full(h2c->dbuf))
+	if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
 		return 0; // incomplete frame
 
 	/* now either the frame is complete or the buffer is complete */
@@ -1736,7 +1736,7 @@
 			/* ensure that what is pending is a valid SETTINGS frame
 			 * without an ACK.
 			 */
-			if (!h2_get_frame_hdr(h2c->dbuf, &hdr)) {
+			if (!h2_get_frame_hdr(&h2c->dbuf, &hdr)) {
 				/* RFC7540#3.5: a GOAWAY frame MAY be omitted */
 				if (h2c->st0 == H2_CS_ERROR)
 					h2c->st0 = H2_CS_ERROR2;
@@ -1768,7 +1768,7 @@
 	}
 
 	/* process as many incoming frames as possible below */
-	while (b_data(h2c->dbuf)) {
+	while (b_data(&h2c->dbuf)) {
 		int ret = 0;
 
 		if (h2c->st0 >= H2_CS_ERROR)
@@ -1777,7 +1777,7 @@
 		if (h2c->st0 == H2_CS_FRAME_H) {
 			struct h2_fh hdr;
 
-			if (!h2_peek_frame_hdr(h2c->dbuf, &hdr))
+			if (!h2_peek_frame_hdr(&h2c->dbuf, &hdr))
 				break;
 
 			if ((int)hdr.len < 0 || (int)hdr.len > global.tune.bufsize) {
@@ -1792,7 +1792,7 @@
 			h2c->dff = hdr.ff;
 			h2c->dpl = 0;
 			h2c->st0 = H2_CS_FRAME_P;
-			h2_skip_frame_hdr(h2c->dbuf);
+			h2_skip_frame_hdr(&h2c->dbuf);
 		}
 
 		/* Only H2_CS_FRAME_P and H2_CS_FRAME_A here */
@@ -1900,8 +1900,8 @@
 		 * the one advertised in GOAWAY. RFC7540#6.8.
 		 */
 		if (unlikely(h2c->last_sid >= 0) && h2c->dsi > h2c->last_sid) {
-			ret = MIN(b_data(h2c->dbuf), h2c->dfl);
-			b_del(h2c->dbuf, ret);
+			ret = MIN(b_data(&h2c->dbuf), h2c->dfl);
+			b_del(&h2c->dbuf, ret);
 			h2c->dfl -= ret;
 			ret = h2c->dfl == 0;
 			goto strm_err;
@@ -1980,8 +1980,8 @@
 			 * the buffer so we drain all of their contents until
 			 * we reach the end.
 			 */
-			ret = MIN(b_data(h2c->dbuf), h2c->dfl);
-			b_del(h2c->dbuf, ret);
+			ret = MIN(b_data(&h2c->dbuf), h2c->dfl);
+			b_del(&h2c->dbuf, ret);
 			h2c->dfl -= ret;
 			ret = h2c->dfl == 0;
 		}
@@ -1999,7 +1999,7 @@
 			break;
 
 		if (h2c->st0 != H2_CS_FRAME_H) {
-			b_del(h2c->dbuf, h2c->dfl);
+			b_del(&h2c->dbuf, h2c->dfl);
 			h2c->st0 = H2_CS_FRAME_H;
 		}
 	}
@@ -2212,12 +2212,12 @@
 		if (h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MBUSY | H2_CF_DEM_MROOM))
 			flags |= CO_SFL_MSG_MORE;
 
-		if (b_data(h2c->mbuf)) {
-			int ret = conn->xprt->snd_buf(conn, h2c->mbuf, b_data(h2c->mbuf), flags);
+		if (b_data(&h2c->mbuf)) {
+			int ret = conn->xprt->snd_buf(conn, &h2c->mbuf, b_data(&h2c->mbuf), flags);
 			if (!ret)
 				break;
-			b_del(h2c->mbuf, ret);
-			b_realign_if_empty(h2c->mbuf);
+			b_del(&h2c->mbuf, ret);
+			b_realign_if_empty(&h2c->mbuf);
 		}
 
 		/* wrote at least one byte, the buffer is not full anymore */
@@ -2226,7 +2226,7 @@
 
 	if (conn->flags & CO_FL_SOCK_WR_SH) {
 		/* output closed, nothing to send, clear the buffer to release it */
-		b_reset(h2c->mbuf);
+		b_reset(&h2c->mbuf);
 	}
 }
 
@@ -2239,13 +2239,13 @@
 	struct h2c *h2c = conn->mux_ctx;
 	struct session *sess = conn->owner;
 
-	if (b_data(h2c->dbuf) && !(h2c->flags & H2_CF_DEM_BLOCK_ANY)) {
+	if (b_data(&h2c->dbuf) && !(h2c->flags & H2_CF_DEM_BLOCK_ANY)) {
 		h2_process_demux(h2c);
 
 		if (h2c->st0 >= H2_CS_ERROR || conn->flags & CO_FL_ERROR)
-			b_reset(h2c->dbuf);
+			b_reset(&h2c->dbuf);
 
-		if (!b_full(h2c->dbuf))
+		if (!b_full(&h2c->dbuf))
 			h2c->flags &= ~H2_CF_DEM_DFULL;
 	}
 
@@ -2302,7 +2302,7 @@
 		}
 	}
 
-	if (!b_data(h2c->dbuf))
+	if (!b_data(&h2c->dbuf))
 		h2_release_buf(h2c, &h2c->dbuf);
 
 	/* stop being notified of incoming data if we can't process them */
@@ -2316,7 +2316,7 @@
 	/* adjust output polling */
 	if (!(conn->flags & CO_FL_SOCK_WR_SH) &&
 	    (h2c->st0 == H2_CS_ERROR ||
-	     b_data(h2c->mbuf) ||
+	     b_data(&h2c->mbuf) ||
 	     (h2c->mws > 0 && !LIST_ISEMPTY(&h2c->fctl_list)) ||
 	     (!(h2c->flags & H2_CF_MUX_BLOCK_ANY) && !LIST_ISEMPTY(&h2c->send_list)))) {
 		__conn_xprt_want_send(conn);
@@ -2327,7 +2327,7 @@
 	}
 
 	if (h2c->task) {
-		if (eb_is_empty(&h2c->streams_by_id) || b_data(h2c->mbuf)) {
+		if (eb_is_empty(&h2c->streams_by_id) || b_data(&h2c->mbuf)) {
 			h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout);
 			task_queue(h2c->task);
 		}
@@ -2363,7 +2363,7 @@
 	h2c_error(h2c, H2_ERR_NO_ERROR);
 	h2_wake_some_streams(h2c, 0, 0);
 
-	if (b_data(h2c->mbuf)) {
+	if (b_data(&h2c->mbuf)) {
 		/* don't even try to send a GOAWAY, the buffer is stuck */
 		h2c->flags |= H2_CF_GOAWAY_FAILED;
 	}
@@ -2373,11 +2373,11 @@
 	if (h2c_send_goaway_error(h2c, NULL) <= 0)
 		h2c->flags |= H2_CF_GOAWAY_FAILED;
 
-	if (b_data(h2c->mbuf) && !(h2c->flags & H2_CF_GOAWAY_FAILED) && conn_xprt_ready(h2c->conn)) {
-		int ret = h2c->conn->xprt->snd_buf(h2c->conn, h2c->mbuf, b_data(h2c->mbuf), 0);
+	if (b_data(&h2c->mbuf) && !(h2c->flags & H2_CF_GOAWAY_FAILED) && conn_xprt_ready(h2c->conn)) {
+		int ret = h2c->conn->xprt->snd_buf(h2c->conn, &h2c->mbuf, b_data(&h2c->mbuf), 0);
 		if (ret > 0) {
-			b_del(h2c->mbuf, ret);
-			b_realign_if_empty(h2c->mbuf);
+			b_del(&h2c->mbuf, ret);
+			b_realign_if_empty(&h2c->mbuf);
 		}
 	}
 
@@ -2436,7 +2436,7 @@
 	if (cs->flags & CS_FL_DATA_WR_ENA) {
 		if (LIST_ISEMPTY(&h2s->list)) {
 			if (LIST_ISEMPTY(&h2s->h2c->send_list) &&
-			    !b_data(h2s->h2c->mbuf) && // not yet subscribed
+			    !b_data(&h2s->h2c->mbuf) && // not yet subscribed
 			    !(cs->conn->flags & CO_FL_SOCK_WR_SH))
 				conn_xprt_want_send(cs->conn);
 			LIST_ADDQ(&h2s->h2c->send_list, &h2s->list);
@@ -2449,7 +2449,7 @@
 	}
 
 	/* this can happen from within si_chk_snd() */
-	if (b_data(h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
+	if (b_data(&h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
 		conn_xprt_want_send(cs->conn);
 }
 
@@ -2506,14 +2506,14 @@
 	    ((h2c->conn->flags & CO_FL_ERROR) ||    /* errors close immediately */
 	     (h2c->st0 >= H2_CS_ERROR && !h2c->task) || /* a timeout stroke earlier */
 	     (h2c->flags & H2_CF_GOAWAY_FAILED) ||
-	     (!b_data(h2c->mbuf) &&  /* mux buffer empty, also process clean events below */
+	     (!b_data(&h2c->mbuf) &&  /* mux buffer empty, also process clean events below */
 	      (conn_xprt_read0_pending(h2c->conn) ||
 	       (h2c->last_sid >= 0 && h2c->max_id >= h2c->last_sid))))) {
 		/* no more stream will come, kill it now */
 		h2_release(h2c->conn);
 	}
 	else if (h2c->task) {
-		if (eb_is_empty(&h2c->streams_by_id) || b_data(h2c->mbuf)) {
+		if (eb_is_empty(&h2c->streams_by_id) || b_data(&h2c->mbuf)) {
 			h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout);
 			task_queue(h2c->task);
 		}
@@ -2546,7 +2546,7 @@
 	    h2c_send_goaway_error(h2s->h2c, h2s) <= 0)
 		goto add_to_list;
 
-	if (b_data(h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
+	if (b_data(&h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
 		conn_xprt_want_send(cs->conn);
 
 	h2s_close(h2s);
@@ -2596,7 +2596,7 @@
 		h2s_close(h2s);
 	}
 
-	if (b_data(h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
+	if (b_data(&h2s->h2c->mbuf) && !(cs->conn->flags & CO_FL_XPRT_WR_ENA))
 		conn_xprt_want_send(cs->conn);
 
  add_to_list:
@@ -2616,7 +2616,7 @@
 static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count, int flags)
 {
 	struct h2c *h2c = h2s->h2c;
-	const uint8_t *hdrs = (uint8_t *)b_head(h2c->dbuf);
+	const uint8_t *hdrs = (uint8_t *)b_head(&h2c->dbuf);
 	struct chunk *tmp = get_trash_chunk();
 	struct http_hdr list[MAX_HTTP_HDR * 2];
 	struct chunk *copy = NULL;
@@ -2632,19 +2632,19 @@
 		return 0;
 	}
 
-	if (b_data(h2c->dbuf) < h2c->dfl && !b_full(h2c->dbuf))
+	if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
 		return 0; // incomplete input frame
 
 	/* if the input buffer wraps, take a temporary copy of it (rare) */
-	wrap = b_wrap(h2c->dbuf) - b_head(h2c->dbuf);
+	wrap = b_wrap(&h2c->dbuf) - b_head(&h2c->dbuf);
 	if (wrap < h2c->dfl) {
 		copy = alloc_trash_chunk();
 		if (!copy) {
 			h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
 			goto fail;
 		}
-		memcpy(copy->str, b_head(h2c->dbuf), wrap);
-		memcpy(copy->str + wrap, b_orig(h2c->dbuf), h2c->dfl - wrap);
+		memcpy(copy->str, b_head(&h2c->dbuf), wrap);
+		memcpy(copy->str + wrap, b_orig(&h2c->dbuf), h2c->dfl - wrap);
 		hdrs = (uint8_t *)copy->str;
 	}
 
@@ -2734,7 +2734,7 @@
 	}
 
 	/* now consume the input data */
-	b_del(h2c->dbuf, h2c->dfl);
+	b_del(&h2c->dbuf, h2c->dfl);
 	h2c->st0 = H2_CS_FRAME_H;
 	b_add(buf, outlen);
 
@@ -2783,10 +2783,10 @@
 	 * after data. padlen+data+padding are included in flen.
 	 */
 	if (h2c->dff & H2_F_DATA_PADDED) {
-		if (b_data(h2c->dbuf) < 1)
+		if (b_data(&h2c->dbuf) < 1)
 			return 0;
 
-		h2c->dpl = *(uint8_t *)b_head(h2c->dbuf);
+		h2c->dpl = *(uint8_t *)b_head(&h2c->dbuf);
 		if (h2c->dpl >= h2c->dfl) {
 			/* RFC7540#6.1 : pad length = length of frame payload or greater */
 			h2c_error(h2c, H2_ERR_PROTOCOL_ERROR);
@@ -2794,7 +2794,7 @@
 		}
 
 		/* skip the padlen byte */
-		b_del(h2c->dbuf, 1);
+		b_del(&h2c->dbuf, 1);
 		h2c->dfl--;
 		h2c->rcvd_c++; h2c->rcvd_s++;
 		h2c->dff &= ~H2_F_DATA_PADDED;
@@ -2804,8 +2804,8 @@
 	if (!flen)
 		goto end_transfer;
 
-	if (flen > b_data(h2c->dbuf)) {
-		flen = b_data(h2c->dbuf);
+	if (flen > b_data(&h2c->dbuf)) {
+		flen = b_data(&h2c->dbuf);
 		if (!flen)
 			return 0;
 	}
@@ -2844,16 +2844,16 @@
 	/* Block1 is the length of the first block before the buffer wraps,
 	 * block2 is the optional second block to reach the end of the frame.
 	 */
-	block1 = b_contig_data(h2c->dbuf, 0);
+	block1 = b_contig_data(&h2c->dbuf, 0);
 	if (block1 > flen)
 		block1 = flen;
 	block2 = flen - block1;
 
 	if (block1)
-		b_putblk(buf, b_head(h2c->dbuf), block1);
+		b_putblk(buf, b_head(&h2c->dbuf), block1);
 
 	if (block2)
-		b_putblk(buf, b_peek(h2c->dbuf, block1), block2);
+		b_putblk(buf, b_peek(&h2c->dbuf, block1), block2);
 
 	if (h2s->flags & H2_SF_DATA_CHNK) {
 		/* emit the CRLF */
@@ -2863,7 +2863,7 @@
 	/* now mark the input data as consumed (will be deleted from the buffer
 	 * by the caller when seeing FRAME_A after sending the window update).
 	 */
-	b_del(h2c->dbuf, flen);
+	b_del(&h2c->dbuf, flen);
 	h2c->dfl    -= flen;
 	h2c->rcvd_c += flen;
 	h2c->rcvd_s += flen;  // warning, this can also affect the closed streams!
@@ -2926,7 +2926,7 @@
 	if (h2c->dsi != h2s->id)
 		return 0; // not for us
 
-	if (!b_size(h2c->dbuf))
+	if (!b_size(&h2c->dbuf))
 		return 0; // empty buffer
 
 	switch (h2c->dft) {
@@ -2994,14 +2994,14 @@
 	chunk_reset(&outbuf);
 
 	while (1) {
-		outbuf.str  = b_tail(h2c->mbuf);
-		outbuf.size = b_contig_space(h2c->mbuf);
+		outbuf.str  = b_tail(&h2c->mbuf);
+		outbuf.size = b_contig_space(&h2c->mbuf);
 		outbuf.len = 0;
 
-		if (outbuf.size >= 9 || !b_space_wraps(h2c->mbuf))
+		if (outbuf.size >= 9 || !b_space_wraps(&h2c->mbuf))
 			break;
 	realign_again:
-		b_slow_realign(h2c->mbuf, trash.str, b_data(h2c->mbuf));
+		b_slow_realign(&h2c->mbuf, trash.str, b_data(&h2c->mbuf));
 	}
 
 	if (outbuf.size < 9) {
@@ -3036,7 +3036,7 @@
 		outbuf.str[outbuf.len++] = list[0].v.ptr[2];
 	}
 	else {
-		if (b_space_wraps(h2c->mbuf))
+		if (b_space_wraps(&h2c->mbuf))
 			goto realign_again;
 
 		h2c->flags |= H2_CF_MUX_MFULL;
@@ -3060,7 +3060,7 @@
 
 		if (!hpack_encode_header(&outbuf, list[hdr].n, list[hdr].v)) {
 			/* output full */
-			if (b_space_wraps(h2c->mbuf))
+			if (b_space_wraps(&h2c->mbuf))
 				goto realign_again;
 
 			h2c->flags |= H2_CF_MUX_MFULL;
@@ -3084,7 +3084,7 @@
 	max -= ret;
 
 	/* commit the H2 response */
-	b_add(h2c->mbuf, outbuf.len);
+	b_add(&h2c->mbuf, outbuf.len);
 	h2s->flags |= H2_SF_HEADERS_SENT;
 
 	/* for now we don't implemented CONTINUATION, so we wait for a
@@ -3151,14 +3151,14 @@
 	chunk_reset(&outbuf);
 
 	while (1) {
-		outbuf.str  = b_tail(h2c->mbuf);
-		outbuf.size = b_contig_space(h2c->mbuf);
+		outbuf.str  = b_tail(&h2c->mbuf);
+		outbuf.size = b_contig_space(&h2c->mbuf);
 		outbuf.len = 0;
 
-		if (outbuf.size >= 9 || !b_space_wraps(h2c->mbuf))
+		if (outbuf.size >= 9 || !b_space_wraps(&h2c->mbuf))
 			break;
 	realign_again:
-		b_slow_realign(h2c->mbuf, trash.str, b_data(h2c->mbuf));
+		b_slow_realign(&h2c->mbuf, trash.str, b_data(&h2c->mbuf));
 	}
 
 	if (outbuf.size < 9) {
@@ -3256,7 +3256,7 @@
 		/* we have an opportunity for enlarging the too small
 		 * available space, let's try.
 		 */
-		if (b_space_wraps(h2c->mbuf))
+		if (b_space_wraps(&h2c->mbuf))
 			goto realign_again;
 		size = outbuf.size - 9;
 	}
@@ -3329,7 +3329,7 @@
 		outbuf.str[4] |= H2_F_DATA_END_STREAM;
 
 	/* commit the H2 response */
-	b_add(h2c->mbuf, size + 9);
+	b_add(&h2c->mbuf, size + 9);
 
 	/* consume incoming H1 response */
 	if (size > 0) {
@@ -3476,7 +3476,7 @@
 	}
 
 	chunk_appendf(msg, " st0=%d flg=0x%08x nbst=%u nbcs=%u fctl_cnt=%d send_cnt=%d tree_cnt=%d orph_cnt=%d dbuf=%u/%u mbuf=%u/%u",
-		      h2c->st0, h2c->flags, h2c->nb_streams, h2c->nb_cs, fctl_cnt, send_cnt, tree_cnt, orph_cnt, (unsigned int)b_data(h2c->dbuf), (unsigned int)b_size(h2c->dbuf), (unsigned int)b_data(h2c->mbuf), (unsigned int)b_size(h2c->mbuf));
+		      h2c->st0, h2c->flags, h2c->nb_streams, h2c->nb_cs, fctl_cnt, send_cnt, tree_cnt, orph_cnt, (unsigned int)b_data(&h2c->dbuf), (unsigned int)b_size(&h2c->dbuf), (unsigned int)b_data(&h2c->mbuf), (unsigned int)b_size(&h2c->mbuf));
 }
 
 /*******************************************************/
diff --git a/src/payload.c b/src/payload.c
index 3aac561..cf5b883 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -466,8 +466,8 @@
 	 * all the part of the request which fits in a buffer is already
 	 * there.
 	 */
-	if (msg_len > channel_recv_limit(req) + b_orig(req->buf) - ci_head(req))
-		msg_len = channel_recv_limit(req) + b_orig(req->buf) - ci_head(req);
+	if (msg_len > channel_recv_limit(req) + b_orig(&req->buf) - ci_head(req))
+		msg_len = channel_recv_limit(req) + b_orig(&req->buf) - ci_head(req);
 
 	if (bleft < msg_len)
 		goto too_short;
@@ -935,10 +935,10 @@
 	while (1) {
 		if (ofs + 12 > ci_data(chn)) {
 			/* not there yet but could it at least fit ? */
-			if (!chn->buf->size)
+			if (!chn->buf.size)
 				goto too_short;
 
-			if (ofs + 12 <= channel_recv_limit(chn) + b_orig(chn->buf) - ci_head(chn))
+			if (ofs + 12 <= channel_recv_limit(chn) + b_orig(&chn->buf) - ci_head(chn))
 				goto too_short;
 
 			goto no_match;
@@ -1011,10 +1011,10 @@
 	ofs = 0; occ = 0;
 	while (1) {
 		if (ofs + 12 > ci_data(chn)) {
-			if (!chn->buf->size)
+			if (!chn->buf.size)
 				goto too_short;
 
-			if (ofs + 12 <= channel_recv_limit(chn) + b_orig(chn->buf) - ci_head(chn))
+			if (ofs + 12 <= channel_recv_limit(chn) + b_orig(&chn->buf) - ci_head(chn))
 				goto too_short;
 
 			goto no_match;
@@ -1048,13 +1048,13 @@
 				smp->data.type = SMP_T_BIN;
 				smp->flags = SMP_F_VOLATILE | SMP_F_CONST;
 
-				if (ofs + body > ci_head(chn) - b_orig(chn->buf) + ci_data(chn)) {
+				if (ofs + body > ci_head(chn) - b_orig(&chn->buf) + ci_data(chn)) {
 					/* incomplete body */
 
-					if (ofs + body > channel_recv_limit(chn) + b_orig(chn->buf) - ci_head(chn)) {
+					if (ofs + body > channel_recv_limit(chn) + b_orig(&chn->buf) - ci_head(chn)) {
 						/* truncate it to whatever will fit */
 						smp->flags |= SMP_F_MAY_CHANGE;
-						body = channel_recv_limit(chn) + b_orig(chn->buf) - ci_head(chn) - ofs;
+						body = channel_recv_limit(chn) + b_orig(&chn->buf) - ci_head(chn) - ofs;
 					}
 				}
 
diff --git a/src/peers.c b/src/peers.c
index 6d5a556..6e549f0 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -576,7 +576,7 @@
 	unsigned int maj_ver, min_ver;
 
 	/* Check if the input buffer is avalaible. */
-	if (si_ic(si)->buf->size == 0)
+	if (si_ic(si)->buf.size == 0)
 		goto full;
 
 	while (1) {
diff --git a/src/proto_http.c b/src/proto_http.c
index 9407542..1d798e6 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -880,7 +880,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 = b_rep_blk(msg->chn->buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
+		delta = b_rep_blk(&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 */
@@ -900,7 +900,7 @@
 	 */
 
 	skip_comma = (ctx->val + ctx->vlen + ctx->tws == hdr->len) ? 0 : 1;
-	delta = b_rep_blk(msg->chn->buf, sol + ctx->del + skip_comma,
+	delta = b_rep_blk(&msg->chn->buf, sol + ctx->del + skip_comma,
 				sol + ctx->val + ctx->vlen + ctx->tws + skip_comma,
 				NULL, 0);
 	hdr->len += delta;
@@ -1103,7 +1103,7 @@
 	c_rew(&s->req, rewind = http_hdr_rewind(&txn->req));
 
 	path = http_get_path(txn);
-	len = b_dist(s->req.buf, path, c_ptr(&s->req, txn->req.sl.rq.u + txn->req.sl.rq.u_l));
+	len = b_dist(&s->req.buf, path, c_ptr(&s->req, txn->req.sl.rq.u + txn->req.sl.rq.u_l));
 
 	c_adv(&s->req, rewind);
 
@@ -1354,7 +1354,7 @@
 		return 0;
 	}
 	/* add HTTP version */
-	delta = b_rep_blk(msg->chn->buf, cur_end, cur_end, " HTTP/1.0\r\n", 11);
+	delta = b_rep_blk(&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,
@@ -1616,7 +1616,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 */
@@ -1643,7 +1643,7 @@
 				return 0;
 			}
 			if (unlikely(ci_tail(req) < c_ptr(req, msg->next) ||
-			             ci_tail(req) > b_wrap(req->buf) - global.tune.maxrewrite))
+			             ci_tail(req) > b_wrap(&req->buf) - global.tune.maxrewrite))
 				channel_slow_realign(req, trash.str);
 		}
 
@@ -1870,7 +1870,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.
@@ -2429,7 +2429,7 @@
 		if (output->len == -1)
 			return -1;
 
-		delta = b_rep_blk(msg->chn->buf, val, val_end, output->str, output->len);
+		delta = b_rep_blk(&msg->chn->buf, val, val_end, output->str, output->len);
 
 		hdr->len += delta;
 		http_msg_move_end(msg, delta);
@@ -3377,7 +3377,7 @@
 		FLT_STRM_CB(s, flt_http_reply(s, txn->status, chunk));
 		co_inject(res->chn, chunk->str, chunk->len);
 		/* "eat" the request */
-		b_del(req->chn->buf, req->sov);
+		b_del(&req->chn->buf, req->sov);
 		req->next -= req->sov;
 		req->sov = 0;
 		s->req.analysers = AN_REQ_HTTP_XFER_BODY | (s->req.analysers & AN_REQ_FLT_END);
@@ -3385,7 +3385,7 @@
 		req->msg_state = HTTP_MSG_CLOSED;
 		res->msg_state = HTTP_MSG_DONE;
 		/* Trim any possible response */
-		b_set_data(res->chn->buf, co_data(res->chn));
+		b_set_data(&res->chn->buf, co_data(res->chn));
 		res->next = res->sov = 0;
 		/* let the server side turn to SI_ST_CLO */
 		channel_shutw_now(req->chn);
@@ -3442,7 +3442,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf->i,
+		req->buf.i,
 		req->analysers);
 
 	/* just in case we have some per-backend tracking */
@@ -3714,7 +3714,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf->i,
+		req->buf.i,
 		req->analysers);
 
 	/*
@@ -3765,7 +3765,7 @@
 			char *cur_end = cur_ptr + txn->req.sl.rq.l;
 			int delta;
 
-			delta = b_rep_blk(req->buf, cur_ptr + msg->sl.rq.u, path, NULL, 0);
+			delta = b_rep_blk(&req->buf, cur_ptr + msg->sl.rq.u, path, NULL, 0);
 			http_msg_move_end(&txn->req, delta);
 			cur_end += delta;
 			if (http_parse_reqline(&txn->req, HTTP_MSG_RQMETH,  cur_ptr, cur_end + 1, NULL, NULL) == NULL)
@@ -3776,7 +3776,7 @@
 			char *cur_end = cur_ptr + txn->req.sl.rq.l;
 			int delta;
 
-			delta = b_rep_blk(req->buf, cur_ptr + msg->sl.rq.u,
+			delta = b_rep_blk(&req->buf, cur_ptr + msg->sl.rq.u,
 						cur_ptr + msg->sl.rq.u + msg->sl.rq.u_l, "/", 1);
 			http_msg_move_end(&txn->req, delta);
 			cur_end += delta;
@@ -4134,14 +4134,14 @@
 		 * TRAILERS state.
 		 */
 		unsigned int chunk;
-		int ret = h1_parse_chunk_size(req->buf, co_data(req) + msg->next, c_data(req), &chunk);
+		int ret = h1_parse_chunk_size(&req->buf, co_data(req) + msg->next, c_data(req), &chunk);
 
 		if (!ret)
 			goto missing_data;
 		else if (ret < 0) {
 			msg->err_pos = ci_data(req) + ret;
 			if (msg->err_pos < 0)
-				msg->err_pos += req->buf->size;
+				msg->err_pos += req->buf.size;
 			stream_inc_http_err_ctr(s);
 			goto return_bad_req;
 		}
@@ -4857,7 +4857,7 @@
 		req,
 		req->rex, req->wex,
 		req->flags,
-		req->buf->i,
+		req->buf.i,
 		req->analysers);
 
 	if (unlikely(msg->msg_state < HTTP_MSG_BODY))
@@ -5130,7 +5130,7 @@
 		}
 
 		if (unlikely(ci_tail(rep) < c_ptr(rep, msg->next) ||
-		             ci_tail(rep) > b_wrap(rep->buf) - global.tune.maxrewrite))
+		             ci_tail(rep) > b_wrap(&rep->buf) - global.tune.maxrewrite))
 			channel_slow_realign(rep, trash.str);
 
 		if (likely(msg->next < ci_data(rep)))
@@ -6072,7 +6072,7 @@
 		res,
 		res->rex, res->wex,
 		res->flags,
-		res->buf->i,
+		res->buf.i,
 		res->analysers);
 
 	if (unlikely(msg->msg_state < HTTP_MSG_BODY))
@@ -6276,7 +6276,7 @@
 	msg->msg_state = HTTP_MSG_ENDING;
 
   ending:
-	/* we may have some pending data starting at res->buf->p such as a last
+	/* we may have some pending data starting at res->buf.p such as a last
 	 * chunk of data or trailers. */
 	ret = FLT_STRM_DATA_CB(s, chn, flt_http_forward_data(s, msg, msg->next),
 			       /* default_ret */ msg->next,
@@ -6297,7 +6297,7 @@
 	return 1;
 
   missing_data_or_waiting:
-	/* we may have some pending data starting at chn->buf->p */
+	/* we may have some pending data starting at chn->buf.p */
 	ret = FLT_STRM_DATA_CB(s, chn, flt_http_forward_data(s, msg, msg->next),
 			       /* default_ret */ msg->next,
 			       /* on_error    */ goto error);
@@ -6345,13 +6345,13 @@
 
 		case HTTP_MSG_CHUNK_CRLF:
 			/* we want the CRLF after the data */
-			ret = h1_skip_chunk_crlf(chn->buf, co_data(chn) + msg->next, c_data(chn));
+			ret = h1_skip_chunk_crlf(&chn->buf, co_data(chn) + msg->next, c_data(chn));
 			if (ret == 0)
 				goto missing_data_or_waiting;
 			if (ret < 0) {
 				msg->err_pos = ci_data(chn) + ret;
 				if (msg->err_pos < 0)
-					msg->err_pos += chn->buf->size;
+					msg->err_pos += chn->buf.size;
 				goto chunk_parsing_error;
 			}
 			msg->next += ret;
@@ -6363,13 +6363,13 @@
 			 * then set ->next to point to the body and switch to
 			 * DATA or TRAILERS state.
 			 */
-			ret = h1_parse_chunk_size(chn->buf, co_data(chn) + msg->next, c_data(chn), &chunk);
+			ret = h1_parse_chunk_size(&chn->buf, co_data(chn) + msg->next, c_data(chn), &chunk);
 			if (ret == 0)
 				goto missing_data_or_waiting;
 			if (ret < 0) {
 				msg->err_pos = ci_data(chn) + ret;
 				if (msg->err_pos < 0)
-					msg->err_pos += chn->buf->size;
+					msg->err_pos += chn->buf.size;
 				goto chunk_parsing_error;
 			}
 
@@ -6407,7 +6407,7 @@
 
 	msg->msg_state = HTTP_MSG_ENDING;
   ending:
-	/* we may have some pending data starting at res->buf->p such as a last
+	/* we may have some pending data starting at res->buf.p such as a last
 	 * chunk of data or trailers. */
 	ret = FLT_STRM_DATA_CB(s, chn, flt_http_forward_data(s, msg, msg->next),
 			  /* default_ret */ msg->next,
@@ -6427,7 +6427,7 @@
 	return 1;
 
   missing_data_or_waiting:
-	/* we may have some pending data starting at chn->buf->p */
+	/* we may have some pending data starting at chn->buf.p */
 	ret = FLT_STRM_DATA_CB(s, chn, flt_http_forward_data(s, msg, msg->next),
 			  /* default_ret */ msg->next,
 			  /* on_error    */ goto error);
@@ -6516,7 +6516,7 @@
 				if (trash.len < 0)
 					return -1;
 
-				delta = b_rep_blk(req->buf, cur_ptr, cur_end, trash.str, trash.len);
+				delta = b_rep_blk(&req->buf, cur_ptr, cur_end, trash.str, 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.
@@ -6529,7 +6529,7 @@
 				break;
 
 			case ACT_REMOVE:
-				delta = b_rep_blk(req->buf, cur_ptr, cur_next, NULL, 0);
+				delta = b_rep_blk(&req->buf, cur_ptr, cur_next, NULL, 0);
 				cur_next += delta;
 
 				http_msg_move_end(&txn->req, delta);
@@ -6604,7 +6604,7 @@
 			if (trash.len < 0)
 				return -1;
 
-			delta = b_rep_blk(req->buf, cur_ptr, cur_end, trash.str, trash.len);
+			delta = b_rep_blk(&req->buf, cur_ptr, cur_end, trash.str, 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.
@@ -6912,7 +6912,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;
@@ -6935,13 +6935,13 @@
 				int stripped_after = 0;
 
 				if (att_end != equal) {
-					stripped_before = b_rep_blk(req->buf, att_end, equal, NULL, 0);
+					stripped_before = b_rep_blk(&req->buf, att_end, equal, NULL, 0);
 					equal   += stripped_before;
 					val_beg += stripped_before;
 				}
 
 				if (val_beg > equal + 1) {
-					stripped_after = b_rep_blk(req->buf, equal + 1, val_beg, NULL, 0);
+					stripped_after = b_rep_blk(&req->buf, equal + 1, val_beg, NULL, 0);
 					val_beg += stripped_after;
 					stripped_before += stripped_after;
 				}
@@ -7122,7 +7122,7 @@
 				if ((s->be->ck_opts & PR_CK_PFX) && (delim != val_end)) {
 					int delta; /* negative */
 
-					delta = b_rep_blk(req->buf, val_beg, delim + 1, NULL, 0);
+					delta = b_rep_blk(&req->buf, val_beg, delim + 1, NULL, 0);
 					val_end  += delta;
 					next     += delta;
 					hdr_end  += delta;
@@ -7145,7 +7145,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)
@@ -7176,11 +7176,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 = b_rep_blk(req->buf, hdr_beg, hdr_next, NULL, 0);
+				delta = b_rep_blk(&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;
@@ -7252,7 +7252,7 @@
 				if (trash.len < 0)
 					return -1;
 
-				delta = b_rep_blk(rtr->buf, cur_ptr, cur_end, trash.str, trash.len);
+				delta = b_rep_blk(&rtr->buf, cur_ptr, cur_end, trash.str, 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.
@@ -7265,7 +7265,7 @@
 				break;
 
 			case ACT_REMOVE:
-				delta = b_rep_blk(rtr->buf, cur_ptr, cur_next, NULL, 0);
+				delta = b_rep_blk(&rtr->buf, cur_ptr, cur_next, NULL, 0);
 				cur_next += delta;
 
 				http_msg_move_end(&txn->rsp, delta);
@@ -7333,7 +7333,7 @@
 			if (trash.len < 0)
 				return -1;
 
-			delta = b_rep_blk(rtr->buf, cur_ptr, cur_end, trash.str, trash.len);
+			delta = b_rep_blk(&rtr->buf, cur_ptr, cur_end, trash.str, 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.
@@ -7588,13 +7588,13 @@
 				int stripped_after = 0;
 
 				if (att_end != equal) {
-					stripped_before = b_rep_blk(res->buf, att_end, equal, NULL, 0);
+					stripped_before = b_rep_blk(&res->buf, att_end, equal, NULL, 0);
 					equal   += stripped_before;
 					val_beg += stripped_before;
 				}
 
 				if (val_beg > equal + 1) {
-					stripped_after = b_rep_blk(res->buf, equal + 1, val_beg, NULL, 0);
+					stripped_after = b_rep_blk(&res->buf, equal + 1, val_beg, NULL, 0);
 					val_beg += stripped_after;
 					stripped_before += stripped_after;
 				}
@@ -7652,7 +7652,7 @@
 					/* this cookie must be deleted */
 					if (*prev == ':' && next == hdr_end) {
 						/* whole header */
-						delta = b_rep_blk(res->buf, hdr_beg, hdr_next, NULL, 0);
+						delta = b_rep_blk(&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;
@@ -7664,7 +7664,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;
@@ -7679,7 +7679,7 @@
 					/* replace bytes val_beg->val_end with the cookie name associated
 					 * with this server since we know it.
 					 */
-					delta = b_rep_blk(res->buf, val_beg, val_end, srv->cookie, srv->cklen);
+					delta = b_rep_blk(&res->buf, val_beg, val_end, srv->cookie, srv->cklen);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
@@ -7693,7 +7693,7 @@
 					/* insert the cookie name associated with this server
 					 * before existing cookie, and insert a delimiter between them..
 					 */
-					delta = b_rep_blk(res->buf, val_beg, val_beg, srv->cookie, srv->cklen + 1);
+					delta = b_rep_blk(&res->buf, val_beg, val_beg, srv->cookie, srv->cklen + 1);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
@@ -7955,7 +7955,7 @@
 
 	HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock);
 	es->len = MIN(ci_data(chn), global.tune.bufsize);
-	len1 = b_wrap(chn->buf) - ci_head(chn);
+	len1 = b_wrap(&chn->buf) - ci_head(chn);
 	len1 = MIN(len1, es->len);
 	len2 = es->len - len1; /* remaining data if buffer wraps */
 
@@ -7965,7 +7965,7 @@
 	if (es->buf) {
 		memcpy(es->buf, ci_head(chn), len1);
 		if (len2)
-			memcpy(es->buf + len1, b_orig(chn->buf), len2);
+			memcpy(es->buf + len1, b_orig(&chn->buf), len2);
 	}
 
 	if (msg->err_pos >= 0)
@@ -7989,7 +7989,7 @@
 	es->t_flags = s->txn->flags;
 	es->m_flags = msg->flags;
 	es->b_out = co_data(chn);
-	es->b_wrap = b_wrap(chn->buf) - ci_head(chn);
+	es->b_wrap = b_wrap(&chn->buf) - ci_head(chn);
 	es->b_tot = chn->total;
 	es->m_clen = msg->chunk_len;
 	es->m_blen = msg->body_len;
@@ -8307,7 +8307,7 @@
 	 * content-length.
 	 */
 	if (unlikely(ci_data(&s->res)))
-		b_set_data(s->res.buf, co_data(&s->res));
+		b_set_data(&s->res.buf, co_data(&s->res));
 
 	/* Now we can realign the response buffer */
 	c_realign_if_empty(&s->res);
@@ -9507,8 +9507,8 @@
 		/* If the buffer does not leave enough free space at the end,
 		 * we must first realign it.
 		 */
-		if (ci_head(&s->req) > b_orig(s->req.buf) &&
-		    ci_head(&s->req) + ci_data(&s->req) > b_wrap(s->req.buf) - global.tune.maxrewrite)
+		if (ci_head(&s->req) > b_orig(&s->req.buf) &&
+		    ci_head(&s->req) + ci_data(&s->req) > b_wrap(&s->req.buf) - global.tune.maxrewrite)
 			channel_slow_realign(&s->req, trash.str);
 
 		if (unlikely(txn->req.msg_state < HTTP_MSG_BODY)) {
@@ -9541,7 +9541,7 @@
 			 * we want this check to be maintained.
 			 */
 			if (unlikely(ci_head(&s->req) + ci_data(&s->req) >
-				     b_wrap(s->req.buf) - global.tune.maxrewrite)) {
+				     b_wrap(&s->req.buf) - global.tune.maxrewrite)) {
 				msg->err_state = msg->msg_state;
 				msg->msg_state = HTTP_MSG_ERROR;
 				smp->data.u.sint = 1;
@@ -9914,8 +9914,8 @@
 	body = c_ptr(msg->chn, -http_data_rewind(msg));
 
 	block1 = len;
-	if (block1 > b_wrap(msg->chn->buf) - body)
-		block1 = b_wrap(msg->chn->buf) - body;
+	if (block1 > b_wrap(&msg->chn->buf) - body)
+		block1 = b_wrap(&msg->chn->buf) - body;
 
 	if (block1 == len) {
 		/* buffer is not wrapped (or empty) */
@@ -9928,7 +9928,7 @@
 		/* buffer is wrapped, we need to defragment it */
 		temp = get_trash_chunk();
 		memcpy(temp->str, body, block1);
-		memcpy(temp->str + block1, b_orig(msg->chn->buf), len - block1);
+		memcpy(temp->str + block1, b_orig(&msg->chn->buf), len - block1);
 		smp->data.type = SMP_T_BIN;
 		smp->data.u.str.str = temp->str;
 		smp->data.u.str.len = len;
@@ -11385,8 +11385,8 @@
 		body = c_ptr(msg->chn, -http_data_rewind(msg));
 
 		block1 = len;
-		if (block1 > b_wrap(msg->chn->buf) - body)
-			block1 = b_wrap(msg->chn->buf) - body;
+		if (block1 > b_wrap(&msg->chn->buf) - body)
+			block1 = b_wrap(&msg->chn->buf) - body;
 
 		if (block1 == len) {
 			/* buffer is not wrapped (or empty) */
@@ -11403,8 +11403,8 @@
 			/* buffer is wrapped, we need to defragment it */
 			smp->ctx.a[0] = body;
 			smp->ctx.a[1] = body + block1;
-			smp->ctx.a[2] = b_orig(msg->chn->buf);
-			smp->ctx.a[3] = b_orig(msg->chn->buf) + ( len - block1 );
+			smp->ctx.a[2] = b_orig(&msg->chn->buf);
+			smp->ctx.a[3] = b_orig(&msg->chn->buf) + ( len - block1 );
 		}
 	}
 	return smp_fetch_param('&', name, name_len, args, smp, kw, private);
@@ -11927,7 +11927,7 @@
 	}
 
 	/* commit changes and adjust end of message */
-	delta = b_rep_blk(s->req.buf, cur_ptr, cur_end, replace + offset, len - offset);
+	delta = b_rep_blk(&s->req.buf, cur_ptr, cur_end, replace + offset, len - offset);
 	txn->req.sl.rq.l += delta;
 	txn->hdr_idx.v[0].len += delta;
 	http_msg_move_end(&txn->req, delta);
@@ -11966,7 +11966,7 @@
 	cur_end = ci_head(&s->res) + txn->rsp.sl.st.r + txn->rsp.sl.st.r_l;
 
 	/* commit changes and adjust message */
-	delta = b_rep_blk(s->res.buf, cur_ptr, cur_end, trash.str, trash.len);
+	delta = b_rep_blk(&s->res.buf, cur_ptr, cur_end, trash.str, trash.len);
 
 	/* adjust res line offsets and lengths */
 	txn->rsp.sl.st.r += c_l - txn->rsp.sl.st.c_l;
diff --git a/src/stats.c b/src/stats.c
index c0c1b35..443024b 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -2045,7 +2045,7 @@
 	case STAT_PX_ST_LI:
 		/* stats.l has been initialized above */
 		for (; appctx->ctx.stats.l != &px->conf.listeners; appctx->ctx.stats.l = l->by_fe.n) {
-			if (buffer_almost_full(rep->buf)) {
+			if (buffer_almost_full(&rep->buf)) {
 				si_applet_cant_put(si);
 				return 0;
 			}
@@ -2078,7 +2078,7 @@
 	case STAT_PX_ST_SV:
 		/* stats.sv has been initialized above */
 		for (; appctx->ctx.stats.sv != NULL; appctx->ctx.stats.sv = sv->next) {
-			if (buffer_almost_full(rep->buf)) {
+			if (buffer_almost_full(&rep->buf)) {
 				si_applet_cant_put(si);
 				return 0;
 			}
@@ -2570,7 +2570,7 @@
 	case STAT_ST_LIST:
 		/* dump proxies */
 		while (appctx->ctx.stats.px) {
-			if (buffer_almost_full(rep->buf)) {
+			if (buffer_almost_full(&rep->buf)) {
 				si_applet_cant_put(si);
 				return 0;
 			}
@@ -3034,7 +3034,7 @@
 		goto out;
 
 	/* Check if the input buffer is avalaible. */
-	if (res->buf->size == 0) {
+	if (res->buf.size == 0) {
 		si_applet_cant_put(si);
 		goto out;
 	}
diff --git a/src/stream.c b/src/stream.c
index cda5d54..d6ba173 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -180,7 +180,8 @@
 	 * when the default backend is assigned.
 	 */
 	s->be  = sess->fe;
-	s->req.buf = s->res.buf = NULL;
+	s->req.buf = BUF_NULL;
+	s->res.buf = BUF_NULL;
 	s->req_cap = NULL;
 	s->res_cap = NULL;
 
@@ -336,7 +337,7 @@
 		LIST_INIT(&s->buffer_wait.list);
 		HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
 	}
-	if (s->req.buf->size || s->res.buf->size) {
+	if (s->req.buf.size || s->res.buf.size) {
 		b_drop(&s->req.buf);
 		b_drop(&s->res.buf);
 		offer_buffers(NULL, tasks_run_queue);
@@ -856,7 +857,7 @@
 		req, &s->res,
 		req->rex, s->res.wex,
 		req->flags, s->res.flags,
-		req->buf->i, req->buf->o, s->res.buf->i, s->res.buf->o, s->si[0].state, s->si[1].state);
+		req->buf->i, req->buf->o, s->res.buf.i, s->res.buf.o, s->si[0].state, s->si[1].state);
 
 	if (si->state == SI_ST_ASS) {
 		/* Server assigned to connection request, we have to try to connect now */
@@ -1051,7 +1052,7 @@
 		&s->req, &s->res,
 		s->req.rex, s->res.wex,
 		s->req.flags, s->res.flags,
-		s->req.buf->i, s->req.buf->o, s->res.buf->i, s->res.buf->o, s->si[0].state, s->si[1].state);
+		s->req.buf.i, s->req.buf.o, s->res.buf.i, s->res.buf.o, s->si[0].state, s->si[1].state);
 
 	if (si->state != SI_ST_REQ)
 		return;
@@ -2978,11 +2979,11 @@
 			     strm->req.wex ?
 			     human_time(TICKS_TO_MS(strm->req.wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
-			     strm->req.buf,
-		             b_orig(strm->req.buf), (unsigned int)co_data(&strm->req),
+			     &strm->req.buf,
+		             b_orig(&strm->req.buf), (unsigned int)co_data(&strm->req),
 			     (unsigned int)ci_head_ofs(&strm->req),
 		             strm->txn ? strm->txn->req.next : 0, (unsigned int)ci_data(&strm->req),
-			     (unsigned int)strm->req.buf->size);
+			     (unsigned int)strm->req.buf.size);
 
 		chunk_appendf(&trash,
 			     "  res=%p (f=0x%06x an=0x%x pipe=%d tofwd=%d total=%lld)\n"
@@ -3007,11 +3008,11 @@
 			     strm->res.wex ?
 			     human_time(TICKS_TO_MS(strm->res.wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
-			     strm->res.buf,
-		             b_orig(strm->res.buf), (unsigned int)co_data(&strm->res),
+			     &strm->res.buf,
+		             b_orig(&strm->res.buf), (unsigned int)co_data(&strm->res),
 		             (unsigned int)ci_head_ofs(&strm->res),
 		             strm->txn ? strm->txn->rsp.next : 0, (unsigned int)ci_data(&strm->res),
-			     (unsigned int)strm->res.buf->size);
+			     (unsigned int)strm->res.buf.size);
 
 		if (ci_putchk(si_ic(si), &trash) == -1) {
 			si_applet_cant_put(si);
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 4b86102..8190108 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -683,7 +683,7 @@
 		if (oc->flags & CF_STREAMER)
 			send_flag |= CO_SFL_STREAMER;
 
-		ret = conn->mux->snd_buf(cs, oc->buf, co_data(oc), send_flag);
+		ret = conn->mux->snd_buf(cs, &oc->buf, co_data(oc), send_flag);
 		if (ret > 0) {
 			oc->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA | CF_WRITE_EVENT;
 
@@ -1189,7 +1189,7 @@
 			break;
 		}
 
-		ret = conn->mux->rcv_buf(cs, ic->buf, max, co_data(ic) ? CO_RFL_BUF_WET : 0);
+		ret = conn->mux->rcv_buf(cs, &ic->buf, max, co_data(ic) ? CO_RFL_BUF_WET : 0);
 		if (cs->flags & CS_FL_RCV_MORE)
 			si->flags |= SI_FL_WAIT_ROOM;
 
@@ -1250,7 +1250,7 @@
 
 	if (cur_read) {
 		if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) &&
-		    (cur_read <= ic->buf->size / 2)) {
+		    (cur_read <= ic->buf.size / 2)) {
 			ic->xfer_large = 0;
 			ic->xfer_small++;
 			if (ic->xfer_small >= 3) {
@@ -1269,7 +1269,7 @@
 			}
 		}
 		else if (!(ic->flags & CF_STREAMER_FAST) &&
-			 (cur_read >= ic->buf->size - global.tune.maxrewrite)) {
+			 (cur_read >= ic->buf.size - global.tune.maxrewrite)) {
 			/* we read a full buffer at once */
 			ic->xfer_small = 0;
 			ic->xfer_large++;