diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 03c44b393..d4ae20b92 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -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 to buffer . 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 into buffer 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 diff --git a/src/buffers.c b/src/buffers.c index ed2aa1e52..6d406c515 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -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 to buffer . Returns -1 in case of success, +/* Try to write string into buffer 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; }