BUG/MEDIUM: mux-h2: don't send more HTX data than requested

It's incorrect to send more bytes than requested, because some filters
(e.g. compression) might intentionally hold on some blocks, so DATA
blocks must not be processed past the advertised byte count. It is not
the case for headers however.

No backport is needed.
This commit is contained in:
Willy Tarreau 2018-12-04 15:25:57 +01:00
parent b08d91fbc5
commit ee57376ffb

View File

@ -4234,7 +4234,7 @@ static size_t h2s_htx_bck_make_req_headers(struct h2s *h2s, struct htx *htx)
* subsequently to a successful send. Returns the number of data bytes
* consumed, or zero if nothing done. Note that EOD/EOM count for 1 byte.
*/
static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx, size_t count)
{
struct h2c *h2c = h2s->h2c;
struct buffer outbuf;
@ -4263,7 +4263,7 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
*/
new_frame:
if (htx_is_empty(htx))
if (!count || htx_is_empty(htx))
goto end;
idx = htx_get_head(htx);
@ -4278,8 +4278,8 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
* deal with. Let's simply remove the EOD and return.
*/
htx_remove_blk(htx, blk);
// FIXME, it seems we must not return it in the total bytes count?
//total++; // EOD counts as one byte
total++; // EOD counts as one byte
count--;
goto end;
}
@ -4334,6 +4334,9 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
goto end;
}
if (fsize > count)
fsize = count;
if (fsize > h2s->mws)
fsize = h2s->mws; // >0
@ -4371,6 +4374,7 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
memcpy(outbuf.area + 9, htx_get_blk_ptr(htx, blk), fsize);
h2s->mws -= fsize;
h2c->mws -= fsize;
count -= fsize;
send_empty:
/* update the frame's size */
@ -4380,8 +4384,8 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct htx *htx)
* meeting EOM. We should optimize this later.
*/
if (type == HTX_BLK_EOM) {
// FIXME, it seems we must not return it in the total bytes count?
// total++; // EOM counts as one byte
total++; // EOM counts as one byte
count--;
es_now = 1;
}
@ -4635,7 +4639,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun
case HTX_BLK_EOD:
case HTX_BLK_EOM:
/* all these cause the emission of a DATA frame (possibly empty) */
ret = h2s_htx_frt_make_resp_data(h2s, htx);
ret = h2s_htx_frt_make_resp_data(h2s, htx, count);
if (ret > 0) {
total += ret;
count -= ret;