mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-20 04:37:04 +00:00
MEDIUM: mux-h1: Support zero-copy forwarding for chunks with an unknown size
Till now, for chunked messages, the H1 mux used the size requested during the zero-copy forwarding negotiation as the chunk size. And till now, this was accurate because the requested size was indeed the chunk size on the producer side. But this will be a problem to implement the zero-copy forwarding on some applets because the content size is not known during the nego but only when it is produced. Thanks to previous patches, it is now possible to know the requested size is not exact and we are able to reserve a larger space to write the chunk size later, in h1_done_ff(), with some padding.
This commit is contained in:
parent
dcb964f8db
commit
91b77c1632
40
src/mux_h1.c
40
src/mux_h1.c
@ -4450,7 +4450,7 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
struct h1s *h1s = __sc_mux_strm(sc);
|
||||
struct h1c *h1c = h1s->h1c;
|
||||
struct h1m *h1m = (!(h1c->flags & H1C_F_IS_BACK) ? &h1s->res : &h1s->req);
|
||||
size_t ret = 0;
|
||||
size_t sz, offset = 0, ret = 0;
|
||||
|
||||
TRACE_ENTER(H1_EV_STRM_SEND, h1c->conn, h1s, 0, (size_t[]){count});
|
||||
|
||||
@ -4487,9 +4487,18 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
h1m->curr_len = count;
|
||||
}
|
||||
else {
|
||||
/* XXX: Unsupported for now but will be added soon ! */
|
||||
h1s->sd->iobuf.flags |= IOBUF_FL_NO_FF;
|
||||
goto out;
|
||||
/* The producer does not know the chunk size, thus this will be emitted at the
|
||||
* end, in done_ff(). So splicing cannot be used (see TODO below).
|
||||
* We will reserve 12 bytes to handle at most 4Go chunk with all CRLFs !
|
||||
* (<8-bytes SIZE><CRLF><CHUNK-DATA><CRLF>)
|
||||
*/
|
||||
if (count > MAX_RANGE(unsigned int))
|
||||
count = MAX_RANGE(unsigned int);
|
||||
offset = 12;
|
||||
/* Add 2 more bytes to finish the previous chunk */
|
||||
if (h1m->state == H1_MSG_CHUNK_CRLF)
|
||||
offset += 2;
|
||||
goto no_splicing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4514,6 +4523,7 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
TRACE_DEVEL("Unable to allocate pipe for splicing, fallback to buffer", H1_EV_STRM_SEND, h1c->conn, h1s);
|
||||
}
|
||||
|
||||
no_splicing:
|
||||
if (!h1_get_buf(h1c, &h1c->obuf)) {
|
||||
h1c->flags |= H1C_F_OUT_ALLOC;
|
||||
TRACE_STATE("waiting for opposite h1c obuf allocation", H1_EV_STRM_SEND|H1_EV_H1S_BLK, h1c->conn, h1s);
|
||||
@ -4523,13 +4533,11 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
if (b_space_wraps(&h1c->obuf))
|
||||
b_slow_realign(&h1c->obuf, trash.area, b_data(&h1c->obuf));
|
||||
|
||||
h1s->sd->iobuf.buf = &h1c->obuf;
|
||||
h1s->sd->iobuf.offset = 0;
|
||||
h1s->sd->iobuf.data = 0;
|
||||
|
||||
/* Cannot forward more than available room in output buffer */
|
||||
if (count > b_room(&h1c->obuf))
|
||||
count = b_room(&h1c->obuf);
|
||||
sz = b_contig_space(&h1c->obuf) - offset;
|
||||
if (count > sz)
|
||||
count = sz;
|
||||
|
||||
if (!count) {
|
||||
h1c->flags |= H1C_F_OUT_FULL;
|
||||
@ -4538,6 +4546,10 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
goto out;
|
||||
}
|
||||
|
||||
h1s->sd->iobuf.buf = &h1c->obuf;
|
||||
h1s->sd->iobuf.offset = offset;
|
||||
h1s->sd->iobuf.data = 0;
|
||||
|
||||
/* forward remaining input data */
|
||||
if (b_data(input)) {
|
||||
size_t xfer = count;
|
||||
@ -4584,6 +4596,16 @@ static size_t h1_done_ff(struct stconn *sc)
|
||||
if (b_room(&h1c->obuf) == sd->iobuf.offset)
|
||||
h1c->flags |= H1C_F_OUT_FULL;
|
||||
|
||||
if (sd->iobuf.offset) {
|
||||
b_add(&h1c->obuf, sd->iobuf.offset);
|
||||
b_del(&h1c->obuf, sd->iobuf.offset);
|
||||
h1_prepend_chunk_size(&h1c->obuf, sd->iobuf.data, sd->iobuf.offset - ((h1m->state == H1_MSG_CHUNK_CRLF) ? 4 : 2));
|
||||
h1_append_chunk_crlf(&h1c->obuf);
|
||||
if (h1m->state == H1_MSG_CHUNK_CRLF)
|
||||
h1_prepend_chunk_crlf(&h1c->obuf);
|
||||
h1m->state = H1_MSG_CHUNK_SIZE;
|
||||
}
|
||||
|
||||
total = sd->iobuf.data;
|
||||
sd->iobuf.buf = NULL;
|
||||
sd->iobuf.offset = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user