REORG: buffers: split buffers into chunk,buffer,channel

Many parts of the channel definition still make use of the "buffer" word.
diff --git a/Makefile b/Makefile
index 72b8888..73df397 100644
--- a/Makefile
+++ b/Makefile
@@ -540,7 +540,8 @@
 endif
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
-       src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
+       src/uri_auth.o src/standard.o src/buffer.o src/log.o src/task.o \
+       src/chunk.o src/channel.o \
        src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
        src/checks.o src/queue.o src/frontend.o src/proxy.o src/peers.o \
        src/arg.o src/stick_table.o src/proto_uxst.o src/connection.o \
@@ -548,7 +549,7 @@
        src/lb_chash.o src/lb_fwlc.o src/lb_fwrr.o src/lb_map.o src/lb_fas.o \
        src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
        src/session.o src/hdr_idx.o src/ev_select.o src/signal.o \
-       src/acl.o src/sample.o src/memory.o src/freq_ctr.o src/auth.o
+       src/acl.o src/sample.o src/memory.o src/freq_ctr.o src/auth.o \
 
 EBTREE_OBJS = $(EBTREE_DIR)/ebtree.o \
               $(EBTREE_DIR)/eb32tree.o $(EBTREE_DIR)/eb64tree.o \
diff --git a/Makefile.bsd b/Makefile.bsd
index 9fc9b61..ca00c7b 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -106,7 +106,8 @@
 LDFLAGS = -g
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
-       src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
+       src/uri_auth.o src/standard.o src/buffer.o src/log.o src/task.o \
+       src/chunk.o src/channel.o \
        src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
        src/checks.o src/queue.o src/frontend.o src/proxy.o src/proto_uxst.o \
        src/proto_http.o src/raw_sock.o src/appsession.o src/backend.o \
diff --git a/Makefile.osx b/Makefile.osx
index 9469be9..a251c4f 100644
--- a/Makefile.osx
+++ b/Makefile.osx
@@ -103,7 +103,8 @@
 LDFLAGS = -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 -mmacosx-version-min=10.4
 
 OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
-       src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
+       src/uri_auth.o src/standard.o src/buffer.o src/log.o src/task.o \
+       src/chunk.o src/channel.o \
        src/time.o src/fd.o src/pipe.o src/regex.o src/cfgparse.o src/server.o \
        src/checks.o src/queue.o src/frontend.o src/proxy.o src/proto_uxst.o \
        src/proto_http.o src/raw_sock.o src/appsession.o src/backend.o \
