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.
diff --git a/src/h3.c b/src/h3.c
index 2a46c1e..f5da761 100644
--- a/src/h3.c
+++ b/src/h3.c
@@ -69,6 +69,8 @@
DECLARE_STATIC_POOL(pool_head_h3, "h3", sizeof(struct h3));
struct h3s {
+ int demux_frame_len;
+ int demux_frame_type;
};
DECLARE_STATIC_POOL(pool_head_h3s, "h3s", sizeof(struct h3s));
@@ -213,10 +215,20 @@
BUG_ON(!appbuf);
htx = htx_from_buf(appbuf);
+ if (len > b_data(buf)) {
+ len = b_data(buf);
+ fin = 0;
+ }
+
+ head = b_head(buf);
retry:
htx_space = htx_free_data_space(htx);
- if (!htx_space || htx_space < len) {
- ABORT_NOW(); /* TODO handle this case properly */
+ if (!htx_space)
+ goto out;
+
+ if (len > htx_space) {
+ len = htx_space;
+ fin = 0;
}
contig = b_contig_data(buf, contig);
@@ -230,10 +242,11 @@
htx_sent += htx_add_data(htx, ist2(head, len));
BUG_ON(htx_sent < len);
- if (fin)
+ if (fin && len == htx_sent)
htx->flags |= HTX_FL_EOM;
- htx_to_buf(htx, appbuf);
+ out:
+ htx_to_buf(htx, appbuf);
return htx_sent;
}
@@ -244,6 +257,7 @@
static int h3_decode_qcs(struct qcs *qcs, int fin, void *ctx)
{
struct buffer *rxbuf = &qcs->rx.buf;
+ struct h3s *h3s = qcs->ctx;
ssize_t ret;
h3_debug_printf(stderr, "%s: STREAM ID: %lu\n", __func__, qcs->id);
@@ -251,26 +265,29 @@
return 0;
while (b_data(rxbuf)) {
- size_t hlen;
uint64_t ftype, flen;
struct buffer b;
char last_stream_frame = 0;
/* Work on a copy of <rxbuf> */
b = h3_b_dup(rxbuf);
- hlen = h3_decode_frm_header(&ftype, &flen, &b);
- if (!hlen)
- break;
+ if (!h3s->demux_frame_len) {
+ size_t hlen = h3_decode_frm_header(&ftype, &flen, &b);
+ if (!hlen)
+ break;
- h3_debug_printf(stderr, "%s: ftype: %llu, flen: %llu\n", __func__,
- (unsigned long long)ftype, (unsigned long long)flen);
- if (flen > b_data(&b) && !b_full(rxbuf))
- break;
+ h3_debug_printf(stderr, "%s: ftype: %lu, flen: %lu\n",
+ __func__, ftype, flen);
- /* TODO handle full rxbuf */
- BUG_ON(flen > b_size(rxbuf));
+ b_del(rxbuf, hlen);
+ h3s->demux_frame_type = ftype;
+ h3s->demux_frame_len = flen;
+ }
- b_del(rxbuf, hlen);
+ flen = h3s->demux_frame_len;
+ ftype = h3s->demux_frame_type;
+ if (flen > b_data(&b) && !b_full(rxbuf))
+ break;
last_stream_frame = (fin && flen == b_data(rxbuf));
switch (ftype) {
@@ -300,6 +317,8 @@
break;
b_del(rxbuf, ret);
+ BUG_ON(h3s->demux_frame_len < ret);
+ h3s->demux_frame_len -= ret;
}
return 0;
@@ -734,6 +753,9 @@
return 1;
qcs->ctx = h3s;
+ h3s->demux_frame_len = 0;
+ h3s->demux_frame_type = 0;
+
return 0;
}