diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 18495b58f..0aa1ff398 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -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 . * If 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 - * . It always starts at buf->w+o. The work area includes the + * . 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); } diff --git a/include/types/buffers.h b/include/types/buffers.h index cc394b25d..f25053215 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -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 */ diff --git a/src/acl.c b/src/acl.c index 430f985d7..507516f31 100644 --- 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) diff --git a/src/buffers.c b/src/buffers.c index 74e3a1069..41d36248c 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -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); diff --git a/src/dumpstats.c b/src/dumpstats.c index 26cbdd6fb..e9f9171dc 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -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)) : "", 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)) : "", 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); diff --git a/src/proto_http.c b/src/proto_http.c index f1167c114..06f658e08 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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; diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 7a3d7140b..17144161b 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -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; } diff --git a/src/stream_sock.c b/src/stream_sock.c index 74fe0b296..0d039ebec 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -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;