diff --git a/include/common/buffer.h b/include/common/buffer.h
new file mode 100644
index 0000000..a51744b
--- /dev/null
+++ b/include/common/buffer.h
@@ -0,0 +1,300 @@
+/*
+ * include/common/buffer.h
+ * Buffer management definitions, macros and inline functions.
+ *
+ * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, version 2.1
+ * exclusively.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _COMMON_BUFFER_H
+#define _COMMON_BUFFER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/config.h>
+
+
+struct buffer {
+	char *p;                        /* buffer's start pointer, separates in and out data */
+	unsigned int size;              /* buffer size in bytes */
+	unsigned int i;                 /* number of input bytes pending for analysis in the buffer */
+	unsigned int o;                 /* number of out bytes the sender can consume from this buffer */
+	char data[0];                   /* <size> bytes */
+};
+
+
+void buffer_dump(FILE *o, struct buffer *b, int from, int to);
+void buffer_slow_realign(struct buffer *buf);
+void buffer_bounce_realign(struct buffer *buf);
+
+/*****************************************************************/
+/* These functions are used to compute various buffer area sizes */
+/*****************************************************************/
+
+/* Returns an absolute pointer for a position relative to the current buffer's
+ * pointer. It is written so that it is optimal when <ofs> is a const. It is
+ * written as a macro instead of an inline function so that the compiler knows
+ * when it can optimize out the sign test on <ofs> when passed an unsigned int.
+ */
+#define b_ptr(b, ofs) \
+	({            \
+		char *__ret = (b)->p + (ofs);                   \
+		if ((ofs) > 0 && __ret >= (b)->data + (b)->size)    \
+			__ret -= (b)->size;                     \
+		else if ((ofs) < 0 && __ret < (b)->data)        \
+			__ret += (b)->size;                     \
+		__ret;                                          \
+	})
+
+/* Returns the start of the input data in a buffer */
+static inline char *bi_ptr(const struct buffer *b)
+{
+	return b->p;
+}
+
+/* Returns the end of the input data in a buffer (pointer to next
+ * insertion point).
+ */
+static inline char *bi_end(const struct buffer *b)
+{
+	char *ret = b->p + b->i;
+
+	if (ret >= b->data + b->size)
+		ret -= b->size;
+	return ret;
+}
+
+/* Returns the amount of input data that can contiguously be read at once */
+static inline int bi_contig_data(const struct buffer *b)
+{
+	int data = b->data + b->size - b->p;
+
+	if (data > b->i)
+		data = b->i;
+	return data;
+}
+
+/* Returns the start of the output data in a buffer */
+static inline char *bo_ptr(const struct buffer *b)
+{
+	char *ret = b->p - b->o;
+
+	if (ret < b->data)
+		ret += b->size;
+	return ret;
+}
+
+/* Returns the end of the output data in a buffer */
+static inline char *bo_end(const struct buffer *b)
+{
+	return b->p;
+}
+
+/* Returns the amount of output data that can contiguously be read at once */
+static inline int bo_contig_data(const struct buffer *b)
+{
+	char *beg = b->p - b->o;
+
+	if (beg < b->data)
+		return b->data - beg;
+	return b->o;
+}
+
+/* Return the buffer's length in bytes by summing the input and the output */
+static inline int buffer_len(const struct buffer *buf)
+{
+	return buf->i + buf->o;
+}
+
+/* Return non-zero only if the buffer is not empty */
+static inline int buffer_not_empty(const struct buffer *buf)
+{
+	return buf->i | buf->o;
+}
+
+/* Return non-zero only if the buffer is empty */
+static inline int buffer_empty(const struct buffer *buf)
+{
+	return !buffer_not_empty(buf);
+}
+
+/* Normalizes a pointer after a subtract */
+static inline char *buffer_wrap_sub(const struct buffer *buf, char *ptr)
+{
+	if (ptr < buf->data)
+		ptr += buf->size;
+	return ptr;
+}
+
+/* Normalizes a pointer after an addition */
+static inline char *buffer_wrap_add(const struct buffer *buf, char *ptr)
+{
+	if (ptr - buf->size >= buf->data)
+		ptr -= buf->size;
+	return ptr;
+}
+
+/* Return the maximum amount of bytes that can be written into the buffer,
+ * including reserved space which may be overwritten.
+ */
+static inline int buffer_total_space(const struct buffer *buf)
+{
+	return buf->size - buffer_len(buf);
+}
+
+/* Returns the number of contiguous bytes between <start> and <start>+<count>,
+ * and enforces a limit on buf->data + buf->size. <start> must be within the
+ * buffer.
+ */
+static inline int buffer_contig_area(const struct buffer *buf, const char *start, int count)
+{
+	if (count > buf->data - start + buf->size)
+		count = buf->data - start + buf->size;
+	return count;
+}
+
+/* Return the amount of bytes that can be written into the buffer at once,
+ * including reserved space which may be overwritten.
+ */
+static inline int buffer_contig_space(const struct buffer *buf)
+{
+	const char *left, *right;
+
+	if (buf->data + buf->o <= buf->p)
+		right = buf->data + buf->size;
+	else
+		right = buf->p + buf->size - buf->o;
+
+	left = buffer_wrap_add(buf, buf->p + buf->i);
+	return right - left;
+}
+
+/* Return the amount of bytes that can be written into the buffer at once,
+ * excluding the amount of reserved space passed in <res>, which is
+ * preserved.
+ */
+static inline int buffer_contig_space_with_res(const struct buffer *buf, int res)
+{
+	/* Proceed differently if the buffer is full, partially used or empty.
+	 * The hard situation is when it's partially used and either data or
+	 * reserved space wraps at the end.
+	 */
+	int spare = buf->size - res;
+
+	if (buffer_len(buf) >= spare)
+		spare = 0;
+	else if (buffer_len(buf)) {
+		spare = buffer_contig_space(buf) - res;
+		if (spare < 0)
+			spare = 0;
+	}
+	return spare;
+}
+
+
+/* Normalizes a pointer which is supposed to be relative to the beginning of a
+ * buffer, so that wrapping is correctly handled. The intent is to use this
+ * when increasing a pointer. Note that the wrapping test is only performed
+ * once, so the original pointer must be between ->data-size and ->data+2*size-1,
+ * otherwise an invalid pointer might be returned.
+ */
+static inline const char *buffer_pointer(const struct buffer *buf, const char *ptr)
+{
+	if (ptr < buf->data)
+		ptr += buf->size;
+	else if (ptr - buf->size >= buf->data)
+		ptr -= buf->size;
+	return ptr;
+}
+
+/* Returns the distance between two pointers, taking into account the ability
+ * to wrap around the buffer's end.
+ */
+static inline int buffer_count(const struct buffer *buf, const char *from, const char *to)
+{
+	int count = to - from;
+	if (count < 0)
+		count += buf->size;
+	return count;
+}
+
+/* returns the amount of pending bytes in the buffer. It is the amount of bytes
+ * that is not scheduled to be sent.
+ */
+static inline int buffer_pending(const struct buffer *buf)
+{
+	return buf->i;
+}
+
+/* Returns the size of the working area which the caller knows ends at <end>.
+ * If <end> equals buf->r (modulo size), then it means that the free area which
+ * follows is part of the working area. Otherwise, the working area stops at
+ * <end>. It always starts at buf->p. The work area includes the
+ * reserved area.
+ */
+static inline int buffer_work_area(const struct buffer *buf, const char *end)
+{
+	end = buffer_pointer(buf, end);
+	if (end == buffer_wrap_add(buf, buf->p + buf->i))
+		/* pointer exactly at end, lets push forwards */
+		end = buffer_wrap_sub(buf, buf->p - buf->o);
+	return buffer_count(buf, buf->p, end);
+}
+
+/* Return 1 if the buffer has less than 1/4 of its capacity free, otherwise 0 */
+static inline int buffer_almost_full(const struct buffer *buf)
+{
+	if (buffer_total_space(buf) < buf->size / 4)
+		return 1;
+	return 0;
+}
+
+/* Cut the first <n> pending bytes in a contiguous buffer. It is illegal to
+ * call this function with remaining data waiting to be sent (o > 0). The
+ * caller must ensure that <n> is smaller than the actual buffer's length.
+ * This is mainly used to remove empty lines at the beginning of a request
+ * or a response.
+ */
+static inline void bi_fast_delete(struct buffer *buf, int n)
+{
+	buf->i -= n;
+	buf->p += n;
+}
+
+/*
+ * Tries to realign the given buffer, and returns how many bytes can be written
+ * there at once without overwriting anything.
+ */
+static inline int buffer_realign(struct buffer *buf)
+{
+	if (!(buf->i | buf->o)) {
+		/* let's realign the buffer to optimize I/O */
+		buf->p = buf->data;
+	}
+	return buffer_contig_space(buf);
+}
+
+
+#endif /* _COMMON_BUFFER_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/include/common/chunk.h b/include/common/chunk.h
new file mode 100644
index 0000000..75eb030
--- /dev/null
+++ b/include/common/chunk.h
@@ -0,0 +1,131 @@
+/*
+ * include/common/chunk.h
+ * Chunk management definitions, macros and inline functions.
+ *
+ * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, version 2.1
+ * exclusively.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _TYPES_CHUNK_H
+#define _TYPES_CHUNK_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/config.h>
+
+
+/* describes a chunk of string */
+struct chunk {
+	char *str;	/* beginning of the string itself. Might not be 0-terminated */
+	int size;	/* total size of the buffer, 0 if the *str is read-only */
+	int len;	/* current size of the string from first to last char. <0 = uninit. */
+};
+
+/* function prototypes */
+
+int chunk_printf(struct chunk *chk, const char *fmt, ...)
+	__attribute__ ((format(printf, 2, 3)));
+
+int chunk_htmlencode(struct chunk *dst, struct chunk *src);
+int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc);
+
+static inline void chunk_init(struct chunk *chk, char *str, size_t size)
+{
+	chk->str  = str;
+	chk->len  = 0;
+	chk->size = size;
+}
+
+/* report 0 in case of error, 1 if OK. */
+static inline int chunk_initlen(struct chunk *chk, char *str, size_t size, int len)
+{
+
+	if (size && len > size)
+		return 0;
+
+	chk->str  = str;
+	chk->len  = len;
+	chk->size = size;
+
+	return 1;
+}
+
+static inline void chunk_initstr(struct chunk *chk, char *str)
+{
+	chk->str = str;
+	chk->len = strlen(str);
+	chk->size = 0;			/* mark it read-only */
+}
+
+static inline int chunk_strcpy(struct chunk *chk, const char *str)
+{
+	size_t len;
+
+	len = strlen(str);
+
+	if (unlikely(len > chk->size))
+		return 0;
+
+	chk->len  = len;
+	memcpy(chk->str, str, len);
+
+	return 1;
+}
+
+static inline void chunk_reset(struct chunk *chk)
+{
+	chk->str  = NULL;
+	chk->len  = -1;
+	chk->size = 0;
+}
+
+static inline void chunk_destroy(struct chunk *chk)
+{
+	if (!chk->size)
+		return;
+
+	if (chk->str)
+		free(chk->str);
+
+	chunk_reset(chk);
+}
+
+/*
+ * frees the destination chunk if already allocated, allocates a new string,
+ * and copies the source into it. The pointer to the destination string is
+ * returned, or NULL if the allocation fails or if any pointer is NULL..
+ */
+static inline char *chunk_dup(struct chunk *dst, const struct chunk *src)
+{
+	if (!dst || !src || !src->str)
+		return NULL;
+	if (dst->str)
+		free(dst->str);
+	dst->len = src->len;
+	dst->str = (char *)malloc(dst->len);
+	memcpy(dst->str, src->str, dst->len);
+	return dst->str;
+}
+
+#endif /* _TYPES_CHUNK_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/include/proto/buffers.h b/include/proto/channel.h
similarity index 60%
rename from include/proto/buffers.h
rename to include/proto/channel.h
index e0d43e9..6b5478d 100644
--- a/include/proto/buffers.h
+++ b/include/proto/channel.h
@@ -1,6 +1,6 @@
 /*
- * include/proto/buffers.h
- * Buffer management definitions, macros and inline functions.
+ * include/proto/channel.h
+ * Channel management definitions, macros and inline functions.
  *
  * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
  *
@@ -19,19 +19,19 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef _PROTO_BUFFERS_H
-#define _PROTO_BUFFERS_H
+#ifndef _PROTO_CHANNEL_H
+#define _PROTO_CHANNEL_H
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <common/config.h>
+#include <common/chunk.h>
 #include <common/memory.h>
 #include <common/ticks.h>
 #include <common/time.h>
 
-#include <types/buffers.h>
 #include <types/global.h>
 
 extern struct pool_head *pool2_buffer;
@@ -47,9 +47,6 @@
 int bo_getblk(struct channel *buf, char *blk, int len, int offset);
 int buffer_replace2(struct channel *b, char *pos, char *end, const char *str, int len);
 int buffer_insert_line2(struct channel *b, char *pos, const char *str, int len);
-void buffer_dump(FILE *o, struct buffer *b, int from, int to);
-void buffer_slow_realign(struct buffer *buf);
-void buffer_bounce_realign(struct buffer *buf);
 unsigned long long buffer_forward(struct channel *buf, unsigned long long bytes);
 
 /* Initialize all fields in the buffer. The BF_OUT_EMPTY flags is set. */
