mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-23 14:51:27 +02:00
MINOR: h3: support HTTP request framing state
Store the current step of HTTP message in h3s stream. This reports if we are in the parsing of headers, content or trailers section. A new enum h3s_st_req is defined for this. This field is stored in h3s struct but only used for request stream. It is left undefined for other streams (control or QPACK streams). h3_is_frame_valid() has been extended to take into account this state information. A connection error H3_FRAME_UNEXPECTED is reported if an invalid frame according to the current state is received; for example a DATA frame at the beginning of a stream.
This commit is contained in:
parent
2c77a5eb8e
commit
8d818c6eab
@ -101,6 +101,14 @@ enum h3s_t {
|
|||||||
H3S_T_UNKNOWN
|
H3S_T_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* State for request streams */
|
||||||
|
enum h3s_st_req {
|
||||||
|
H3S_ST_REQ_BEFORE = 0, /* initial state */
|
||||||
|
H3S_ST_REQ_HEADERS, /* header section received */
|
||||||
|
H3S_ST_REQ_DATA, /* first DATA frame for content received */
|
||||||
|
H3S_ST_REQ_TRAILERS, /* trailer section received */
|
||||||
|
};
|
||||||
|
|
||||||
extern const struct qcc_app_ops h3_ops;
|
extern const struct qcc_app_ops h3_ops;
|
||||||
|
|
||||||
size_t h3_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, int flags);
|
size_t h3_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, int flags);
|
||||||
|
12
src/h3.c
12
src/h3.c
@ -138,6 +138,7 @@ struct h3s {
|
|||||||
struct h3c *h3c;
|
struct h3c *h3c;
|
||||||
|
|
||||||
enum h3s_t type;
|
enum h3s_t type;
|
||||||
|
enum h3s_st_req st_req; /* only used for request streams */
|
||||||
int demux_frame_len;
|
int demux_frame_len;
|
||||||
int demux_frame_type;
|
int demux_frame_type;
|
||||||
|
|
||||||
@ -284,8 +285,11 @@ static int h3_is_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype)
|
|||||||
|
|
||||||
switch (ftype) {
|
switch (ftype) {
|
||||||
case H3_FT_DATA:
|
case H3_FT_DATA:
|
||||||
|
return h3s->type != H3S_T_CTRL && (h3s->st_req == H3S_ST_REQ_HEADERS ||
|
||||||
|
h3s->st_req == H3S_ST_REQ_DATA);
|
||||||
|
|
||||||
case H3_FT_HEADERS:
|
case H3_FT_HEADERS:
|
||||||
return h3s->type != H3S_T_CTRL;
|
return h3s->type != H3S_T_CTRL && h3s->st_req != H3S_ST_REQ_TRAILERS;
|
||||||
|
|
||||||
case H3_FT_CANCEL_PUSH:
|
case H3_FT_CANCEL_PUSH:
|
||||||
case H3_FT_GOAWAY:
|
case H3_FT_GOAWAY:
|
||||||
@ -344,6 +348,8 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
|
|||||||
|
|
||||||
TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
|
TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
|
||||||
|
|
||||||
|
/* TODO support trailer parsing in this function */
|
||||||
|
|
||||||
/* TODO support buffer wrapping */
|
/* TODO support buffer wrapping */
|
||||||
BUG_ON(b_head(buf) + len >= b_wrap(buf));
|
BUG_ON(b_head(buf) + len >= b_wrap(buf));
|
||||||
ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
|
ret = qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp,
|
||||||
@ -673,6 +679,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
|||||||
ret = h3_data_to_htx(qcs, b, flen, last_stream_frame);
|
ret = h3_data_to_htx(qcs, b, flen, last_stream_frame);
|
||||||
/* TODO handle error reporting. Stream closure required. */
|
/* TODO handle error reporting. Stream closure required. */
|
||||||
if (ret < 0) { ABORT_NOW(); }
|
if (ret < 0) { ABORT_NOW(); }
|
||||||
|
h3s->st_req = H3S_ST_REQ_DATA;
|
||||||
break;
|
break;
|
||||||
case H3_FT_HEADERS:
|
case H3_FT_HEADERS:
|
||||||
ret = h3_headers_to_htx(qcs, b, flen, last_stream_frame);
|
ret = h3_headers_to_htx(qcs, b, flen, last_stream_frame);
|
||||||
@ -684,6 +691,8 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
|||||||
qcc_emit_cc_app(qcs->qcc, h3c->err, 1);
|
qcc_emit_cc_app(qcs->qcc, h3c->err, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
h3s->st_req = (h3s->st_req == H3S_ST_REQ_BEFORE) ?
|
||||||
|
H3S_ST_REQ_HEADERS : H3S_ST_REQ_TRAILERS;
|
||||||
break;
|
break;
|
||||||
case H3_FT_CANCEL_PUSH:
|
case H3_FT_CANCEL_PUSH:
|
||||||
case H3_FT_PUSH_PROMISE:
|
case H3_FT_PUSH_PROMISE:
|
||||||
@ -1070,6 +1079,7 @@ static int h3_attach(struct qcs *qcs, void *conn_ctx)
|
|||||||
|
|
||||||
if (quic_stream_is_bidi(qcs->id)) {
|
if (quic_stream_is_bidi(qcs->id)) {
|
||||||
h3s->type = H3S_T_REQ;
|
h3s->type = H3S_T_REQ;
|
||||||
|
h3s->st_req = H3S_ST_REQ_BEFORE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* stream type must be decoded for unidirectional streams */
|
/* stream type must be decoded for unidirectional streams */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user