]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: channel/htx: Add functions for forward HTX data
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 5 Dec 2018 10:56:15 +0000 (11:56 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 5 Dec 2018 16:29:30 +0000 (17:29 +0100)
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.

include/proto/channel.h
src/proto_htx.c
src/stream.c

index 56bf5cf61c56d03767cfd2eae3eb4d218869ea40..dd9b1afa21e951a502707692fd654fde4852e87b 100644 (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 */
 /*********************************************************************/
index 3232d0a2ef2836835aa5f5872a09c4f2b3eb9afe..c613e72e2c8e782c1690cb51441de35decf416a4 100644 (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)) {
index ed913d119b23d4b7c3eb906de807c4d4413cf9a2..be58e77bd663fa17bc732a0d30723047ed5b8377 100644 (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