@@ -70,109 +67,6 @@
 /* These functions are used to compute various buffer area sizes */
 /*****************************************************************/
 
-/* Returns an absolute pointer for a position relative to the current buffer's
- * pointer. It is written so that it is optimal when <ofs> is a const. It is
- * written as a macro instead of an inline function so that the compiler knows
- * when it can optimize out the sign test on <ofs> when passed an unsigned int.
- */
-#define b_ptr(b, ofs) \
-	({            \
-		char *__ret = (b)->p + (ofs);                   \
-		if ((ofs) > 0 && __ret >= (b)->data + (b)->size)    \
-			__ret -= (b)->size;                     \
-		else if ((ofs) < 0 && __ret < (b)->data)        \
-			__ret += (b)->size;                     \
-		__ret;                                          \
-	})
-
-/* Returns the start of the input data in a buffer */
-static inline char *bi_ptr(const struct buffer *b)
-{
-	return b->p;
-}
-
-/* Returns the end of the input data in a buffer (pointer to next
- * insertion point).
- */
-static inline char *bi_end(const struct buffer *b)
-{
-	char *ret = b->p + b->i;
-
-	if (ret >= b->data + b->size)
-		ret -= b->size;
-	return ret;
-}
-
-/* Returns the amount of input data that can contiguously be read at once */
-static inline int bi_contig_data(const struct buffer *b)
-{
-	int data = b->data + b->size - b->p;
-
-	if (data > b->i)
-		data = b->i;
-	return data;
-}
-
-/* Returns the start of the output data in a buffer */
-static inline char *bo_ptr(const struct buffer *b)
-{
-	char *ret = b->p - b->o;
-
-	if (ret < b->data)
-		ret += b->size;
-	return ret;
-}
-
-/* Returns the end of the output data in a buffer */
-static inline char *bo_end(const struct buffer *b)
-{
-	return b->p;
-}
-
-/* Returns the amount of output data that can contiguously be read at once */
-static inline int bo_contig_data(const struct buffer *b)
-{
-	char *beg = b->p - b->o;
-
-	if (beg < b->data)
-		return b->data - beg;
-	return b->o;
-}
-
-/* Return the buffer's length in bytes by summing the input and the output */
-static inline int buffer_len(const struct buffer *buf)
-{
-	return buf->i + buf->o;
-}
-
-/* Return non-zero only if the buffer is not empty */
-static inline int buffer_not_empty(const struct buffer *buf)
-{
-	return buf->i | buf->o;
-}
-
-/* Return non-zero only if the buffer is empty */
-static inline int buffer_empty(const struct buffer *buf)
-{
-	return !buffer_not_empty(buf);
-}
-
-/* Normalizes a pointer after a subtract */
-static inline char *buffer_wrap_sub(const struct buffer *buf, char *ptr)
-{
-	if (ptr < buf->data)
-		ptr += buf->size;
-	return ptr;
-}
-
-/* Normalizes a pointer after an addition */
-static inline char *buffer_wrap_add(const struct buffer *buf, char *ptr)
-{
-	if (ptr - buf->size >= buf->data)
-		ptr -= buf->size;
-	return ptr;
-}
-
 /* Return the number of reserved bytes in the buffer, which ensures that once
  * all pending data are forwarded, the buffer still has global.tune.maxrewrite
  * bytes free. The result is between 0 and global.maxrewrite, which is itself
@@ -254,41 +148,6 @@
 	return 0;
 }
 
-/* Return the maximum amount of bytes that can be written into the buffer,
- * including reserved space which may be overwritten.
- */
-static inline int buffer_total_space(const struct buffer *buf)
-{
-	return buf->size - buffer_len(buf);
-}
-
-/* Returns the number of contiguous bytes between <start> and <start>+<count>,
- * and enforces a limit on buf->data + buf->size. <start> must be within the
- * buffer.
- */
-static inline int buffer_contig_area(const struct buffer *buf, const char *start, int count)
-{
-	if (count > buf->data - start + buf->size)
-		count = buf->data - start + buf->size;
-	return count;
-}
-
-/* Return the amount of bytes that can be written into the buffer at once,
- * including reserved space which may be overwritten.
- */
-static inline int buffer_contig_space(const struct buffer *buf)
-{
-	const char *left, *right;
-
-	if (buf->data + buf->o <= buf->p)
-		right = buf->data + buf->size;
-	else
-		right = buf->p + buf->size - buf->o;
-
-	left = buffer_wrap_add(buf, buf->p + buf->i);
-	return right - left;
-}
-
 /* Advances the buffer by <adv> bytes, which means that the buffer
  * pointer advances, and that as many bytes from in are transferred
  * to out. The caller is responsible for ensuring that adv is always
@@ -317,29 +176,6 @@
 }
 
 /* Return the amount of bytes that can be written into the buffer at once,
- * excluding the amount of reserved space passed in <res>, which is
- * preserved.
- */
-static inline int buffer_contig_space_with_res(const struct buffer *buf, int res)
-{
-	/* Proceed differently if the buffer is full, partially used or empty.
-	 * The hard situation is when it's partially used and either data or
-	 * reserved space wraps at the end.
-	 */
-	int spare = buf->size - res;
-
-	if (buffer_len(buf) >= spare)
-		spare = 0;
-	else if (buffer_len(buf)) {
-		spare = buffer_contig_space(buf) - res;
-		if (spare < 0)
-			spare = 0;
-	}
-	return spare;
-}
-
-
-/* Return the amount of bytes that can be written into the buffer at once,
  * excluding reserved space, which is preserved.
  */
 static inline int buffer_contig_space_res(const struct channel *chn)
