From: Christopher Faulet Date: Mon, 14 Oct 2019 12:17:00 +0000 (+0200) Subject: BUG/MINOR: mux-h1: Mark the output buffer as full when the xfer is interrupted X-Git-Tag: v2.1-dev3~78 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a61aa544b4b95d1416fe5684ca2d3a0e110e9743;p=thirdparty%2Fhaproxy.git BUG/MINOR: mux-h1: Mark the output buffer as full when the xfer is interrupted When an outgoing HTX message is formatted to a raw message, if we fail to copy data of an HTX block into the output buffer, we mark it as full. Before it was only done calling the function buf_room_for_htx_data(). But this function is designed to optimize input processing. This patch must be backported to 2.0 and 1.9. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index b09b1b9d4a..3c3beadff8 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1576,7 +1576,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun vlen = sz; if (vlen > count) { if (type != HTX_BLK_DATA) - goto copy; + goto full; vlen = count; } @@ -1592,7 +1592,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun h1s->meth = sl->info.req.meth; h1_parse_req_vsn(h1m, sl); if (!htx_reqline_to_h1(sl, &tmp)) - goto copy; + goto full; h1m->flags |= H1_MF_XFER_LEN; if (sl->flags & HTX_SL_F_BODYLESS) h1m->flags |= H1_MF_CLEN; @@ -1607,7 +1607,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun h1s->status = sl->info.res.status; h1_parse_res_vsn(h1m, sl); if (!htx_stline_to_h1(sl, &tmp)) - goto copy; + goto full; if (sl->flags & HTX_SL_F_XFER_LEN) h1m->flags |= H1_MF_XFER_LEN; if (sl->info.res.status < 200 && @@ -1654,7 +1654,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV)) h1_adjust_case_outgoing_hdr(h1s, h1m, &n); if (!htx_hdr_to_h1(n, v, &tmp)) - goto copy; + goto full; skip_hdr: h1m->state = H1_MSG_HDR_L2_LWS; break; @@ -1676,7 +1676,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV)) h1_adjust_case_outgoing_hdr(h1s, h1m, &n); if (!htx_hdr_to_h1(n, v, &tmp)) - goto copy; + goto full; } h1s->flags |= H1S_F_HAVE_O_CONN; } @@ -1694,7 +1694,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV)) h1_adjust_case_outgoing_hdr(h1s, h1m, &n); if (!htx_hdr_to_h1(n, v, &tmp)) - goto copy; + goto full; TRACE_STATE("add \"Transfer-Encoding: chunked\"", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s); h1m->flags |= H1_MF_CHNK; } @@ -1712,14 +1712,14 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV)) h1_adjust_case_outgoing_hdr(h1s, h1m, &n); if (!htx_hdr_to_h1(n, v, &tmp)) - goto copy; + goto full; } TRACE_STATE("add server name header", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s); h1s->flags |= H1S_F_HAVE_SRV_NAME; } if (!chunk_memcat(&tmp, "\r\n", 2)) - goto copy; + goto full; TRACE_PROTO((!(h1m->flags & H1_MF_RESP) ? "H1 request headers xferred" : "H1 response headers xferred"), H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s); @@ -1756,7 +1756,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun /* Chunked message without explicit trailers */ if (h1m->flags & H1_MF_CHNK) { if (!chunk_memcat(&tmp, "0\r\n\r\n", 5)) - goto copy; + goto full; } goto done; } @@ -1764,7 +1764,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun /* If the message is not chunked, never * add the last chunk. */ if ((h1m->flags & H1_MF_CHNK) && !chunk_memcat(&tmp, "0\r\n", 3)) - goto copy; + goto full; TRACE_PROTO("sending message trailers", H1_EV_TX_DATA|H1_EV_TX_TLRS, h1c->conn, h1s, chn_htx); goto trailers; } @@ -1775,7 +1775,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun v = htx_get_blk_value(chn_htx, blk); v.len = vlen; if (!htx_data_to_h1(v, &tmp, !!(h1m->flags & H1_MF_CHNK))) - goto copy; + goto full; if (h1m->state == H1_MSG_DATA) TRACE_PROTO((!(h1m->flags & H1_MF_RESP) ? "H1 request payload data xferred" : "H1 response payload data xferred"), @@ -1799,7 +1799,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (type == HTX_BLK_EOT) { if (!chunk_memcat(&tmp, "\r\n", 2)) - goto copy; + goto full; TRACE_PROTO((!(h1m->flags & H1_MF_RESP) ? "H1 request trailers xferred" : "H1 response trailers xferred"), H1_EV_TX_DATA|H1_EV_TX_TLRS, h1c->conn, h1s); } @@ -1811,7 +1811,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun if (h1c->px->options2 & (PR_O2_H1_ADJ_BUGCLI|PR_O2_H1_ADJ_BUGSRV)) h1_adjust_case_outgoing_hdr(h1s, h1m, &n); if (!htx_hdr_to_h1(n, v, &tmp)) - goto copy; + goto full; } break; @@ -1871,6 +1871,11 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun end: TRACE_LEAVE(H1_EV_TX_DATA, h1c->conn, h1s, chn_htx, (size_t[]){total}); return total; + + full: + TRACE_STATE("h1c obuf full", H1_EV_TX_DATA|H1_EV_H1S_BLK, h1c->conn, h1s); + h1c->flags |= H1C_F_OUT_FULL; + goto copy; } /*********************************************************/