]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: channel: Rely on HTX version if appropriate in channel_may_recv()
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 7 Apr 2021 06:10:41 +0000 (08:10 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 6 May 2021 07:19:05 +0000 (09:19 +0200)
When channel_may_recv() is called for an HTX stream, the HTX version,
channel_htx_may_recv() is called. This patch is mandatory to fix a bug
related to the abortonclose option.

include/haproxy/channel.h

index aa1996f4f9288ae604f41af29b664248319835d9..efa85ba07df6a938f7d80483a004ad85f77fb62a 100644 (file)
@@ -432,27 +432,18 @@ static inline int channel_may_send(const struct channel *chn)
        return chn_cons(chn)->state == SI_ST_EST;
 }
 
-/* Returns non-zero if the channel can still receive data. This is used to
- * decide when to stop reading into a buffer when we want to ensure that we
- * leave the reserve untouched after all pending outgoing data are forwarded.
- * The reserved space is taken into account if ->to_forward indicates that an
- * end of transfer is close to happen. Note that both ->buf.o and ->to_forward
- * are considered as available since they're supposed to leave the buffer. The
- * test is optimized to avoid as many operations as possible for the fast case
- * and to be used as an "if" condition. Just like channel_recv_limit(), we
- * never allow to overwrite the reserve until the output stream interface is
- * connected, otherwise we could spin on a POST with http-send-name-header.
- */
-static inline int channel_may_recv(const struct channel *chn)
+/* HTX version of channel_may_recv(). Returns non-zero if the channel can still
+ * receive data. */
+static inline int channel_htx_may_recv(const struct channel *chn, const struct htx *htx)
 {
-       int rem = chn->buf.size;
+       uint32_t rem;
 
-       if (b_is_null(&chn->buf))
+       if (!htx->size)
                return 1;
 
-       rem -= b_data(&chn->buf);
+       rem = htx_free_data_space(htx);
        if (!rem)
-               return 0; /* buffer already full */
+               return 0; /* htx already full */
 
        if (rem > global.tune.maxrewrite)
                return 1; /* reserve not yet reached */
@@ -467,29 +458,44 @@ static inline int channel_may_recv(const struct channel *chn)
         * the reserve, and we want to ensure they're covered by scheduled
         * forwards.
         */
-       rem = ci_data(chn) + global.tune.maxrewrite - chn->buf.size;
-       return rem < 0 || (unsigned int)rem < chn->to_forward;
+       rem += co_data(chn);
+       if (rem > global.tune.maxrewrite)
+               return 1;
+
+       return (global.tune.maxrewrite - rem < chn->to_forward);
 }
 
-/* HTX version of channel_may_recv(). Returns non-zero if the channel can still
- * receive data. */
-static inline int channel_htx_may_recv(const struct channel *chn, const struct htx *htx)
+/* Returns non-zero if the channel can still receive data. This is used to
+ * decide when to stop reading into a buffer when we want to ensure that we
+ * leave the reserve untouched after all pending outgoing data are forwarded.
+ * The reserved space is taken into account if ->to_forward indicates that an
+ * end of transfer is close to happen. Note that both ->buf.o and ->to_forward
+ * are considered as available since they're supposed to leave the buffer. The
+ * test is optimized to avoid as many operations as possible for the fast case
+ * and to be used as an "if" condition. Just like channel_recv_limit(), we
+ * never allow to overwrite the reserve until the output stream interface is
+ * connected, otherwise we could spin on a POST with http-send-name-header.
+ */
+static inline int channel_may_recv(const struct channel *chn)
 {
-       uint32_t rem;
+       int rem = chn->buf.size;
 
-       if (!htx->size)
-               return 1;
+       if (IS_HTX_STRM(chn_strm(chn)))
+               return channel_htx_may_recv(chn, htxbuf(&chn->buf));
 
-       if (!channel_may_send(chn))
-               return 0; /* don't touch reserve until we can send */
+       if (b_is_null(&chn->buf))
+               return 1;
 
-       rem = htx_free_data_space(htx);
+       rem -= b_data(&chn->buf);
        if (!rem)
-               return 0; /* htx already full */
+               return 0; /* buffer already full */
 
        if (rem > global.tune.maxrewrite)
                return 1; /* reserve not yet reached */
 
+       if (!channel_may_send(chn))
+               return 0; /* don't touch reserve until we can send */
+
        /* Now we know there's some room left in the reserve and we may
         * forward. As long as i-to_fwd < size-maxrw, we may still
         * receive. This is equivalent to i+maxrw-size < to_fwd,
@@ -497,11 +503,8 @@ static inline int channel_htx_may_recv(const struct channel *chn, const struct h
         * the reserve, and we want to ensure they're covered by scheduled
         * forwards.
         */
-       rem += co_data(chn);
-       if (rem > global.tune.maxrewrite)
-               return 1;
-
-       return (global.tune.maxrewrite - rem < chn->to_forward);
+       rem = ci_data(chn) + global.tune.maxrewrite - chn->buf.size;
+       return rem < 0 || (unsigned int)rem < chn->to_forward;
 }
 
 /* Returns true if the channel's input is already closed */