@@ -347,63 +183,6 @@
 	return buffer_contig_space_with_res(&chn->buf, buffer_reserved(chn));
 }
 
-/* Normalizes a pointer which is supposed to be relative to the beginning of a
- * buffer, so that wrapping is correctly handled. The intent is to use this
- * when increasing a pointer. Note that the wrapping test is only performed
- * once, so the original pointer must be between ->data-size and ->data+2*size-1,
- * otherwise an invalid pointer might be returned.
- */
-static inline const char *buffer_pointer(const struct buffer *buf, const char *ptr)
-{
-	if (ptr < buf->data)
-		ptr += buf->size;
-	else if (ptr - buf->size >= buf->data)
-		ptr -= buf->size;
-	return ptr;
-}
-
-/* Returns the distance between two pointers, taking into account the ability
- * to wrap around the buffer's end.
- */
-static inline int buffer_count(const struct buffer *buf, const char *from, const char *to)
-{
-	int count = to - from;
-	if (count < 0)
-		count += buf->size;
-	return count;
-}
-
-/* returns the amount of pending bytes in the buffer. It is the amount of bytes
- * that is not scheduled to be sent.
- */
-static inline int buffer_pending(const struct buffer *buf)
-{
-	return buf->i;
-}
-
-/* Returns the size of the working area which the caller knows ends at <end>.
- * If <end> equals buf->r (modulo size), then it means that the free area which
- * follows is part of the working area. Otherwise, the working area stops at
- * <end>. It always starts at buf->p. The work area includes the
- * reserved area.
- */
-static inline int buffer_work_area(const struct buffer *buf, const char *end)
-{
-	end = buffer_pointer(buf, end);
-	if (end == buffer_wrap_add(buf, buf->p + buf->i))
-		/* pointer exactly at end, lets push forwards */
-		end = buffer_wrap_sub(buf, buf->p - buf->o);
-	return buffer_count(buf, buf->p, end);
-}
-
-/* Return 1 if the buffer has less than 1/4 of its capacity free, otherwise 0 */
-static inline int buffer_almost_full(const struct buffer *buf)
-{
-	if (buffer_total_space(buf) < buf->size / 4)
-		return 1;
-	return 0;
-}
-
 /* Returns true if the buffer's input is already closed */
 static inline int buffer_input_closed(struct channel *buf)
 {
@@ -485,18 +264,6 @@
 		buf->flags |= BF_FULL;
 }
 
-/* Cut the first <n> pending bytes in a contiguous buffer. It is illegal to
- * call this function with remaining data waiting to be sent (o > 0). The
- * caller must ensure that <n> is smaller than the actual buffer's length.
- * This is mainly used to remove empty lines at the beginning of a request
- * or a response.
- */
-static inline void bi_fast_delete(struct buffer *buf, int n)
-{
-	buf->i -= n;
-	buf->p += n;
-}
-
 /* marks the buffer as "shutdown" ASAP for reads */
 static inline void buffer_shutr_now(struct channel *buf)
 {
@@ -575,19 +342,6 @@
 }
 
 /*
- * Tries to realign the given buffer, and returns how many bytes can be written
- * there at once without overwriting anything.
- */
-static inline int buffer_realign(struct buffer *buf)
-{
-	if (!(buf->i | buf->o)) {
-		/* let's realign the buffer to optimize I/O */
-		buf->p = buf->data;
-	}
-	return buffer_contig_space(buf);
-}
-
-/*
  * Advance the buffer's read pointer by <len> bytes. This is useful when data
  * have been read directly from the buffer. It is illegal to call this function
  * with <len> causing a wrapping at the end of the buffer. It's the caller's
@@ -669,91 +423,8 @@
 	return buffer_replace2(b, pos, end, str, strlen(str));
 }
 
-/*
- *
- * Functions below are used to manage chunks
- *
- */
-
-static inline void chunk_init(struct chunk *chk, char *str, size_t size) {
-	chk->str  = str;
-	chk->len  = 0;
-	chk->size = size;
-}
-
-/* report 0 in case of error, 1 if OK. */
-static inline int chunk_initlen(struct chunk *chk, char *str, size_t size, int len) {
-
-	if (size && len > size)
-		return 0;
-
-	chk->str  = str;
-	chk->len  = len;
-	chk->size = size;
-
-	return 1;
-}
-
-static inline void chunk_initstr(struct chunk *chk, char *str) {
-	chk->str = str;
-	chk->len = strlen(str);
-	chk->size = 0;			/* mark it read-only */
-}
-
-static inline int chunk_strcpy(struct chunk *chk, const char *str) {
-	size_t len;
-
-	len = strlen(str);
-
-	if (unlikely(len > chk->size))
-		return 0;
-
-	chk->len  = len;
-	memcpy(chk->str, str, len);
-
-	return 1;
-}
-
-int chunk_printf(struct chunk *chk, const char *fmt, ...)
-	__attribute__ ((format(printf, 2, 3)));
-
-int chunk_htmlencode(struct chunk *dst, struct chunk *src);
-int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc);
-
-static inline void chunk_reset(struct chunk *chk) {
-	chk->str  = NULL;
-	chk->len  = -1;
-	chk->size = 0;
-}
-
-static inline void chunk_destroy(struct chunk *chk) {
-
-	if (!chk->size)
-		return;
-
-	if (chk->str)
-		free(chk->str);
-
-	chunk_reset(chk);
-}
-
-/*
- * frees the destination chunk if already allocated, allocates a new string,
- * and copies the source into it. The pointer to the destination string is
- * returned, or NULL if the allocation fails or if any pointer is NULL..
- */
-static inline char *chunk_dup(struct chunk *dst, const struct chunk *src) {
-	if (!dst || !src || !src->str)
-		return NULL;
-	if (dst->str)
-		free(dst->str);
-	dst->len = src->len;
-	dst->str = (char *)malloc(dst->len);
-	memcpy(dst->str, src->str, dst->len);
-	return dst->str;
-}
 
-#endif /* _PROTO_BUFFERS_H */
+#endif /* _PROTO_CHANNEL_H */
 
 /*
  * Local variables:
diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index 449ddc1..b6a689c 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -24,8 +24,7 @@
 #define _PROTO_DUMPSTATS_H
 
 #include <common/config.h>
-#include <types/buffers.h>
-#include <types/session.h>
+#include <types/stream_interface.h>
 
 /* Flags for applet.ctx.stats.flags */
 #define STAT_FMT_CSV    0x00000001	/* dump the stats in CSV format instead of HTML */
