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.
This commit is contained in:
Willy Tarreau 2018-12-01 18:59:00 +01:00
parent 86724e2e8a
commit bcd3bb3ca2

View File

@ -20,6 +20,8 @@
#include <common/net_helper.h>
#include <proto/connection.h>
#include <proto/h1.h>
#include <proto/http_htx.h>
#include <proto/htx.h>
#include <proto/stream.h>
#include <types/session.h>
#include <eb32tree.h>
@ -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);