From: Christopher Faulet Date: Wed, 5 Dec 2018 10:53:24 +0000 (+0100) Subject: MEDIUM: htx: Rework conversion from a buffer to an htx structure X-Git-Tag: v1.9-dev10~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27ba2dc6d6ec92f68ef745bd30e6a00f59802da8;p=thirdparty%2Fhaproxy.git MEDIUM: htx: Rework conversion from a buffer to an htx structure Now, the function htx_from_buf() will set the buffer's length to its size automatically. In return, the caller should call htx_to_buf() at the end to be sure to leave the buffer hosting the HTX message in the right state. When the caller can use the function htxbuf() to get the HTX message without any update on the underlying buffer. --- diff --git a/include/proto/htx.h b/include/proto/htx.h index fdd305646e..d803947cd0 100644 --- a/include/proto/htx.h +++ b/include/proto/htx.h @@ -541,21 +541,49 @@ static inline size_t buf_room_for_htx_data(const struct buffer *buf) return room; } -/* Returns an HTX message using the buffer . */ -static inline struct htx *htx_from_buf(struct buffer *buf) + +/* Returns an HTX message using the buffer . Unlike htx_from_buf(), this + * function does not update to the buffer. */ +static inline struct htx *htxbuf(const struct buffer *buf) { - struct htx *htx; + struct htx *htx; - if (b_is_null(buf)) - return &htx_empty; - htx = (struct htx *)(buf->area); - if (!b_data(buf)) { + if (b_is_null(buf)) + return &htx_empty; + htx = ((struct htx *)(buf->area)); + if (!b_data(buf)) { htx->size = buf->size - sizeof(*htx); - htx_reset(htx); + htx_reset(htx); } return htx; } +/* Returns an HTX message using the buffer . is updated to appear as + * full. It is the caller responsibility to call htx_to_buf() when it finish to + * manipulate the HTX message to update accordingly. + * + * If the caller can call htxbuf() function to avoir any update of the + * buffer. + */ +static inline struct htx *htx_from_buf(struct buffer *buf) +{ + struct htx *htx = htxbuf(buf); + + b_set_data(buf, b_size(buf)); + return htx; +} + +/* Upate accordingly to the HTX message */ +static inline void htx_to_buf(struct htx *htx, struct buffer *buf) +{ + if (!htx->used) { + htx_reset(htx); + b_set_data(buf, 0); + } + else + b_set_data(buf, b_size(buf)); +} + /* Returns 1 if the message is empty, otherwise it returns 0. */ static inline int htx_is_empty(const struct htx *htx) { diff --git a/src/filters.c b/src/filters.c index 2b8238957f..6368b20b93 100644 --- a/src/filters.c +++ b/src/filters.c @@ -930,7 +930,7 @@ flt_analyze_http_headers(struct stream *s, struct channel *chn, unsigned int an_ } RESUME_FILTER_END; if (IS_HTX_STRM(s)) { - struct htx *htx = htx_from_buf(&chn->buf); + struct htx *htx = htxbuf(&chn->buf); int32_t pos; for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 5e0ee59a7f..7ffff76313 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -197,7 +197,7 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, unsigned int offset, unsigned int len) { struct comp_state *st = filter->ctx; - struct htx *htx = htx_from_buf(&msg->chn->buf); + struct htx *htx = htxbuf(&msg->chn->buf); struct htx_blk *blk; struct htx_ret htx_ret; int ret, consumed = 0, to_forward = 0; @@ -575,7 +575,7 @@ http_select_comp_reqhdr(struct comp_state *st, struct stream *s, struct http_msg static int htx_select_comp_reqhdr(struct comp_state *st, struct stream *s, struct http_msg *msg) { - struct htx *htx = htx_from_buf(&msg->chn->buf); + struct htx *htx = htxbuf(&msg->chn->buf); struct http_hdr_ctx ctx; struct comp_algo *comp_algo = NULL; struct comp_algo *comp_algo_back = NULL; @@ -818,7 +818,7 @@ fail: static int htx_select_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *msg) { - struct htx *htx = htx_from_buf(&msg->chn->buf); + struct htx *htx = htxbuf(&msg->chn->buf); struct http_txn *txn = s->txn; struct http_hdr_ctx ctx; struct comp_type *comp_type; diff --git a/src/flt_trace.c b/src/flt_trace.c index 0dd655c6bd..92a51bf156 100644 --- a/src/flt_trace.c +++ b/src/flt_trace.c @@ -412,7 +412,7 @@ trace_http_headers(struct stream *s, struct filter *filter, channel_label(msg->chn), proxy_mode(s), stream_pos(s)); if (IS_HTX_STRM(s)) { - struct htx *htx = htx_from_buf(&msg->chn->buf); + struct htx *htx = htxbuf(&msg->chn->buf); struct htx_sl *sl = http_find_stline(htx); int32_t pos; @@ -473,7 +473,7 @@ trace_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg offset, len, ret); if (conf->hexdump) - trace_htx_hexdump(htx_from_buf(&msg->chn->buf), offset, len); + trace_htx_hexdump(htxbuf(&msg->chn->buf), offset, len); if (ret != len) task_wakeup(s->task, TASK_WOKEN_MSG); diff --git a/src/http_fetch.c b/src/http_fetch.c index 81f6669c92..5f579d1f1a 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -73,7 +73,7 @@ static int get_http_auth(struct sample *smp) if (IS_HTX_STRM(s) || (smp->px->mode == PR_MODE_TCP)) { /* HTX version */ - struct htx *htx = htx_from_buf(&s->req.buf); + struct htx *htx = htxbuf(&s->req.buf); struct http_hdr_ctx ctx = { .blk = NULL }; struct ist hdr; @@ -82,7 +82,6 @@ static int get_http_auth(struct sample *smp) else hdr = ist("Authorization"); - htx = htx_from_buf(&s->req.buf); ctx.blk = NULL; if (!http_find_header(htx, hdr, &ctx, 0)) return 0; @@ -191,7 +190,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args) if (px->mode == PR_MODE_HTTP) { if ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) { - htx = htx_from_buf(&s->req.buf); + htx = htxbuf(&s->req.buf); if (htx_is_empty(htx) || htx_get_tail_type(htx) < HTX_BLK_EOH) { /* Parsing is done by the mux, just wait */ smp->flags |= SMP_F_MAY_CHANGE; @@ -212,7 +211,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args) /* otherwise everything's ready for the request */ } else { - htx = htx_from_buf(&s->res.buf); + htx = htxbuf(&s->res.buf); if (htx_is_empty(htx) || htx_get_tail_type(htx) < HTX_BLK_EOH) { /* Parsing is done by the mux, just wait */ smp->flags |= SMP_F_MAY_CHANGE; diff --git a/src/http_htx.c b/src/http_htx.c index 58629785cb..9a1dfb4691 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -675,8 +675,6 @@ static struct htx *http_str_to_htx(struct buffer *buf, struct ist raw) } if (!htx_add_endof(htx, HTX_BLK_EOM)) goto error; - - b_set_data(buf, b_size(buf)); return htx; error: diff --git a/src/htx.c b/src/htx.c index 0d7ddc1538..d691c2e585 100644 --- a/src/htx.c +++ b/src/htx.c @@ -24,7 +24,7 @@ struct htx htx_empty = { .size = 0, .data = 0, .used = 0 }; struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk) { struct buffer *chunk = get_trash_chunk(); - struct htx *tmp = htx_from_buf(chunk); + struct htx *tmp = htxbuf(chunk); struct htx_blk *newblk, *oldblk; uint32_t new, old; uint32_t addr, blksz; diff --git a/src/mux_h1.c b/src/mux_h1.c index 4646812126..0b085c2c69 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1207,7 +1207,6 @@ static size_t h1_process_input(struct h1c *h1c, struct buffer *buf, int flags) int errflag; htx = htx_from_buf(buf); - b_set_data(buf, b_size(buf)); count = b_data(&h1c->ibuf); max = htx_free_space(htx); if (flags & CO_RFL_KEEP_RSV) { @@ -1261,12 +1260,7 @@ static size_t h1_process_input(struct h1c *h1c, struct buffer *buf, int flags) b_del(&h1c->ibuf, total); end: - if (htx_is_not_empty(htx)) - b_set_data(buf, b_size(buf)); - else { - htx_reset(htx); - b_set_data(buf, 0); - } + htx_to_buf(htx, buf); if (h1c->flags & H1C_F_IN_FULL && buf_room_for_htx_data(&h1c->ibuf)) { h1c->flags &= ~H1C_F_IN_FULL; @@ -1288,10 +1282,9 @@ static size_t h1_process_input(struct h1c *h1c, struct buffer *buf, int flags) return total; parsing_err: - // FIXME: create an error snapshot here b_reset(&h1c->ibuf); htx->flags |= HTX_FL_PARSING_ERROR; - b_set_data(buf, b_size(buf)); + htx_to_buf(htx, buf); h1s->cs->flags |= CS_FL_EOS; return 0; } @@ -1497,10 +1490,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (!buf_room_for_htx_data(&h1c->obuf)) h1c->flags |= H1C_F_OUT_FULL; - if (htx_is_empty(chn_htx)) { - htx_reset(chn_htx); - b_set_data(buf, 0); - } + htx_to_buf(chn_htx, buf); end: return total; } diff --git a/src/mux_h2.c b/src/mux_h2.c index 5585ac2c2c..e94ec67e55 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -3118,6 +3118,8 @@ static int h2s_decode_headers(struct h2s *h2s) } leave: + if (htx) + htx_to_buf(htx, &h2s->rxbuf); free_trash_chunk(copy); return outlen; fail: @@ -3319,9 +3321,12 @@ try_again: h2s->flags |= H2_SF_ES_RCVD; h2s->cs->flags |= CS_FL_REOS; } - + if (htx) + htx_to_buf(htx, csbuf); return 1; fail: + if (htx) + htx_to_buf(htx, csbuf); return 0; } @@ -4515,8 +4520,8 @@ static size_t h2_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t coun htx_ret = htx_xfer_blks(buf_htx, h2s_htx, count, HTX_BLK_EOM); buf_htx->extra = h2s_htx->extra; - if (htx_is_not_empty(buf_htx)) - b_set_data(buf, b_size(buf)); + htx_to_buf(buf_htx, buf); + htx_to_buf(h2s_htx, &h2s->rxbuf); ret = htx_ret.ret; } else { @@ -4719,10 +4724,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun } if (htx) { - if (htx_is_empty(htx)) { - htx_reset(htx); - b_set_data(buf, 0); - } + htx_to_buf(htx, buf); } else { b_del(buf, total); } diff --git a/src/proto_htx.c b/src/proto_htx.c index e76d0bffc0..3232d0a2ef 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -95,7 +95,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit) ci_data(req), req->analysers); - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); /* we're speaking HTTP here, so let's speak HTTP to the client */ s->srv_error = http_return_srv_error; @@ -496,7 +496,7 @@ int htx_process_req_common(struct stream *s, struct channel *req, int an_bit, st ci_data(req), req->analysers); - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); /* just in case we have some per-backend tracking */ stream_inc_be_http_req_ctr(s); @@ -771,7 +771,7 @@ int htx_process_request(struct stream *s, struct channel *req, int an_bit) * whatever we want with the remaining request. Also, now we * may have separate values for ->fe, ->be. */ - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); /* * If HTTP PROXY is set we simply get remote server address parsing @@ -1057,7 +1057,7 @@ int htx_wait_for_request_body(struct stream *s, struct channel *req, int an_bit) ci_data(req), req->analysers); - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); if (msg->msg_state < HTTP_MSG_BODY) goto missing_data; @@ -1178,7 +1178,7 @@ int htx_request_forward_body(struct stream *s, struct channel *req, int an_bit) ci_data(req), req->analysers); - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); if ((req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) || ((req->flags & CF_SHUTW) && (req->to_forward || co_data(req)))) { @@ -1450,7 +1450,7 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit) ci_data(rep), rep->analysers); - htx = htx_from_buf(&rep->buf); + htx = htxbuf(&rep->buf); /* * Now we quickly check if we have found a full valid response. @@ -1820,7 +1820,7 @@ int htx_process_res_common(struct stream *s, struct channel *rep, int an_bit, st ci_data(rep), rep->analysers); - htx = htx_from_buf(&rep->buf); + htx = htxbuf(&rep->buf); /* The stats applet needs to adjust the Connection header but we don't * apply any filter there. @@ -2136,7 +2136,7 @@ int htx_response_forward_body(struct stream *s, struct channel *res, int an_bit) ci_data(res), res->analysers); - htx = htx_from_buf(&res->buf); + htx = htxbuf(&res->buf); if ((res->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) || ((res->flags & CF_SHUTW) && (res->to_forward || co_data(res)))) { @@ -2359,7 +2359,7 @@ int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct /* * Create the location */ - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); switch(rule->type) { case REDIRECT_TYPE_SCHEME: { struct http_hdr_ctx ctx; @@ -2540,7 +2540,6 @@ int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct s->logs.tv_request = now; data = htx->data - co_data(res); - b_set_data(&res->buf, b_size(&res->buf)); c_adv(res, data); res->total += data; @@ -2632,7 +2631,6 @@ static int htx_reply_103_early_hints(struct channel *res) } data = htx->data - co_data(res); - b_set_data(&res->buf, b_size(&res->buf)); c_adv(res, data); res->total += data; return 0; @@ -2669,7 +2667,6 @@ static int htx_add_early_hint_header(struct stream *s, int early_hints, const st goto fail; free_trash_chunk(value); - b_set_data(&res->buf, b_size(&res->buf)); return 1; fail: @@ -2697,7 +2694,7 @@ static int htx_add_early_hint_header(struct stream *s, int early_hints, const st int htx_req_replace_stline(int action, const char *replace, int len, struct proxy *px, struct stream *s) { - struct htx *htx = htx_from_buf(&s->req.buf); + struct htx *htx = htxbuf(&s->req.buf); switch (action) { case 0: // method @@ -2731,7 +2728,7 @@ int htx_req_replace_stline(int action, const char *replace, int len, */ void htx_res_set_status(unsigned int status, const char *reason, struct stream *s) { - struct htx *htx = htx_from_buf(&s->res.buf); + struct htx *htx = htxbuf(&s->res.buf); char *res; chunk_reset(&trash); @@ -2769,7 +2766,7 @@ static enum rule_result htx_req_get_intercept_rule(struct proxy *px, struct list int act_flags = 0; int early_hints = 0; - htx = htx_from_buf(&s->req.buf); + htx = htxbuf(&s->req.buf); /* If "the current_rule_list" match the executed rule list, we are in * resume condition. If a resume is needed it is always in the action @@ -3157,7 +3154,7 @@ static enum rule_result htx_res_get_intercept_rule(struct proxy *px, struct list enum rule_result rule_ret = HTTP_RULE_RES_CONT; int act_flags = 0; - htx = htx_from_buf(&s->res.buf); + htx = htxbuf(&s->res.buf); /* If "the current_rule_list" match the executed rule list, we are in * resume condition. If a resume is needed it is always in the action @@ -3493,7 +3490,7 @@ static int htx_apply_filter_to_req_headers(struct stream *s, struct channel *req struct buffer *hdr = get_trash_chunk(); int32_t pos; - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { struct htx_blk *blk = htx_get_blk(htx, pos); @@ -3587,7 +3584,7 @@ static int htx_apply_filter_to_req_line(struct stream *s, struct channel *req, s struct buffer *reqline = get_trash_chunk(); int done; - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); if (unlikely(txn->flags & (TX_CLDENY | TX_CLTARPIT))) return 1; @@ -3709,7 +3706,7 @@ static int htx_apply_filter_to_resp_headers(struct stream *s, struct channel *re struct buffer *hdr = get_trash_chunk(); int32_t pos; - htx = htx_from_buf(&res->buf); + htx = htxbuf(&res->buf); for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { struct htx_blk *blk = htx_get_blk(htx, pos); @@ -3798,7 +3795,7 @@ static int htx_apply_filter_to_sts_line(struct stream *s, struct channel *res, s struct buffer *resline = get_trash_chunk(); int done; - htx = htx_from_buf(&res->buf); + htx = htxbuf(&res->buf); if (unlikely(txn->flags & TX_SVDENY)) return 1; @@ -3920,7 +3917,7 @@ static void htx_manage_client_side_cookies(struct stream *s, struct channel *req char *prev, *att_beg, *att_end, *equal, *val_beg, *val_end, *next; int preserve_hdr; - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); ctx.blk = NULL; while (http_find_header(htx, ist("Cookie"), &ctx, 1)) { del_from = NULL; /* nothing to be deleted */ @@ -4321,7 +4318,7 @@ static void htx_manage_server_side_cookies(struct stream *s, struct channel *res char *prev, *att_beg, *att_end, *equal, *val_beg, *val_end, *next; int is_cookie2; - htx = htx_from_buf(&res->buf); + htx = htxbuf(&res->buf); ctx.blk = NULL; while (1) { @@ -4601,7 +4598,7 @@ void htx_check_request_for_cacheability(struct stream *s, struct channel *req) if ((txn->flags & (TX_CACHEABLE|TX_CACHE_IGNORE)) == TX_CACHE_IGNORE) return; /* nothing more to do here */ - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); pragma_found = cc_found = 0; for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { struct htx_blk *blk = htx_get_blk(htx, pos); @@ -4690,7 +4687,7 @@ void htx_check_response_for_cacheability(struct stream *s, struct channel *res) return; } - htx = htx_from_buf(&res->buf); + htx = htxbuf(&res->buf); for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { struct htx_blk *blk = htx_get_blk(htx, pos); enum htx_blk_type type = htx_get_blk_type(blk); @@ -4767,7 +4764,7 @@ int htx_send_name_header(struct stream *s, struct proxy *be, const char *srv_nam uint32_t data; hdr = ist2(be->server_id_hdr_name, be->server_id_hdr_len); - htx = htx_from_buf(&s->req.buf); + htx = htxbuf(&s->req.buf); data = htx->data; ctx.blk = NULL; @@ -4806,7 +4803,7 @@ static int htx_stats_check_uri(struct stream *s, struct http_txn *txn, struct pr if (txn->meth != HTTP_METH_GET && txn->meth != HTTP_METH_HEAD && txn->meth != HTTP_METH_POST) return 0; - htx = htx_from_buf(&s->req.buf); + htx = htxbuf(&s->req.buf); sl = http_find_stline(htx); uri = htx_sl_req_uri(sl); @@ -4849,7 +4846,7 @@ static int htx_handle_stats(struct stream *s, struct channel *req) if ((msg->flags & HTTP_MSGF_VER_11) && (txn->meth != HTTP_METH_HEAD)) appctx->ctx.stats.flags |= STAT_CHUNKED; - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); sl = http_find_stline(htx); lookup = HTX_SL_REQ_UPTR(sl) + uri_auth->uri_len; end = HTX_SL_REQ_UPTR(sl) + HTX_SL_REQ_ULEN(sl); @@ -5002,7 +4999,7 @@ void htx_perform_server_redirect(struct stream *s, struct stream_interface *si) } /* 2: add the request Path */ - htx = htx_from_buf(&req->buf); + htx = htxbuf(&req->buf); sl = http_find_stline(htx); path = http_get_path(htx_sl_req_uri(sl)); if (!path.ptr) @@ -5037,7 +5034,6 @@ void htx_perform_server_redirect(struct stream *s, struct stream_interface *si) * Send the message */ data = htx->data - co_data(res); - b_set_data(&res->buf, b_size(&res->buf)); c_adv(res, data); res->total += data; @@ -5333,7 +5329,6 @@ void htx_server_error(struct stream *s, struct stream_interface *si, int err, chn->buf.data = msg->data; memcpy(chn->buf.area, msg->area, msg->data); htx = htx_from_buf(&chn->buf); - b_set_data(&chn->buf, b_size(&chn->buf)); c_adv(chn, htx->data); chn->total += htx->data; } @@ -5364,7 +5359,6 @@ void htx_reply_and_close(struct stream *s, short status, struct buffer *msg) chn->buf.data = msg->data; memcpy(chn->buf.area, msg->area, msg->data); htx = htx_from_buf(&chn->buf); - b_set_data(&chn->buf, b_size(&chn->buf)); c_adv(chn, htx->data); chn->total += htx->data; } @@ -5410,7 +5404,6 @@ static int htx_reply_100_continue(struct stream *s) goto fail; data = htx->data - co_data(res); - b_set_data(&res->buf, b_size(&res->buf)); c_adv(res, data); res->total += data; return 0; @@ -5472,7 +5465,6 @@ static int htx_reply_40x_unauthorized(struct stream *s, const char *auth_realm) goto fail; data = htx->data - co_data(res); - b_set_data(&res->buf, b_size(&res->buf)); c_adv(res, data); res->total += data; diff --git a/src/stats.c b/src/stats.c index 57968860fc..c85d411d49 100644 --- a/src/stats.c +++ b/src/stats.c @@ -3218,8 +3218,6 @@ static void htx_stats_io_handler(struct appctx *appctx) } if (appctx->st0 == STAT_HTTP_DONE) { - struct htx_blk *blk; - /* Don't add EOD and TLR because mux-h1 will take care of it */ if (!htx_add_endof(res_htx, HTX_BLK_EOM)) { si_rx_room_blk(si); @@ -3227,20 +3225,10 @@ static void htx_stats_io_handler(struct appctx *appctx) } /* eat the whole request */ - req_htx = htx_from_buf(&req->buf); - blk = htx_get_head_blk(req_htx); - while (blk) { - enum htx_blk_type type = htx_get_blk_type(blk); - - blk = htx_remove_blk(req_htx, blk); - if (type == HTX_BLK_EOM) - break; - } + req_htx = htxbuf(&req->buf); + htx_reset(req_htx); + htx_to_buf(req_htx, &req->buf); co_set_data(req, 0); - if (htx_is_empty(req_htx)) { - htx_reset(req_htx); - b_set_data(&req->buf, 0); - } res->flags |= CF_READ_NULL; si_shutr(si); } @@ -3262,14 +3250,9 @@ static void htx_stats_io_handler(struct appctx *appctx) * deciding to wake the applet up. It saves it from looping when * emitting large blocks into small TCP windows. */ - if (htx_is_empty(res_htx)) { - htx_reset(res_htx); - b_set_data(&res->buf, 0); - } - else { - b_set_data(&res->buf, b_size(&res->buf)); + htx_to_buf(res_htx, &res->buf); + if (!channel_is_empty(res)) si_stop_get(si); - } }