diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 2b2b2acce..a95e5a1f8 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->lr = buf->p = buf->data; + buf->p = buf->data; } /*****************************************************************/ @@ -317,7 +317,7 @@ static inline void buffer_erase(struct buffer *buf) buf->o = 0; buf->i = 0; buf->to_forward = 0; - buf->lr = buf->p = buf->data; + buf->p = buf->data; buf->flags &= ~(BF_FULL | BF_OUT_EMPTY); if (!buf->pipe) buf->flags |= BF_OUT_EMPTY; @@ -338,7 +338,6 @@ static inline void buffer_cut_tail(struct buffer *buf) return; buf->i = 0; - buf->lr = buf->p; buf->flags &= ~BF_FULL; if (buffer_len(buf) >= buffer_max_len(buf)) buf->flags |= BF_FULL; @@ -442,7 +441,7 @@ static inline int buffer_realign(struct buffer *buf) { if (!(buf->i | buf->o)) { /* let's realign the buffer to optimize I/O */ - buf->p = buf->lr = buf->data; + buf->p = buf->data; } return buffer_contig_space(buf); } @@ -457,7 +456,7 @@ static inline void buffer_skip(struct buffer *buf, int len) { buf->o -= len; if (buffer_len(buf) == 0) - buf->p = buf->lr = buf->data; + buf->p = buf->data; if (buffer_len(buf) < buffer_max_len(buf)) buf->flags &= ~BF_FULL; diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index 0eed363ea..e7d1da6d7 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -113,6 +113,7 @@ struct chunk *error_message(struct session *s, int msgnum); /* to be used when contents change in an HTTP message */ #define http_msg_move_end(msg, bytes) do { \ unsigned int _bytes = (bytes); \ + (msg)->next += (_bytes); \ (msg)->col += (_bytes); \ (msg)->sov += (_bytes); \ (msg)->eoh += (_bytes); \ diff --git a/include/types/buffers.h b/include/types/buffers.h index 59254551f..ab5612912 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -180,7 +180,6 @@ 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 *lr; /* last read 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 */ diff --git a/include/types/proto_http.h b/include/types/proto_http.h index 463149ae3..02468fa49 100644 --- a/include/types/proto_http.h +++ b/include/types/proto_http.h @@ -304,6 +304,7 @@ enum { struct http_msg { unsigned int msg_state; /* where we are in the current message parsing */ unsigned int flags; /* flags describing the message (HTTP version, ...) */ + unsigned int next; /* pointer to next byte to parse, relative to buf->p */ unsigned int col, sov; /* current header: colon, start of value */ unsigned int eoh; /* End Of Headers, relative to buffer */ char *sol; /* start of line, also start of message when fully parsed */ diff --git a/src/buffers.c b/src/buffers.c index 91a0cbbc7..0352177a4 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -315,12 +315,13 @@ int buffer_get_block(struct buffer *buf, char *blk, int len, int offset) /* This function writes the string at position which must be in * buffer , and moves just after the end of . 's parameters - * (l, r, lr) are updated to be valid after the shift. the shift value + * and are updated to be valid after the shift. The shift value * (positive or negative) is returned. If there's no space left, the move is - * not done. The function does not adjust ->o nor BF_OUT_EMPTY because - * it does not make sense to use it on data scheduled to be sent. The string - * length is taken from parameter . If is null, the pointer - * is allowed to be null. + * not done. The function does not adjust ->o nor BF_OUT_EMPTY because it + * does not make sense to use it on data scheduled to be sent. For the same + * reason, it does not make sense to call this function on unparsed data, so + * is not updated. The string length is taken from parameter . If + * is null, the pointer is allowed to be null. */ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len) { @@ -343,13 +344,11 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int if (len) memcpy(pos, str, len); - /* we only move data after the displaced zone */ - if (b->lr > pos) b->lr += delta; b->i += delta; b->flags &= ~BF_FULL; if (buffer_len(b) == 0) - b->p = b->lr = b->data; + b->p = b->data; if (buffer_len(b) >= buffer_max_len(b)) b->flags |= BF_FULL; @@ -361,7 +360,8 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int * argument informs about the length of string so that we don't have to * measure it. It does not include the "\r\n". If is NULL, then the buffer * is only opened for len+2 bytes but nothing is copied in. It may be useful in - * some circumstances. The send limit is *not* adjusted. + * some circumstances. The send limit is *not* adjusted. Same comments as above + * for the valid use cases. * * The number of bytes added is returned on success. 0 is returned on failure. */ @@ -384,8 +384,6 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len) pos[len + 1] = '\n'; } - /* we only move data after the displaced zone */ - if (b->lr > pos) b->lr += delta; b->i += delta; b->flags &= ~BF_FULL; @@ -569,8 +567,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 p=%p lr=%p\n", - b->data, b->o, b->i, b->p, b->lr); + fprintf(o, " data=%p o=%d i=%d p=%p\n", + b->data, b->o, b->i, b->p); if (!to || to > buffer_len(b)) to = buffer_len(b); diff --git a/src/dumpstats.c b/src/dumpstats.c index d0baa7106..106ea8cb5 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 p=%d lr=%d total=%lld\n", + " data=%p p=%d next=%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->p - sess->req->data), - (int)(sess->req->lr - sess->req->data), + sess->txn.req.next, sess->req->total); chunk_printf(&msg, @@ -3418,13 +3418,13 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si) chunk_printf(&msg, " wex=%s\n" - " data=%p p=%d lr=%d total=%lld\n", + " data=%p p=%d next=%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->p - sess->rep->data), - (int)(sess->rep->lr - sess->rep->data), + sess->txn.rsp.next, sess->rep->total); if (buffer_feed_chunk(si->ib, &msg) >= 0) diff --git a/src/proto_http.c b/src/proto_http.c index aebca1bc1..bf9980cc5 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -390,17 +390,17 @@ static void http_silent_debug(int line, struct session *s) { int size = 0; size += snprintf(trash + size, sizeof(trash) - size, - "[%04d] req: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p lr=%p sm=%d fw=%ld tf=%08x\n", + "[%04d] req: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p o=%p sm=%d fw=%ld tf=%08x\n", line, s->si[0].state, s->si[0].fd, s->txn.req.msg_state, s->req->flags, s->req->analysers, - s->req->data, s->req->size, s->req->l, s->req->w, s->req->r, s->req->lr, s->req->o, s->req->to_forward, s->txn.flags); + s->req->data, s->req->size, s->req->l, s->req->w, s->req->r, s->req->p, s->req->o, s->req->to_forward, s->txn.flags); write(-1, trash, size); size = 0; size += snprintf(trash + size, sizeof(trash) - size, - " %04d rep: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p lr=%p sm=%d fw=%ld\n", + " %04d rep: p=%d(%d) s=%d bf=%08x an=%08x data=%p size=%d l=%d w=%p r=%p o=%p sm=%d fw=%ld\n", line, s->si[1].state, s->si[1].fd, s->txn.rsp.msg_state, s->rep->flags, s->rep->analysers, - s->rep->data, s->rep->size, s->rep->l, s->rep->w, s->rep->r, s->rep->lr, s->rep->o, s->rep->to_forward); + s->rep->data, s->rep->size, s->rep->l, s->rep->w, s->rep->r, s->rep->p, s->rep->o, s->rep->to_forward); write(-1, trash, size); } @@ -951,8 +951,9 @@ void capture_headers(char *som, struct hdr_idx *idx, * labels and variable names. Note that msg->sol is left unchanged. */ const char *http_parse_stsline(struct http_msg *msg, const char *msg_buf, + const char *msg_start, unsigned int state, const char *ptr, const char *end, - char **ret_ptr, unsigned int *ret_state) + unsigned int *ret_ptr, unsigned int *ret_state) { switch (state) { case HTTP_MSG_RPVER: @@ -1035,7 +1036,7 @@ const char *http_parse_stsline(struct http_msg *msg, const char *msg_buf, if (ret_state) *ret_state = state; if (ret_ptr) - *ret_ptr = (char *)ptr; + *ret_ptr = ptr - msg_start; return NULL; } @@ -1059,8 +1060,9 @@ const char *http_parse_stsline(struct http_msg *msg, const char *msg_buf, * labels and variable names. Note that msg->sol is left unchanged. */ const char *http_parse_reqline(struct http_msg *msg, const char *msg_buf, + const char *msg_start, unsigned int state, const char *ptr, const char *end, - char **ret_ptr, unsigned int *ret_state) + unsigned int *ret_ptr, unsigned int *ret_state) { switch (state) { case HTTP_MSG_RQMETH: @@ -1177,7 +1179,7 @@ const char *http_parse_reqline(struct http_msg *msg, const char *msg_buf, if (ret_state) *ret_state = state; if (ret_ptr) - *ret_ptr = (char *)ptr; + *ret_ptr = ptr - msg_start; return NULL; } @@ -1278,7 +1280,7 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx register char *ptr, *end; /* request pointers, to avoid dereferences */ state = msg->msg_state; - ptr = buf->lr; + ptr = buffer_wrap_add(buf, buf->p + msg->next); end = buffer_wrap_add(buf, buf->p + buf->i); if (unlikely(ptr >= end)) @@ -1332,8 +1334,9 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx case HTTP_MSG_RPCODE: case HTTP_MSG_RPCODE_SP: case HTTP_MSG_RPREASON: - ptr = (char *)http_parse_stsline(msg, buf->data, state, ptr, end, - &buf->lr, &msg->msg_state); + ptr = (char *)http_parse_stsline(msg, buf->data, buf->p, + state, ptr, end, + &msg->next, &msg->msg_state); if (unlikely(!ptr)) return; @@ -1402,8 +1405,9 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx case HTTP_MSG_RQURI: case HTTP_MSG_RQURI_SP: case HTTP_MSG_RQVER: - ptr = (char *)http_parse_reqline(msg, buf->data, state, ptr, end, - &buf->lr, &msg->msg_state); + ptr = (char *)http_parse_reqline(msg, buf->data, buf->p, + state, ptr, end, + &msg->next, &msg->msg_state); if (unlikely(!ptr)) return; @@ -1561,8 +1565,8 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx /* Assumes msg->sol points to the first of either CR or LF */ EXPECT_LF_HERE(ptr, http_msg_invalid); ptr++; - buf->lr = ptr; - msg->col = msg->sov = buf->lr - buf->data; + msg->next = ptr - buf->p; + msg->col = msg->sov = ptr - buf->data; msg->eoh = msg->sol - buf->data; msg->sol = buf->data + msg->som; msg->msg_state = HTTP_MSG_BODY; @@ -1581,13 +1585,13 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx http_msg_ood: /* out of data */ msg->msg_state = state; - buf->lr = ptr; + msg->next = ptr - buf->p; return; http_msg_invalid: /* invalid message */ msg->msg_state = HTTP_MSG_ERROR; - buf->lr = ptr; + msg->next = ptr - buf->p; return; } @@ -1616,7 +1620,7 @@ static int http_upgrade_v09_to_v10(struct buffer *req, struct http_msg *msg, str delta = buffer_replace2(req, cur_end, cur_end, " HTTP/1.0\r\n", 11); http_msg_move_end(msg, delta); cur_end += delta; - cur_end = (char *)http_parse_reqline(msg, req->data, + cur_end = (char *)http_parse_reqline(msg, req->data, req->p, HTTP_MSG_RQMETH, msg->sol, cur_end + 1, NULL, NULL); @@ -1741,7 +1745,7 @@ void http_change_connection_header(struct http_txn *txn, struct http_msg *msg, s return; } -/* Parse the chunk size at buf->lr. Once done, it adjusts ->lr to point to the +/* Parse the chunk size at msg->next. Once done, it adjusts ->next to point to the * first byte of body, and increments msg->sov by the number of bytes parsed, * so that we know we can forward between ->som and ->sov. Note that due to * possible wrapping at the end of the buffer, it is possible that msg->sov is @@ -1751,7 +1755,8 @@ void http_change_connection_header(struct http_txn *txn, struct http_msg *msg, s */ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) { - char *ptr = buf->lr; + char *ptr = buffer_wrap_add(buf, buf->p + msg->next); + char *ptr_old = ptr; char *end = buf->data + buf->size; char *stop = buffer_wrap_add(buf, buf->p + buf->i); unsigned int chunk = 0; @@ -1775,7 +1780,7 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) } /* empty size not allowed */ - if (ptr == buf->lr) + if (ptr == ptr_old) goto error; while (http_is_spht[(unsigned char)*ptr]) { @@ -1826,11 +1831,11 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) } /* OK we found our CRLF and now points to the next byte, - * which may or may not be present. We save that into ->lr and + * which may or may not be present. We save that into ->next and * ->sov. */ - msg->sov += ptr - buf->lr; - buf->lr = ptr; + msg->sov += ptr - ptr_old; + msg->next = buffer_count(buf, buf->p, ptr); msg->chunk_len = chunk; msg->body_len += chunk; msg->msg_state = chunk ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS; @@ -1841,13 +1846,13 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) } /* This function skips trailers in the buffer associated with HTTP - * message . The first visited position is buf->lr. If the end of + * message . The first visited position is msg->next. If the end of * the trailers is found, it is automatically scheduled to be forwarded, * msg->msg_state switches to HTTP_MSG_DONE, and the function returns >0. * If not enough data are available, the function does not change anything - * except maybe buf->lr and msg->sov if it could parse some lines, and returns + * except maybe msg->next and msg->sov if it could parse some lines, and returns * zero. If a parse error is encountered, the function returns < 0 and does not - * change anything except maybe buf->lr and msg->sov. Note that the message + * change anything except maybe msg->next and msg->sov. Note that the message * must already be in HTTP_MSG_TRAILERS state before calling this function, * which implies that all non-trailers data have already been scheduled for * forwarding, and that the difference between msg->som and msg->sov exactly @@ -1857,10 +1862,10 @@ int http_parse_chunk_size(struct buffer *buf, struct http_msg *msg) */ int http_forward_trailers(struct buffer *buf, struct http_msg *msg) { - /* we have buf->lr which points to next line. Look for CRLF. */ + /* we have msg->next which points to next line. Look for CRLF. */ while (1) { char *p1 = NULL, *p2 = NULL; - char *ptr = buf->lr; + char *ptr = buffer_wrap_add(buf, buf->p + msg->next); char *stop = buffer_wrap_add(buf, buf->p + buf->i); int bytes; @@ -1894,7 +1899,7 @@ int http_forward_trailers(struct buffer *buf, struct http_msg *msg) if (p2 >= buf->data + buf->size) p2 = buf->data; - bytes = p2 - buf->lr; + bytes = p2 - buffer_wrap_add(buf, buf->p + msg->next); if (bytes < 0) bytes += buf->size; @@ -1903,23 +1908,24 @@ int http_forward_trailers(struct buffer *buf, struct http_msg *msg) if (msg->sov >= buf->size) msg->sov -= buf->size; - if (p1 == buf->lr) { + if (p1 == buffer_wrap_add(buf, buf->p + 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. */ - buf->lr = p2; + msg->next = buffer_count(buf, buf->p, p2); msg->msg_state = HTTP_MSG_DONE; return 1; } /* OK, next line then */ - buf->lr = p2; + msg->next = buffer_count(buf, buf->p, p2); } } /* This function may be called only in HTTP_MSG_DATA_CRLF. It reads the CRLF or * a possible LF alone at the end of a chunk. It automatically adjusts msg->sov, - * ->som, buf->lr in order to include this part into the next forwarding phase. + * ->som, ->next in order to include this part into the next forwarding phase. + * Note that the caller must ensure that ->p points to the first byte to parse. * It also sets msg_state to HTTP_MSG_CHUNK_SIZE and returns >0 on success. If * not enough data are available, the function does not change anything and * returns zero. If a parse error is encountered, the function returns < 0 and @@ -1936,7 +1942,7 @@ int http_skip_chunk_crlf(struct buffer *buf, struct http_msg *msg) * against the correct length. */ bytes = 1; - ptr = buf->lr; + ptr = buf->p; if (*ptr == '\r') { bytes++; ptr++; @@ -1955,7 +1961,7 @@ int http_skip_chunk_crlf(struct buffer *buf, struct http_msg *msg) ptr++; if (ptr >= buf->data + buf->size) ptr = buf->data; - buf->lr = ptr; + msg->next = bytes; /* prepare the CRLF to be forwarded. msg->som may be before data but we don't care */ msg->sov = ptr - buf->data; msg->som = msg->sov - bytes; @@ -1990,7 +1996,6 @@ void http_buffer_heavy_realign(struct buffer *buf, struct http_msg *msg) /* adjust all known pointers */ buf->p = buf->data; - buf->lr += off; if (buf->lr >= end) buf->lr -= buf->size; msg->sol += off; if (msg->sol >= end) msg->sol -= buf->size; msg->eol += off; if (msg->eol >= end) msg->eol -= buf->size; @@ -2032,7 +2037,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * req->data + msg->som = beginning of request * req->data + msg->eoh = end of processed headers / start of current one * msg->eol = end of current header or line (LF or CRLF) - * req->lr = first non-visited byte + * msg->next = first non-visited byte * req->r = end of data * * At end of parsing, we may perform a capture of the error (if any), and @@ -2067,7 +2072,7 @@ 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) < req->lr || + 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 (req->o) { if (req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) @@ -2077,7 +2082,7 @@ 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) < req->lr || + 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) http_buffer_heavy_realign(req, msg); } @@ -2091,7 +2096,7 @@ 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) < s->rep->lr || + 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)) { if (s->rep->o) { if (s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) @@ -2104,7 +2109,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) } } - if (likely(req->lr < buffer_wrap_add(req, req->p + req->i))) + if (likely(msg->next < req->i)) /* some unparsed data are available */ http_msg_analyzer(req, msg, &txn->hdr_idx); } @@ -2312,7 +2317,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * complete the request parsing by setting a few fields we will need * later. At this point, we have the last CRLF at req->data + msg->eoh. * If the request is in HTTP/0.9 form, the rule is still true, and eoh - * points to the CRLF of the request line. req->lr points to the first + * points to the CRLF of the request line. msg->next points to the first * byte after the last LF. msg->col and msg->sov point to the first * byte of data. msg->eol cannot be trusted because it may have been * left uninitialized (for instance in the absence of headers). @@ -3589,10 +3594,11 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit) if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) { /* we have msg->col and msg->sov which both point to the first * byte of message body. msg->som still points to the beginning - * of the message. We must save the body in req->lr because it + * of the message. We must save the body in msg->next because it * survives buffer re-alignments. */ - req->lr = req->data + msg->sov; + msg->next = buffer_count(req, req->p, req->data + msg->sov); + if (msg->flags & HTTP_MSGF_TE_CHNK) msg->msg_state = HTTP_MSG_CHUNK_SIZE; else @@ -3601,7 +3607,7 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit) if (msg->msg_state == HTTP_MSG_CHUNK_SIZE) { /* read the chunk size and assign it to ->chunk_len, then - * set ->sov and ->lr to point to the body and switch to DATA or + * set ->sov and ->next to point to the body and switch to DATA or * TRAILERS state. */ int ret = http_parse_chunk_size(req, msg); @@ -3835,9 +3841,6 @@ void http_end_txn_clean_session(struct session *s) buffer_auto_read(s->rep); buffer_auto_close(s->rep); - /* make ->lr point to the first non-forwarded byte */ - 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; @@ -4206,10 +4209,11 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) { /* we have msg->col and msg->sov which both point to the first * byte of message body. msg->som still points to the beginning - * of the message. We must save the body in req->lr because it + * of the message. We must save the body in msg->next because it * survives buffer re-alignments. */ - req->lr = req->data + msg->sov; + msg->next = buffer_count(req, req->p, req->data + msg->sov); + if (msg->flags & HTTP_MSGF_TE_CHNK) msg->msg_state = HTTP_MSG_CHUNK_SIZE; else { @@ -4227,6 +4231,7 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) msg->som = msg->sov; if (likely(bytes < 0)) /* sov may have wrapped at the end */ bytes += req->size; + msg->next -= bytes; /* will be forwarded */ msg->chunk_len += (unsigned int)bytes; msg->chunk_len -= buffer_forward(req, msg->chunk_len); } @@ -4244,7 +4249,7 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) } else if (msg->msg_state == HTTP_MSG_CHUNK_SIZE) { /* read the chunk size and assign it to ->chunk_len, then - * set ->sov and ->lr to point to the body and switch to DATA or + * set ->sov and ->next to point to the body and switch to DATA or * TRAILERS state. */ int ret = http_parse_chunk_size(req, msg); @@ -4263,7 +4268,6 @@ 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->p; ret = http_skip_chunk_crlf(req, msg); if (ret == 0) @@ -4473,7 +4477,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) * rep->data + msg->som = beginning of response * rep->data + msg->eoh = end of processed headers / start of current one * msg->eol = end of current header or line (LF or CRLF) - * rep->lr = first non-visited byte + * msg->next = first non-visited byte * rep->r = end of data * Once we reach MSG_BODY, rep->sol = rep->data + msg->som */ @@ -4485,7 +4489,7 @@ 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) < rep->lr || + 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)) { if (rep->o) { /* some data has still not left the buffer, wake us once that's done */ @@ -4499,7 +4503,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit) http_buffer_heavy_realign(rep, msg); } - if (likely(rep->lr < buffer_wrap_add(rep, rep->p + rep->i))) + if (likely(msg->next < rep->i)) http_msg_analyzer(rep, msg, &txn->hdr_idx); } @@ -5044,7 +5048,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s */ if (unlikely(txn->status == 100)) { hdr_idx_init(&txn->hdr_idx); - buffer_forward(rep, rep->lr - msg->sol); + msg->next -= buffer_forward(rep, rep->p + msg->next - msg->sol); msg->msg_state = HTTP_MSG_RPBEFORE; txn->status = 0; rep->analysers |= AN_RES_WAIT_HTTP | an_bit; @@ -5268,10 +5272,11 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit if (msg->msg_state < HTTP_MSG_CHUNK_SIZE) { /* we have msg->col and msg->sov which both point to the first * byte of message body. msg->som still points to the beginning - * of the message. We must save the body in req->lr because it + * of the message. We must save the body in msg->next because it * survives buffer re-alignments. */ - res->lr = res->data + msg->sov; + msg->next = buffer_count(res, res->p, res->data + msg->sov); + if (msg->flags & HTTP_MSGF_TE_CHNK) msg->msg_state = HTTP_MSG_CHUNK_SIZE; else { @@ -5289,11 +5294,11 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit msg->som = msg->sov; if (likely(bytes < 0)) /* sov may have wrapped at the end */ bytes += res->size; + msg->next -= bytes; /* will be forwarded */ msg->chunk_len += (unsigned int)bytes; msg->chunk_len -= buffer_forward(res, msg->chunk_len); } - if (msg->msg_state == HTTP_MSG_DATA) { /* must still forward */ if (res->to_forward) @@ -5307,7 +5312,8 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit } else if (msg->msg_state == HTTP_MSG_CHUNK_SIZE) { /* read the chunk size and assign it to ->chunk_len, then - * set ->sov to point to the body and switch to DATA or TRAILERS state. + * set ->sov and ->next to point to the body and switch to DATA or + * TRAILERS state. */ int ret = http_parse_chunk_size(res, msg); @@ -5324,7 +5330,6 @@ 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->p; ret = http_skip_chunk_crlf(res, msg); if (!ret) @@ -5402,6 +5407,7 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit msg->som = msg->sov; if (likely(bytes < 0)) /* sov may have wrapped at the end */ bytes += res->size; + msg->next -= bytes; /* will be forwarded */ msg->chunk_len += (unsigned int)bytes; msg->chunk_len -= buffer_forward(res, msg->chunk_len); } @@ -5698,7 +5704,7 @@ int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_e http_msg_move_end(&txn->req, delta); cur_end += delta; - cur_end = (char *)http_parse_reqline(&txn->req, req->data, + cur_end = (char *)http_parse_reqline(&txn->req, req->data, req->p, HTTP_MSG_RQMETH, cur_ptr, cur_end + 1, NULL, NULL); @@ -6537,7 +6543,7 @@ int apply_filter_to_sts_line(struct session *t, struct buffer *rtr, struct hdr_e http_msg_move_end(&txn->rsp, delta); cur_end += delta; - cur_end = (char *)http_parse_stsline(&txn->rsp, rtr->data, + cur_end = (char *)http_parse_stsline(&txn->rsp, rtr->data, rtr->p, HTTP_MSG_RPVER, cur_ptr, cur_end + 1, NULL, NULL); @@ -7247,10 +7253,10 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s, if (msg->err_pos >= 0) es->pos = msg->err_pos - msg->som; - else if (buf->lr >= (buf->data + msg->som)) - es->pos = buf->lr - (buf->data + msg->som); + else if (buffer_wrap_add(buf, buf->p + msg->next) >= (buf->data + msg->som)) + es->pos = buffer_wrap_add(buf, buf->p + msg->next) - (buf->data + msg->som); else - es->pos = buf->lr - (buf->data + msg->som) + buf->size; + es->pos = buffer_wrap_add(buf, buf->p + msg->next) - (buf->data + msg->som) + buf->size; es->when = date; // user-visible date es->sid = s->uniq_id; @@ -7361,9 +7367,11 @@ void http_init_txn(struct session *s) txn->req.flags = 0; txn->req.sol = txn->req.eol = NULL; txn->req.som = txn->req.eoh = 0; /* relative to the buffer */ + txn->req.next = 0; txn->rsp.flags = 0; txn->rsp.sol = txn->rsp.eol = NULL; txn->rsp.som = txn->rsp.eoh = 0; /* relative to the buffer */ + txn->rsp.next = 0; txn->req.chunk_len = 0LL; txn->req.body_len = 0LL; txn->rsp.chunk_len = 0LL; @@ -8118,7 +8126,7 @@ acl_fetch_proto_http(struct proxy *px, struct session *s, void *l7, int dir, } /* Try to decode HTTP request */ - if (likely(req->lr < buffer_wrap_add(req, req->p + req->i))) + if (likely(msg->next < req->i)) http_msg_analyzer(req, msg, &txn->hdr_idx); if (unlikely(msg->msg_state < HTTP_MSG_BODY)) { diff --git a/src/stream_sock.c b/src/stream_sock.c index 3d462ab02..0baf825bf 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -282,7 +282,7 @@ int stream_sock_read(int fd) { */ if (buffer_empty(b)) { /* let's realign the buffer to optimize I/O */ - b->p = b->lr = b->data; + b->p = b->data; } else if (b->data + b->o < b->p && b->p + b->i < b->data + b->size) { @@ -647,7 +647,7 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b) b->o -= ret; if (likely(!buffer_len(b))) /* optimize data alignment in the buffer */ - b->lr = b->p = b->data; + b->p = b->data; if (likely(buffer_len(b) < buffer_max_len(b))) b->flags &= ~BF_FULL;