]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: buffers: replace buf->w with buf->p - buf->o
authorWilly Tarreau <w@1wt.eu>
Fri, 2 Mar 2012 15:13:16 +0000 (16:13 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 10:28:10 +0000 (12:28 +0200)
This change introduces the buffer's base pointer, which is the limit between
incoming and outgoing data. It's the point where the parsing should start
from. A number of computations have already been greatly simplified, but
more simplifications are expected to come from the removal of buf->r.

The changes appear good and have revealed occasional improper use of some
pointers. It is possible that this patch has introduced bugs or revealed
some, although preliminary testings tend to indicate that everything still
works as it should.

include/proto/buffers.h
include/types/buffers.h
src/acl.c
src/buffers.c
src/dumpstats.c
src/proto_http.c
src/proto_tcp.c
src/stream_sock.c

index 18495b58fb568e96a42b3cbd6b6beb3a429fd976..0aa1ff398c528527bc7e5790b21f62a08ed1bc88 100644 (file)
@@ -62,7 +62,7 @@ static inline void buffer_init(struct buffer *buf)
        buf->analysers = 0;
        buf->cons = NULL;
        buf->flags = BF_OUT_EMPTY;
-       buf->r = buf->lr = buf->w = buf->data;
+       buf->r = buf->lr = buf->p = buf->data;
 }
 
 /*****************************************************************/
