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.
This commit is contained in:
Christopher Faulet 2018-12-05 11:56:15 +01:00 committed by Willy Tarreau
parent 27ba2dc6d6
commit b2aedea142
3 changed files with 63 additions and 30 deletions

View File

@ -36,6 +36,7 @@
#include <types/global.h>
#include <types/stream.h>
#include <types/stream_interface.h>
#include <types/htx.h>
#include <proto/task.h>
@ -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 */
/*********************************************************************/

View File

@ -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)) {

View File

@ -46,6 +46,7 @@
#include <proto/hdr_idx.h>
#include <proto/hlua.h>
#include <proto/http_rules.h>
#include <proto/htx.h>
#include <proto/listener.h>
#include <proto/log.h>
#include <proto/raw_sock.h>
@ -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