From: Willy Tarreau Date: Thu, 17 Apr 2014 19:14:47 +0000 (+0200) Subject: MAJOR: http: reset msg->sov after headers are forwarded X-Git-Tag: v1.5-dev23~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1234f4a21028051d0249d3b34fd8b3360a2f2318;p=thirdparty%2Fhaproxy.git MAJOR: http: reset msg->sov after headers are forwarded In order to avoid abusively relying on buf->o to guess how many bytes to rewind during a redispatch, we now clear msg->sov. Thus the meaning of this field is exactly "how many bytes of headers are left to be forwarded". It is still possible to rewind because msg->eoh + msg->eol equal that value before scheduling the forwarding, so we can always subtract them. --- diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index 53f0eca04c..2c8b062a99 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -134,10 +134,13 @@ enum http_meth_t find_http_meth(const char *str, const int len); /* Return the amount of bytes that need to be rewound before buf->p to access * the current message's headers. The purpose is to be able to easily fetch * the message's beginning before headers are forwarded, as well as after. + * The principle is that msg->eoh and msg->eol are immutable while msg->sov + * equals the sum of the two before forwarding and is zero after forwarding, + * so the difference cancels the rewinding. */ static inline int http_hdr_rewind(const struct http_msg *msg) { - return msg->chn->buf->o; + return msg->eoh + msg->eol - msg->sov; } /* Return the amount of bytes that need to be rewound before buf->p to access @@ -179,7 +182,7 @@ static inline int http_body_bytes(const struct http_msg *msg) { int len; - len = buffer_len(msg->chn->buf) - msg->sov - msg->sol; + len = msg->chn->buf->i - msg->sov - msg->sol; if (len > msg->body_len) len = msg->body_len; return len; diff --git a/src/proto_http.c b/src/proto_http.c index 0c30d0e018..328f28b51b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -5064,6 +5064,7 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit msg->chunk_len += msg->next; msg->chunk_len -= channel_forward(req, msg->chunk_len); msg->next = 0; + msg->sov = 0; } if (msg->msg_state == HTTP_MSG_DATA) { @@ -6188,6 +6189,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi */ channel_forward(res, msg->sov); msg->next = 0; + msg->sov = 0; if (msg->flags & HTTP_MSGF_TE_CHNK) msg->msg_state = HTTP_MSG_CHUNK_SIZE; @@ -6213,6 +6215,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi msg->chunk_len += msg->next; msg->chunk_len -= channel_forward(res, msg->chunk_len); msg->next = 0; + msg->sov = 0; } } @@ -6302,6 +6305,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi /* forwarding trailers */ channel_forward(res, msg->next); msg->next = 0; + msg->sov = 0; } /* we're in HTTP_MSG_DONE now, but we might still have * some data pending, so let's loop over once. @@ -6373,6 +6377,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi msg->chunk_len += msg->next; msg->chunk_len -= channel_forward(res, msg->chunk_len); msg->next = 0; + msg->sov = 0; } }