From c623c17b13770682930b0d22e71bbe71630d7152 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 18 Apr 2014 09:53:50 +0200 Subject: [PATCH] MEDIUM: http: start to centralize the forwarding code Doing so avoids calling channel_forward() for each part of the chunk parsing and lowers the number of calls to channel_forward() to only one per buffer, resulting in about 11% performance increase on small chunks forwarding rate. --- src/proto_http.c | 58 ++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index ac7fe01ff5..8e0b0bf408 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -6219,28 +6219,28 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi while (1) { http_silent_debug(__LINE__, s); - /* we may have some pending data starting at res->buf->p */ - if (s->comp_algo == NULL) { - if (msg->chunk_len || msg->next) { - msg->chunk_len += msg->next; - msg->chunk_len -= channel_forward(res, msg->chunk_len); - msg->next = 0; - msg->sov = 0; - } - } - switch (msg->msg_state - HTTP_MSG_DATA) { case HTTP_MSG_DATA - HTTP_MSG_DATA: /* must still forward */ - if (compressing) { + /* we may have some pending data starting at res->buf->p */ + if (unlikely(s->comp_algo)) { ret = http_compression_buffer_add_data(s, res->buf, tmpbuf); if (ret < 0) goto aborted_xfer; + + if (res->to_forward || msg->chunk_len) { + res->flags |= CF_WAKE_WRITE; + goto missing_data; + } } - if (res->to_forward || msg->chunk_len) { + if (msg->chunk_len > res->buf->i - msg->next) { res->flags |= CF_WAKE_WRITE; goto missing_data; } + else { + msg->next += msg->chunk_len; + msg->chunk_len = 0; + } /* nothing left to forward */ if (msg->flags & HTTP_MSGF_TE_CHNK) { @@ -6296,11 +6296,6 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_TRAILERS, s->fe); goto return_bad_res; } - /* forwarding trailers */ - channel_forward(res, msg->next); - msg->next = 0; - msg->sov = 0; - /* we're in HTTP_MSG_DONE now, fall through */ default: @@ -6311,6 +6306,12 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi compressing = 0; } + /* we may have some pending data starting at res->buf->p + * such as a last chunk of data or trailers. + */ + b_adv(res->buf, msg->next); + msg->next = 0; + ret = msg->msg_state; /* for keep-alive we don't want to forward closes on DONE */ if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL || @@ -6339,11 +6340,18 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi } missing_data: + /* we may have some pending data starting at res->buf->p */ if (unlikely(compressing)) { http_compression_buffer_end(s, &res->buf, &tmpbuf, msg->msg_state >= HTTP_MSG_TRAILERS); compressing = 0; } + if ((s->comp_algo == NULL || msg->msg_state >= HTTP_MSG_TRAILERS)) { + b_adv(res->buf, msg->next); + msg->next = 0; + msg->chunk_len -= channel_forward(res, msg->chunk_len); + } + if (res->flags & CF_SHUTW) goto aborted_xfer; @@ -6367,16 +6375,6 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi if (!s->req->analysers) goto return_bad_res; - /* forward any pending data starting at res->buf->p */ - if (s->comp_algo == NULL) { - if (msg->chunk_len || msg->next) { - msg->chunk_len += msg->next; - msg->chunk_len -= channel_forward(res, msg->chunk_len); - msg->next = 0; - msg->sov = 0; - } - } - /* When TE: chunked is used, we need to get there again to parse remaining * chunks even if the server has closed, so we don't want to set CF_DONTCLOSE. * Similarly, with keep-alive on the client side, we don't want to forward a @@ -6413,6 +6411,12 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi compressing = 0; } + /* we may have some pending data starting at res->buf->p */ + if (s->comp_algo == NULL) { + b_adv(res->buf, msg->next); + msg->next = 0; + } + txn->rsp.msg_state = HTTP_MSG_ERROR; /* don't send any error message as we're in the body */ stream_int_retnclose(res->cons, NULL); -- 2.39.5