Mercurial > hg > nginx
annotate src/http/v3/ngx_http_v3_parse.c @ 8765:687445803d0f quic
HTTP/3: reject empty DATA and HEADERS frames on control stream.
Previously only non-empty frames were rejected.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 05 May 2021 13:28:05 +0300 |
parents | 12f18e0bca09 |
children | 0981329169ea |
rev | line source |
---|---|
8226 | 1 |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
8550
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
13 #define ngx_http_v3_is_v2_frame(type) \ |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
14 ((type) == 0x02 || (type) == 0x06 || (type) == 0x08 || (type) == 0x09) |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
15 |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
16 |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
17 static ngx_int_t ngx_http_v3_parse_settings(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
18 ngx_http_v3_parse_settings_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
19 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
20 static ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
21 ngx_http_v3_parse_varlen_int_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
22 static ngx_int_t ngx_http_v3_parse_prefix_int(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
23 ngx_http_v3_parse_prefix_int_t *st, ngx_uint_t prefix, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
24 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
25 static ngx_int_t ngx_http_v3_parse_header_block_prefix(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
26 ngx_http_v3_parse_header_block_prefix_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
27 static ngx_int_t ngx_http_v3_parse_header_rep(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
28 ngx_http_v3_parse_header_rep_t *st, ngx_uint_t base, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
29 static ngx_int_t ngx_http_v3_parse_literal(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
30 ngx_http_v3_parse_literal_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
31 static ngx_int_t ngx_http_v3_parse_header_ri(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
32 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
33 static ngx_int_t ngx_http_v3_parse_header_lri(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
34 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
35 static ngx_int_t ngx_http_v3_parse_header_l(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
36 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
37 static ngx_int_t ngx_http_v3_parse_header_pbi(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
38 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
39 static ngx_int_t ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
40 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
41 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
42 static ngx_int_t ngx_http_v3_parse_header_inr(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
43 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
44 static ngx_int_t ngx_http_v3_parse_header_iwnr(ngx_connection_t *c, |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
45 ngx_http_v3_parse_header_t *st, u_char ch); |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
46 |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
47 static ngx_int_t ngx_http_v3_parse_lookup(ngx_connection_t *c, |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
48 ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *name, ngx_str_t *value); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
49 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
50 |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
51 static ngx_int_t |
8226 | 52 ngx_http_v3_parse_varlen_int(ngx_connection_t *c, |
53 ngx_http_v3_parse_varlen_int_t *st, u_char ch) | |
54 { | |
55 enum { | |
56 sw_start = 0, | |
57 sw_length_2, | |
58 sw_length_3, | |
59 sw_length_4, | |
60 sw_length_5, | |
61 sw_length_6, | |
62 sw_length_7, | |
63 sw_length_8 | |
64 }; | |
65 | |
66 switch (st->state) { | |
67 | |
68 case sw_start: | |
69 | |
70 st->value = ch; | |
71 if (st->value & 0xc0) { | |
72 st->state = sw_length_2; | |
73 break; | |
74 } | |
75 | |
76 goto done; | |
77 | |
78 case sw_length_2: | |
79 | |
80 st->value = (st->value << 8) + ch; | |
81 if ((st->value & 0xc000) == 0x4000) { | |
82 st->value &= 0x3fff; | |
83 goto done; | |
84 } | |
85 | |
86 st->state = sw_length_3; | |
87 break; | |
88 | |
89 case sw_length_4: | |
90 | |
91 st->value = (st->value << 8) + ch; | |
92 if ((st->value & 0xc0000000) == 0x80000000) { | |
93 st->value &= 0x3fffffff; | |
94 goto done; | |
95 } | |
96 | |
97 st->state = sw_length_5; | |
98 break; | |
99 | |
100 case sw_length_3: | |
101 case sw_length_5: | |
102 case sw_length_6: | |
103 case sw_length_7: | |
104 | |
105 st->value = (st->value << 8) + ch; | |
106 st->state++; | |
107 break; | |
108 | |
109 case sw_length_8: | |
110 | |
111 st->value = (st->value << 8) + ch; | |
112 st->value &= 0x3fffffffffffffff; | |
113 goto done; | |
114 } | |
115 | |
116 return NGX_AGAIN; | |
117 | |
118 done: | |
119 | |
120 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
121 "http3 parse varlen int %uL", st->value); | |
122 | |
123 st->state = sw_start; | |
124 return NGX_DONE; | |
125 } | |
126 | |
127 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
128 static ngx_int_t |
8226 | 129 ngx_http_v3_parse_prefix_int(ngx_connection_t *c, |
130 ngx_http_v3_parse_prefix_int_t *st, ngx_uint_t prefix, u_char ch) | |
131 { | |
8455
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
132 ngx_uint_t mask; |
8226 | 133 enum { |
134 sw_start = 0, | |
135 sw_value | |
136 }; | |
137 | |
138 switch (st->state) { | |
139 | |
140 case sw_start: | |
141 | |
8455
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
142 mask = (1 << prefix) - 1; |
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
143 st->value = ch & mask; |
8226 | 144 |
8455
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
145 if (st->value != mask) { |
8226 | 146 goto done; |
147 } | |
148 | |
8455
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
149 st->shift = 0; |
8226 | 150 st->state = sw_value; |
151 break; | |
152 | |
153 case sw_value: | |
154 | |
8463
2576485b93d4
HTTP/3: fixed overflow in prefixed integer parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8462
diff
changeset
|
155 st->value += (uint64_t) (ch & 0x7f) << st->shift; |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
156 |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
157 if (st->shift == 56 |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
158 && ((ch & 0x80) || (st->value & 0xc000000000000000))) |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
159 { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
160 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
161 "client exceeded integer size limit"); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
162 return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD; |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
163 } |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
164 |
8226 | 165 if (ch & 0x80) { |
8455
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
8454
diff
changeset
|
166 st->shift += 7; |
8226 | 167 break; |
168 } | |
169 | |
170 goto done; | |
171 } | |
172 | |
173 return NGX_AGAIN; | |
174 | |
175 done: | |
176 | |
177 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
178 "http3 parse prefix int %uL", st->value); | |
179 | |
180 st->state = sw_start; | |
181 return NGX_DONE; | |
182 } | |
183 | |
184 | |
185 ngx_int_t | |
186 ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st, | |
187 u_char ch) | |
188 { | |
189 ngx_int_t rc; | |
190 enum { | |
191 sw_start = 0, | |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
192 sw_type, |
8226 | 193 sw_length, |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
194 sw_skip, |
8226 | 195 sw_prefix, |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
196 sw_verify, |
8226 | 197 sw_header_rep, |
198 sw_done | |
199 }; | |
200 | |
201 switch (st->state) { | |
202 | |
203 case sw_start: | |
204 | |
205 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers"); | |
206 | |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
207 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
208 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
209 /* fall through */ |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
210 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
211 case sw_type: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
212 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
213 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
214 if (rc != NGX_DONE) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
215 return rc; |
8226 | 216 } |
217 | |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
218 st->type = st->vlint.value; |
8550
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
219 |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
220 if (ngx_http_v3_is_v2_frame(st->type)) { |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
221 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
222 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
223 |
8226 | 224 st->state = sw_length; |
225 break; | |
226 | |
227 case sw_length: | |
228 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
229 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
230 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
231 return rc; |
8226 | 232 } |
233 | |
234 st->length = st->vlint.value; | |
235 | |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
236 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
237 "http3 parse headers type:%ui, len:%ui", |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
238 st->type, st->length); |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
239 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
240 if (st->type != NGX_HTTP_V3_FRAME_HEADERS) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
241 st->state = st->length > 0 ? sw_skip : sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
242 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
243 } |
8226 | 244 |
8552
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8550
diff
changeset
|
245 if (st->length == 0) { |
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8550
diff
changeset
|
246 return NGX_HTTP_V3_ERR_FRAME_ERROR; |
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8550
diff
changeset
|
247 } |
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8550
diff
changeset
|
248 |
8226 | 249 st->state = sw_prefix; |
250 break; | |
251 | |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
252 case sw_skip: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
253 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
254 if (--st->length == 0) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
255 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
256 } |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
257 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
258 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
259 |
8226 | 260 case sw_prefix: |
261 | |
8552
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8550
diff
changeset
|
262 if (--st->length == 0) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
263 return NGX_HTTP_V3_ERR_FRAME_ERROR; |
8226 | 264 } |
265 | |
266 rc = ngx_http_v3_parse_header_block_prefix(c, &st->prefix, ch); | |
267 if (rc != NGX_DONE) { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
268 return rc; |
8226 | 269 } |
270 | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
271 st->state = sw_verify; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
272 break; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
273 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
274 case sw_verify: |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
275 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
276 rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
277 if (rc != NGX_OK) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
278 return rc; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
279 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
280 |
8226 | 281 st->state = sw_header_rep; |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
282 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
283 /* fall through */ |
8226 | 284 |
285 case sw_header_rep: | |
286 | |
287 rc = ngx_http_v3_parse_header_rep(c, &st->header_rep, st->prefix.base, | |
288 ch); | |
289 | |
8467
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8466
diff
changeset
|
290 if (--st->length == 0 && rc == NGX_AGAIN) { |
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8466
diff
changeset
|
291 return NGX_HTTP_V3_ERR_FRAME_ERROR; |
8226 | 292 } |
293 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
294 if (rc != NGX_DONE) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
295 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
296 } |
8226 | 297 |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
298 if (st->length == 0) { |
8226 | 299 goto done; |
300 } | |
301 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
302 return NGX_OK; |
8226 | 303 } |
304 | |
305 return NGX_AGAIN; | |
306 | |
307 done: | |
308 | |
309 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done"); | |
310 | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
311 if (st->prefix.insert_count > 0) { |
8630
279ad36f2f4b
QUIC: renamed c->qs to c->quic.
Roman Arutyunyan <arut@nginx.com>
parents:
8552
diff
changeset
|
312 if (ngx_http_v3_client_ack_header(c, c->quic->id) != NGX_OK) { |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
313 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
314 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
315 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
316 |
8226 | 317 st->state = sw_start; |
318 return NGX_DONE; | |
319 } | |
320 | |
321 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
322 static ngx_int_t |
8226 | 323 ngx_http_v3_parse_header_block_prefix(ngx_connection_t *c, |
324 ngx_http_v3_parse_header_block_prefix_t *st, u_char ch) | |
325 { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
326 ngx_int_t rc; |
8226 | 327 enum { |
328 sw_start = 0, | |
329 sw_req_insert_count, | |
330 sw_delta_base, | |
331 sw_read_delta_base | |
332 }; | |
333 | |
334 switch (st->state) { | |
335 | |
336 case sw_start: | |
337 | |
338 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
339 "http3 parse header block prefix"); | |
340 | |
341 st->state = sw_req_insert_count; | |
342 | |
343 /* fall through */ | |
344 | |
345 case sw_req_insert_count: | |
346 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
347 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 8, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
348 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
349 return rc; |
8226 | 350 } |
351 | |
352 st->insert_count = st->pint.value; | |
353 st->state = sw_delta_base; | |
354 break; | |
355 | |
356 case sw_delta_base: | |
357 | |
358 st->sign = (ch & 0x80) ? 1 : 0; | |
359 st->state = sw_read_delta_base; | |
360 | |
361 /* fall through */ | |
362 | |
363 case sw_read_delta_base: | |
364 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
365 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
366 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
367 return rc; |
8226 | 368 } |
369 | |
370 st->delta_base = st->pint.value; | |
371 goto done; | |
372 } | |
373 | |
374 return NGX_AGAIN; | |
375 | |
376 done: | |
377 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
378 rc = ngx_http_v3_decode_insert_count(c, &st->insert_count); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
379 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
380 return rc; |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
381 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
382 |
8226 | 383 if (st->sign) { |
384 st->base = st->insert_count - st->delta_base - 1; | |
385 } else { | |
386 st->base = st->insert_count + st->delta_base; | |
387 } | |
388 | |
389 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
390 "http3 parse header block prefix done " | |
8478
d2f716e668e8
Fixed format specifiers.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8467
diff
changeset
|
391 "insert_count:%ui, sign:%ui, delta_base:%ui, base:%ui", |
8226 | 392 st->insert_count, st->sign, st->delta_base, st->base); |
393 | |
394 st->state = sw_start; | |
395 return NGX_DONE; | |
396 } | |
397 | |
398 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
399 static ngx_int_t |
8226 | 400 ngx_http_v3_parse_header_rep(ngx_connection_t *c, |
401 ngx_http_v3_parse_header_rep_t *st, ngx_uint_t base, u_char ch) | |
402 { | |
403 ngx_int_t rc; | |
404 enum { | |
405 sw_start = 0, | |
406 sw_header_ri, | |
407 sw_header_lri, | |
408 sw_header_l, | |
409 sw_header_pbi, | |
410 sw_header_lpbi | |
411 }; | |
412 | |
413 if (st->state == sw_start) { | |
414 | |
415 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
416 "http3 parse header representation"); | |
417 | |
418 ngx_memzero(&st->header, sizeof(ngx_http_v3_parse_header_t)); | |
419 | |
420 st->header.base = base; | |
421 | |
422 if (ch & 0x80) { | |
423 /* Indexed Header Field */ | |
424 | |
425 st->state = sw_header_ri; | |
426 | |
427 } else if (ch & 0x40) { | |
428 /* Literal Header Field With Name Reference */ | |
429 | |
430 st->state = sw_header_lri; | |
431 | |
432 } else if (ch & 0x20) { | |
433 /* Literal Header Field Without Name Reference */ | |
434 | |
435 st->state = sw_header_l; | |
436 | |
437 } else if (ch & 0x10) { | |
438 /* Indexed Header Field With Post-Base Index */ | |
439 | |
440 st->state = sw_header_pbi; | |
441 | |
442 } else { | |
443 /* Literal Header Field With Post-Base Name Reference */ | |
444 | |
445 st->state = sw_header_lpbi; | |
446 } | |
447 } | |
448 | |
449 switch (st->state) { | |
450 | |
451 case sw_header_ri: | |
452 rc = ngx_http_v3_parse_header_ri(c, &st->header, ch); | |
453 break; | |
454 | |
455 case sw_header_lri: | |
456 rc = ngx_http_v3_parse_header_lri(c, &st->header, ch); | |
457 break; | |
458 | |
459 case sw_header_l: | |
460 rc = ngx_http_v3_parse_header_l(c, &st->header, ch); | |
461 break; | |
462 | |
463 case sw_header_pbi: | |
464 rc = ngx_http_v3_parse_header_pbi(c, &st->header, ch); | |
465 break; | |
466 | |
467 case sw_header_lpbi: | |
468 rc = ngx_http_v3_parse_header_lpbi(c, &st->header, ch); | |
469 break; | |
470 | |
471 default: | |
472 rc = NGX_OK; | |
473 } | |
474 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
475 if (rc != NGX_DONE) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
476 return rc; |
8226 | 477 } |
478 | |
479 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
480 "http3 parse header representation done"); | |
481 | |
482 st->state = sw_start; | |
483 return NGX_DONE; | |
484 } | |
485 | |
486 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
487 static ngx_int_t |
8226 | 488 ngx_http_v3_parse_literal(ngx_connection_t *c, ngx_http_v3_parse_literal_t *st, |
489 u_char ch) | |
490 { | |
8705
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8666
diff
changeset
|
491 ngx_uint_t n; |
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8666
diff
changeset
|
492 ngx_http_core_srv_conf_t *cscf; |
8226 | 493 enum { |
494 sw_start = 0, | |
495 sw_value | |
496 }; | |
497 | |
498 switch (st->state) { | |
499 | |
500 case sw_start: | |
501 | |
502 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
503 "http3 parse literal huff:%ui, len:%ui", | |
504 st->huffman, st->length); | |
505 | |
506 n = st->length; | |
507 | |
8705
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8666
diff
changeset
|
508 cscf = ngx_http_v3_get_module_srv_conf(c, ngx_http_core_module); |
8454
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
8295
diff
changeset
|
509 |
8705
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8666
diff
changeset
|
510 if (n > cscf->large_client_header_buffers.size) { |
8457
a7f64438aa3c
HTTP/3: downgraded literal size error level to NGX_LOG_INFO.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
511 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
8705
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8666
diff
changeset
|
512 "client sent too large header field"); |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
513 return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD; |
8454
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
8295
diff
changeset
|
514 } |
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
8295
diff
changeset
|
515 |
8226 | 516 if (st->huffman) { |
517 n = n * 8 / 5; | |
518 st->huffstate = 0; | |
519 } | |
520 | |
521 st->last = ngx_pnalloc(c->pool, n + 1); | |
522 if (st->last == NULL) { | |
523 return NGX_ERROR; | |
524 } | |
525 | |
526 st->value.data = st->last; | |
527 st->state = sw_value; | |
528 | |
529 /* fall through */ | |
530 | |
531 case sw_value: | |
532 | |
533 if (st->huffman) { | |
534 if (ngx_http_v2_huff_decode(&st->huffstate, &ch, 1, &st->last, | |
535 st->length == 1, c->log) | |
536 != NGX_OK) | |
537 { | |
538 return NGX_ERROR; | |
539 } | |
540 | |
541 } else { | |
542 *st->last++ = ch; | |
543 } | |
544 | |
545 if (--st->length) { | |
546 break; | |
547 } | |
548 | |
549 st->value.len = st->last - st->value.data; | |
550 *st->last = '\0'; | |
551 goto done; | |
552 } | |
553 | |
554 return NGX_AGAIN; | |
555 | |
556 done: | |
557 | |
558 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
559 "http3 parse literal done \"%V\"", &st->value); | |
560 | |
561 st->state = sw_start; | |
562 return NGX_DONE; | |
563 } | |
564 | |
565 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
566 static ngx_int_t |
8226 | 567 ngx_http_v3_parse_header_ri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, |
568 u_char ch) | |
569 { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
570 ngx_int_t rc; |
8226 | 571 enum { |
572 sw_start = 0, | |
573 sw_index | |
574 }; | |
575 | |
576 switch (st->state) { | |
577 | |
578 case sw_start: | |
579 | |
580 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header ri"); | |
581 | |
582 st->dynamic = (ch & 0x40) ? 0 : 1; | |
583 st->state = sw_index; | |
584 | |
585 /* fall through */ | |
586 | |
587 case sw_index: | |
588 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
589 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
590 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
591 return rc; |
8226 | 592 } |
593 | |
594 st->index = st->pint.value; | |
595 goto done; | |
596 } | |
597 | |
598 return NGX_AGAIN; | |
599 | |
600 done: | |
601 | |
602 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
603 "http3 parse header ri done %s%ui]", | |
604 st->dynamic ? "dynamic[-" : "static[", st->index); | |
605 | |
606 if (st->dynamic) { | |
607 st->index = st->base - st->index - 1; | |
608 } | |
609 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
610 rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
611 &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
612 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
613 return rc; |
8226 | 614 } |
615 | |
616 st->state = sw_start; | |
617 return NGX_DONE; | |
618 } | |
619 | |
620 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
621 static ngx_int_t |
8226 | 622 ngx_http_v3_parse_header_lri(ngx_connection_t *c, |
623 ngx_http_v3_parse_header_t *st, u_char ch) | |
624 { | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
625 ngx_int_t rc; |
8226 | 626 enum { |
627 sw_start = 0, | |
628 sw_index, | |
629 sw_value_len, | |
630 sw_read_value_len, | |
631 sw_value | |
632 }; | |
633 | |
634 switch (st->state) { | |
635 | |
636 case sw_start: | |
637 | |
638 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header lri"); | |
639 | |
640 st->dynamic = (ch & 0x10) ? 0 : 1; | |
641 st->state = sw_index; | |
642 | |
643 /* fall through */ | |
644 | |
645 case sw_index: | |
646 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
647 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
648 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
649 return rc; |
8226 | 650 } |
651 | |
652 st->index = st->pint.value; | |
653 st->state = sw_value_len; | |
654 break; | |
655 | |
656 case sw_value_len: | |
657 | |
658 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
659 st->state = sw_read_value_len; | |
660 | |
661 /* fall through */ | |
662 | |
663 case sw_read_value_len: | |
664 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
665 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
666 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
667 return rc; |
8226 | 668 } |
669 | |
670 st->literal.length = st->pint.value; | |
671 if (st->literal.length == 0) { | |
672 goto done; | |
673 } | |
674 | |
675 st->state = sw_value; | |
676 break; | |
677 | |
678 case sw_value: | |
679 | |
680 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
681 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
682 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
683 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
684 |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
685 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
686 goto done; |
8226 | 687 } |
688 | |
689 return NGX_AGAIN; | |
690 | |
691 done: | |
692 | |
693 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
694 "http3 parse header lri done %s%ui] \"%V\"", | |
695 st->dynamic ? "dynamic[-" : "static[", | |
696 st->index, &st->value); | |
697 | |
698 if (st->dynamic) { | |
699 st->index = st->base - st->index - 1; | |
700 } | |
701 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
702 rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, NULL); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
703 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
704 return rc; |
8226 | 705 } |
706 | |
707 st->state = sw_start; | |
708 return NGX_DONE; | |
709 } | |
710 | |
711 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
712 static ngx_int_t |
8226 | 713 ngx_http_v3_parse_header_l(ngx_connection_t *c, |
714 ngx_http_v3_parse_header_t *st, u_char ch) | |
715 { | |
716 ngx_int_t rc; | |
717 enum { | |
718 sw_start = 0, | |
719 sw_name_len, | |
720 sw_name, | |
721 sw_value_len, | |
722 sw_read_value_len, | |
723 sw_value | |
724 }; | |
725 | |
726 switch (st->state) { | |
727 | |
728 case sw_start: | |
729 | |
730 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header l"); | |
731 | |
732 st->literal.huffman = (ch & 0x08) ? 1 : 0; | |
733 st->state = sw_name_len; | |
734 | |
735 /* fall through */ | |
736 | |
737 case sw_name_len: | |
738 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
739 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
740 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
741 return rc; |
8226 | 742 } |
743 | |
744 st->literal.length = st->pint.value; | |
745 if (st->literal.length == 0) { | |
746 return NGX_ERROR; | |
747 } | |
748 | |
749 st->state = sw_name; | |
750 break; | |
751 | |
752 case sw_name: | |
753 | |
754 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
755 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
756 return rc; |
8226 | 757 } |
758 | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
759 st->name = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
760 st->state = sw_value_len; |
8226 | 761 break; |
762 | |
763 case sw_value_len: | |
764 | |
765 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
766 st->state = sw_read_value_len; | |
767 | |
768 /* fall through */ | |
769 | |
770 case sw_read_value_len: | |
771 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
772 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
773 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
774 return rc; |
8226 | 775 } |
776 | |
777 st->literal.length = st->pint.value; | |
778 if (st->literal.length == 0) { | |
8649
5a92523e50d3
HTTP/3: null-terminate empty header value.
Roman Arutyunyan <arut@nginx.com>
parents:
8630
diff
changeset
|
779 st->value.data = (u_char *) ""; |
8226 | 780 goto done; |
781 } | |
782 | |
783 st->state = sw_value; | |
784 break; | |
785 | |
786 case sw_value: | |
787 | |
788 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
789 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
790 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
791 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
792 |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
793 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
794 goto done; |
8226 | 795 } |
796 | |
797 return NGX_AGAIN; | |
798 | |
799 done: | |
800 | |
801 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
802 "http3 parse header l done \"%V\" \"%V\"", | |
803 &st->name, &st->value); | |
804 | |
805 st->state = sw_start; | |
806 return NGX_DONE; | |
807 } | |
808 | |
809 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
810 static ngx_int_t |
8226 | 811 ngx_http_v3_parse_header_pbi(ngx_connection_t *c, |
812 ngx_http_v3_parse_header_t *st, u_char ch) | |
813 { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
814 ngx_int_t rc; |
8226 | 815 enum { |
816 sw_start = 0, | |
817 sw_index | |
818 }; | |
819 | |
820 switch (st->state) { | |
821 | |
822 case sw_start: | |
823 | |
824 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header pbi"); | |
825 | |
826 st->state = sw_index; | |
827 | |
828 /* fall through */ | |
829 | |
830 case sw_index: | |
831 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
832 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
833 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
834 return rc; |
8226 | 835 } |
836 | |
837 st->index = st->pint.value; | |
838 goto done; | |
839 } | |
840 | |
841 return NGX_AGAIN; | |
842 | |
843 done: | |
844 | |
845 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
846 "http3 parse header pbi done dynamic[+%ui]", st->index); | |
847 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
848 rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
849 &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
850 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
851 return rc; |
8226 | 852 } |
853 | |
854 st->state = sw_start; | |
855 return NGX_DONE; | |
856 } | |
857 | |
858 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
859 static ngx_int_t |
8226 | 860 ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, |
861 ngx_http_v3_parse_header_t *st, u_char ch) | |
862 { | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
863 ngx_int_t rc; |
8226 | 864 enum { |
865 sw_start = 0, | |
866 sw_index, | |
867 sw_value_len, | |
868 sw_read_value_len, | |
869 sw_value | |
870 }; | |
871 | |
872 switch (st->state) { | |
873 | |
874 case sw_start: | |
875 | |
876 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
877 "http3 parse header lpbi"); | |
878 | |
879 st->state = sw_index; | |
880 | |
881 /* fall through */ | |
882 | |
883 case sw_index: | |
884 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
885 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
886 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
887 return rc; |
8226 | 888 } |
889 | |
890 st->index = st->pint.value; | |
891 st->state = sw_value_len; | |
892 break; | |
893 | |
894 case sw_value_len: | |
895 | |
896 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
897 st->state = sw_read_value_len; | |
898 | |
899 /* fall through */ | |
900 | |
901 case sw_read_value_len: | |
902 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
903 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
904 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
905 return rc; |
8226 | 906 } |
907 | |
908 st->literal.length = st->pint.value; | |
909 if (st->literal.length == 0) { | |
910 goto done; | |
911 } | |
912 | |
913 st->state = sw_value; | |
914 break; | |
915 | |
916 case sw_value: | |
917 | |
918 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
919 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
920 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
921 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
922 |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
923 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
924 goto done; |
8226 | 925 } |
926 | |
927 return NGX_AGAIN; | |
928 | |
929 done: | |
930 | |
931 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
932 "http3 parse header lpbi done dynamic[+%ui] \"%V\"", | |
933 st->index, &st->value); | |
934 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
935 rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, NULL); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
936 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
937 return rc; |
8226 | 938 } |
939 | |
940 st->state = sw_start; | |
941 return NGX_DONE; | |
942 } | |
943 | |
944 | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
945 static ngx_int_t |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
946 ngx_http_v3_parse_lookup(ngx_connection_t *c, ngx_uint_t dynamic, |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
947 ngx_uint_t index, ngx_str_t *name, ngx_str_t *value) |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
948 { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
949 u_char *p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
950 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
951 if (!dynamic) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
952 if (ngx_http_v3_lookup_static(c, index, name, value) != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
953 return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
954 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
955 |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
956 return NGX_OK; |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
957 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
958 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
959 if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
960 return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED; |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
961 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
962 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
963 if (name) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
964 p = ngx_pnalloc(c->pool, name->len + 1); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
965 if (p == NULL) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
966 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
967 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
968 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
969 ngx_memcpy(p, name->data, name->len); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
970 p[name->len] = '\0'; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
971 name->data = p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
972 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
973 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
974 if (value) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
975 p = ngx_pnalloc(c->pool, value->len + 1); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
976 if (p == NULL) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
977 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
978 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
979 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
980 ngx_memcpy(p, value->data, value->len); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
981 p[value->len] = '\0'; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
982 value->data = p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
983 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
984 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
985 return NGX_OK; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
986 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
987 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
988 |
8226 | 989 ngx_int_t |
990 ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch) | |
991 { | |
992 ngx_http_v3_parse_control_t *st = data; | |
993 | |
994 ngx_int_t rc; | |
995 enum { | |
996 sw_start = 0, | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
997 sw_first_type, |
8226 | 998 sw_type, |
999 sw_length, | |
8497 | 1000 sw_cancel_push, |
8226 | 1001 sw_settings, |
1002 sw_max_push_id, | |
1003 sw_skip | |
1004 }; | |
1005 | |
1006 switch (st->state) { | |
1007 | |
1008 case sw_start: | |
1009 | |
1010 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse control"); | |
1011 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1012 st->state = sw_first_type; |
8226 | 1013 |
1014 /* fall through */ | |
1015 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1016 case sw_first_type: |
8226 | 1017 case sw_type: |
1018 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1019 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1020 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1021 return rc; |
8226 | 1022 } |
1023 | |
1024 st->type = st->vlint.value; | |
1025 | |
1026 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1027 "http3 parse frame type:%ui", st->type); | |
1028 | |
8765
687445803d0f
HTTP/3: reject empty DATA and HEADERS frames on control stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8762
diff
changeset
|
1029 if (ngx_http_v3_is_v2_frame(st->type) |
687445803d0f
HTTP/3: reject empty DATA and HEADERS frames on control stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8762
diff
changeset
|
1030 || st->type == NGX_HTTP_V3_FRAME_DATA |
687445803d0f
HTTP/3: reject empty DATA and HEADERS frames on control stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8762
diff
changeset
|
1031 || st->type == NGX_HTTP_V3_FRAME_HEADERS) |
687445803d0f
HTTP/3: reject empty DATA and HEADERS frames on control stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8762
diff
changeset
|
1032 { |
8550
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1033 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1034 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1035 |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1036 if (st->state == sw_first_type |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1037 && st->type != NGX_HTTP_V3_FRAME_SETTINGS) |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1038 { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1039 return NGX_HTTP_V3_ERR_MISSING_SETTINGS; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1040 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1041 |
8226 | 1042 st->state = sw_length; |
1043 break; | |
1044 | |
1045 case sw_length: | |
1046 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1047 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1048 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1049 return rc; |
8226 | 1050 } |
1051 | |
1052 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1053 "http3 parse frame len:%uL", st->vlint.value); | |
1054 | |
1055 st->length = st->vlint.value; | |
1056 if (st->length == 0) { | |
1057 st->state = sw_type; | |
1058 break; | |
1059 } | |
1060 | |
1061 switch (st->type) { | |
1062 | |
8497 | 1063 case NGX_HTTP_V3_FRAME_CANCEL_PUSH: |
1064 st->state = sw_cancel_push; | |
1065 break; | |
1066 | |
8226 | 1067 case NGX_HTTP_V3_FRAME_SETTINGS: |
1068 st->state = sw_settings; | |
1069 break; | |
1070 | |
1071 case NGX_HTTP_V3_FRAME_MAX_PUSH_ID: | |
1072 st->state = sw_max_push_id; | |
1073 break; | |
1074 | |
1075 default: | |
1076 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1077 "http3 parse skip unknown frame"); | |
1078 st->state = sw_skip; | |
1079 } | |
1080 | |
1081 break; | |
1082 | |
8497 | 1083 case sw_cancel_push: |
1084 | |
1085 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); | |
1086 | |
1087 if (--st->length == 0 && rc == NGX_AGAIN) { | |
1088 return NGX_HTTP_V3_ERR_FRAME_ERROR; | |
1089 } | |
1090 | |
1091 if (rc != NGX_DONE) { | |
1092 return rc; | |
1093 } | |
1094 | |
1095 rc = ngx_http_v3_cancel_push(c, st->vlint.value); | |
1096 if (rc != NGX_OK) { | |
1097 return rc; | |
1098 } | |
1099 | |
1100 st->state = sw_type; | |
1101 break; | |
1102 | |
8226 | 1103 case sw_settings: |
1104 | |
1105 rc = ngx_http_v3_parse_settings(c, &st->settings, ch); | |
1106 | |
8467
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8466
diff
changeset
|
1107 if (--st->length == 0 && rc == NGX_AGAIN) { |
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8466
diff
changeset
|
1108 return NGX_HTTP_V3_ERR_SETTINGS_ERROR; |
8226 | 1109 } |
1110 | |
1111 if (rc != NGX_DONE) { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1112 return rc; |
8226 | 1113 } |
1114 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1115 if (st->length == 0) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1116 st->state = sw_type; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1117 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1118 |
8226 | 1119 break; |
1120 | |
1121 case sw_max_push_id: | |
1122 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1123 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
8497 | 1124 |
1125 if (--st->length == 0 && rc == NGX_AGAIN) { | |
1126 return NGX_HTTP_V3_ERR_FRAME_ERROR; | |
1127 } | |
1128 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1129 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1130 return rc; |
8226 | 1131 } |
1132 | |
8497 | 1133 rc = ngx_http_v3_set_max_push_id(c, st->vlint.value); |
1134 if (rc != NGX_OK) { | |
1135 return rc; | |
1136 } | |
8226 | 1137 |
1138 st->state = sw_type; | |
1139 break; | |
1140 | |
1141 case sw_skip: | |
1142 | |
1143 if (--st->length == 0) { | |
1144 st->state = sw_type; | |
1145 } | |
1146 | |
1147 break; | |
1148 } | |
1149 | |
1150 return NGX_AGAIN; | |
1151 } | |
1152 | |
1153 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
1154 static ngx_int_t |
8226 | 1155 ngx_http_v3_parse_settings(ngx_connection_t *c, |
1156 ngx_http_v3_parse_settings_t *st, u_char ch) | |
1157 { | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1158 ngx_int_t rc; |
8226 | 1159 enum { |
1160 sw_start = 0, | |
1161 sw_id, | |
1162 sw_value | |
1163 }; | |
1164 | |
1165 switch (st->state) { | |
1166 | |
1167 case sw_start: | |
1168 | |
1169 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse settings"); | |
1170 | |
1171 st->state = sw_id; | |
1172 | |
1173 /* fall through */ | |
1174 | |
1175 case sw_id: | |
1176 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1177 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1178 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1179 return rc; |
8226 | 1180 } |
1181 | |
1182 st->id = st->vlint.value; | |
1183 st->state = sw_value; | |
1184 break; | |
1185 | |
1186 case sw_value: | |
1187 | |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1188 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1189 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1190 return rc; |
8226 | 1191 } |
1192 | |
1193 if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1194 return NGX_HTTP_V3_ERR_SETTINGS_ERROR; |
8226 | 1195 } |
1196 | |
1197 goto done; | |
1198 } | |
1199 | |
1200 return NGX_AGAIN; | |
1201 | |
1202 done: | |
1203 | |
1204 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse settings done"); | |
1205 | |
1206 st->state = sw_start; | |
1207 return NGX_DONE; | |
1208 } | |
1209 | |
1210 | |
1211 ngx_int_t | |
1212 ngx_http_v3_parse_encoder(ngx_connection_t *c, void *data, u_char ch) | |
1213 { | |
1214 ngx_http_v3_parse_encoder_t *st = data; | |
1215 | |
1216 ngx_int_t rc; | |
1217 enum { | |
1218 sw_start = 0, | |
1219 sw_inr, | |
1220 sw_iwnr, | |
1221 sw_capacity, | |
1222 sw_duplicate | |
1223 }; | |
1224 | |
1225 if (st->state == sw_start) { | |
1226 | |
1227 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1228 "http3 parse encoder instruction"); | |
1229 | |
1230 if (ch & 0x80) { | |
1231 /* Insert With Name Reference */ | |
1232 | |
1233 st->state = sw_inr; | |
1234 | |
1235 } else if (ch & 0x40) { | |
1236 /* Insert Without Name Reference */ | |
1237 | |
1238 st->state = sw_iwnr; | |
1239 | |
1240 } else if (ch & 0x20) { | |
1241 /* Set Dynamic Table Capacity */ | |
1242 | |
1243 st->state = sw_capacity; | |
1244 | |
1245 } else { | |
1246 /* Duplicate */ | |
1247 | |
1248 st->state = sw_duplicate; | |
1249 } | |
1250 } | |
1251 | |
1252 switch (st->state) { | |
1253 | |
1254 case sw_inr: | |
1255 | |
1256 rc = ngx_http_v3_parse_header_inr(c, &st->header, ch); | |
1257 if (rc != NGX_DONE) { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1258 return rc; |
8226 | 1259 } |
1260 | |
1261 goto done; | |
1262 | |
1263 case sw_iwnr: | |
1264 | |
1265 rc = ngx_http_v3_parse_header_iwnr(c, &st->header, ch); | |
1266 if (rc != NGX_DONE) { | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1267 return rc; |
8226 | 1268 } |
1269 | |
1270 goto done; | |
1271 | |
1272 case sw_capacity: | |
1273 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1274 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1275 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1276 return rc; |
8226 | 1277 } |
1278 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1279 rc = ngx_http_v3_set_capacity(c, st->pint.value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1280 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1281 return rc; |
8226 | 1282 } |
1283 | |
1284 goto done; | |
1285 | |
1286 case sw_duplicate: | |
1287 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1288 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1289 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1290 return rc; |
8226 | 1291 } |
1292 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1293 rc = ngx_http_v3_duplicate(c, st->pint.value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1294 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1295 return rc; |
8226 | 1296 } |
1297 | |
1298 goto done; | |
1299 } | |
1300 | |
1301 return NGX_AGAIN; | |
1302 | |
1303 done: | |
1304 | |
1305 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1306 "http3 parse encoder instruction done"); | |
1307 | |
1308 st->state = sw_start; | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
1309 return NGX_AGAIN; |
8226 | 1310 } |
1311 | |
1312 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
1313 static ngx_int_t |
8226 | 1314 ngx_http_v3_parse_header_inr(ngx_connection_t *c, |
1315 ngx_http_v3_parse_header_t *st, u_char ch) | |
1316 { | |
1317 ngx_int_t rc; | |
1318 enum { | |
1319 sw_start = 0, | |
1320 sw_name_index, | |
1321 sw_value_len, | |
1322 sw_read_value_len, | |
1323 sw_value | |
1324 }; | |
1325 | |
1326 switch (st->state) { | |
1327 | |
1328 case sw_start: | |
1329 | |
1330 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header inr"); | |
1331 | |
1332 st->dynamic = (ch & 0x40) ? 0 : 1; | |
1333 st->state = sw_name_index; | |
1334 | |
1335 /* fall through */ | |
1336 | |
1337 case sw_name_index: | |
1338 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1339 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1340 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1341 return rc; |
8226 | 1342 } |
1343 | |
1344 st->index = st->pint.value; | |
1345 st->state = sw_value_len; | |
1346 break; | |
1347 | |
1348 case sw_value_len: | |
1349 | |
1350 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
1351 st->state = sw_read_value_len; | |
1352 | |
1353 /* fall through */ | |
1354 | |
1355 case sw_read_value_len: | |
1356 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1357 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1358 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1359 return rc; |
8226 | 1360 } |
1361 | |
1362 st->literal.length = st->pint.value; | |
1363 if (st->literal.length == 0) { | |
1364 goto done; | |
1365 } | |
1366 | |
1367 st->state = sw_value; | |
1368 break; | |
1369 | |
1370 case sw_value: | |
1371 | |
1372 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1373 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1374 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1375 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1376 |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1377 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1378 goto done; |
8226 | 1379 } |
1380 | |
1381 return NGX_AGAIN; | |
1382 | |
1383 done: | |
1384 | |
1385 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1386 "http3 parse header inr done %s[%ui] \"%V\"", | |
1387 st->dynamic ? "dynamic" : "static", | |
1388 st->index, &st->value); | |
1389 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1390 rc = ngx_http_v3_ref_insert(c, st->dynamic, st->index, &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1391 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1392 return rc; |
8226 | 1393 } |
1394 | |
1395 st->state = sw_start; | |
1396 return NGX_DONE; | |
1397 } | |
1398 | |
1399 | |
8666
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8649
diff
changeset
|
1400 static ngx_int_t |
8226 | 1401 ngx_http_v3_parse_header_iwnr(ngx_connection_t *c, |
1402 ngx_http_v3_parse_header_t *st, u_char ch) | |
1403 { | |
1404 ngx_int_t rc; | |
1405 enum { | |
1406 sw_start = 0, | |
1407 sw_name_len, | |
1408 sw_name, | |
1409 sw_value_len, | |
1410 sw_read_value_len, | |
1411 sw_value | |
1412 }; | |
1413 | |
1414 switch (st->state) { | |
1415 | |
1416 case sw_start: | |
1417 | |
1418 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1419 "http3 parse header iwnr"); | |
1420 | |
1421 st->literal.huffman = (ch & 0x20) ? 1 : 0; | |
1422 st->state = sw_name_len; | |
1423 | |
1424 /* fall through */ | |
1425 | |
1426 case sw_name_len: | |
1427 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1428 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1429 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1430 return rc; |
8226 | 1431 } |
1432 | |
1433 st->literal.length = st->pint.value; | |
1434 if (st->literal.length == 0) { | |
1435 return NGX_ERROR; | |
1436 } | |
1437 | |
1438 st->state = sw_name; | |
1439 break; | |
1440 | |
1441 case sw_name: | |
1442 | |
1443 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1444 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1445 return rc; |
8226 | 1446 } |
1447 | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1448 st->name = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1449 st->state = sw_value_len; |
8226 | 1450 break; |
1451 | |
1452 case sw_value_len: | |
1453 | |
1454 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
1455 st->state = sw_read_value_len; | |
1456 | |
1457 /* fall through */ | |
1458 | |
1459 case sw_read_value_len: | |
1460 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1461 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1462 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1463 return rc; |
8226 | 1464 } |
1465 | |
1466 st->literal.length = st->pint.value; | |
1467 if (st->literal.length == 0) { | |
1468 goto done; | |
1469 } | |
1470 | |
1471 st->state = sw_value; | |
1472 break; | |
1473 | |
1474 case sw_value: | |
1475 | |
1476 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1477 if (rc != NGX_DONE) { |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1478 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1479 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1480 |
8465
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1481 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
8464
diff
changeset
|
1482 goto done; |
8226 | 1483 } |
1484 | |
1485 return NGX_AGAIN; | |
1486 | |
1487 done: | |
1488 | |
1489 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1490 "http3 parse header iwnr done \"%V\":\"%V\"", | |
1491 &st->name, &st->value); | |
1492 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1493 rc = ngx_http_v3_insert(c, &st->name, &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1494 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1495 return rc; |
8226 | 1496 } |
1497 | |
1498 st->state = sw_start; | |
1499 return NGX_DONE; | |
1500 } | |
1501 | |
1502 | |
1503 ngx_int_t | |
1504 ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch) | |
1505 { | |
1506 ngx_http_v3_parse_decoder_t *st = data; | |
1507 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1508 ngx_int_t rc; |
8226 | 1509 enum { |
1510 sw_start = 0, | |
1511 sw_ack_header, | |
1512 sw_cancel_stream, | |
1513 sw_inc_insert_count | |
1514 }; | |
1515 | |
1516 if (st->state == sw_start) { | |
1517 | |
1518 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1519 "http3 parse decoder instruction"); | |
1520 | |
1521 if (ch & 0x80) { | |
1522 /* Header Acknowledgement */ | |
1523 | |
1524 st->state = sw_ack_header; | |
1525 | |
1526 } else if (ch & 0x40) { | |
1527 /* Stream Cancellation */ | |
1528 | |
1529 st->state = sw_cancel_stream; | |
1530 | |
1531 } else { | |
1532 /* Insert Count Increment */ | |
1533 | |
1534 st->state = sw_inc_insert_count; | |
1535 } | |
1536 } | |
1537 | |
1538 switch (st->state) { | |
1539 | |
1540 case sw_ack_header: | |
1541 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1542 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1543 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1544 return rc; |
8226 | 1545 } |
1546 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1547 rc = ngx_http_v3_ack_header(c, st->pint.value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1548 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1549 return rc; |
8226 | 1550 } |
1551 | |
1552 goto done; | |
1553 | |
1554 case sw_cancel_stream: | |
1555 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1556 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1557 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1558 return rc; |
8226 | 1559 } |
1560 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1561 rc = ngx_http_v3_cancel_stream(c, st->pint.value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1562 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1563 return rc; |
8226 | 1564 } |
1565 | |
1566 goto done; | |
1567 | |
1568 case sw_inc_insert_count: | |
1569 | |
8464
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1570 rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, ch); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1571 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
8463
diff
changeset
|
1572 return rc; |
8226 | 1573 } |
1574 | |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1575 rc = ngx_http_v3_inc_insert_count(c, st->pint.value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1576 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8457
diff
changeset
|
1577 return rc; |
8226 | 1578 } |
1579 | |
1580 goto done; | |
1581 } | |
1582 | |
1583 return NGX_AGAIN; | |
1584 | |
1585 done: | |
1586 | |
1587 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1588 "http3 parse decoder instruction done"); | |
1589 | |
1590 st->state = sw_start; | |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8455
diff
changeset
|
1591 return NGX_AGAIN; |
8226 | 1592 } |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1593 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1594 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1595 ngx_int_t |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1596 ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1597 u_char ch) |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1598 { |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1599 ngx_int_t rc; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1600 enum { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1601 sw_start = 0, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1602 sw_type, |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1603 sw_length, |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1604 sw_skip |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1605 }; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1606 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1607 switch (st->state) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1608 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1609 case sw_start: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1610 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1611 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1612 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1613 st->state = sw_type; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1614 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1615 /* fall through */ |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1616 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1617 case sw_type: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1618 |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1619 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1620 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1621 return rc; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1622 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1623 |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1624 st->type = st->vlint.value; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1625 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1626 if (st->type == NGX_HTTP_V3_FRAME_HEADERS) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1627 /* trailers */ |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1628 goto done; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1629 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1630 |
8550
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1631 if (ngx_http_v3_is_v2_frame(st->type)) { |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1632 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1633 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8549
diff
changeset
|
1634 |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1635 st->state = sw_length; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1636 break; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1637 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1638 case sw_length: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1639 |
8466
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1640 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1641 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8465
diff
changeset
|
1642 return rc; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1643 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1644 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1645 st->length = st->vlint.value; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1646 |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1647 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1648 "http3 parse data type:%ui, len:%ui", |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1649 st->type, st->length); |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1650 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1651 if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1652 st->state = sw_skip; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1653 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1654 } |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1655 |
8549
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1656 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1657 return NGX_OK; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1658 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1659 case sw_skip: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1660 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1661 if (--st->length == 0) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1662 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1663 } |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1664 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8497
diff
changeset
|
1665 break; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1666 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1667 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1668 return NGX_AGAIN; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1669 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1670 done: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1671 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1672 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data done"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1673 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1674 st->state = sw_start; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1675 return NGX_DONE; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8227
diff
changeset
|
1676 } |