From c0b6db283058791287974a62f0f70a50d2602caa Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Wed, 17 Sep 2025 17:30:32 +0200 Subject: [PATCH] MINOR: stconn: Add two fields in sedesc to replace the HTX extra value For now, the HTX extra value is used to specify the known part, in bytes, of the HTTP payload we will receive. It may concerne the full payload if a content-length is specified or the current chunk for a chunk-encoded message. The main purpose of this value is to be used on the opposite side to be able to announce chunks bigger than a buffer. It can also be used to check the validity of the payload on the sending path, to properly detect too big or too short payload. However, setting this information in the HTX message itself is not really appropriate because the information is lost when the HTX message is consumed and the underlying buffer released. So the producer must take care to always add it in all HTX messages. it is especially an issue when the payload is altered by a filter. So to fix this design issue, the information will be moved in the sedesc. It is a persistent area to save the information. In addition, to avoid the ambiguity between what the producer say and what the consumer see, the information will be splitted in two fields. In this patch, the fields are added: * kip : The known input payload length * kop : The known output payload lenght The producer will be responsible to set value. The stream will be responsible to decrement and increment accordingly. And the consumer will be responsible to remove consumed bytes from . --- include/haproxy/stconn-t.h | 24 ++++++++++++++++++++++++ include/haproxy/stconn.h | 6 ++++++ src/stconn.c | 3 +++ 3 files changed, 33 insertions(+) diff --git a/include/haproxy/stconn-t.h b/include/haproxy/stconn-t.h index 08326df91..2195ea14b 100644 --- a/include/haproxy/stconn-t.h +++ b/include/haproxy/stconn-t.h @@ -311,6 +311,27 @@ struct se_abort_info { * NOTE: and must only be used via the SC api to compute read/write * expiration date. * + * is the known input payload length. It is set by the stream endpoint + * that produce data and decremented once consumed by the app + * loyer. Depending on the enpoint, this value may be unset. It may be set + * only once if the payload lenght is fully known from the begining (a + * HTTP message with a content-length for instance), or incremented + * periodically when more data are expected (a chunk-encoded HTTP message + * for instance). On the app side, this value is decremented when data are + * scheduled to be forwarded to the other side and is incremented + * accordingly. + * + * is the known output payload length still expected from the app + * layer. It is set by the app layer, when data are forwarded to the + * stream endpoint and decremented when the endpoint the value was + * processed (for instance when a size of the next chunk is emitted). + * + * NOTE: and act like communicating vessels and are just used as an + * information from the producer side to allow optimisations on the + * consumer side. These value may be unset by the producer or just never + * used by the consumer. When set, these values reflect the data already + * present in the channel buffer, and those which will come soon. + * */ struct sedesc { void *se; /* the stream endpoint, i.e. the mux stream or the appctx */ @@ -323,6 +344,9 @@ struct sedesc { unsigned int lra; /* the last read activity */ unsigned int fsb; /* the first send blocked */ struct xref xref; /* cross reference with the opposite SC */ + + unsigned long long kip; /* Known input payload length (see above) */ + unsigned long long kop; /* Known outgoing payload length (see above) */ }; /* sc_app_ops describes the application layer's operations and notification diff --git a/include/haproxy/stconn.h b/include/haproxy/stconn.h index dacf403e5..3897db6c1 100644 --- a/include/haproxy/stconn.h +++ b/include/haproxy/stconn.h @@ -148,6 +148,12 @@ static inline struct sedesc *se_opposite(struct sedesc *se) return seo; } +static inline void se_fwd_kip(struct sedesc *se) +{ + se->kop += se->kip; + se->kip = 0; +} + /* stream connector version */ static forceinline void sc_ep_zero(struct stconn *sc) { diff --git a/src/stconn.c b/src/stconn.c index ff439d190..99dc0256b 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -109,6 +109,9 @@ void sedesc_init(struct sedesc *sedesc) sedesc->iobuf.buf = NULL; sedesc->iobuf.offset = sedesc->iobuf.data = 0; sedesc->iobuf.flags = IOBUF_FL_NONE; + + sedesc->kip = 0; + sedesc->kop = 0; } /* Tries to alloc an endpoint and initialize it. Returns NULL on failure. */