From: Christopher Faulet Date: Wed, 7 Apr 2021 06:10:41 +0000 (+0200) Subject: MINOR: channel: Rely on HTX version if appropriate in channel_may_recv() X-Git-Tag: v2.4-dev19~135 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1c235e57d0087e86074178f682c24f8aa44e0fcd;p=thirdparty%2Fhaproxy.git MINOR: channel: Rely on HTX version if appropriate in channel_may_recv() 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. --- diff --git a/include/haproxy/channel.h b/include/haproxy/channel.h index aa1996f4f9..efa85ba07d 100644 --- a/include/haproxy/channel.h +++ b/include/haproxy/channel.h @@ -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 */