comparison src/http/v3/ngx_http_v3_parse.c @ 8549:d70a38acaea0 quic

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.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 24 Aug 2020 09:56:36 +0300
parents 0596fe1aee16
children 234e9d89ff7f
comparison
equal deleted inserted replaced
8548:9ffef6054abf 8549:d70a38acaea0
153 u_char ch) 153 u_char ch)
154 { 154 {
155 ngx_int_t rc; 155 ngx_int_t rc;
156 enum { 156 enum {
157 sw_start = 0, 157 sw_start = 0,
158 sw_type,
158 sw_length, 159 sw_length,
160 sw_skip,
159 sw_prefix, 161 sw_prefix,
160 sw_verify, 162 sw_verify,
161 sw_header_rep, 163 sw_header_rep,
162 sw_done 164 sw_done
163 }; 165 };
166 168
167 case sw_start: 169 case sw_start:
168 170
169 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers"); 171 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers");
170 172
171 if (ch != NGX_HTTP_V3_FRAME_HEADERS) { 173 st->state = sw_type;
172 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; 174
173 } 175 /* fall through */
174 176
177 case sw_type:
178
179 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch);
180 if (rc != NGX_DONE) {
181 return rc;
182 }
183
184 st->type = st->vlint.value;
175 st->state = sw_length; 185 st->state = sw_length;
176 break; 186 break;
177 187
178 case sw_length: 188 case sw_length:
179 189
182 return rc; 192 return rc;
183 } 193 }
184 194
185 st->length = st->vlint.value; 195 st->length = st->vlint.value;
186 196
187 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 197 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
188 "http3 parse headers len:%ui", st->length); 198 "http3 parse headers type:%ui, len:%ui",
199 st->type, st->length);
200
201 if (st->type != NGX_HTTP_V3_FRAME_HEADERS) {
202 st->state = st->length > 0 ? sw_skip : sw_type;
203 break;
204 }
189 205
190 st->state = sw_prefix; 206 st->state = sw_prefix;
207 break;
208
209 case sw_skip:
210
211 if (--st->length == 0) {
212 st->state = sw_type;
213 }
214
191 break; 215 break;
192 216
193 case sw_prefix: 217 case sw_prefix:
194 218
195 if (st->length-- == 0) { 219 if (st->length-- == 0) {
1527 { 1551 {
1528 ngx_int_t rc; 1552 ngx_int_t rc;
1529 enum { 1553 enum {
1530 sw_start = 0, 1554 sw_start = 0,
1531 sw_type, 1555 sw_type,
1532 sw_length 1556 sw_length,
1557 sw_skip
1533 }; 1558 };
1534 1559
1535 switch (st->state) { 1560 switch (st->state) {
1536 1561
1537 case sw_start: 1562 case sw_start:
1547 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); 1572 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch);
1548 if (rc != NGX_DONE) { 1573 if (rc != NGX_DONE) {
1549 return rc; 1574 return rc;
1550 } 1575 }
1551 1576
1552 if (st->vlint.value != NGX_HTTP_V3_FRAME_DATA) { 1577 st->type = st->vlint.value;
1553 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; 1578
1579 if (st->type == NGX_HTTP_V3_FRAME_HEADERS) {
1580 /* trailers */
1581 goto done;
1554 } 1582 }
1555 1583
1556 st->state = sw_length; 1584 st->state = sw_length;
1557 break; 1585 break;
1558 1586
1563 return rc; 1591 return rc;
1564 } 1592 }
1565 1593
1566 st->length = st->vlint.value; 1594 st->length = st->vlint.value;
1567 1595
1568 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 1596 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1569 "http3 parse data frame len:%ui", st->length); 1597 "http3 parse data type:%ui, len:%ui",
1570 1598 st->type, st->length);
1571 goto done; 1599
1600 if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) {
1601 st->state = sw_skip;
1602 break;
1603 }
1604
1605 st->state = sw_type;
1606 return NGX_OK;
1607
1608 case sw_skip:
1609
1610 if (--st->length == 0) {
1611 st->state = sw_type;
1612 }
1613
1614 break;
1572 } 1615 }
1573 1616
1574 return NGX_AGAIN; 1617 return NGX_AGAIN;
1575 1618
1576 done: 1619 done: