Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_parse.c @ 8379:0f8565e0fc76 quic
QUIC: HKDF API compatibility with OpenSSL master branch.
OpenSSL 3.0 started to require HKDF-Extract output PRK length pointer
used to represent the amount of data written to contain the length of
the key buffer before the call. EVP_PKEY_derive() documents this.
See HKDF_Extract() internal implementation update in this change:
https://github.com/openssl/openssl/commit/5a285ad
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Wed, 31 Mar 2021 21:43:17 +0300 |
parents | ae2e68f206f9 |
children | 12f18e0bca09 |
rev | line source |
---|---|
7692 | 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 | |
8088
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
13 #define ngx_http_v3_is_v2_frame(type) \ |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
14 ((type) == 0x02 || (type) == 0x06 || (type) == 0x08 || (type) == 0x09) |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
15 |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
16 |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
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:
8233
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:
8233
diff
changeset
|
19 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
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:
8233
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:
8233
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:
8233
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:
8233
diff
changeset
|
24 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
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:
8233
diff
changeset
|
41 |
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
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:
8233
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:
8233
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:
8233
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:
8233
diff
changeset
|
46 |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
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:
7950
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:
7950
diff
changeset
|
49 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
50 |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
51 static ngx_int_t |
7692 | 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 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
128 static ngx_int_t |
7692 | 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 { | |
7950
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
132 ngx_uint_t mask; |
7692 | 133 enum { |
134 sw_start = 0, | |
135 sw_value | |
136 }; | |
137 | |
138 switch (st->state) { | |
139 | |
140 case sw_start: | |
141 | |
7950
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
142 mask = (1 << prefix) - 1; |
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
143 st->value = ch & mask; |
7692 | 144 |
7950
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
145 if (st->value != mask) { |
7692 | 146 goto done; |
147 } | |
148 | |
7950
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
149 st->shift = 0; |
7692 | 150 st->state = sw_value; |
151 break; | |
152 | |
153 case sw_value: | |
154 | |
7958
2576485b93d4
HTTP/3: fixed overflow in prefixed integer parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7957
diff
changeset
|
155 st->value += (uint64_t) (ch & 0x7f) << st->shift; |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
156 |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
157 if (st->shift == 56 |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
158 && ((ch & 0x80) || (st->value & 0xc000000000000000))) |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
159 { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
161 "client exceeded integer size limit"); |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
163 } |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
164 |
7692 | 165 if (ch & 0x80) { |
7950
b0e81f49d7c0
HTTP/3: fixed prefixed integer encoding and decoding.
Roman Arutyunyan <arut@nginx.com>
parents:
7949
diff
changeset
|
166 st->shift += 7; |
7692 | 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, | |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
192 sw_type, |
7692 | 193 sw_length, |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
194 sw_skip, |
7692 | 195 sw_prefix, |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
196 sw_verify, |
7692 | 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 | |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
207 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
208 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
209 /* fall through */ |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
210 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
211 case sw_type: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
212 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
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:
8015
diff
changeset
|
214 if (rc != NGX_DONE) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
215 return rc; |
7692 | 216 } |
217 | |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
218 st->type = st->vlint.value; |
8088
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
219 |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
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:
8087
diff
changeset
|
221 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
222 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
223 |
7692 | 224 st->state = sw_length; |
225 break; | |
226 | |
227 case sw_length: | |
228 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
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:
7960
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:
7960
diff
changeset
|
231 return rc; |
7692 | 232 } |
233 | |
234 st->length = st->vlint.value; | |
235 | |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
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:
8015
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:
8015
diff
changeset
|
238 st->type, st->length); |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
239 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
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:
8015
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:
8015
diff
changeset
|
242 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
243 } |
7692 | 244 |
8090
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8088
diff
changeset
|
245 if (st->length == 0) { |
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8088
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:
8088
diff
changeset
|
247 } |
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8088
diff
changeset
|
248 |
7692 | 249 st->state = sw_prefix; |
250 break; | |
251 | |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
252 case sw_skip: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
253 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
254 if (--st->length == 0) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
255 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
256 } |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
257 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
258 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
259 |
7692 | 260 case sw_prefix: |
261 | |
8090
351d62300832
HTTP/3: rearranged length check when parsing header.
Roman Arutyunyan <arut@nginx.com>
parents:
8088
diff
changeset
|
262 if (--st->length == 0) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
263 return NGX_HTTP_V3_ERR_FRAME_ERROR; |
7692 | 264 } |
265 | |
266 rc = ngx_http_v3_parse_header_block_prefix(c, &st->prefix, ch); | |
267 if (rc != NGX_DONE) { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
268 return rc; |
7692 | 269 } |
270 | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
271 st->state = sw_verify; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
272 break; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
273 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
274 case sw_verify: |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
275 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
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:
7950
diff
changeset
|
277 if (rc != NGX_OK) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
278 return rc; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
279 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
280 |
7692 | 281 st->state = sw_header_rep; |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
282 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
283 /* fall through */ |
7692 | 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 | |
7962
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
7961
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:
7961
diff
changeset
|
291 return NGX_HTTP_V3_ERR_FRAME_ERROR; |
7692 | 292 } |
293 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
295 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
296 } |
7692 | 297 |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
298 if (st->length == 0) { |
7692 | 299 goto done; |
300 } | |
301 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
302 return NGX_OK; |
7692 | 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 | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
311 if (st->prefix.insert_count > 0) { |
8200
279ad36f2f4b
QUIC: renamed c->qs to c->quic.
Roman Arutyunyan <arut@nginx.com>
parents:
8090
diff
changeset
|
312 if (ngx_http_v3_client_ack_header(c, c->quic->id) != NGX_OK) { |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
313 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
314 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
315 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
316 |
7692 | 317 st->state = sw_start; |
318 return NGX_DONE; | |
319 } | |
320 | |
321 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
322 static ngx_int_t |
7692 | 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 { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
326 ngx_int_t rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
348 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
349 return rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
366 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
367 return rc; |
7692 | 368 } |
369 | |
370 st->delta_base = st->pint.value; | |
371 goto done; | |
372 } | |
373 | |
374 return NGX_AGAIN; | |
375 | |
376 done: | |
377 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
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:
7952
diff
changeset
|
380 return rc; |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
381 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
382 |
7692 | 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 " | |
7996
d2f716e668e8
Fixed format specifiers.
Sergey Kandaurov <pluknet@nginx.com>
parents:
7962
diff
changeset
|
391 "insert_count:%ui, sign:%ui, delta_base:%ui, base:%ui", |
7692 | 392 st->insert_count, st->sign, st->delta_base, st->base); |
393 | |
394 st->state = sw_start; | |
395 return NGX_DONE; | |
396 } | |
397 | |
398 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
399 static ngx_int_t |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
476 return rc; |
7692 | 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 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
487 static ngx_int_t |
7692 | 488 ngx_http_v3_parse_literal(ngx_connection_t *c, ngx_http_v3_parse_literal_t *st, |
489 u_char ch) | |
490 { | |
8317
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8259
diff
changeset
|
491 ngx_uint_t n; |
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8259
diff
changeset
|
492 ngx_http_core_srv_conf_t *cscf; |
7692 | 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 | |
8317
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8259
diff
changeset
|
508 cscf = ngx_http_v3_get_module_srv_conf(c, ngx_http_core_module); |
7949
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
7761
diff
changeset
|
509 |
8317
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8259
diff
changeset
|
510 if (n > cscf->large_client_header_buffers.size) { |
7952
a7f64438aa3c
HTTP/3: downgraded literal size error level to NGX_LOG_INFO.
Roman Arutyunyan <arut@nginx.com>
parents:
7951
diff
changeset
|
511 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
8317
ae2e68f206f9
HTTP/3: removed http3_max_field_size.
Roman Arutyunyan <arut@nginx.com>
parents:
8259
diff
changeset
|
512 "client sent too large header field"); |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
513 return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD; |
7949
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
7761
diff
changeset
|
514 } |
032cb35ce758
HTTP/3: http3_max_field_size directive to limit string size.
Roman Arutyunyan <arut@nginx.com>
parents:
7761
diff
changeset
|
515 |
7692 | 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 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
566 static ngx_int_t |
7692 | 567 ngx_http_v3_parse_header_ri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, |
568 u_char ch) | |
569 { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
570 ngx_int_t rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
590 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
591 return rc; |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
611 &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
613 return rc; |
7692 | 614 } |
615 | |
616 st->state = sw_start; | |
617 return NGX_DONE; | |
618 } | |
619 | |
620 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
621 static ngx_int_t |
7692 | 622 ngx_http_v3_parse_header_lri(ngx_connection_t *c, |
623 ngx_http_v3_parse_header_t *st, u_char ch) | |
624 { | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
625 ngx_int_t rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
648 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
649 return rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
666 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
667 return rc; |
7692 | 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); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
681 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
682 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
683 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
684 |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
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:
7959
diff
changeset
|
686 goto done; |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
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:
7952
diff
changeset
|
704 return rc; |
7692 | 705 } |
706 | |
707 st->state = sw_start; | |
708 return NGX_DONE; | |
709 } | |
710 | |
711 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
712 static ngx_int_t |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
740 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
741 return rc; |
7692 | 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); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
755 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
756 return rc; |
7692 | 757 } |
758 | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
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:
7959
diff
changeset
|
760 st->state = sw_value_len; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
773 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
774 return rc; |
7692 | 775 } |
776 | |
777 st->literal.length = st->pint.value; | |
778 if (st->literal.length == 0) { | |
8233
5a92523e50d3
HTTP/3: null-terminate empty header value.
Roman Arutyunyan <arut@nginx.com>
parents:
8200
diff
changeset
|
779 st->value.data = (u_char *) ""; |
7692 | 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); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
789 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
790 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
791 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
792 |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
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:
7959
diff
changeset
|
794 goto done; |
7692 | 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 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
810 static ngx_int_t |
7692 | 811 ngx_http_v3_parse_header_pbi(ngx_connection_t *c, |
812 ngx_http_v3_parse_header_t *st, u_char ch) | |
813 { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
814 ngx_int_t rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
833 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
834 return rc; |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
849 &st->value); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
diff
changeset
|
851 return rc; |
7692 | 852 } |
853 | |
854 st->state = sw_start; | |
855 return NGX_DONE; | |
856 } | |
857 | |
858 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
859 static ngx_int_t |
7692 | 860 ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, |
861 ngx_http_v3_parse_header_t *st, u_char ch) | |
862 { | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
863 ngx_int_t rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
886 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
887 return rc; |
7692 | 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 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
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:
7958
diff
changeset
|
904 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
905 return rc; |
7692 | 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); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
919 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
920 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
921 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
922 |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
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:
7959
diff
changeset
|
924 goto done; |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
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:
7952
diff
changeset
|
937 return rc; |
7692 | 938 } |
939 | |
940 st->state = sw_start; | |
941 return NGX_DONE; | |
942 } | |
943 | |
944 | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
945 static ngx_int_t |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
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:
7950
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:
7950
diff
changeset
|
948 { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
949 u_char *p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
950 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
951 if (!dynamic) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
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:
7952
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:
7952
diff
changeset
|
954 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
955 |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
956 return NGX_OK; |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
957 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
958 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
959 if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
960 return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED; |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
961 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
962 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
963 if (name) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
964 p = ngx_pnalloc(c->pool, name->len + 1); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
965 if (p == NULL) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
966 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
967 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
968 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
969 ngx_memcpy(p, name->data, name->len); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
970 p[name->len] = '\0'; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
971 name->data = p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
972 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
973 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
974 if (value) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
975 p = ngx_pnalloc(c->pool, value->len + 1); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
976 if (p == NULL) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
977 return NGX_ERROR; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
978 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
979 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
980 ngx_memcpy(p, value->data, value->len); |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
981 p[value->len] = '\0'; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
982 value->data = p; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
983 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
984 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
985 return NGX_OK; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
986 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
987 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
988 |
7692 | 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, | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
997 sw_first_type, |
7692 | 998 sw_type, |
999 sw_length, | |
8015 | 1000 sw_cancel_push, |
7692 | 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 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1012 st->state = sw_first_type; |
7692 | 1013 |
1014 /* fall through */ | |
1015 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1016 case sw_first_type: |
7692 | 1017 case sw_type: |
1018 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
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:
7960
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:
7960
diff
changeset
|
1021 return rc; |
7692 | 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 | |
8088
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1029 if (ngx_http_v3_is_v2_frame(st->type)) { |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1030 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1031 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1032 |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1033 if (st->state == sw_first_type |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1034 && 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:
7952
diff
changeset
|
1035 { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1036 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:
7952
diff
changeset
|
1037 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1038 |
7692 | 1039 st->state = sw_length; |
1040 break; | |
1041 | |
1042 case sw_length: | |
1043 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1044 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:
7960
diff
changeset
|
1045 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1046 return rc; |
7692 | 1047 } |
1048 | |
1049 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1050 "http3 parse frame len:%uL", st->vlint.value); | |
1051 | |
1052 st->length = st->vlint.value; | |
1053 if (st->length == 0) { | |
1054 st->state = sw_type; | |
1055 break; | |
1056 } | |
1057 | |
1058 switch (st->type) { | |
1059 | |
8015 | 1060 case NGX_HTTP_V3_FRAME_CANCEL_PUSH: |
1061 st->state = sw_cancel_push; | |
1062 break; | |
1063 | |
7692 | 1064 case NGX_HTTP_V3_FRAME_SETTINGS: |
1065 st->state = sw_settings; | |
1066 break; | |
1067 | |
1068 case NGX_HTTP_V3_FRAME_MAX_PUSH_ID: | |
1069 st->state = sw_max_push_id; | |
1070 break; | |
1071 | |
1072 default: | |
1073 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1074 "http3 parse skip unknown frame"); | |
1075 st->state = sw_skip; | |
1076 } | |
1077 | |
1078 break; | |
1079 | |
8015 | 1080 case sw_cancel_push: |
1081 | |
1082 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); | |
1083 | |
1084 if (--st->length == 0 && rc == NGX_AGAIN) { | |
1085 return NGX_HTTP_V3_ERR_FRAME_ERROR; | |
1086 } | |
1087 | |
1088 if (rc != NGX_DONE) { | |
1089 return rc; | |
1090 } | |
1091 | |
1092 rc = ngx_http_v3_cancel_push(c, st->vlint.value); | |
1093 if (rc != NGX_OK) { | |
1094 return rc; | |
1095 } | |
1096 | |
1097 st->state = sw_type; | |
1098 break; | |
1099 | |
7692 | 1100 case sw_settings: |
1101 | |
1102 rc = ngx_http_v3_parse_settings(c, &st->settings, ch); | |
1103 | |
7962
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
7961
diff
changeset
|
1104 if (--st->length == 0 && rc == NGX_AGAIN) { |
e02250b55b17
HTTP/3: simplified handling return codes from parse functions.
Roman Arutyunyan <arut@nginx.com>
parents:
7961
diff
changeset
|
1105 return NGX_HTTP_V3_ERR_SETTINGS_ERROR; |
7692 | 1106 } |
1107 | |
1108 if (rc != NGX_DONE) { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1109 return rc; |
7692 | 1110 } |
1111 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1112 if (st->length == 0) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1113 st->state = sw_type; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1114 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1115 |
7692 | 1116 break; |
1117 | |
1118 case sw_max_push_id: | |
1119 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1120 rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch); |
8015 | 1121 |
1122 if (--st->length == 0 && rc == NGX_AGAIN) { | |
1123 return NGX_HTTP_V3_ERR_FRAME_ERROR; | |
1124 } | |
1125 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1126 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1127 return rc; |
7692 | 1128 } |
1129 | |
8015 | 1130 rc = ngx_http_v3_set_max_push_id(c, st->vlint.value); |
1131 if (rc != NGX_OK) { | |
1132 return rc; | |
1133 } | |
7692 | 1134 |
1135 st->state = sw_type; | |
1136 break; | |
1137 | |
1138 case sw_skip: | |
1139 | |
1140 if (--st->length == 0) { | |
1141 st->state = sw_type; | |
1142 } | |
1143 | |
1144 break; | |
1145 } | |
1146 | |
1147 return NGX_AGAIN; | |
1148 } | |
1149 | |
1150 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
1151 static ngx_int_t |
7692 | 1152 ngx_http_v3_parse_settings(ngx_connection_t *c, |
1153 ngx_http_v3_parse_settings_t *st, u_char ch) | |
1154 { | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1155 ngx_int_t rc; |
7692 | 1156 enum { |
1157 sw_start = 0, | |
1158 sw_id, | |
1159 sw_value | |
1160 }; | |
1161 | |
1162 switch (st->state) { | |
1163 | |
1164 case sw_start: | |
1165 | |
1166 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse settings"); | |
1167 | |
1168 st->state = sw_id; | |
1169 | |
1170 /* fall through */ | |
1171 | |
1172 case sw_id: | |
1173 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1174 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:
7960
diff
changeset
|
1175 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1176 return rc; |
7692 | 1177 } |
1178 | |
1179 st->id = st->vlint.value; | |
1180 st->state = sw_value; | |
1181 break; | |
1182 | |
1183 case sw_value: | |
1184 | |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1185 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:
7960
diff
changeset
|
1186 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1187 return rc; |
7692 | 1188 } |
1189 | |
1190 if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1191 return NGX_HTTP_V3_ERR_SETTINGS_ERROR; |
7692 | 1192 } |
1193 | |
1194 goto done; | |
1195 } | |
1196 | |
1197 return NGX_AGAIN; | |
1198 | |
1199 done: | |
1200 | |
1201 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse settings done"); | |
1202 | |
1203 st->state = sw_start; | |
1204 return NGX_DONE; | |
1205 } | |
1206 | |
1207 | |
1208 ngx_int_t | |
1209 ngx_http_v3_parse_encoder(ngx_connection_t *c, void *data, u_char ch) | |
1210 { | |
1211 ngx_http_v3_parse_encoder_t *st = data; | |
1212 | |
1213 ngx_int_t rc; | |
1214 enum { | |
1215 sw_start = 0, | |
1216 sw_inr, | |
1217 sw_iwnr, | |
1218 sw_capacity, | |
1219 sw_duplicate | |
1220 }; | |
1221 | |
1222 if (st->state == sw_start) { | |
1223 | |
1224 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1225 "http3 parse encoder instruction"); | |
1226 | |
1227 if (ch & 0x80) { | |
1228 /* Insert With Name Reference */ | |
1229 | |
1230 st->state = sw_inr; | |
1231 | |
1232 } else if (ch & 0x40) { | |
1233 /* Insert Without Name Reference */ | |
1234 | |
1235 st->state = sw_iwnr; | |
1236 | |
1237 } else if (ch & 0x20) { | |
1238 /* Set Dynamic Table Capacity */ | |
1239 | |
1240 st->state = sw_capacity; | |
1241 | |
1242 } else { | |
1243 /* Duplicate */ | |
1244 | |
1245 st->state = sw_duplicate; | |
1246 } | |
1247 } | |
1248 | |
1249 switch (st->state) { | |
1250 | |
1251 case sw_inr: | |
1252 | |
1253 rc = ngx_http_v3_parse_header_inr(c, &st->header, ch); | |
1254 if (rc != NGX_DONE) { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1255 return rc; |
7692 | 1256 } |
1257 | |
1258 goto done; | |
1259 | |
1260 case sw_iwnr: | |
1261 | |
1262 rc = ngx_http_v3_parse_header_iwnr(c, &st->header, ch); | |
1263 if (rc != NGX_DONE) { | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1264 return rc; |
7692 | 1265 } |
1266 | |
1267 goto done; | |
1268 | |
1269 case sw_capacity: | |
1270 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1271 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:
7958
diff
changeset
|
1272 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1273 return rc; |
7692 | 1274 } |
1275 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1276 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:
7952
diff
changeset
|
1277 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1278 return rc; |
7692 | 1279 } |
1280 | |
1281 goto done; | |
1282 | |
1283 case sw_duplicate: | |
1284 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1285 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:
7958
diff
changeset
|
1286 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1287 return rc; |
7692 | 1288 } |
1289 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1290 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:
7952
diff
changeset
|
1291 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1292 return rc; |
7692 | 1293 } |
1294 | |
1295 goto done; | |
1296 } | |
1297 | |
1298 return NGX_AGAIN; | |
1299 | |
1300 done: | |
1301 | |
1302 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1303 "http3 parse encoder instruction done"); | |
1304 | |
1305 st->state = sw_start; | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
1306 return NGX_AGAIN; |
7692 | 1307 } |
1308 | |
1309 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
1310 static ngx_int_t |
7692 | 1311 ngx_http_v3_parse_header_inr(ngx_connection_t *c, |
1312 ngx_http_v3_parse_header_t *st, u_char ch) | |
1313 { | |
1314 ngx_int_t rc; | |
1315 enum { | |
1316 sw_start = 0, | |
1317 sw_name_index, | |
1318 sw_value_len, | |
1319 sw_read_value_len, | |
1320 sw_value | |
1321 }; | |
1322 | |
1323 switch (st->state) { | |
1324 | |
1325 case sw_start: | |
1326 | |
1327 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header inr"); | |
1328 | |
1329 st->dynamic = (ch & 0x40) ? 0 : 1; | |
1330 st->state = sw_name_index; | |
1331 | |
1332 /* fall through */ | |
1333 | |
1334 case sw_name_index: | |
1335 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1336 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:
7958
diff
changeset
|
1337 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1338 return rc; |
7692 | 1339 } |
1340 | |
1341 st->index = st->pint.value; | |
1342 st->state = sw_value_len; | |
1343 break; | |
1344 | |
1345 case sw_value_len: | |
1346 | |
1347 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
1348 st->state = sw_read_value_len; | |
1349 | |
1350 /* fall through */ | |
1351 | |
1352 case sw_read_value_len: | |
1353 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1354 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:
7958
diff
changeset
|
1355 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1356 return rc; |
7692 | 1357 } |
1358 | |
1359 st->literal.length = st->pint.value; | |
1360 if (st->literal.length == 0) { | |
1361 goto done; | |
1362 } | |
1363 | |
1364 st->state = sw_value; | |
1365 break; | |
1366 | |
1367 case sw_value: | |
1368 | |
1369 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1370 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1371 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1372 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1373 |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1374 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1375 goto done; |
7692 | 1376 } |
1377 | |
1378 return NGX_AGAIN; | |
1379 | |
1380 done: | |
1381 | |
1382 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1383 "http3 parse header inr done %s[%ui] \"%V\"", | |
1384 st->dynamic ? "dynamic" : "static", | |
1385 st->index, &st->value); | |
1386 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1387 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:
7952
diff
changeset
|
1388 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1389 return rc; |
7692 | 1390 } |
1391 | |
1392 st->state = sw_start; | |
1393 return NGX_DONE; | |
1394 } | |
1395 | |
1396 | |
8259
ab6aaa8e86b0
HTTP/3: staticize internal parsing functions.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8233
diff
changeset
|
1397 static ngx_int_t |
7692 | 1398 ngx_http_v3_parse_header_iwnr(ngx_connection_t *c, |
1399 ngx_http_v3_parse_header_t *st, u_char ch) | |
1400 { | |
1401 ngx_int_t rc; | |
1402 enum { | |
1403 sw_start = 0, | |
1404 sw_name_len, | |
1405 sw_name, | |
1406 sw_value_len, | |
1407 sw_read_value_len, | |
1408 sw_value | |
1409 }; | |
1410 | |
1411 switch (st->state) { | |
1412 | |
1413 case sw_start: | |
1414 | |
1415 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1416 "http3 parse header iwnr"); | |
1417 | |
1418 st->literal.huffman = (ch & 0x20) ? 1 : 0; | |
1419 st->state = sw_name_len; | |
1420 | |
1421 /* fall through */ | |
1422 | |
1423 case sw_name_len: | |
1424 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1425 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:
7958
diff
changeset
|
1426 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1427 return rc; |
7692 | 1428 } |
1429 | |
1430 st->literal.length = st->pint.value; | |
1431 if (st->literal.length == 0) { | |
1432 return NGX_ERROR; | |
1433 } | |
1434 | |
1435 st->state = sw_name; | |
1436 break; | |
1437 | |
1438 case sw_name: | |
1439 | |
1440 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1441 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1442 return rc; |
7692 | 1443 } |
1444 | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1445 st->name = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1446 st->state = sw_value_len; |
7692 | 1447 break; |
1448 | |
1449 case sw_value_len: | |
1450 | |
1451 st->literal.huffman = (ch & 0x80) ? 1 : 0; | |
1452 st->state = sw_read_value_len; | |
1453 | |
1454 /* fall through */ | |
1455 | |
1456 case sw_read_value_len: | |
1457 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1458 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:
7958
diff
changeset
|
1459 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1460 return rc; |
7692 | 1461 } |
1462 | |
1463 st->literal.length = st->pint.value; | |
1464 if (st->literal.length == 0) { | |
1465 goto done; | |
1466 } | |
1467 | |
1468 st->state = sw_value; | |
1469 break; | |
1470 | |
1471 case sw_value: | |
1472 | |
1473 rc = ngx_http_v3_parse_literal(c, &st->literal, ch); | |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1474 if (rc != NGX_DONE) { |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1475 return rc; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1476 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1477 |
7960
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1478 st->value = st->literal.value; |
5611bbb852ce
HTTP/3: simplifed handling ngx_http_v3_parse_literal() return code.
Roman Arutyunyan <arut@nginx.com>
parents:
7959
diff
changeset
|
1479 goto done; |
7692 | 1480 } |
1481 | |
1482 return NGX_AGAIN; | |
1483 | |
1484 done: | |
1485 | |
1486 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1487 "http3 parse header iwnr done \"%V\":\"%V\"", | |
1488 &st->name, &st->value); | |
1489 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1490 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:
7952
diff
changeset
|
1491 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1492 return rc; |
7692 | 1493 } |
1494 | |
1495 st->state = sw_start; | |
1496 return NGX_DONE; | |
1497 } | |
1498 | |
1499 | |
1500 ngx_int_t | |
1501 ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch) | |
1502 { | |
1503 ngx_http_v3_parse_decoder_t *st = data; | |
1504 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1505 ngx_int_t rc; |
7692 | 1506 enum { |
1507 sw_start = 0, | |
1508 sw_ack_header, | |
1509 sw_cancel_stream, | |
1510 sw_inc_insert_count | |
1511 }; | |
1512 | |
1513 if (st->state == sw_start) { | |
1514 | |
1515 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1516 "http3 parse decoder instruction"); | |
1517 | |
1518 if (ch & 0x80) { | |
1519 /* Header Acknowledgement */ | |
1520 | |
1521 st->state = sw_ack_header; | |
1522 | |
1523 } else if (ch & 0x40) { | |
1524 /* Stream Cancellation */ | |
1525 | |
1526 st->state = sw_cancel_stream; | |
1527 | |
1528 } else { | |
1529 /* Insert Count Increment */ | |
1530 | |
1531 st->state = sw_inc_insert_count; | |
1532 } | |
1533 } | |
1534 | |
1535 switch (st->state) { | |
1536 | |
1537 case sw_ack_header: | |
1538 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1539 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:
7958
diff
changeset
|
1540 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1541 return rc; |
7692 | 1542 } |
1543 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1544 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:
7952
diff
changeset
|
1545 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1546 return rc; |
7692 | 1547 } |
1548 | |
1549 goto done; | |
1550 | |
1551 case sw_cancel_stream: | |
1552 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1553 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:
7958
diff
changeset
|
1554 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1555 return rc; |
7692 | 1556 } |
1557 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1558 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:
7952
diff
changeset
|
1559 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1560 return rc; |
7692 | 1561 } |
1562 | |
1563 goto done; | |
1564 | |
1565 case sw_inc_insert_count: | |
1566 | |
7959
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1567 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:
7958
diff
changeset
|
1568 if (rc != NGX_DONE) { |
fdb8edc8e496
HTTP/3: limited prefixed integer size by 62 bits.
Roman Arutyunyan <arut@nginx.com>
parents:
7958
diff
changeset
|
1569 return rc; |
7692 | 1570 } |
1571 | |
7955
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1572 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:
7952
diff
changeset
|
1573 if (rc != NGX_OK) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
7952
diff
changeset
|
1574 return rc; |
7692 | 1575 } |
1576 | |
1577 goto done; | |
1578 } | |
1579 | |
1580 return NGX_AGAIN; | |
1581 | |
1582 done: | |
1583 | |
1584 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1585 "http3 parse decoder instruction done"); | |
1586 | |
1587 st->state = sw_start; | |
7951
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
7950
diff
changeset
|
1588 return NGX_AGAIN; |
7692 | 1589 } |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1590 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1591 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1592 ngx_int_t |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1593 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:
7693
diff
changeset
|
1594 u_char ch) |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1595 { |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1596 ngx_int_t rc; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1597 enum { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1598 sw_start = 0, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1599 sw_type, |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1600 sw_length, |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1601 sw_skip |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1602 }; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1603 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1604 switch (st->state) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1605 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1606 case sw_start: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1607 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1608 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:
7693
diff
changeset
|
1609 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1610 st->state = sw_type; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1611 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1612 /* fall through */ |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1613 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1614 case sw_type: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1615 |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1616 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:
7960
diff
changeset
|
1617 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1618 return rc; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1619 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1620 |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1621 st->type = st->vlint.value; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1622 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1623 if (st->type == NGX_HTTP_V3_FRAME_HEADERS) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1624 /* trailers */ |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1625 goto done; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1626 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1627 |
8088
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1628 if (ngx_http_v3_is_v2_frame(st->type)) { |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1629 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED; |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1630 } |
234e9d89ff7f
HTTP/3: reject HTTP/2 frames.
Roman Arutyunyan <arut@nginx.com>
parents:
8087
diff
changeset
|
1631 |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1632 st->state = sw_length; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1633 break; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1634 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1635 case sw_length: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1636 |
7961
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1637 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:
7960
diff
changeset
|
1638 if (rc != NGX_DONE) { |
4fd709540daf
HTTP/3: put ngx_http_v3_parse_varlen_int() return code in variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7960
diff
changeset
|
1639 return rc; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1640 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1641 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1642 st->length = st->vlint.value; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1643 |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1644 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:
8015
diff
changeset
|
1645 "http3 parse data type:%ui, len:%ui", |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1646 st->type, st->length); |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1647 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1648 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:
8015
diff
changeset
|
1649 st->state = sw_skip; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1650 break; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1651 } |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1652 |
8087
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1653 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1654 return NGX_OK; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1655 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1656 case sw_skip: |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1657 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1658 if (--st->length == 0) { |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1659 st->state = sw_type; |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1660 } |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1661 |
d70a38acaea0
HTTP/3: skip unknown frames on request stream.
Roman Arutyunyan <arut@nginx.com>
parents:
8015
diff
changeset
|
1662 break; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1663 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1664 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1665 return NGX_AGAIN; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1666 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1667 done: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1668 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1669 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:
7693
diff
changeset
|
1670 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1671 st->state = sw_start; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1672 return NGX_DONE; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7693
diff
changeset
|
1673 } |