diff --git a/include/proto/buffers.h b/include/proto/buffers.h index f35da6496..5caff85fb 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -69,6 +69,75 @@ static inline void buffer_init(struct buffer *buf) /* These functions are used to compute various buffer area sizes */ /*****************************************************************/ +/* Returns an absolute pointer for a position relative to the current buffer's + * pointer. It is written so that it is optimal when is a const. It is + * written as a macro instead of an inline function so that the compiler knows + * when it can optimize out the sign test on when passed an unsigned int. + */ +#define b_ptr(b, ofs) \ + ({ \ + char *__ret = (b)->p + (ofs); \ + if ((ofs) > 0 && __ret >= (b)->data + (b)->size) \ + __ret -= (b)->size; \ + else if ((ofs) < 0 && __ret < (b)->data) \ + __ret += (b)->size; \ + __ret; \ + }) + +/* Returns the start of the input data in a buffer */ +static inline char *bi_ptr(const struct buffer *b) +{ + return b->p; +} + +/* Returns the end of the input data in a buffer (pointer to next + * insertion point). + */ +static inline char *bi_end(const struct buffer *b) +{ + char *ret = b->p + b->i; + + if (ret >= b->data + b->size) + ret -= b->size; + return ret; +} + +/* Returns the amount of input data that can contiguously be read at once */ +static inline int bi_contig_data(const struct buffer *b) +{ + int data = b->data + b->size - b->p; + + if (data > b->i) + data = b->i; + return data; +} + +/* Returns the start of the output data in a buffer */ +static inline char *bo_ptr(const struct buffer *b) +{ + char *ret = b->p - b->o; + + if (ret < b->data) + ret += b->size; + return ret; +} + +/* Returns the end of the output data in a buffer */ +static inline char *bo_end(const struct buffer *b) +{ + return b->p; +} + +/* Returns the amount of output data that can contiguously be read at once */ +static inline int bo_contig_data(const struct buffer *b) +{ + char *beg = b->p - b->o; + + if (beg < b->data) + return b->data - beg; + return b->o; +} + /* Return the buffer's length in bytes by summing the input and the output */ static inline int buffer_len(const struct buffer *buf) { diff --git a/src/buffers.c b/src/buffers.c index 0352177a4..40aa57a96 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -46,7 +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->p = b_ptr(buf, (unsigned int)bytes); buf->o += bytes; buf->i -= bytes; buf->flags &= ~BF_OUT_EMPTY; @@ -54,7 +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->p = bi_end(buf); buf->o += forwarded; buf->i = 0; @@ -122,7 +122,7 @@ int buffer_write(struct buffer *buf, const char *msg, int len) memcpy(buf->p, msg, len); buf->o += len; - buf->p = buffer_wrap_add(buf, buf->p + len); + buf->p = b_ptr(buf, len); buf->total += len; buf->flags &= ~(BF_OUT_EMPTY|BF_FULL); @@ -147,7 +147,7 @@ int buffer_put_char(struct buffer *buf, char c) if (buf->flags & BF_FULL) return -1; - *buffer_wrap_add(buf, buf->p + buf->i) = c; + *bi_end(buf) = c; buf->i++; if (buffer_len(buf) >= buffer_max_len(buf)) @@ -198,7 +198,7 @@ int buffer_put_block(struct buffer *buf, const char *blk, int len) /* OK so the data fits in the buffer in one or two blocks */ max = buffer_contig_space_with_res(buf, buf->size - max); - memcpy(buffer_wrap_add(buf, buf->p + buf->i), blk, MIN(len, max)); + memcpy(bi_end(buf), blk, MIN(len, max)); if (len > max) memcpy(buf->data, blk + max, len - max); @@ -213,7 +213,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->p = b_ptr(buf, fwd); buf->flags &= ~BF_OUT_EMPTY; } @@ -251,7 +251,7 @@ int buffer_get_line(struct buffer *buf, char *str, int len) goto out; } - p = buffer_wrap_sub(buf, buf->p - buf->o); + p = bo_ptr(buf); if (max > buf->o) { max = buf->o; @@ -297,14 +297,14 @@ int buffer_get_block(struct buffer *buf, char *blk, int len, int offset) return 0; } - firstblock = buf->data + buf->size - buffer_wrap_sub(buf, buf->p - buf->o); + firstblock = buf->data + buf->size - bo_ptr(buf); if (firstblock > offset) { if (firstblock >= len + offset) { - memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, len); + memcpy(blk, bo_ptr(buf) + offset, len); return len; } - memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, firstblock - offset); + memcpy(blk, bo_ptr(buf) + offset, firstblock - offset); memcpy(blk + firstblock - offset, buf->data, len - firstblock + offset); return len; } @@ -329,16 +329,16 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int delta = len - (end - pos); - if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size) + if (bi_end(b) + delta >= b->data + b->size) return 0; /* no space left */ if (buffer_not_empty(b) && - delta + buffer_wrap_add(b, b->p + b->i) > buffer_wrap_sub(b, b->p - b->o) && - buffer_wrap_sub(b, b->p - b->o) >= buffer_wrap_add(b, b->p + b->i)) + bi_end(b) + delta > bo_ptr(b) && + bo_ptr(b) >= bi_end(b)) return 0; /* no space left before wrapping data */ /* first, protect the end of the buffer */ - memmove(end + delta, end, buffer_wrap_add(b, b->p + b->i) - end); + memmove(end + delta, end, bi_end(b) - end); /* now, copy str over pos */ if (len) @@ -371,11 +371,11 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len) delta = len + 2; - if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size) + if (bi_end(b) + delta >= b->data + b->size) return 0; /* no space left */ /* first, protect the end of the buffer */ - memmove(pos + delta, pos, buffer_wrap_add(b, b->p + b->i) - pos); + memmove(pos + delta, pos, bi_end(b) - pos); /* now, copy str over pos */ if (len && str) { @@ -405,7 +405,7 @@ void buffer_bounce_realign(struct buffer *buf) int advance, to_move; char *from, *to; - from = buffer_wrap_sub(buf, buf->p - buf->o); + from = bo_ptr(buf); advance = buf->data + buf->size - from; if (!advance) return; @@ -435,11 +435,11 @@ void buffer_bounce_realign(struct buffer *buf) * empty area is either between buf->r and from or before from or * after buf->r. */ - if (from > buffer_wrap_add(buf, buf->p + buf->i)) { - if (to >= buffer_wrap_add(buf, buf->p + buf->i) && to < from) + if (from > bi_end(buf)) { + if (to >= bi_end(buf) && to < from) break; - } else if (from < buffer_wrap_add(buf, buf->p + buf->i)) { - if (to < from || to >= buffer_wrap_add(buf, buf->p + buf->i)) + } else if (from < bi_end(buf)) { + if (to < from || to >= bi_end(buf)) break; } diff --git a/src/proto_http.c b/src/proto_http.c index 0dc2b51d6..eac0319cf 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1744,10 +1744,10 @@ void http_change_connection_header(struct http_txn *txn, struct http_msg *msg, i int http_parse_chunk_size(struct http_msg *msg) { const struct buffer *buf = msg->buf; - const char *ptr = buffer_wrap_add(buf, buf->p + msg->next); + const char *ptr = b_ptr(buf, msg->next); const char *ptr_old = ptr; const char *end = buf->data + buf->size; - const char *stop = buffer_wrap_add(buf, buf->p + buf->i); + const char *stop = bi_end(buf); unsigned int chunk = 0; /* The chunk size is in the following form, though we are only @@ -1856,8 +1856,8 @@ int http_forward_trailers(struct http_msg *msg) /* we have msg->next which points to next line. Look for CRLF. */ while (1) { const char *p1 = NULL, *p2 = NULL; - const char *ptr = buffer_wrap_add(buf, buf->p + msg->next); - const char *stop = buffer_wrap_add(buf, buf->p + buf->i); + const char *ptr = b_ptr(buf, msg->next); + const char *stop = bi_end(buf); int bytes; /* scan current line and stop at LF or CRLF */ @@ -1890,7 +1890,7 @@ int http_forward_trailers(struct http_msg *msg) if (p2 >= buf->data + buf->size) p2 = buf->data; - bytes = p2 - buffer_wrap_add(buf, buf->p + msg->next); + bytes = p2 - b_ptr(buf, msg->next); if (bytes < 0) bytes += buf->size; @@ -1899,7 +1899,7 @@ int http_forward_trailers(struct http_msg *msg) if (msg->sov >= buf->size) msg->sov -= buf->size; - if (p1 == buffer_wrap_add(buf, buf->p + msg->next)) { + if (p1 == b_ptr(buf, msg->next)) { /* LF/CRLF at beginning of line => end of trailers at p2. * Everything was scheduled for forwarding, there's nothing * left from this message. @@ -2058,8 +2058,8 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) if (buffer_not_empty(req) && msg->msg_state < HTTP_MSG_ERROR) { if ((txn->flags & TX_NOT_FIRST) && unlikely((req->flags & BF_FULL) || - buffer_wrap_add(req, req->p + req->i) < buffer_wrap_add(req, req->p + msg->next) || - buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite)) { + bi_end(req) < b_ptr(req, msg->next) || + bi_end(req) > req->data + req->size - global.tune.maxrewrite)) { if (req->o) { if (req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) goto failed_keep_alive; @@ -2068,8 +2068,8 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */ return 0; } - if (buffer_wrap_add(req, req->p + req->i) < buffer_wrap_add(req, req->p + msg->next) || - buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite) + if (bi_end(req) < b_ptr(req, msg->next) || + bi_end(req) > req->data + req->size - global.tune.maxrewrite) http_message_realign(msg); } @@ -2082,8 +2082,8 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) */ if ((txn->flags & TX_NOT_FIRST) && unlikely((s->rep->flags & BF_FULL) || - buffer_wrap_add(s->rep, s->rep->p + s->rep->i) < buffer_wrap_add(s->rep, s->rep->p + txn->rsp.next) || - buffer_wrap_add(s->rep, s->rep->p + s->rep->i) > s->rep->data + s->rep->size - global.tune.maxrewrite)) { + bi_end(s->rep) < b_ptr(s->rep, txn->rsp.next) || + bi_end(s->rep) > s->rep->data + s->rep->size - global.tune.maxrewrite)) { if (s->rep->o) { if (s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) goto failed_keep_alive; @@ -3812,7 +3812,7 @@ void http_end_txn_clean_session(struct session *s) if (s->req->i) { if (s->rep->o && !(s->rep->flags & BF_FULL) && - buffer_wrap_add(s->rep, s->rep->p + s->rep->i) <= s->rep->data + s->rep->size - global.tune.maxrewrite) + bi_end(s->rep) <= s->rep->data + s->rep->size - global.tune.maxrewrite) s->rep->flags |= BF_EXPECT_MORE; } @@ -4469,8 +4469,8 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) */ if (buffer_not_empty(rep) && msg->msg_state < HTTP_MSG_ERROR) { if (unlikely((rep->flags & BF_FULL) || - buffer_wrap_add(rep, rep->p + rep->i) < buffer_wrap_add(rep, rep->p + msg->next) || - buffer_wrap_add(rep, rep->p + rep->i) > rep->data + rep->size - global.tune.maxrewrite)) { + bi_end(rep) < b_ptr(rep, msg->next) || + bi_end(rep) > rep->data + rep->size - global.tune.maxrewrite)) { if (rep->o) { /* some data has still not left the buffer, wake us once that's done */ if (rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) @@ -7221,24 +7221,24 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s, { struct buffer *buf = msg->buf; - if (buffer_wrap_add(buf, buf->p + buf->i) <= (buf->p + msg->som)) { /* message wraps */ + if (bi_end(buf) <= (buf->p + msg->som)) { /* message wraps */ int len1 = buf->size - msg->som - (buf->p - buf->data); - es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->p + msg->som) + buf->size; + es->len = bi_end(buf) - (buf->p + msg->som) + buf->size; memcpy(es->buf, buf->p + msg->som, MIN(len1, sizeof(es->buf))); if (es->len > len1 && len1 < sizeof(es->buf)) memcpy(es->buf, buf->data, MIN(es->len, sizeof(es->buf)) - len1); } else { - es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->p + msg->som); + es->len = bi_end(buf) - (buf->p + msg->som); memcpy(es->buf, buf->p + msg->som, MIN(es->len, sizeof(es->buf))); } if (msg->err_pos >= 0) es->pos = msg->err_pos - msg->som - (buf->p - buf->data); - else if (buffer_wrap_add(buf, buf->p + msg->next) >= (buf->p + msg->som)) - es->pos = buffer_wrap_add(buf, buf->p + msg->next) - (buf->p + msg->som); + else if (b_ptr(buf, msg->next) >= (buf->p + msg->som)) + es->pos = b_ptr(buf, msg->next) - (buf->p + msg->som); else - es->pos = buffer_wrap_add(buf, buf->p + msg->next) - (buf->p + msg->som) + buf->size; + es->pos = b_ptr(buf, msg->next) - (buf->p + msg->som) + buf->size; es->when = date; // user-visible date es->sid = s->uniq_id; diff --git a/src/stream_sock.c b/src/stream_sock.c index 0baf825bf..038e8c81a 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -295,7 +295,7 @@ int stream_sock_read(int fd) { /* * 2. read the largest possible block */ - ret = recv(fd, buffer_wrap_add(b, b->p + b->i), max, 0); + ret = recv(fd, bi_end(b), max, 0); if (ret > 0) { b->i += ret; @@ -311,7 +311,7 @@ int stream_sock_read(int fd) { } b->o += fwd; b->i -= fwd; - b->p = buffer_wrap_add(b, b->p + fwd); + b->p = b_ptr(b, fwd); b->flags &= ~BF_OUT_EMPTY; } @@ -626,7 +626,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, buffer_wrap_sub(b, b->p - b->o), max, send_flag); + ret = send(si->fd, bo_ptr(b), max, send_flag); } else { int skerr; socklen_t lskerr = sizeof(skerr); @@ -635,7 +635,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, buffer_wrap_sub(b, b->p - b->o), max, MSG_DONTWAIT); + ret = send(si->fd, bo_ptr(b), max, MSG_DONTWAIT); } if (ret > 0) {