mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-23 06:41:32 +02:00
MINOR: h3: support DATA demux if buffer full
Previously, h3 layer was not able to demux a DATA frame if not fully received in the Rx buffer. This causes evident limitation and prevents to be able to demux a frame bigger than the buffer. Improve h3_data_to_htx() to support partial frame demuxing. The demux state is preserved in the h3s new fields : this is useful to keep the current type and length of the demuxed frame.
This commit is contained in:
parent
67e92d3652
commit
48f01bda86
52
src/h3.c
52
src/h3.c
@ -69,6 +69,8 @@ struct h3 {
|
|||||||
DECLARE_STATIC_POOL(pool_head_h3, "h3", sizeof(struct h3));
|
DECLARE_STATIC_POOL(pool_head_h3, "h3", sizeof(struct h3));
|
||||||
|
|
||||||
struct h3s {
|
struct h3s {
|
||||||
|
int demux_frame_len;
|
||||||
|
int demux_frame_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_STATIC_POOL(pool_head_h3s, "h3s", sizeof(struct h3s));
|
DECLARE_STATIC_POOL(pool_head_h3s, "h3s", sizeof(struct h3s));
|
||||||
@ -213,10 +215,20 @@ static int h3_data_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len,
|
|||||||
BUG_ON(!appbuf);
|
BUG_ON(!appbuf);
|
||||||
htx = htx_from_buf(appbuf);
|
htx = htx_from_buf(appbuf);
|
||||||
|
|
||||||
|
if (len > b_data(buf)) {
|
||||||
|
len = b_data(buf);
|
||||||
|
fin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
head = b_head(buf);
|
||||||
retry:
|
retry:
|
||||||
htx_space = htx_free_data_space(htx);
|
htx_space = htx_free_data_space(htx);
|
||||||
if (!htx_space || htx_space < len) {
|
if (!htx_space)
|
||||||
ABORT_NOW(); /* TODO handle this case properly */
|
goto out;
|
||||||
|
|
||||||
|
if (len > htx_space) {
|
||||||
|
len = htx_space;
|
||||||
|
fin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
contig = b_contig_data(buf, contig);
|
contig = b_contig_data(buf, contig);
|
||||||
@ -230,10 +242,11 @@ static int h3_data_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len,
|
|||||||
htx_sent += htx_add_data(htx, ist2(head, len));
|
htx_sent += htx_add_data(htx, ist2(head, len));
|
||||||
BUG_ON(htx_sent < len);
|
BUG_ON(htx_sent < len);
|
||||||
|
|
||||||
if (fin)
|
if (fin && len == htx_sent)
|
||||||
htx->flags |= HTX_FL_EOM;
|
htx->flags |= HTX_FL_EOM;
|
||||||
htx_to_buf(htx, appbuf);
|
|
||||||
|
|
||||||
|
out:
|
||||||
|
htx_to_buf(htx, appbuf);
|
||||||
return htx_sent;
|
return htx_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +257,7 @@ static int h3_data_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len,
|
|||||||
static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
|
static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
|
||||||
{
|
{
|
||||||
struct buffer *rxbuf = &qcs->rx.buf;
|
struct buffer *rxbuf = &qcs->rx.buf;
|
||||||
|
struct h3s *h3s = qcs->ctx;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
h3_debug_printf(stderr, "%s: STREAM ID: %lu\n", __func__, qcs->id);
|
h3_debug_printf(stderr, "%s: STREAM ID: %lu\n", __func__, qcs->id);
|
||||||
@ -251,26 +265,29 @@ static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (b_data(rxbuf)) {
|
while (b_data(rxbuf)) {
|
||||||
size_t hlen;
|
|
||||||
uint64_t ftype, flen;
|
uint64_t ftype, flen;
|
||||||
struct buffer b;
|
struct buffer b;
|
||||||
char last_stream_frame = 0;
|
char last_stream_frame = 0;
|
||||||
|
|
||||||
/* Work on a copy of <rxbuf> */
|
/* Work on a copy of <rxbuf> */
|
||||||
b = h3_b_dup(rxbuf);
|
b = h3_b_dup(rxbuf);
|
||||||
hlen = h3_decode_frm_header(&ftype, &flen, &b);
|
if (!h3s->demux_frame_len) {
|
||||||
if (!hlen)
|
size_t hlen = h3_decode_frm_header(&ftype, &flen, &b);
|
||||||
break;
|
if (!hlen)
|
||||||
|
break;
|
||||||
|
|
||||||
h3_debug_printf(stderr, "%s: ftype: %llu, flen: %llu\n", __func__,
|
h3_debug_printf(stderr, "%s: ftype: %lu, flen: %lu\n",
|
||||||
(unsigned long long)ftype, (unsigned long long)flen);
|
__func__, ftype, flen);
|
||||||
|
|
||||||
|
b_del(rxbuf, hlen);
|
||||||
|
h3s->demux_frame_type = ftype;
|
||||||
|
h3s->demux_frame_len = flen;
|
||||||
|
}
|
||||||
|
|
||||||
|
flen = h3s->demux_frame_len;
|
||||||
|
ftype = h3s->demux_frame_type;
|
||||||
if (flen > b_data(&b) && !b_full(rxbuf))
|
if (flen > b_data(&b) && !b_full(rxbuf))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* TODO handle full rxbuf */
|
|
||||||
BUG_ON(flen > b_size(rxbuf));
|
|
||||||
|
|
||||||
b_del(rxbuf, hlen);
|
|
||||||
last_stream_frame = (fin && flen == b_data(rxbuf));
|
last_stream_frame = (fin && flen == b_data(rxbuf));
|
||||||
|
|
||||||
switch (ftype) {
|
switch (ftype) {
|
||||||
@ -300,6 +317,8 @@ static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
b_del(rxbuf, ret);
|
b_del(rxbuf, ret);
|
||||||
|
BUG_ON(h3s->demux_frame_len < ret);
|
||||||
|
h3s->demux_frame_len -= ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -734,6 +753,9 @@ static int h3_attach(struct qcs *qcs)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
qcs->ctx = h3s;
|
qcs->ctx = h3s;
|
||||||
|
h3s->demux_frame_len = 0;
|
||||||
|
h3s->demux_frame_type = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user