Skip to content

Commit cc39535

Browse files
committed
MINOR: mux_quic: handle incomplete QMux record read
QMux implements a record layer which is used to encapsulate QUIC frames. This patch implements reception of an incomplete record in qcc_qstrm_recv(). BUG_ON() failures are removed and now reading will continue until the whole record is received or a fatal error occurs. Several adjustments were made in the logic for read operation. Previously, read syscall was only performed if either data buffer was empty or current record was incomplete. An extra condition is added to perform read if there is data in the buffer but not enough to decode a record header. Another change is that buffer realign is also performed in this latter case and if buffer wrapping position has been reached.
1 parent 61e839c commit cc39535

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

src/mux_quic_qstrm.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ int qcc_qstrm_recv(struct qcc *qcc)
105105
struct connection *conn = qcc->conn;
106106
struct buffer *buf = &qcc->rx.qstrm_buf;
107107
struct buffer buf_rec;
108-
int total = 0, frm_ret;
108+
int total = 0, dec = 1, frm_ret;
109109
size_t ret = 1;
110110

111111
TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
@@ -125,8 +125,11 @@ int qcc_qstrm_recv(struct qcc *qcc)
125125
/* Wrapping is not supported for QMux reception. */
126126
BUG_ON(b_data(buf) != b_contig_data(buf, 0));
127127

128-
/* If current record is too big, realign buffer for more room. */
129-
if (b_head(buf) + qcc->rx.rlen > b_wrap(buf)) {
128+
/* Realign buffer if current record too big or cannot decode
129+
* record header and wrapping position reached.
130+
*/
131+
if (b_head(buf) + qcc->rx.rlen > b_wrap(buf) ||
132+
(!dec && b_head(buf) + b_data(buf) == b_wrap(buf))) {
130133
BUG_ON(qcc->rx.rlen > b_size(buf)); /* TODO max_record_size */
131134
memmove(b_orig(buf), b_head(buf), b_data(buf));
132135
buf->head = 0;
@@ -136,7 +139,12 @@ int qcc_qstrm_recv(struct qcc *qcc)
136139
b_realign_if_empty(buf);
137140
}
138141

139-
if ((!b_data(buf) && !qcc->rx.rlen) || qcc->rx.rlen > b_data(buf)) {
142+
/* Try read if record header not yet read and no data available
143+
* or hreader cannot be decoded, or either if current record
144+
* is incomplete.
145+
*/
146+
if ((!qcc->rx.rlen && (!b_data(buf) || !dec)) ||
147+
qcc->rx.rlen > b_data(buf)) {
140148
/* Previous realign operation should ensure send cannot result in data wrapping. */
141149
BUG_ON(b_data(buf) && b_tail(buf) == b_orig(buf));
142150
ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, b_contig_space(buf), NULL, 0, 0);
@@ -147,11 +155,15 @@ int qcc_qstrm_recv(struct qcc *qcc)
147155
}
148156

149157
if (b_data(buf) && !qcc->rx.rlen) {
150-
int ret2 = b_quic_dec_int(&qcc->rx.rlen, buf, NULL);
151-
BUG_ON(!ret2); /* TODO incomplete record length */
152-
if (b_head(buf) + qcc->rx.rlen > b_wrap(buf))
158+
dec = b_quic_dec_int(&qcc->rx.rlen, buf, NULL);
159+
/* Restart read if an incomplete record has been received
160+
* until there is no more new data available.
161+
*/
162+
if (ret && (!dec ||
163+
b_head(buf) + qcc->rx.rlen > b_wrap(buf) ||
164+
b_data(buf) < qcc->rx.rlen)) {
153165
goto recv;
154-
BUG_ON(b_data(buf) < qcc->rx.rlen); /* TODO incomplete record */
166+
}
155167
}
156168

157169
/* TODO realign necessary if record boundary at the extreme end of the buffer */

0 commit comments

Comments
 (0)