diff --git a/include/types/arg.h b/include/types/arg.h
index 2762674..666a51f 100644
--- a/include/types/arg.h
+++ b/include/types/arg.h
@@ -24,7 +24,8 @@
 
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <types/buffers.h>
+
+#include <common/chunk.h>
 
 enum {
 	ARGT_STOP = 0, /* end of the arg list */
diff --git a/include/types/buffers.h b/include/types/channel.h
similarity index 89%
rename from include/types/buffers.h
rename to include/types/channel.h
index 200e26c..cd16d9c 100644
--- a/include/types/buffers.h
+++ b/include/types/channel.h
@@ -1,8 +1,8 @@
 /*
- * include/types/buffers.h
- * Buffer management definitions, macros and inline functions.
+ * include/types/channel.h
+ * Channel management definitions, macros and inline functions.
  *
- * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
+ * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,15 +19,17 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef _TYPES_BUFFERS_H
-#define _TYPES_BUFFERS_H
+#ifndef _TYPES_CHANNEL_H
+#define _TYPES_CHANNEL_H
 
 #include <common/config.h>
-#include <common/memory.h>
+#include <common/chunk.h>
+#include <common/buffer.h>
 #include <types/stream_interface.h>
 
-/* The BF_* macros designate Buffer Flags, which may be ORed in the bit field
- * member 'flags' in struct channel. Here we have several types of flags :
+/* The BF_* macros designate Channel Flags (originally "Buffer Flags"), which
+ * may be ORed in the bit field member 'flags' in struct channel. Here we have
+ * several types of flags :
  *
  *   - pure status flags, reported by the lower layer, which must be cleared
  *     before doing further I/O :
@@ -47,8 +49,8 @@
  *
  * The flags have been arranged for readability, so that the read and write
  * bits have the same position in a byte (read being the lower byte and write
- * the second one). All flag names are relative to the buffer. For instance,
- * 'write' indicates the direction from the buffer to the stream interface.
+ * the second one). All flag names are relative to the channel. For instance,
+ * 'write' indicates the direction from the channel to the stream interface.
  */
 
 #define BF_READ_NULL      0x000001  /* last read detected on producer side */
@@ -57,7 +59,7 @@
 #define BF_READ_ERROR     0x000008  /* unrecoverable error on producer side */
 #define BF_READ_ACTIVITY  (BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR)
 
-#define BF_FULL           0x000010  /* buffer cannot accept any more data (l >= max len) */
+#define BF_FULL           0x000010  /* channel cannot accept any more data (l >= max len) */
 #define BF_SHUTR          0x000020  /* producer has already shut down */
 #define BF_SHUTR_NOW      0x000040  /* the producer must shut down for reads ASAP */
 #define BF_READ_NOEXP     0x000080  /* producer should not expire */
@@ -107,7 +109,7 @@
 #define BF_HIJACK         0x040000  /* the producer is temporarily replaced by ->hijacker */
 #define BF_ANA_TIMEOUT    0x080000  /* the analyser timeout has expired */
 #define BF_READ_ATTACHED  0x100000  /* the read side is attached for the first time */
-#define BF_KERN_SPLICING  0x200000  /* kernel splicing desired for this buffer */
+#define BF_KERN_SPLICING  0x200000  /* kernel splicing desired for this channel */
 #define BF_READ_DONTWAIT  0x400000  /* wake the task up after every read (eg: HTTP request) */
 #define BF_AUTO_CONNECT   0x800000  /* consumer may attempt to establish a new connection */
 
@@ -116,7 +118,7 @@
 #define BF_SEND_DONTWAIT 0x4000000  /* don't wait for sending data (one-shoot) */
 #define BF_NEVER_WAIT    0x8000000  /* never wait for sending data (permanent) */
 
-#define BF_WAKE_ONCE    0x10000000  /* pretend there is activity on this buffer (one-shoot) */
+#define BF_WAKE_ONCE    0x10000000  /* pretend there is activity on this channel (one-shoot) */
 
 /* Use these masks to clear the flags before going back to lower layers */
 #define BF_CLEAR_READ     (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED))
@@ -130,7 +132,7 @@
 #define BF_MASK_STATIC          (BF_OUT_EMPTY|BF_FULL|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)
 
 
-/* Analysers (buffer->analysers).
+/* Analysers (channel->analysers).
  * Those bits indicate that there are some processing to do on the buffer
  * contents. It will probably evolve into a linked list later. Those
  * analysers could be compared to higher level processors.
@@ -164,24 +166,9 @@
 /* Magic value to forward infinite size (TCP, ...), used with ->to_forward */
 #define BUF_INFINITE_FORWARD    MAX_RANGE(int)
 
-/* describes a chunk of string */
-struct chunk {
-	char *str;	/* beginning of the string itself. Might not be 0-terminated */
-	int size;	/* total size of the buffer, 0 if the *str is read-only */
-	int len;	/* current size of the string from first to last char. <0 = uninit. */
-};
-
 /* needed for a declaration below */
 struct session;
 
-struct buffer {
-	char *p;                        /* buffer's start pointer, separates in and out data */
-	unsigned int size;              /* buffer size in bytes */
-	unsigned int i;                 /* number of input bytes pending for analysis in the buffer */
-	unsigned int o;                 /* number of out bytes the sender can consume from this buffer */
-	char data[0];                   /* <size> bytes */
-};
-
 struct channel {
 	unsigned int flags;             /* BF_* */
 	int rex;                        /* expiration date for a read, in ticks */
@@ -189,14 +176,14 @@
 	int rto;                        /* read timeout, in ticks */
 	int wto;                        /* write timeout, in ticks */
 	unsigned int to_forward;        /* number of bytes to forward after out without a wake-up */
-	unsigned int analysers;         /* bit field indicating what to do on the buffer */
+	unsigned int analysers;         /* bit field indicating what to do on the channel */
 	int analyse_exp;                /* expiration date for current analysers (if set) */
 	void (*hijacker)(struct session *, struct channel *); /* alternative content producer */
 	unsigned char xfer_large;       /* number of consecutive large xfers */
 	unsigned char xfer_small;       /* number of consecutive small xfers */
 	unsigned long long total;       /* total data read */
-	struct stream_interface *prod;  /* producer attached to this buffer */
-	struct stream_interface *cons;  /* consumer attached to this buffer */
+	struct stream_interface *prod;  /* producer attached to this channel */
+	struct stream_interface *cons;  /* consumer attached to this channel */
 	struct pipe *pipe;		/* non-NULL only when data present */
 	struct buffer buf;		/* embedded buffer for now, will move */
 };
@@ -291,7 +278,7 @@
        long.
  */
 
-#endif /* _TYPES_BUFFERS_H */
+#endif /* _TYPES_CHANNEL_H */
 
 /*
  * Local variables:
diff --git a/include/types/global.h b/include/types/global.h
index b4fa23e..b55481b 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -25,6 +25,7 @@
 #include <netinet/in.h>
 
 #include <common/config.h>
+#include <types/freq_ctr.h>
 #include <types/log.h>
 #include <types/protocols.h>
 #include <types/proxy.h>
diff --git a/include/types/log.h b/include/types/log.h
index 2086860..ac985fc 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -26,6 +26,7 @@
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <common/config.h>
+#include <common/mini-clist.h>
 
 #define MAX_SYSLOG_LEN          1024
 #define NB_LOG_FACILITIES       24
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index 158f094..665ec75 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -22,9 +22,9 @@
 #ifndef _TYPES_PROTO_HTTP_H
 #define _TYPES_PROTO_HTTP_H
 
+#include <common/chunk.h>
 #include <common/config.h>
 
-#include <types/buffers.h>
 #include <types/hdr_idx.h>
 
 /* These are the flags that are found in txn->flags */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index c93edd2..13a08a5 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -28,6 +28,7 @@
 #include <arpa/inet.h>
 
 #include <common/appsession.h>
+#include <common/chunk.h>
 #include <common/config.h>
 #include <common/mini-clist.h>
 #include <common/regex.h>
@@ -37,7 +38,6 @@
 
 #include <types/acl.h>
 #include <types/backend.h>
-#include <types/buffers.h>
 #include <types/counters.h>
 #include <types/freq_ctr.h>
 #include <types/log.h>
diff --git a/include/types/sample.h b/include/types/sample.h
index b806a12..2f5ce86 100644
--- a/include/types/sample.h
+++ b/include/types/sample.h
@@ -25,8 +25,9 @@
 
 #include <sys/socket.h>
 #include <netinet/in.h>
+
+#include <common/chunk.h>
 #include <types/arg.h>
-#include <types/buffers.h>
 
 /* input and output sample types */
 enum {
@@ -78,6 +79,9 @@
 	SMP_F_VOLATILE   = (1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6), /* any volatility condition */
 };
 
+/* needed below */
+struct session;
+
 /* a sample context might be used by any sample fetch function in order to
  * store information needed across multiple calls (eg: restart point for a
  * next occurrence). By definition it may store up to 8 pointers, or any
diff --git a/include/types/server.h b/include/types/server.h
index c952885..689441c 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -29,7 +29,6 @@
 #include <common/mini-clist.h>
 #include <eb32tree.h>
 
-#include <types/buffers.h>
 #include <types/connection.h>
 #include <types/counters.h>
 #include <types/freq_ctr.h>
diff --git a/include/types/session.h b/include/types/session.h
index 9180a94..cce55a4 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -31,7 +31,7 @@
 #include <common/config.h>
 #include <common/mini-clist.h>
 
-#include <types/buffers.h>
+#include <types/channel.h>
 #include <types/proto_http.h>
 #include <types/proxy.h>
 #include <types/queue.h>
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 5985619..87f951e 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -25,7 +25,7 @@
 #include <stdlib.h>
 #include <sys/socket.h>
 
-#include <types/buffers.h>
+#include <types/channel.h>
 #include <types/connection.h>
 #include <common/config.h>
 
diff --git a/src/acl.c b/src/acl.c
index 1680ac9..d8e35b2 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -24,7 +24,7 @@
 #include <proto/acl.h>
 #include <proto/arg.h>
 #include <proto/auth.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/log.h>
 #include <proto/proxy.h>
 #include <proto/stick_table.h>
diff --git a/src/backend.c b/src/backend.c
index b777cc3..998e02c 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -19,6 +19,7 @@
 #include <ctype.h>
 #include <sys/types.h>
 
+#include <common/buffer.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
@@ -30,7 +31,7 @@
 #include <proto/acl.h>
 #include <proto/arg.h>
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/frontend.h>
 #include <proto/lb_chash.h>
 #include <proto/lb_fas.h>
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 0000000..764f692
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,143 @@
+/*
+ * Buffer management functions.
+ *
+ * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <common/config.h>
+#include <common/buffer.h>
+
+#include <types/global.h>
+
+/* This function realigns input data in a possibly wrapping buffer so that it
+ * becomes contiguous and starts at the beginning of the buffer area. The
+ * function may only be used when the buffer's output is empty.
+ */
+void buffer_slow_realign(struct buffer *buf)
+{
+	/* two possible cases :
+	 *   - the buffer is in one contiguous block, we move it in-place
+	 *   - the buffer is in two blocks, we move it via the swap_buffer
+	 */
+	if (buf->i) {
+		int block1 = buf->i;
+		int block2 = 0;
+		if (buf->p + buf->i > buf->data + buf->size) {
+			/* non-contiguous block */
+			block1 = buf->data + buf->size - buf->p;
+			block2 = buf->p + buf->i - (buf->data + buf->size);
+		}
+		if (block2)
+			memcpy(swap_buffer, buf->data, block2);
+		memmove(buf->data, buf->p, block1);
+		if (block2)
+			memcpy(buf->data + block1, swap_buffer, block2);
+	}
+
+	buf->p = buf->data;
+}
+
+
+/* Realigns a possibly non-contiguous buffer by bouncing bytes from source to
+ * destination. It does not use any intermediate buffer and does the move in
+ * place, though it will be slower than a simple memmove() on contiguous data,
+ * so it's desirable to use it only on non-contiguous buffers. No pointers are
+ * changed, the caller is responsible for that.
+ */
+void buffer_bounce_realign(struct buffer *buf)
+{
+	int advance, to_move;
+	char *from, *to;
+
+	from = bo_ptr(buf);
+	advance = buf->data + buf->size - from;
+	if (!advance)
+		return;
+
+	to_move = buffer_len(buf);
+	while (to_move) {
+		char last, save;
+
+		last = *from;
+		to = from + advance;
+		if (to >= buf->data + buf->size)
+			to -= buf->size;
+
+		while (1) {
+			save = *to;
+			*to  = last;
+			last = save;
+			to_move--;
+			if (!to_move)
+				break;
+
+			/* check if we went back home after rotating a number of bytes */
+			if (to == from)
+				break;
+
+			/* if we ended up in the empty area, let's walk to next place. The
+			 * empty area is either between buf->r and from or before from or
+			 * after buf->r.
+			 */
+			if (from > bi_end(buf)) {
+				if (to >= bi_end(buf) && to < from)
+					break;
+			} else if (from < bi_end(buf)) {
+				if (to < from || to >= bi_end(buf))
+					break;
+			}
+
+			/* we have overwritten a byte of the original set, let's move it */
+			to += advance;
+			if (to >= buf->data + buf->size)
+				to -= buf->size;
+		}
+
+		from++;
+		if (from >= buf->data + buf->size)
+			from -= buf->size;
+	}
+}
+
+
+/*
+ * Dumps part or all of a buffer.
+ */
+void buffer_dump(FILE *o, struct buffer *b, int from, int to)
+{
+	fprintf(o, "Dumping buffer %p\n", b);
+	fprintf(o, "  data=%p o=%d i=%d p=%p\n",
+		b->data, b->o, b->i, b->p);
+
+	if (!to || to > buffer_len(b))
+		to = buffer_len(b);
+
+	fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
+	for (; from < to; from++) {
+		if ((from & 15) == 0)
+			fprintf(o, "  %04x: ", from);
+		fprintf(o, "%02x ", b->data[from]);
+		if ((from & 15) == 7)
+			fprintf(o, "- ");
+		else if (((from & 15) == 15) && (from != to-1))
+			fprintf(o, "\n");
+	}
+	fprintf(o, "\n--\n");
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 44397fc..9781783 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -26,6 +26,7 @@
 #include <netinet/tcp.h>
 
 #include <common/cfgparse.h>
+#include <common/chunk.h>
 #include <common/config.h>
 #include <common/errors.h>
 #include <common/memory.h>
@@ -40,7 +41,7 @@
 #include <proto/acl.h>
 #include <proto/auth.h>
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/checks.h>
 #include <proto/dumpstats.h>
 #include <proto/frontend.h>
diff --git a/src/buffers.c b/src/channel.c
similarity index 67%
rename from src/buffers.c
rename to src/channel.c
index db4b435..2789e89 100644
--- a/src/buffers.c
+++ b/src/channel.c
@@ -1,7 +1,7 @@
 /*
- * Buffer management functions.
+ * Channel management functions.
  *
- * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,9 +17,14 @@
 
 #include <common/config.h>
 #include <common/memory.h>
-#include <proto/buffers.h>
+#include <common/buffer.h>
+#include <proto/channel.h>
 #include <types/global.h>
 
+
+/* Note: this code has not yet been completely cleaned up and still refers to
+ * the word "buffer" when "channel" is meant instead.
+ */
 struct pool_head *pool2_buffer;
 
 
@@ -385,229 +390,7 @@
 	return delta;
 }
 
-
-/* This function realigns input data in a possibly wrapping buffer so that it
- * becomes contiguous and starts at the beginning of the buffer area. The
- * function may only be used when the buffer's output is empty.
- */
-void buffer_slow_realign(struct buffer *buf)
-{
-	/* two possible cases :
-	 *   - the buffer is in one contiguous block, we move it in-place
-	 *   - the buffer is in two blocks, we move it via the swap_buffer
-	 */
-	if (buf->i) {
-		int block1 = buf->i;
-		int block2 = 0;
-		if (buf->p + buf->i > buf->data + buf->size) {
-			/* non-contiguous block */
-			block1 = buf->data + buf->size - buf->p;
-			block2 = buf->p + buf->i - (buf->data + buf->size);
-		}
-		if (block2)
-			memcpy(swap_buffer, buf->data, block2);
-		memmove(buf->data, buf->p, block1);
-		if (block2)
-			memcpy(buf->data + block1, swap_buffer, block2);
-	}
-
-	buf->p = buf->data;
-}
-
-/* Realigns a possibly non-contiguous buffer by bouncing bytes from source to
- * destination. It does not use any intermediate buffer and does the move in
- * place, though it will be slower than a simple memmove() on contiguous data,
- * so it's desirable to use it only on non-contiguous buffers. No pointers are
- * changed, the caller is responsible for that.
- */
-void buffer_bounce_realign(struct buffer *buf)
-{
-	int advance, to_move;
-	char *from, *to;
-
-	from = bo_ptr(buf);
-	advance = buf->data + buf->size - from;
-	if (!advance)
-		return;
-
-	to_move = buffer_len(buf);
-	while (to_move) {
-		char last, save;
-
-		last = *from;
-		to = from + advance;
-		if (to >= buf->data + buf->size)
-			to -= buf->size;
-
-		while (1) {
-			save = *to;
-			*to  = last;
-			last = save;
-			to_move--;
-			if (!to_move)
-				break;
-
-			/* check if we went back home after rotating a number of bytes */
-			if (to == from)
-				break;
-
-			/* if we ended up in the empty area, let's walk to next place. The
-			 * empty area is either between buf->r and from or before from or
-			 * after buf->r.
-			 */
-			if (from > bi_end(buf)) {
-				if (to >= bi_end(buf) && to < from)
-					break;
-			} else if (from < bi_end(buf)) {
-				if (to < from || to >= bi_end(buf))
-					break;
-			}
-
-			/* we have overwritten a byte of the original set, let's move it */
-			to += advance;
-			if (to >= buf->data + buf->size)
-				to -= buf->size;
-		}
-
-		from++;
-		if (from >= buf->data + buf->size)
-			from -= buf->size;
-	}
-}
-
-
-/*
- * Does an snprintf() at the end of chunk <chk>, respecting the limit of
- * at most chk->size chars. If the chk->len is over, nothing is added. Returns
- * the new chunk size.
- */
-int chunk_printf(struct chunk *chk, const char *fmt, ...)
-{
-	va_list argp;
-	int ret;
-
-	if (!chk->str || !chk->size)
-		return 0;
-
-	va_start(argp, fmt);
-	ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp);
-	if (ret >= chk->size - chk->len)
-		/* do not copy anything in case of truncation */
-		chk->str[chk->len] = 0;
-	else
-		chk->len += ret;
-	va_end(argp);
-	return chk->len;
-}
-
-/*
- * Encode chunk <src> into chunk <dst>, respecting the limit of at most
- * chk->size chars. Replace non-printable or special chracters with "&#%d;".
- * If the chk->len is over, nothing is added. Returns the new chunk size.
- */
-int chunk_htmlencode(struct chunk *dst, struct chunk *src) {
-
-	int i, l;
-	int olen, free;
-	char c;
-
-	olen = dst->len;
-
-	for (i = 0; i < src->len; i++) {
-		free = dst->size - dst->len;
-
-		if (!free) {
-			dst->len = olen;
-			return dst->len;
-		}
-
-		c = src->str[i];
-
-		if (!isascii(c) || !isprint((unsigned char)c) || c == '&' || c == '"' || c == '\'' || c == '<' || c == '>') {
-			l = snprintf(dst->str + dst->len, free, "&#%u;", (unsigned char)c);
-
-			if (free < l) {
-				dst->len = olen;
-				return dst->len;
-			}
-
-			dst->len += l;
-		} else {
-			dst->str[dst->len] = c;
-			dst->len++;
-		}
-	}
-
-	return dst->len;
-}
-
 /*
- * Encode chunk <src> into chunk <dst>, respecting the limit of at most
- * chk->size chars. Replace non-printable or char passed in qc with "<%02X>".
- * If the chk->len is over, nothing is added. Returns the new chunk size.
- */
-int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc) {
-	int i, l;
-	int olen, free;
-	char c;
-
-	olen = dst->len;
-
-	for (i = 0; i < src->len; i++) {
-		free = dst->size - dst->len;
-
-		if (!free) {
-			dst->len = olen;
-			return dst->len;
-		}
-
-		c = src->str[i];
-
-		if (!isascii(c) || !isprint((unsigned char)c) || c == '<' || c == '>' || c == qc) {
-			l = snprintf(dst->str + dst->len, free, "<%02X>", (unsigned char)c);
-
-			if (free < l) {
-				dst->len = olen;
-				return dst->len;
-			}
-
-			dst->len += l;
-		} else {
-			dst->str[dst->len] = c;
-			dst->len++;
-		}
-	}
-
-	return dst->len;
-}
-
-/*
- * Dumps part or all of a buffer.
- */
-void buffer_dump(FILE *o, struct buffer *b, int from, int to)
-{
-	fprintf(o, "Dumping buffer %p\n", b);
-	fprintf(o, "  data=%p o=%d i=%d p=%p\n",
-		b->data, b->o, b->i, b->p);
-
-	if (!to || to > buffer_len(b))
-		to = buffer_len(b);
-
-	fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
-	for (; from < to; from++) {
-		if ((from & 15) == 0)
-			fprintf(o, "  %04x: ", from);
-		fprintf(o, "%02x ", b->data[from]);
-		if ((from & 15) == 7)
-			fprintf(o, "- ");
-		else if (((from & 15) == 15) && (from != to-1))
-			fprintf(o, "\n");
-	}
-	fprintf(o, "\n--\n");
-}
-
-
-/*
  * Local variables:
  *  c-indent-level: 8
  *  c-basic-offset: 8
diff --git a/src/checks.c b/src/checks.c
index 2cde26b..93f93df 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -26,6 +26,7 @@
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 
+#include <common/chunk.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/mini-clist.h>
@@ -36,7 +37,6 @@
 
 #include <proto/backend.h>
 #include <proto/checks.h>
-#include <proto/buffers.h>
 #include <proto/fd.h>
 #include <proto/log.h>
 #include <proto/queue.h>
diff --git a/src/chunk.c b/src/chunk.c
new file mode 100644
index 0000000..a4cbb7d
--- /dev/null
+++ b/src/chunk.c
@@ -0,0 +1,133 @@
+/*
+ * Chunk management functions.
+ *
+ * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <common/config.h>
+#include <common/chunk.h>
+
+/*
+ * Does an snprintf() at the end of chunk <chk>, respecting the limit of
+ * at most chk->size chars. If the chk->len is over, nothing is added. Returns
+ * the new chunk size.
+ */
+int chunk_printf(struct chunk *chk, const char *fmt, ...)
+{
+	va_list argp;
+	int ret;
+
+	if (!chk->str || !chk->size)
+		return 0;
+
+	va_start(argp, fmt);
+	ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp);
+	if (ret >= chk->size - chk->len)
+		/* do not copy anything in case of truncation */
+		chk->str[chk->len] = 0;
+	else
+		chk->len += ret;
+	va_end(argp);
+	return chk->len;
+}
+
+/*
+ * Encode chunk <src> into chunk <dst>, respecting the limit of at most
+ * chk->size chars. Replace non-printable or special chracters with "&#%d;".
+ * If the chk->len is over, nothing is added. Returns the new chunk size.
+ */
+int chunk_htmlencode(struct chunk *dst, struct chunk *src)
+{
+	int i, l;
+	int olen, free;
+	char c;
+
+	olen = dst->len;
+
+	for (i = 0; i < src->len; i++) {
+		free = dst->size - dst->len;
+
+		if (!free) {
+			dst->len = olen;
+			return dst->len;
+		}
+
+		c = src->str[i];
+
+		if (!isascii(c) || !isprint((unsigned char)c) || c == '&' || c == '"' || c == '\'' || c == '<' || c == '>') {
+			l = snprintf(dst->str + dst->len, free, "&#%u;", (unsigned char)c);
+
+			if (free < l) {
+				dst->len = olen;
+				return dst->len;
+			}
+
+			dst->len += l;
+		} else {
+			dst->str[dst->len] = c;
+			dst->len++;
+		}
+	}
+
+	return dst->len;
+}
+
+/*
+ * Encode chunk <src> into chunk <dst>, respecting the limit of at most
+ * chk->size chars. Replace non-printable or char passed in qc with "<%02X>".
+ * If the chk->len is over, nothing is added. Returns the new chunk size.
+ */
+int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc)
+{
+	int i, l;
+	int olen, free;
+	char c;
+
+	olen = dst->len;
+
+	for (i = 0; i < src->len; i++) {
+		free = dst->size - dst->len;
+
+		if (!free) {
+			dst->len = olen;
+			return dst->len;
+		}
+
+		c = src->str[i];
+
+		if (!isascii(c) || !isprint((unsigned char)c) || c == '<' || c == '>' || c == qc) {
+			l = snprintf(dst->str + dst->len, free, "<%02X>", (unsigned char)c);
+
+			if (free < l) {
+				dst->len = olen;
+				return dst->len;
+			}
+
+			dst->len += l;
+		} else {
+			dst->str[dst->len] = c;
+			dst->len++;
+		}
+	}
+
+	return dst->len;
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index f7252a4..f150d98 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -40,7 +40,7 @@
 #include <types/global.h>
 
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/checks.h>
 #include <proto/dumpstats.h>
 #include <proto/fd.h>
diff --git a/src/frontend.c b/src/frontend.c
index b07d3d1..ad4b970 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -22,6 +22,7 @@
 
 #include <netinet/tcp.h>
 
+#include <common/chunk.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
@@ -32,7 +33,7 @@
 
 #include <proto/acl.h>
 #include <proto/arg.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/fd.h>
 #include <proto/frontend.h>
 #include <proto/log.h>
diff --git a/src/haproxy.c b/src/haproxy.c
index f104740..3427dcc 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -52,6 +52,7 @@
 #include <common/appsession.h>
 #include <common/base64.h>
 #include <common/cfgparse.h>
+#include <common/chunk.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/defaults.h>
@@ -73,7 +74,7 @@
 #include <proto/auth.h>
 #include <proto/acl.h>
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/checks.h>
 #include <proto/fd.h>
 #include <proto/hdr_idx.h>
diff --git a/src/peers.c b/src/peers.c
index c293971..894502a 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -28,7 +28,7 @@
 #include <types/peers.h>
 
 #include <proto/acl.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/fd.h>
 #include <proto/log.h>
 #include <proto/hdr_idx.h>
diff --git a/src/proto_http.c b/src/proto_http.c
index de1cec6..a7e7b6e 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -27,6 +27,7 @@
 
 #include <common/appsession.h>
 #include <common/base64.h>
+#include <common/chunk.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
@@ -45,7 +46,7 @@
 #include <proto/arg.h>
 #include <proto/auth.h>
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/checks.h>
 #include <proto/dumpstats.h>
 #include <proto/fd.h>
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 9ff5b66..bdab4ab 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -39,9 +39,8 @@
 
 #include <proto/acl.h>
 #include <proto/arg.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/connection.h>
-//#include <proto/frontend.h>
 #include <proto/log.h>
 #include <proto/port_range.h>
 #include <proto/protocols.h>
@@ -52,7 +51,6 @@
 #include <proto/stick_table.h>
 #include <proto/stream_interface.h>
 #include <proto/task.h>
-#include <proto/buffers.h>
 
 #ifdef CONFIG_HAP_CTTPROXY
 #include <import/ip_tproxy.h>
diff --git a/src/raw_sock.c b/src/raw_sock.c
index e13749e..80c8fb3 100644
--- a/src/raw_sock.c
+++ b/src/raw_sock.c
@@ -22,6 +22,7 @@
 
 #include <netinet/tcp.h>
 
+#include <common/buffer.h>
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
@@ -29,7 +30,6 @@
 #include <common/ticks.h>
 #include <common/time.h>
 
-#include <proto/buffers.h>
 #include <proto/connection.h>
 #include <proto/fd.h>
 #include <proto/freq_ctr.h>
diff --git a/src/sample.c b/src/sample.c
index f14b99b..aec94fe 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -14,10 +14,10 @@
 #include <string.h>
 #include <arpa/inet.h>
 
+#include <common/chunk.h>
 #include <common/standard.h>
 
 #include <proto/arg.h>
-#include <proto/buffers.h>
 #include <proto/sample.h>
 
 /* static sample used in sample_process() when <p> is NULL */
diff --git a/src/session.c b/src/session.c
index f2330d6..db6dec4 100644
--- a/src/session.c
+++ b/src/session.c
@@ -24,7 +24,7 @@
 #include <proto/acl.h>
 #include <proto/arg.h>
 #include <proto/backend.h>
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/checks.h>
 #include <proto/connection.h>
 #include <proto/dumpstats.h>
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 764bb3b..fe80b91 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -26,7 +26,7 @@
 #include <common/ticks.h>
 #include <common/time.h>
 
-#include <proto/buffers.h>
+#include <proto/channel.h>
 #include <proto/connection.h>
 #include <proto/fd.h>
 #include <proto/frontend.h>