MINOR: mux-quic/h3: adjust demuxing function return values

Clean the API used by decode_qcs() and transcoder internal functions.
Parsing functions now returns a ssize_t which represents the number of
consumed bytes or a negative error code. The total consumed bytes is
returned via decode_qcs().

The API is now unified and cleaner. The MUX can thus simply use the
return value of decode_qcs() instead of substracting the data bytes in
the buffer before and after the call. Transcoders functions are not
anymore obliged to remove consumed bytes from the buffer which was not
obvious.
This commit is contained in:
Amaury Denoyelle 2022-06-07 17:30:55 +02:00
parent 62eef85961
commit 1f21ebdd76
4 changed files with 45 additions and 44 deletions

View File

@ -140,7 +140,7 @@ struct qcs {
struct qcc_app_ops {
int (*init)(struct qcc *qcc);
int (*attach)(struct qcs *qcs, void *conn_ctx);
int (*decode_qcs)(struct qcs *qcs, struct buffer *b, int fin);
ssize_t (*decode_qcs)(struct qcs *qcs, struct buffer *b, int fin);
size_t (*snd_buf)(struct stconn *sc, struct buffer *buf, size_t count, int flags);
void (*detach)(struct qcs *qcs);
int (*finalize)(void *ctx);

View File

@ -145,10 +145,10 @@ DECLARE_STATIC_POOL(pool_head_h3s, "h3s", sizeof(struct h3s));
/* Initialize an uni-stream <qcs> by reading its type from <b>.
*
* Returns 0 on success else non-zero.
* Returns the count of consumed bytes or a negative error code.
*/
static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
struct buffer *b)
static ssize_t h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
struct buffer *b)
{
/* decode unidirectional stream type */
struct h3s *h3s = qcs->ctx;
@ -169,7 +169,7 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
case H3_UNI_S_T_CTRL:
if (h3c->flags & H3_CF_UNI_CTRL_SET) {
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
return 1;
return -1;
}
h3c->flags |= H3_CF_UNI_CTRL_SET;
h3s->type = H3S_T_CTRL;
@ -183,7 +183,7 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
case H3_UNI_S_T_QPACK_DEC:
if (h3c->flags & H3_CF_UNI_QPACK_DEC_SET) {
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
return 1;
return -1;
}
h3c->flags |= H3_CF_UNI_QPACK_DEC_SET;
h3s->type = H3S_T_QPACK_DEC;
@ -193,7 +193,7 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
case H3_UNI_S_T_QPACK_ENC:
if (h3c->flags & H3_CF_UNI_QPACK_ENC_SET) {
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
return 1;
return -1;
}
h3c->flags |= H3_CF_UNI_QPACK_ENC_SET;
h3s->type = H3S_T_QPACK_ENC;
@ -207,21 +207,21 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
* streams that have unknown or unsupported types.
*/
qcs->flags |= QC_SF_READ_ABORTED;
return 1;
return -1;
};
h3s->flags |= H3_SF_UNI_INIT;
TRACE_LEAVE(H3_EV_H3S_NEW, qcs->qcc->conn, qcs);
return 0;
return len;
}
/* Parse an uni-stream <qcs> from <rxbuf> which does not contains H3 frames.
* This may be used for QPACK encoder/decoder streams for example.
*
* Returns 0 on success else non-zero.
* Returns the number of consumed bytes or a negative error code.
*/
static int h3_parse_uni_stream_no_h3(struct qcs *qcs, struct buffer *b)
static ssize_t h3_parse_uni_stream_no_h3(struct qcs *qcs, struct buffer *b)
{
struct h3s *h3s = qcs->ctx;
@ -231,11 +231,11 @@ static int h3_parse_uni_stream_no_h3(struct qcs *qcs, struct buffer *b)
switch (h3s->type) {
case H3S_T_QPACK_DEC:
if (qpack_decode_dec(qcs, NULL))
return 1;
return -1;
break;
case H3S_T_QPACK_ENC:
if (qpack_decode_enc(qcs, NULL))
return 1;
return -1;
break;
case H3S_T_UNKNOWN:
default:
@ -243,6 +243,7 @@ static int h3_parse_uni_stream_no_h3(struct qcs *qcs, struct buffer *b)
ABORT_NOW();
}
/* TODO adjust return code */
return 0;
}
@ -320,10 +321,10 @@ static int h3_is_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype)
* in a local HTX buffer and transfer to the stream connector layer. <fin> must be
* set if this is the last data to transfer from this stream.
*
* Returns the number of bytes handled or a negative error code.
* Returns the number of consumed bytes or a negative error code.
*/
static int h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
uint64_t len, char fin)
static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
uint64_t len, char fin)
{
struct buffer htx_buf = BUF_NULL;
struct buffer *tmp = get_trash_chunk();
@ -418,10 +419,10 @@ static int h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
* HTX buffer. <fin> must be set if this is the last data to transfer from this
* stream.
*
* Returns the number of bytes handled or a negative error code.
* Returns the number of consumed bytes or a negative error code.
*/
static int h3_data_to_htx(struct qcs *qcs, const struct buffer *buf,
uint64_t len, char fin)
static ssize_t h3_data_to_htx(struct qcs *qcs, const struct buffer *buf,
uint64_t len, char fin)
{
struct buffer *appbuf;
struct htx *htx = NULL;
@ -484,10 +485,10 @@ static int h3_data_to_htx(struct qcs *qcs, const struct buffer *buf,
/* Parse a SETTINGS frame of length <len> of payload <buf>.
*
* Returns the number of bytes handled or a negative error code.
* Returns the number of consumed bytes or a negative error code.
*/
static size_t h3_parse_settings_frm(struct h3c *h3c, const struct buffer *buf,
size_t len)
static ssize_t h3_parse_settings_frm(struct h3c *h3c, const struct buffer *buf,
size_t len)
{
struct buffer b;
uint64_t id, value;
@ -568,26 +569,30 @@ static size_t h3_parse_settings_frm(struct h3c *h3c, const struct buffer *buf,
*
* Returns 0 on success else non-zero.
*/
static int h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
{
struct h3s *h3s = qcs->ctx;
struct h3c *h3c = h3s->h3c;
ssize_t ret;
ssize_t total = 0, ret;
h3_debug_printf(stderr, "%s: STREAM ID: %lu\n", __func__, qcs->id);
if (!b_data(b))
return 0;
if (quic_stream_is_uni(qcs->id) && !(h3s->flags & H3_SF_UNI_INIT)) {
if (h3_init_uni_stream(h3c, qcs, b))
return 1;
if ((ret = h3_init_uni_stream(h3c, qcs, b)) < 0)
return -1;
total += ret;
}
if (quic_stream_is_uni(qcs->id) && (h3s->flags & H3_SF_UNI_NO_H3)) {
/* For non-h3 STREAM, parse it and return immediately. */
if (h3_parse_uni_stream_no_h3(qcs, b))
return 1;
return 0;
if ((ret = h3_parse_uni_stream_no_h3(qcs, b)) < 0)
return -1;
total += ret;
return total;
}
while (b_data(b) && !(qcs->flags & QC_SF_DEM_FULL)) {
@ -605,6 +610,7 @@ static int h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
h3s->demux_frame_type = ftype;
h3s->demux_frame_len = flen;
total += hlen;
if (!h3_is_frame_valid(h3c, qcs, ftype)) {
qcc_emit_cc_app(qcs->qcc, H3_FRAME_UNEXPECTED);
@ -679,6 +685,7 @@ static int h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
BUG_ON(h3s->demux_frame_len < ret);
h3s->demux_frame_len -= ret;
b_del(b, ret);
total += ret;
}
}
@ -686,7 +693,7 @@ static int h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
* However, currently, io-cb of MUX does not handle Rx.
*/
return 0;
return total;
}
/* Returns buffer for data sending.

View File

@ -8,7 +8,7 @@
#include <haproxy/http.h>
#include <haproxy/mux_quic.h>
static int hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
{
struct htx *htx;
struct htx_sl *sl;
@ -62,7 +62,7 @@ static int hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
if (!sl)
return 1;
return -1;
sl->flags |= HTX_SL_F_BODYLESS;
sl->info.req.meth = find_http_meth("GET", 3);
@ -72,15 +72,14 @@ static int hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
sc = qc_attach_sc(qcs, &htx_buf);
if (!sc)
return 1;
return -1;
b_reset(b);
b_free(&htx_buf);
if (fin)
htx->flags |= HTX_FL_EOM;
return 0;
return b_data(b);
}
static struct buffer *mux_get_buf(struct qcs *qcs)

View File

@ -439,24 +439,19 @@ static void qcs_consume(struct qcs *qcs, uint64_t bytes)
static int qcc_decode_qcs(struct qcc *qcc, struct qcs *qcs)
{
struct buffer b;
size_t data, done;
int ret;
ssize_t ret;
TRACE_ENTER(QMUX_EV_QCS_RECV, qcc->conn, qcs);
b = qcs_b_dup(&qcs->rx.ncbuf);
data = b_data(&b);
ret = qcc->app_ops->decode_qcs(qcs, &b, qcs->flags & QC_SF_FIN_RECV);
if (ret) {
if (ret < 0) {
TRACE_DEVEL("leaving on decoding error", QMUX_EV_QCS_RECV, qcc->conn, qcs);
return 1;
}
BUG_ON_HOT(data < b_data(&b));
done = data - b_data(&b);
if (done) {
qcs_consume(qcs, done);
if (ret) {
qcs_consume(qcs, ret);
qcs_notify_recv(qcs);
}