aboutsummaryrefslogtreecommitdiff
path: root/src/http/v3/ngx_http_v3_parse.c
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2020-08-24 09:56:36 +0300
committerRoman Arutyunyan <arut@nginx.com>2020-08-24 09:56:36 +0300
commitd294369915461ba764426c709301b6c66ed33681 (patch)
tree46e9bef435e7e40be5ca421b1c7e8a4465c304f1 /src/http/v3/ngx_http_v3_parse.c
parent46173bd4b40023fd5e35bfe77b9ac2205e0c6bb0 (diff)
downloadnginx-d294369915461ba764426c709301b6c66ed33681.tar.gz
nginx-d294369915461ba764426c709301b6c66ed33681.zip
HTTP/3: skip unknown frames on request stream.
As per HTTP/3 draft 29, section 4.1: Frames of unknown types (Section 9), including reserved frames (Section 7.2.8) MAY be sent on a request or push stream before, after, or interleaved with other frames described in this section. Also, trailers frame is now used as an indication of the request body end.
Diffstat (limited to 'src/http/v3/ngx_http_v3_parse.c')
-rw-r--r--src/http/v3/ngx_http_v3_parse.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c
index 1a7aa17f8..8f47b4d99 100644
--- a/src/http/v3/ngx_http_v3_parse.c
+++ b/src/http/v3/ngx_http_v3_parse.c
@@ -155,7 +155,9 @@ ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st,
ngx_int_t rc;
enum {
sw_start = 0,
+ sw_type,
sw_length,
+ sw_skip,
sw_prefix,
sw_verify,
sw_header_rep,
@@ -168,10 +170,18 @@ ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st,
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers");
- if (ch != NGX_HTTP_V3_FRAME_HEADERS) {
- return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
+ st->state = sw_type;
+
+ /* fall through */
+
+ case sw_type:
+
+ rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch);
+ if (rc != NGX_DONE) {
+ return rc;
}
+ st->type = st->vlint.value;
st->state = sw_length;
break;
@@ -184,12 +194,26 @@ ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st,
st->length = st->vlint.value;
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 parse headers len:%ui", st->length);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http3 parse headers type:%ui, len:%ui",
+ st->type, st->length);
+
+ if (st->type != NGX_HTTP_V3_FRAME_HEADERS) {
+ st->state = st->length > 0 ? sw_skip : sw_type;
+ break;
+ }
st->state = sw_prefix;
break;
+ case sw_skip:
+
+ if (--st->length == 0) {
+ st->state = sw_type;
+ }
+
+ break;
+
case sw_prefix:
if (st->length-- == 0) {
@@ -1529,7 +1553,8 @@ ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
enum {
sw_start = 0,
sw_type,
- sw_length
+ sw_length,
+ sw_skip
};
switch (st->state) {
@@ -1549,8 +1574,11 @@ ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
return rc;
}
- if (st->vlint.value != NGX_HTTP_V3_FRAME_DATA) {
- return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
+ st->type = st->vlint.value;
+
+ if (st->type == NGX_HTTP_V3_FRAME_HEADERS) {
+ /* trailers */
+ goto done;
}
st->state = sw_length;
@@ -1565,10 +1593,25 @@ ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
st->length = st->vlint.value;
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http3 parse data frame len:%ui", st->length);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http3 parse data type:%ui, len:%ui",
+ st->type, st->length);
- goto done;
+ if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) {
+ st->state = sw_skip;
+ break;
+ }
+
+ st->state = sw_type;
+ return NGX_OK;
+
+ case sw_skip:
+
+ if (--st->length == 0) {
+ st->state = sw_type;
+ }
+
+ break;
}
return NGX_AGAIN;