[MEDIUM] add a send limit to a buffer

For keep-alive, line-mode protocols and splicing, we will need to
limit the sender to process a certain amount of bytes. The limit
is automatically set to the buffer size when analysers are detached
from the buffer.
diff --git a/src/buffers.c b/src/buffers.c
index f7e672d..3938fc3 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -30,7 +30,8 @@
 
 
 /* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
- * success, or the number of bytes available otherwise.
+ * success, or the number of bytes available otherwise. The send limit is
+ * automatically adjusted with the amount of data written.
  * FIXME-20060521: handle unaligned data.
  */
 int buffer_write(struct buffer *buf, const char *msg, int len)
@@ -44,6 +45,7 @@
 
 	memcpy(buf->r, msg, len);
 	buf->l += len;
+	buf->send_max += len;
 	buf->r += len;
 	buf->total += len;
 	if (buf->r == buf->data + BUFSIZE)
@@ -60,7 +62,8 @@
 
 /* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
  * success, or the number of bytes available otherwise. If the chunk
- * has been written, its size is automatically reset to zero.
+ * has been written, its size is automatically reset to zero. The send limit is
+ * automatically adjusted with the amount of data written.
  */
 int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
 {
@@ -76,6 +79,7 @@
 
 	memcpy(buf->r, chunk->str, chunk->len);
 	buf->l += chunk->len;
+	buf->send_max += chunk->len;
 	buf->r += chunk->len;
 	buf->total += chunk->len;
 	if (buf->r == buf->data + BUFSIZE)
@@ -133,7 +137,7 @@
 
 /*
  * same except that the string length is given, which allows str to be NULL if
- * len is 0.
+ * len is 0. The send limit is *not* adjusted.
  */
 int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
 {
@@ -178,7 +182,7 @@
  * argument informs about the length of string <str> so that we don't have to
  * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
  * is only opened for len+2 bytes but nothing is copied in. It may be useful in
- * some circumstances.
+ * some circumstances. The send limit is *not* adjusted.
  *
  * The number of bytes added is returned on success. 0 is returned on failure.
  */
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index e31398a..21c50fc 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -799,6 +799,10 @@
 			resync = 1;
 	}
 
+	/* if noone is interested in analysing data, let's forward everything */
+	if (!s->req->analysers && !(s->req->flags & BF_HIJACK))
+		s->req->send_max = s->req->l;
+
 	/* reflect what the L7 analysers have seen last */
 	rqf_last = s->req->flags;
 
@@ -869,6 +873,10 @@
 			resync = 1;
 	}
 
+	/* if noone is interested in analysing data, let's forward everything */
+	if (!s->rep->analysers && !(s->rep->flags & BF_HIJACK))
+		s->rep->send_max = s->rep->l;
+
 	/* reflect what the L7 analysers have seen last */
 	rpf_last = s->rep->flags;
 
diff --git a/src/session.c b/src/session.c
index 6bad79a..95ece53 100644
--- a/src/session.c
+++ b/src/session.c
@@ -744,6 +744,10 @@
 			resync = 1;
 	}
 
+	/* if noone is interested in analysing data, let's forward everything */
+	if (!s->req->analysers && !(s->req->flags & BF_HIJACK))
+		s->req->send_max = s->req->l;
+
 	/* reflect what the L7 analysers have seen last */
 	rqf_last = s->req->flags;
 
@@ -849,6 +853,10 @@
 			resync = 1;
 	}
 
+	/* if noone is interested in analysing data, let's forward everything */
+	if (!s->rep->analysers && !(s->rep->flags & BF_HIJACK))
+		s->rep->send_max = s->rep->l;
+
 	/* reflect what the L7 analysers have seen last */
 	rpf_last = s->rep->flags;
 
diff --git a/src/stream_sock.c b/src/stream_sock.c
index d4a603c..68471ed 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -114,6 +114,10 @@
 			b->l += ret;
 			cur_read += ret;
 
+			/* if noone is interested in analysing data, let's forward everything */
+			if (!b->analysers)
+				b->send_max += ret;
+
 			if (fdtab[fd].state == FD_STCONN)
 				fdtab[fd].state = FD_STREADY;
 
@@ -306,6 +310,10 @@
 			max = b->data + BUFSIZE - b->w;
 		}
 
+		/* limit the amount of outgoing data if required */
+		if (max > b->send_max)
+			max = b->send_max;
+
 		if (max == 0) {
 			/* may be we have received a connection acknowledgement in TCP mode without data */
 			if (likely(fdtab[fd].state == FD_STCONN)) {
@@ -363,6 +371,7 @@
 		if (ret > 0) {
 			b->l -= ret;
 			b->w += ret;
+			b->send_max -= ret;
 
 			if (fdtab[fd].state == FD_STCONN)
 				fdtab[fd].state = FD_STREADY;