From: Christopher Faulet Date: Wed, 5 Dec 2018 10:56:15 +0000 (+0100) Subject: MEDIUM: channel/htx: Add functions for forward HTX data X-Git-Tag: v1.9-dev10~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2aedea142bba94927c978802134c2289b3098c0;p=thirdparty%2Fhaproxy.git MEDIUM: channel/htx: Add functions for forward HTX data To ease the fast forwarding and the infinte forwarding on HTX proxies, 2 functions have been added to let the channel be almost aware of the way data are stored in its buffer. By calling these functions instead of legacy ones, we are sure to forward the right amount of data. --- diff --git a/include/proto/channel.h b/include/proto/channel.h index 56bf5cf61c..dd9b1afa21 100644 --- a/include/proto/channel.h +++ b/include/proto/channel.h @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -360,6 +361,24 @@ static inline void channel_forward_forever(struct channel *chn) chn->to_forward = CHN_INFINITE_FORWARD; } +static inline unsigned long long channel_htx_forward(struct channel *chn, struct htx *htx, unsigned long long bytes) +{ + unsigned long long ret; + + b_set_data(&chn->buf, htx->data); + ret = channel_forward(chn, bytes); + b_set_data(&chn->buf, b_size(&chn->buf)); + return ret; +} + + +static inline void channel_htx_forward_forever(struct channel *chn, struct htx *htx) +{ + b_set_data(&chn->buf, htx->data); + channel_forward_forever(chn); + b_set_data(&chn->buf, b_size(&chn->buf)); +} + /*********************************************************************/ /* These functions are used to compute various channel content sizes */ /*********************************************************************/ diff --git a/src/proto_htx.c b/src/proto_htx.c index 3232d0a2ef..c613e72e2c 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -1245,10 +1245,8 @@ int htx_request_forward_body(struct stream *s, struct channel *req, int an_bit) * right length is then restored. We must do that, because when an HTX * message is stored into a buffer, it appears as full. */ - b_set_data(&req->buf, co_data(req)); - if (msg->flags & HTTP_MSGF_XFER_LEN) - htx->extra -= channel_forward(req, htx->extra); - b_set_data(&req->buf, b_size(&req->buf)); + if ((msg->flags & HTTP_MSGF_XFER_LEN) && htx->extra) + htx->extra -= channel_htx_forward(req, htx, htx->extra); } /* Check if the end-of-message is reached and if so, switch the message @@ -2185,10 +2183,8 @@ int htx_response_forward_body(struct stream *s, struct channel *res, int an_bit) * right length is then restored. We must do that, because when an HTX * message is stored into a buffer, it appears as full. */ - b_set_data(&res->buf, co_data(res)); - if (msg->flags & HTTP_MSGF_XFER_LEN) - htx->extra -= channel_forward(res, htx->extra); - b_set_data(&res->buf, b_size(&res->buf)); + if ((msg->flags & HTTP_MSGF_XFER_LEN) && htx->extra) + htx->extra -= channel_htx_forward(res, htx, htx->extra); } if (!(msg->flags & HTTP_MSGF_XFER_LEN)) { diff --git a/src/stream.c b/src/stream.c index ed913d119b..be58e77bd6 100644 --- a/src/stream.c +++ b/src/stream.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -2184,19 +2185,27 @@ redo: channel_auto_close(req); c_adv(req, ci_data(req)); - /* We'll let data flow between the producer (if still connected) - * to the consumer (which might possibly not be connected yet). - */ - if (!(req->flags & (CF_SHUTR|CF_SHUTW_NOW))) - channel_forward_forever(req); + if (IS_HTX_STRM(s) && s->txn) { + /* We'll let data flow between the producer (if still connected) + * to the consumer (which might possibly not be connected yet). + */ + if (!(req->flags & (CF_SHUTR|CF_SHUTW_NOW))) + channel_htx_forward_forever(req, htxbuf(&req->buf)); + } + else { + /* We'll let data flow between the producer (if still connected) + * to the consumer (which might possibly not be connected yet). + */ + if (!(req->flags & (CF_SHUTR|CF_SHUTW_NOW))) + channel_forward_forever(req); - /* Just in order to support fetching HTTP contents after start - * of forwarding when the HTTP forwarding analyser is not used, - * we simply reset msg->sov so that HTTP rewinding points to the - * headers. - */ - if (IS_HTX_STRM(s) && s->txn) + /* Just in order to support fetching HTTP contents after start + * of forwarding when the HTTP forwarding analyser is not used, + * we simply reset msg->sov so that HTTP rewinding points to the + * headers. + */ s->txn->req.sov = s->txn->req.eoh + s->txn->req.eol - co_data(req); + } } /* check if it is wise to enable kernel splicing to forward request data */ @@ -2345,19 +2354,28 @@ redo: channel_auto_close(res); c_adv(res, ci_data(res)); - /* We'll let data flow between the producer (if still connected) - * to the consumer. - */ - if (!(res->flags & (CF_SHUTR|CF_SHUTW_NOW))) - channel_forward_forever(res); - /* Just in order to support fetching HTTP contents after start - * of forwarding when the HTTP forwarding analyser is not used, - * we simply reset msg->sov so that HTTP rewinding points to the - * headers. - */ - if (IS_HTX_STRM(s) && s->txn) + if (IS_HTX_STRM(s) && s->txn) { + /* We'll let data flow between the producer (if still connected) + * to the consumer. + */ + if (!(res->flags & (CF_SHUTR|CF_SHUTW_NOW))) + channel_htx_forward_forever(res, htxbuf(&res->buf)); + } + else { + /* We'll let data flow between the producer (if still connected) + * to the consumer. + */ + if (!(res->flags & (CF_SHUTR|CF_SHUTW_NOW))) + channel_forward_forever(res); + + /* Just in order to support fetching HTTP contents after start + * of forwarding when the HTTP forwarding analyser is not used, + * we simply reset msg->sov so that HTTP rewinding points to the + * headers. + */ s->txn->rsp.sov = s->txn->rsp.eoh + s->txn->rsp.eol - co_data(res); + } /* if we have no analyser anymore in any direction and have a * tunnel timeout set, use it now. Note that we must respect