]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] buffers: provide new buffer_feed*() function
authorWilly Tarreau <w@1wt.eu>
Mon, 31 Aug 2009 06:09:57 +0000 (08:09 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 19 Sep 2009 12:53:46 +0000 (14:53 +0200)
This functions act like their buffer_write*() counter-parts,
except that they're specifically designed to be used from a
stream interface handler, as they carefully check size limits
and automatically advance the read pointer depending on the
to_forward attribute.

buffer_feed_chunk() is an inline calling buffer_feed() as both
are the sames. For this reason, buffer_write_chunk() has also
been turned into an inline which calls buffer_write().

include/proto/buffers.h
src/buffers.c

index 03c44b3930acd19fd628991e7f950dbea1886f90..d4ae20b92ad5ed7cdb7f90e72fd48eb4386662fc 100644 (file)
@@ -348,7 +348,7 @@ static inline void buffer_skip(struct buffer *buf, int len)
 }
 
 int buffer_write(struct buffer *buf, const char *msg, int len);
-int buffer_write_chunk(struct buffer *buf, struct chunk *chunk);
+int buffer_feed(struct buffer *buf, const char *str, int len);
 int buffer_replace(struct buffer *b, char *pos, char *end, const char *str);
 int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len);
 int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
@@ -356,6 +356,41 @@ int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
        __attribute__ ((format(printf, 3, 4)));
 void buffer_dump(FILE *o, struct buffer *b, int from, int to);
 
+
+/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of success,
+ * -2 if it is larger than the buffer size, or the number of bytes available
+ * otherwise. If the chunk has been written, its size is automatically reset
+ * to zero. The send limit is automatically adjusted with the amount of data
+ * written.
+ */
+static inline int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
+{
+       int ret;
+
+       ret = buffer_write(buf, chunk->str, chunk->len);
+       if (ret == -1)
+               chunk->len = 0;
+       return ret;
+}
+
+/* Try to write chunk <chunk> into buffer <buf> after length controls. This is
+ * the equivalent of buffer_write_chunk() except that to_forward and send_max
+ * are updated and that max_len is respected. Returns -1 in case of success,
+ * -2 if it is larger than the buffer size, or the number of bytes available
+ * otherwise. If the chunk has been written, its size is automatically reset
+ * to zero. The send limit is automatically adjusted with the amount of data
+ * written.
+ */
+static inline int buffer_feed_chunk(struct buffer *buf, struct chunk *chunk)
+{
+       int ret;
+
+       ret = buffer_feed(buf, chunk->str, chunk->len);
+       if (ret == -1)
+               chunk->len = 0;
+       return ret;
+}
+
 /*
  * frees the destination chunk if already allocated, allocates a new string,
  * and copies the source into it. The pointer to the destination string is
index ed2aa1e525cb103daf78352815bd632c3161b59d..6d406c515b484ca9fa641fe0ca5ef713d9e9cb47 100644 (file)
@@ -39,7 +39,8 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
 {
        int max;
 
-       max = buffer_realign(buf);
+       if (len == 0)
+               return -1;
 
        if (len > buf->size) {
                /* we can't write this chunk and will never be able to, because
@@ -50,6 +51,8 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
                return -2;
        }
 
+       max = buffer_realign(buf);
+
        if (len > max)
                return max;
 
@@ -70,48 +73,49 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
        return -1;
 }
 
-/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of success,
+/* Try to write string <str> into buffer <buf> after length controls. This
+ * is the equivalent of buffer_write() except that to_forward and send_max
+ * are updated and that max_len is respected. Returns -1 in case of success,
  * -2 if it is larger than the buffer size, or the number of bytes available
- * otherwise. If the chunk has been written, its size is automatically reset
- * to zero. The send limit is automatically adjusted with the amount of data
+ * otherwise. The send limit is automatically adjusted with the amount of data
  * written.
  */
-int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
+int buffer_feed(struct buffer *buf, const char *str, int len)
 {
        int max;
 
-       if (chunk->len == 0)
+       if (len == 0)
                return -1;
 
-       if (chunk->len > buf->size) {
+       if (len > buf->max_len) {
                /* we can't write this chunk and will never be able to, because
-                * it is larger than the buffer. This must be reported as an
-                * error. Then we return -2 so that writers that don't care can
-                * ignore it and go on, and others can check for this value.
+                * it is larger than the buffer's current max size.
                 */
                return -2;
        }
 
-       max = buffer_realign(buf);
+       max = buffer_contig_space(buf);
 
-       if (chunk->len > max)
+       if (len > max)
                return max;
 
-       memcpy(buf->r, chunk->str, chunk->len);
-       buf->l += chunk->len;
-       buf->send_max += chunk->len;
-       buf->r += chunk->len;
-       buf->total += chunk->len;
+       memcpy(buf->r, str, len);
+       buf->l += len;
+       buf->r += len;
+       buf->total += len;
+       if (buf->to_forward > 0) {
+               int fwd = MIN(buf->to_forward, len);
+               buf->send_max   += fwd;
+               buf->to_forward -= fwd;
+       }
+
        if (buf->r == buf->data + buf->size)
                buf->r = buf->data;
 
        buf->flags &= ~(BF_EMPTY|BF_FULL);
-       if (buf->l == 0)
-               buf->flags |= BF_EMPTY;
        if (buf->l >= buf->max_len)
                buf->flags |= BF_FULL;
 
-       chunk->len = 0;
        return -1;
 }