From: Willy Tarreau Date: Sat, 1 Dec 2018 17:59:00 +0000 (+0100) Subject: MEDIUM: mux-h2: make h2_snd_buf() HTX-aware X-Git-Tag: v1.9-dev9~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bcd3bb3ca224c5e28881051b3aae51e085a0110f;p=thirdparty%2Fhaproxy.git MEDIUM: mux-h2: make h2_snd_buf() HTX-aware Now h2_snd_buf() will check the proxy's mode to decide whether to use HTX-specific send functions or legacy functions. In HTX mode, the HTX blocks of the output buffer will be parsed and the related functions will be called accordingly based on the block type, and unimplemented blocks will be skipped. For now all blocks are skipped, this is only helpful for debugging. --- diff --git a/src/mux_h2.c b/src/mux_h2.c index c07cdd9621..898c51a7bd 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -3652,6 +3654,11 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun struct h2s *h2s = cs->ctx; size_t total = 0; size_t ret; + struct htx *htx; + struct htx_blk *blk; + enum htx_blk_type btype; + uint32_t bsize; + int32_t idx; if (h2s->send_wait) { h2s->send_wait->wait_reason &= ~SUB_CALL_UNSUBSCRIBE; @@ -3662,9 +3669,31 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun if (h2s->h2c->st0 < H2_CS_FRAME_H) return 0; + /* htx will be enough to decide if we're using HTX or legacy */ + htx = (h2s->h2c->proxy->options2 & PR_O2_USE_HTX) ? htx_from_buf(buf) : NULL; + if (!(h2s->flags & H2_SF_OUTGOING_DATA) && count) h2s->flags |= H2_SF_OUTGOING_DATA; + if (htx) { + while (count && !htx_is_empty(htx)) { + idx = htx_get_head(htx); + blk = htx_get_blk(htx, idx); + btype = htx_get_blk_type(blk); + bsize = htx_get_blksz(blk); + + switch (btype) { + default: + htx_remove_blk(htx, blk); + total += bsize; + count -= bsize; + break; + } + } + goto done; + } + + /* legacy transfer mode */ while (h2s->h1m.state < H1_MSG_DONE && count) { if (h2s->h1m.state <= H1_MSG_LAST_LF) { ret = h2s_frt_make_resp_headers(h2s, buf, total, count); @@ -3702,6 +3731,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun break; } + done: if (h2s->st >= H2_SS_ERROR) { /* trim any possibly pending data after we close (extra CR-LF, * unprocessed trailers, abnormal extra data, ...) @@ -3717,12 +3747,20 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun h2s_close(h2s); } - b_del(buf, total); + if (htx) { + if (htx_is_empty(htx)) { + htx_reset(htx); + b_set_data(buf, 0); + } + } else { + b_del(buf, total); + } /* The mux is full, cancel the pending tasks */ if ((h2s->h2c->flags & H2_CF_MUX_BLOCK_ANY) || (h2s->flags & H2_SF_BLK_MBUSY)) h2_stop_senders(h2s->h2c); + if (total > 0) { if (!(h2s->h2c->wait_event.wait_reason & SUB_CAN_SEND)) tasklet_wakeup(h2s->h2c->wait_event.task);