@@ -186,7 +186,7 @@ static inline int buffer_contig_space_res(const struct buffer *buf)
        if (buffer_len(buf) >= spare)
                spare = 0;
        else if (buffer_len(buf)) {
-               spare = buf->w - res - buf->r;
+               spare = buffer_wrap_sub(buf, buf->p - buf->o) - res - buf->r;
                if (spare <= 0)
                        spare += buf->size;
                spare = buffer_contig_area(buf, buf->r, spare);
@@ -209,7 +209,7 @@ static inline int buffer_contig_space_with_res(const struct buffer *buf, int res
        if (buffer_len(buf) >= spare)
                spare = 0;
        else if (buffer_len(buf)) {
-               spare = buf->w - res - buf->r;
+               spare = buffer_wrap_sub(buf, buf->p - buf->o) - res - buf->r;
                if (spare <= 0)
                        spare += buf->size;
                spare = buffer_contig_area(buf, buf->r, spare);
@@ -254,15 +254,15 @@ static inline int buffer_pending(const struct buffer *buf)
 /* 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->w+o. The work area includes the
+ * <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 == buf->r) /* pointer exactly at end, lets push forwards */
-               end = buf->w;
-       return buffer_count(buf, buffer_pointer(buf, buf->w + buf->o), end);
+               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 */
@@ -312,6 +312,7 @@ static inline void buffer_check_timeouts(struct buffer *b)
  */
 static inline void buffer_flush(struct buffer *buf)
 {
+       buf->p = buf->r;
        buf->o += buf->i;
        buf->i = 0;
        if (buf->o)
@@ -327,7 +328,7 @@ static inline void buffer_erase(struct buffer *buf)
        buf->o = 0;
        buf->i = 0;
        buf->to_forward = 0;
-       buf->r = buf->lr = buf->w = buf->data;
+       buf->r = buf->lr = buf->p = buf->data;
        buf->flags &= ~(BF_FULL | BF_OUT_EMPTY);
        if (!buf->pipe)
                buf->flags |= BF_OUT_EMPTY;
@@ -348,7 +349,7 @@ static inline void buffer_cut_tail(struct buffer *buf)
                return;
 
        buf->i = 0;
-       buf->r = buf->w + buf->o;
+       buf->r = buf->p;
        if (buf->r >= buf->data + buf->size)
                buf->r -= buf->size;
        buf->lr = buf->r;
@@ -364,9 +365,7 @@ static inline void buffer_cut_tail(struct buffer *buf)
 static inline void buffer_ignore(struct buffer *buf, int n)
 {
        buf->i -= n;
-       buf->w += n;
-       if (buf->w >= buf->data + buf->size)
-               buf->w -= buf->size;
+       buf->p = buffer_wrap_add(buf, buf->p + n);
        buf->flags &= ~BF_FULL;
        if (buffer_len(buf) >= buffer_max_len(buf))
                buf->flags |= BF_FULL;
@@ -457,7 +456,7 @@ static inline int buffer_realign(struct buffer *buf)
 {
        if (!(buf->i | buf->o)) {
                /* let's realign the buffer to optimize I/O */
-               buf->r = buf->w = buf->lr = buf->data;
+               buf->r = buf->p = buf->lr = buf->data;
        }
        return buffer_contig_space(buf);
 }
@@ -470,13 +469,9 @@ static inline int buffer_realign(struct buffer *buf)
  */
 static inline void buffer_skip(struct buffer *buf, int len)
 {
-       buf->w += len;
-       if (buf->w >= buf->data + buf->size)
-               buf->w -= buf->size; /* wrap around the buffer */
-
        buf->o -= len;
        if (buffer_len(buf) == 0)
-               buf->r = buf->w = buf->lr = buf->data;
+               buf->r = buf->p = buf->lr = buf->data;
 
        if (buffer_len(buf) < buffer_max_len(buf))
                buf->flags &= ~BF_FULL;
@@ -549,7 +544,7 @@ static inline int buffer_get_char(struct buffer *buf)
                        return -2;
                return -1;
        }
-       return *buf->w;
+       return *buffer_wrap_sub(buf, buf->p - buf->o);
 }
 
 
index cc394b25d92bc174fef1565374d60d4e885880a0..f25053215e36d6948f3f207d9e91d667555071c2 100644 (file)
@@ -180,7 +180,8 @@ struct buffer {
        int wex;                        /* expiration date for a write or connect, in ticks */
        int rto;                        /* read timeout, in ticks */
        int wto;                        /* write timeout, in ticks */
-       char *r, *w, *lr;               /* read ptr, write ptr, last read */
+       char *r, *lr;                   /* read ptr, last read */
+       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 */
index 430f985d71c3adfb5bea5c2b5d9da8f39235aef8..507516f31e433490e2b5b06019d6c27297824b27 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -123,7 +123,7 @@ acl_fetch_ssl_hello_type(struct proxy *px, struct session *l4, void *l7, int dir
        b = ((dir & ACL_DIR_MASK) == ACL_DIR_RTR) ? l4->rep : l4->req;
 
        bleft = b->i;
-       data = (const unsigned char *)b->w;
+       data = (const unsigned char *)b->p;
 
        if (!bleft)
                goto too_short;
@@ -191,7 +191,7 @@ acl_fetch_req_ssl_ver(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!bleft)
                goto too_short;
 
-       data = (const unsigned char *)l4->req->w;
+       data = (const unsigned char *)l4->req->p;
        if ((*data >= 0x14 && *data <= 0x17) || (*data == 0xFF)) {
                /* SSLv3 header format */
                if (bleft < 5)
@@ -259,8 +259,8 @@ acl_fetch_req_ssl_ver(struct proxy *px, struct session *l4, void *l7, int dir,
         * all the part of the request which fits in a buffer is already
         * there.
         */
-       if (msg_len > buffer_max_len(l4->req) + l4->req->data - l4->req->w)
-               msg_len = buffer_max_len(l4->req) + l4->req->data - l4->req->w;
+       if (msg_len > buffer_max_len(l4->req) + l4->req->data - l4->req->p)
+               msg_len = buffer_max_len(l4->req) + l4->req->data - l4->req->p;
 
        if (bleft < msg_len)
                goto too_short;
@@ -325,7 +325,7 @@ acl_fetch_ssl_hello_sni(struct proxy *px, struct session *l4, void *l7, int dir,
        b = ((dir & ACL_DIR_MASK) == ACL_DIR_RTR) ? l4->rep : l4->req;
 
        bleft = b->i;
-       data = (unsigned char *)b->w;
+       data = (unsigned char *)b->p;
 
        /* Check for SSL/TLS Handshake */
        if (!bleft)
@@ -463,7 +463,7 @@ acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
        if (bleft <= 11)
                goto too_short;
 
-       data = (const unsigned char *)l4->req->w + 11;
+       data = (const unsigned char *)l4->req->p + 11;
        bleft -= 11;
 
        if (bleft <= 7)
index 74e3a1069c06abeb659970b0713c4a17f4f0086b..41d36248c917207e1e1edc24f0ccb89b9e08b682 100644 (file)
@@ -46,6 +46,7 @@ unsigned long long buffer_forward(struct buffer *buf, unsigned long long bytes)
        if (!bytes)
                return 0;
        if (bytes <= (unsigned long long)buf->i) {
+               buf->p = buffer_wrap_add(buf, buf->p + bytes);
                buf->o += bytes;
                buf->i -= bytes;
                buf->flags &= ~BF_OUT_EMPTY;
@@ -53,6 +54,7 @@ unsigned long long buffer_forward(struct buffer *buf, unsigned long long bytes)
        }
 
        forwarded = buf->i;
+       buf->p = buffer_wrap_add(buf, buf->p + forwarded);
        buf->o += forwarded;
        buf->i = 0;
 
@@ -118,10 +120,9 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
 
        memcpy(buf->r, msg, len);
        buf->o += len;
-       buf->r += len;
+       buf->p = buffer_wrap_add(buf, buf->p + len);
+       buf->r = buffer_wrap_add(buf, buf->r + len);
        buf->total += len;
-       if (buf->r == buf->data + buf->size)
-               buf->r = buf->data;
 
        buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
        if (buffer_len(buf) >= buffer_max_len(buf))
@@ -216,6 +217,7 @@ int buffer_put_block(struct buffer *buf, const char *blk, int len)
                }
                buf->o += fwd;
                buf->i -= fwd;
+               buf->p = buffer_wrap_add(buf, buf->p + fwd);
                buf->flags &= ~BF_OUT_EMPTY;
        }
 
@@ -256,7 +258,7 @@ int buffer_get_line(struct buffer *buf, char *str, int len)
                goto out;
        }
 
-       p = buf->w;
+       p = buffer_wrap_sub(buf, buf->p - buf->o);
 
        if (max > buf->o) {
                max = buf->o;
@@ -269,9 +271,7 @@ int buffer_get_line(struct buffer *buf, char *str, int len)
 
                if (*p == '\n')
                        break;
-               p++;
-               if (p == buf->data + buf->size)
-                       p = buf->data;
+               p = buffer_wrap_add(buf, p + 1);
        }
        if (ret > 0 && ret < len && ret < buf->o &&
            *(str-1) != '\n' &&
@@ -304,14 +304,14 @@ int buffer_get_block(struct buffer *buf, char *blk, int len, int offset)
                return 0;
        }
 
-       firstblock = buf->data + buf->size - buf->w;
+       firstblock = buf->data + buf->size - buffer_wrap_sub(buf, buf->p - buf->o);
        if (firstblock > offset) {
                if (firstblock >= len + offset) {
-                       memcpy(blk, buf->w + offset, len);
+                       memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, len);
                        return len;
                }
 
-               memcpy(blk, buf->w + offset, firstblock - offset);
+               memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, firstblock - offset);
                memcpy(blk + firstblock - offset, buf->data, len - firstblock + offset);
                return len;
        }
@@ -338,7 +338,8 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int
        if (delta + b->r >= b->data + b->size)
                return 0;  /* no space left */
 
-       if (delta + b->r > b->w && b->w >= b->r && buffer_not_empty(b))
+       if (delta + b->r > buffer_wrap_sub(b, b->p - b->o) &&
+           buffer_wrap_sub(b, b->p - b->o) >= b->r && buffer_not_empty(b))
                return 0;  /* no space left before wrapping data */
 
        /* first, protect the end of the buffer */
@@ -355,7 +356,7 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int
 
        b->flags &= ~BF_FULL;
        if (buffer_len(b) == 0)
-               b->r = b->w = b->lr = b->data;
+               b->r = b->p = b->lr = b->data;
        if (buffer_len(b) >= buffer_max_len(b))
                b->flags |= BF_FULL;
 
@@ -414,11 +415,11 @@ void buffer_bounce_realign(struct buffer *buf)
        int advance, to_move;
        char *from, *to;
 
-       advance = buf->data + buf->size - buf->w;
+       from = buffer_wrap_sub(buf, buf->p - buf->o);
+       advance = buf->data + buf->size - from;
        if (!advance)
                return;
 
-       from = buf->w;
        to_move = buffer_len(buf);
        while (to_move) {
                char last, save;
@@ -576,8 +577,8 @@ int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc) {
 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 r=%p w=%p lr=%p\n",
-               b->data, b->o, b->i, b->r, b->w, b->lr);
+       fprintf(o, "  data=%p o=%d i=%d r=%p p=%p lr=%p\n",
+               b->data, b->o, b->i, b->r, b->p, b->lr);
 
        if (!to || to > buffer_len(b))
                to = buffer_len(b);
index 26cbdd6fb41406b1fce19a0cbe51c5665ddaaab4..e9f9171dcca6905d0216dbc3c640a76bc68e14e7 100644 (file)
@@ -3389,13 +3389,13 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
 
                chunk_printf(&msg,
                             " wex=%s\n"
-                            "      data=%p r=%d w=%d lr=%d total=%lld\n",
+                            "      data=%p r=%d p=%d lr=%d total=%lld\n",
                             sess->req->wex ?
                             human_time(TICKS_TO_MS(sess->req->wex - now_ms),
                                        TICKS_TO_MS(1000)) : "<NEVER>",
                             sess->req->data,
                             (int)(sess->req->r - sess->req->data),
-                            (int)(sess->req->w - sess->req->data),
+                            (int)(sess->req->p - sess->req->data),
                             (int)(sess->req->lr - sess->req->data),
                             sess->req->total);
 
@@ -3419,13 +3419,13 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
 
                chunk_printf(&msg,
                             " wex=%s\n"
-                            "      data=%p r=%d w=%d lr=%d total=%lld\n",
+                            "      data=%p r=%d p=%d lr=%d total=%lld\n",
                             sess->rep->wex ?
                             human_time(TICKS_TO_MS(sess->rep->wex - now_ms),
                                        TICKS_TO_MS(1000)) : "<NEVER>",
                             sess->rep->data,
                             (int)(sess->rep->r - sess->rep->data),
-                            (int)(sess->rep->w - sess->rep->data),
+                            (int)(sess->rep->p - sess->rep->data),
                             (int)(sess->rep->lr - sess->rep->data),
                             sess->rep->total);
 
index f1167c11454f2119143d747ab412a6a526a9bafd..06f658e08dda2e7ef9b702a7162fbeb630993186 100644 (file)
@@ -1297,9 +1297,8 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
                         * first if we need to remove some CRLF. We can only
                         * do this when o=0.
                         */
-                       char *beg = buf->w + buf->o;
-                       if (beg >= buf->data + buf->size)
-                               beg -= buf->size;
+                       char *beg = buf->p;
+
                        if (unlikely(ptr != beg)) {
                                if (buf->o)
                                        goto http_msg_ood;
@@ -1366,9 +1365,8 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
                         * first if we need to remove some CRLF. We can only
                         * do this when o=0.
                         */
-                       char *beg = buf->w + buf->o;
-                       if (beg >= buf->data + buf->size)
-                               beg -= buf->size;
+                       char *beg = buf->p;
+
                        if (likely(ptr != beg)) {
                                if (buf->o)
                                        goto http_msg_ood;
@@ -1963,10 +1961,11 @@ int http_skip_chunk_crlf(struct buffer *buf, struct http_msg *msg)
        return 1;
 }
 
+/* This function may only be used when the buffer's o is empty */
 void http_buffer_heavy_realign(struct buffer *buf, struct http_msg *msg)
 {
        char *end = buf->data + buf->size;
-       int off = buf->data + buf->size - buf->w;
+       int off = buf->data + buf->size - buf->p;
 
        /* two possible cases :
         *   - the buffer is in one contiguous block, we move it in-place
@@ -1975,20 +1974,20 @@ void http_buffer_heavy_realign(struct buffer *buf, struct http_msg *msg)
        if (buf->i) {
                int block1 = buf->i;
                int block2 = 0;
-               if (buf->r <= buf->w) {
+               if (buf->r <= buf->p) {
                        /* non-contiguous block */
-                       block1 = buf->data + buf->size - buf->w;
+                       block1 = buf->data + buf->size - buf->p;
                        block2 = buf->r - buf->data;
                }
                if (block2)
                        memcpy(swap_buffer, buf->data, block2);
-               memmove(buf->data, buf->w, block1);
+               memmove(buf->data, buf->p, block1);
                if (block2)
                        memcpy(buf->data + block1, swap_buffer, block2);
        }
 
        /* adjust all known pointers */
-       buf->w    = buf->data;
+       buf->p = buf->data;
        buf->lr  += off; if (buf->lr  >= end) buf->lr  -= buf->size;
        buf->r   += off; if (buf->r   >= end) buf->r   -= buf->size;
        msg->sol += off; if (msg->sol >= end) msg->sol -= buf->size;
@@ -3835,13 +3834,8 @@ void http_end_txn_clean_session(struct session *s)
        buffer_auto_close(s->rep);
 
        /* make ->lr point to the first non-forwarded byte */
-       s->req->lr = s->req->w + s->req->o;
-       if (s->req->lr >= s->req->data + s->req->size)
-               s->req->lr -= s->req->size;
-       s->rep->lr = s->rep->w + s->rep->o;
-       if (s->rep->lr >= s->rep->data + s->rep->size)
-               s->rep->lr -= s->req->size;
-
+       s->req->lr = s->req->p;
+       s->rep->lr = s->rep->p;
        s->req->analysers = s->listener->analysers;
        s->req->analysers &= ~AN_REQ_DECODE_PROXY;
        s->rep->analysers = 0;
@@ -4267,10 +4261,7 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit)
                        /* we want the CRLF after the data */
                        int ret;
 
-                       req->lr = req->w + req->o;
-                       if (req->lr >= req->data + req->size)
-                               req->lr -= req->size;
-
+                       req->lr = req->p;
                        ret = http_skip_chunk_crlf(req, msg);
 
                        if (ret == 0)
@@ -5331,10 +5322,7 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit
                        /* we want the CRLF after the data */
                        int ret;
 
-                       res->lr = res->w + res->o;
-                       if (res->lr >= res->data + res->size)
-                               res->lr -= res->size;
-
+                       res->lr = res->p;
                        ret = http_skip_chunk_crlf(res, msg);
 
                        if (!ret)
@@ -7458,9 +7446,7 @@ void http_reset_txn(struct session *s)
         */
        if (unlikely(s->rep->i)) {
                s->rep->i = 0;
-               s->rep->r = s->rep->w + s->rep->o;
-               if (s->rep->r >= s->rep->data + s->rep->size)
-                       s->rep->r -= s->rep->size;
+               s->rep->r = s->rep->p;
        }
 
        s->req->rto = s->fe->timeout.client;
index 7a3d7140b3d50296d500f5b84f2d54053ead8462..17144161bc7a361a61854996ffe2a5541277660c 100644 (file)
@@ -1484,7 +1484,7 @@ pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir,
                return 0;
 
        for (i = 0; i < len_size; i++) {
-               buf_size = (buf_size << 8) + ((unsigned char *)b->w)[i + len_offset];
+               buf_size = (buf_size << 8) + ((unsigned char *)b->p)[i + len_offset];
        }
 
        if (!buf_size)
@@ -1494,7 +1494,7 @@ pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, int dir,
                return 0;
 
        /* init chunk as read only */
-       chunk_initlen(&data->str, b->w + buf_offset, 0, buf_size);
+       chunk_initlen(&data->str, b->p + buf_offset, 0, buf_size);
 
        return 1;
 }
@@ -1557,7 +1557,7 @@ pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, int dir,
                return 0;
 
        /* init chunk as read only */
-       chunk_initlen(&data->str, b->w + buf_offset, 0, buf_size);
+       chunk_initlen(&data->str, b->p + buf_offset, 0, buf_size);
 
        return 1;
 }
index 74fe0b296fa6724e7516385aff00ae79d8f9b4e9..0d039ebecd15593f64bfcddf5631e52ec80aa588 100644 (file)
@@ -282,9 +282,10 @@ int stream_sock_read(int fd) {
                 */
                if (buffer_empty(b)) {
                        /* let's realign the buffer to optimize I/O */
-                       b->r = b->w = b->lr = b->data;
+                       b->r = b->p = b->lr = b->data;
                }
-               else if (b->r > b->w) {
+               else if (b->data + b->o < b->p &&
+                        b->p + b->i < b->data + b->size) {
                        /* remaining space wraps at the end, with a moving limit */
                        if (max > b->data + b->size - b->r)
                                max = b->data + b->size - b->r;
@@ -311,6 +312,7 @@ int stream_sock_read(int fd) {
                                }
                                b->o += fwd;
                                b->i -= fwd;
+                               b->p = buffer_wrap_add(b, b->p + fwd);
                                b->flags &= ~BF_OUT_EMPTY;
                        }
 
@@ -598,14 +600,11 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
         * data left, and that there are sendable buffered data.
         */
        while (1) {
-               if (b->r > b->w)
-                       max = b->r - b->w;
-               else
-                       max = b->data + b->size - b->w;
+               max = b->o;
 
-               /* limit the amount of outgoing data if required */
-               if (max > b->o)
-                       max = b->o;
+               /* outgoing data may wrap at the end */
+               if (b->data + max > b->p)
+                       max = b->data + max - b->p;
 
                /* check if we want to inform the kernel that we're interested in
                 * sending more data after this call. We want this if :
@@ -633,7 +632,7 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
                        if (b->flags & BF_SEND_DONTWAIT)
                                send_flag &= ~MSG_MORE;
 
-                       ret = send(si->fd, b->w, max, send_flag);
+                       ret = send(si->fd, buffer_wrap_sub(b, b->p - b->o), max, send_flag);
                } else {
                        int skerr;
                        socklen_t lskerr = sizeof(skerr);
@@ -642,7 +641,7 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
                        if (ret == -1 || skerr)
                                ret = -1;
                        else
-                               ret = send(si->fd, b->w, max, MSG_DONTWAIT);
+                               ret = send(si->fd, buffer_wrap_sub(b, b->p - b->o), max, MSG_DONTWAIT);
                }
 
                if (ret > 0) {
@@ -651,14 +650,10 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
 
                        b->flags |= BF_WRITE_PARTIAL;
 
-                       b->w += ret;
-                       if (b->w == b->data + b->size)
-                               b->w = b->data; /* wrap around the buffer */
-
                        b->o -= ret;
                        if (likely(!buffer_len(b)))
                                /* optimize data alignment in the buffer */
-                               b->r = b->w = b->lr = b->data;
+                               b->r = b->p = b->lr = b->data;
 
                        if (likely(buffer_len(b) < buffer_max_len(b)))
                                b->flags &= ~BF_FULL;