Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_parse.c @ 8384:c61fcdc1b8e3 quic
UDP: extended datagram context.
Sometimes it is required to process datagram properties at higher level (i.e.
QUIC is interested in source address which may change and IP options). The
patch adds ngx_udp_dgram_t structure used to pass packet-related information
in c->udp.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Fri, 02 Apr 2021 18:58:19 +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 } |