Mercurial > hg > nginx
comparison src/http/v3/ngx_http_v3_streams.c @ 8226:268f4389130d quic
Refactored HTTP/3 parser.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 18 Mar 2020 13:46:35 +0300 |
parents | 38c0898b6df7 |
children | ac41c53e446d |
comparison
equal
deleted
inserted
replaced
8225:714a19dba6af | 8226:268f4389130d |
---|---|
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | 11 |
12 | 12 |
13 #define NGX_HTTP_V3_CONTROL_STREAM 0x00 | 13 typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data, |
14 #define NGX_HTTP_V3_PUSH_STREAM 0x01 | 14 u_char ch); |
15 #define NGX_HTTP_V3_ENCODER_STREAM 0x02 | |
16 #define NGX_HTTP_V3_DECODER_STREAM 0x03 | |
17 | 15 |
18 | 16 |
19 typedef struct { | 17 typedef struct { |
20 uint32_t signature; /* QSTR */ | 18 uint32_t signature; /* QSTR */ |
21 u_char buf[4]; | 19 |
22 | 20 ngx_http_v3_handler_pt handler; |
23 ngx_uint_t len; | 21 void *data; |
24 ngx_uint_t type; | 22 |
25 ngx_uint_t state; | 23 ngx_uint_t type; |
26 ngx_uint_t index; | 24 ngx_uint_t client; /* unsigned client:1; */ |
27 ngx_uint_t offset; | |
28 | |
29 ngx_str_t name; | |
30 ngx_str_t value; | |
31 | |
32 unsigned client:1; | |
33 unsigned dynamic:1; | |
34 unsigned huffman:1; | |
35 } ngx_http_v3_uni_stream_t; | 25 } ngx_http_v3_uni_stream_t; |
36 | 26 |
37 | 27 |
38 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | 28 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); |
39 static void ngx_http_v3_uni_stream_cleanup(void *data); | 29 static void ngx_http_v3_uni_stream_cleanup(void *data); |
40 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); | 30 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); |
41 static void ngx_http_v3_dummy_stream_handler(ngx_event_t *rev); | 31 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); |
42 static void ngx_http_v3_client_encoder_handler(ngx_event_t *rev); | |
43 static void ngx_http_v3_client_decoder_handler(ngx_event_t *rev); | |
44 | |
45 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, | 32 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, |
46 ngx_uint_t type); | 33 ngx_uint_t type); |
47 static ngx_connection_t *ngx_http_v3_get_server_encoder(ngx_connection_t *c); | 34 static ngx_connection_t *ngx_http_v3_get_control(ngx_connection_t *c); |
48 static ngx_connection_t *ngx_http_v3_get_server_decoder(ngx_connection_t *c); | 35 static ngx_connection_t *ngx_http_v3_get_encoder(ngx_connection_t *c); |
36 static ngx_connection_t *ngx_http_v3_get_decoder(ngx_connection_t *c); | |
49 | 37 |
50 | 38 |
51 void | 39 void |
52 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) | 40 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) |
53 { | 41 { |
54 ngx_pool_cleanup_t *cln; | 42 ngx_pool_cleanup_t *cln; |
55 ngx_http_v3_uni_stream_t *us; | 43 ngx_http_v3_uni_stream_t *us; |
56 | 44 |
57 c->log->connection = c->number; | 45 c->log->connection = c->number; |
58 | 46 |
47 /* XXX */ | |
48 (void) ngx_http_v3_get_control(c); | |
49 (void) ngx_http_v3_get_encoder(c); | |
50 (void) ngx_http_v3_get_decoder(c); | |
51 | |
59 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 52 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
60 "http3 new uni stream id:0x%uXL", c->qs->id); | 53 "http3 new uni stream id:0x%uxL", c->qs->id); |
61 | 54 |
62 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); | 55 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); |
63 if (us == NULL) { | 56 if (us == NULL) { |
64 ngx_http_v3_close_uni_stream(c); | 57 ngx_http_v3_close_uni_stream(c); |
65 return; | 58 return; |
79 | 72 |
80 cln->handler = ngx_http_v3_uni_stream_cleanup; | 73 cln->handler = ngx_http_v3_uni_stream_cleanup; |
81 cln->data = c; | 74 cln->data = c; |
82 | 75 |
83 c->read->handler = ngx_http_v3_read_uni_stream_type; | 76 c->read->handler = ngx_http_v3_read_uni_stream_type; |
84 c->read->handler(c->read); | 77 ngx_http_v3_read_uni_stream_type(c->read); |
85 } | 78 } |
86 | 79 |
87 | 80 |
88 static void | 81 static void |
89 ngx_http_v3_close_uni_stream(ngx_connection_t *c) | 82 ngx_http_v3_close_uni_stream(ngx_connection_t *c) |
113 | 106 |
114 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); | 107 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); |
115 | 108 |
116 switch (us->type) { | 109 switch (us->type) { |
117 | 110 |
118 case NGX_HTTP_V3_ENCODER_STREAM: | 111 case NGX_HTTP_V3_STREAM_ENCODER: |
119 | 112 |
120 if (us->client) { | 113 if (us->client) { |
121 h3c->client_encoder = NULL; | 114 h3c->client_encoder = NULL; |
122 } else { | 115 } else { |
123 h3c->server_encoder = NULL; | 116 h3c->server_encoder = NULL; |
124 } | 117 } |
125 | 118 |
126 break; | 119 break; |
127 | 120 |
128 case NGX_HTTP_V3_DECODER_STREAM: | 121 case NGX_HTTP_V3_STREAM_DECODER: |
129 | 122 |
130 if (us->client) { | 123 if (us->client) { |
131 h3c->client_decoder = NULL; | 124 h3c->client_decoder = NULL; |
132 } else { | 125 } else { |
133 h3c->server_decoder = NULL; | 126 h3c->server_decoder = NULL; |
134 } | 127 } |
135 | 128 |
136 break; | 129 break; |
130 | |
131 case NGX_HTTP_V3_STREAM_CONTROL: | |
132 | |
133 if (us->client) { | |
134 h3c->client_control = NULL; | |
135 } else { | |
136 h3c->server_control = NULL; | |
137 } | |
138 | |
139 break; | |
137 } | 140 } |
138 } | 141 } |
139 | 142 |
140 | 143 |
141 static void | 144 static void |
142 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) | 145 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) |
143 { | 146 { |
144 u_char *p; | 147 u_char ch; |
145 ssize_t n, len; | 148 ssize_t n; |
146 ngx_connection_t *c; | 149 ngx_connection_t *c; |
147 ngx_http_v3_connection_t *h3c; | 150 ngx_http_v3_connection_t *h3c; |
148 ngx_http_v3_uni_stream_t *us; | 151 ngx_http_v3_uni_stream_t *st; |
149 | 152 |
150 c = rev->data; | 153 c = rev->data; |
151 us = c->data; | 154 st = c->data; |
152 h3c = c->qs->parent->data; | 155 h3c = c->qs->parent->data; |
153 | 156 |
154 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); | 157 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); |
155 | 158 |
156 while (rev->ready) { | 159 while (rev->ready) { |
157 | 160 |
158 p = &us->buf[us->len]; | 161 n = c->recv(c, &ch, 1); |
159 | |
160 if (us->len == 0) { | |
161 len = 1; | |
162 } else { | |
163 len = (us->buf[0] >> 6) + 1 - us->len; | |
164 } | |
165 | |
166 n = c->recv(c, p, len); | |
167 | 162 |
168 if (n == NGX_ERROR) { | 163 if (n == NGX_ERROR) { |
169 goto failed; | 164 goto failed; |
170 } | 165 } |
171 | 166 |
167 if (n == NGX_AGAIN || n != 1) { | |
168 break; | |
169 } | |
170 | |
171 st->type = ch; | |
172 | |
173 switch (st->type) { | |
174 | |
175 case NGX_HTTP_V3_STREAM_ENCODER: | |
176 | |
177 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
178 "http3 encoder stream"); | |
179 | |
180 if (h3c->client_encoder) { | |
181 goto failed; | |
182 } | |
183 | |
184 h3c->client_encoder = c; | |
185 st->handler = ngx_http_v3_parse_encoder; | |
186 n = sizeof(ngx_http_v3_parse_encoder_t); | |
187 | |
188 break; | |
189 | |
190 case NGX_HTTP_V3_STREAM_DECODER: | |
191 | |
192 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
193 "http3 decoder stream"); | |
194 | |
195 if (h3c->client_decoder) { | |
196 goto failed; | |
197 } | |
198 | |
199 h3c->client_decoder = c; | |
200 st->handler = ngx_http_v3_parse_decoder; | |
201 n = sizeof(ngx_http_v3_parse_decoder_t); | |
202 | |
203 break; | |
204 | |
205 case NGX_HTTP_V3_STREAM_CONTROL: | |
206 | |
207 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
208 "http3 control stream"); | |
209 | |
210 if (h3c->client_control) { | |
211 goto failed; | |
212 } | |
213 | |
214 h3c->client_control = c; | |
215 st->handler = ngx_http_v3_parse_control; | |
216 n = sizeof(ngx_http_v3_parse_control_t); | |
217 | |
218 break; | |
219 | |
220 default: | |
221 | |
222 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
223 "http3 stream 0x%02xi", st->type); | |
224 n = 0; | |
225 } | |
226 | |
227 if (n) { | |
228 st->data = ngx_pcalloc(c->pool, n); | |
229 if (st->data == NULL) { | |
230 goto failed; | |
231 } | |
232 } | |
233 | |
234 rev->handler = ngx_http_v3_uni_read_handler; | |
235 ngx_http_v3_uni_read_handler(rev); | |
236 return; | |
237 } | |
238 | |
239 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
240 goto failed; | |
241 } | |
242 | |
243 return; | |
244 | |
245 failed: | |
246 | |
247 ngx_http_v3_close_uni_stream(c); | |
248 } | |
249 | |
250 | |
251 static void | |
252 ngx_http_v3_uni_read_handler(ngx_event_t *rev) | |
253 { | |
254 u_char buf[128]; | |
255 ssize_t n; | |
256 ngx_int_t rc, i; | |
257 ngx_connection_t *c; | |
258 ngx_http_v3_uni_stream_t *st; | |
259 | |
260 c = rev->data; | |
261 st = c->data; | |
262 | |
263 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); | |
264 | |
265 while (rev->ready) { | |
266 | |
267 n = c->recv(c, buf, sizeof(buf)); | |
268 | |
269 if (n == NGX_ERROR || n == 0) { | |
270 goto failed; | |
271 } | |
272 | |
172 if (n == NGX_AGAIN) { | 273 if (n == NGX_AGAIN) { |
173 break; | 274 break; |
174 } | 275 } |
175 | 276 |
176 us->len += n; | 277 if (st->handler == NULL) { |
177 | 278 continue; |
178 if (n != len) { | 279 } |
179 break; | 280 |
180 } | 281 for (i = 0; i < n; i++) { |
181 | 282 |
182 if ((us->buf[0] >> 6) + 1 == us->len) { | 283 rc = st->handler(c, st->data, buf[i]); |
183 us->type = ngx_http_v3_decode_varlen_int(us->buf); | 284 |
184 | 285 if (rc == NGX_ERROR) { |
185 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
186 "http3 stream type:%ui", us->type); | |
187 | |
188 switch (us->type) { | |
189 | |
190 case NGX_HTTP_V3_ENCODER_STREAM: | |
191 if (h3c->client_encoder) { | |
192 goto failed; | |
193 } | |
194 | |
195 h3c->client_encoder = c; | |
196 rev->handler = ngx_http_v3_client_encoder_handler; | |
197 break; | |
198 | |
199 case NGX_HTTP_V3_DECODER_STREAM: | |
200 if (h3c->client_decoder) { | |
201 goto failed; | |
202 } | |
203 | |
204 h3c->client_decoder = c; | |
205 rev->handler = ngx_http_v3_client_decoder_handler; | |
206 break; | |
207 | |
208 case NGX_HTTP_V3_CONTROL_STREAM: | |
209 case NGX_HTTP_V3_PUSH_STREAM: | |
210 | |
211 /* ignore these */ | |
212 | |
213 default: | |
214 rev->handler = ngx_http_v3_dummy_stream_handler; | |
215 } | |
216 | |
217 rev->handler(rev); | |
218 return; | |
219 } | |
220 } | |
221 | |
222 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
223 goto failed; | |
224 } | |
225 | |
226 return; | |
227 | |
228 failed: | |
229 | |
230 ngx_http_v3_close_uni_stream(c); | |
231 } | |
232 | |
233 | |
234 static void | |
235 ngx_http_v3_dummy_stream_handler(ngx_event_t *rev) | |
236 { | |
237 u_char buf[128]; | |
238 ngx_connection_t *c; | |
239 | |
240 /* read out and ignore */ | |
241 | |
242 c = rev->data; | |
243 | |
244 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy stream reader"); | |
245 | |
246 while (rev->ready) { | |
247 if (c->recv(c, buf, sizeof(buf)) == NGX_ERROR) { | |
248 goto failed; | |
249 } | |
250 } | |
251 | |
252 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
253 goto failed; | |
254 } | |
255 | |
256 return; | |
257 | |
258 failed: | |
259 | |
260 ngx_http_v3_close_uni_stream(c); | |
261 } | |
262 | |
263 | |
264 static void | |
265 ngx_http_v3_client_encoder_handler(ngx_event_t *rev) | |
266 { | |
267 u_char v; | |
268 ssize_t n; | |
269 ngx_str_t name, value; | |
270 ngx_uint_t dynamic, huffman, index, offset; | |
271 ngx_connection_t *c, *pc; | |
272 ngx_http_v3_uni_stream_t *st; | |
273 enum { | |
274 sw_start = 0, | |
275 sw_inr_name_index, | |
276 sw_inr_value_length, | |
277 sw_inr_read_value_length, | |
278 sw_inr_value, | |
279 sw_iwnr_name_length, | |
280 sw_iwnr_name, | |
281 sw_iwnr_value_length, | |
282 sw_iwnr_read_value_length, | |
283 sw_iwnr_value, | |
284 sw_capacity, | |
285 sw_duplicate | |
286 } state; | |
287 | |
288 c = rev->data; | |
289 st = c->data; | |
290 pc = c->qs->parent; | |
291 | |
292 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client encoder"); | |
293 | |
294 state = st->state; | |
295 dynamic = st->dynamic; | |
296 huffman = st->huffman; | |
297 index = st->index; | |
298 offset = st->offset; | |
299 name = st->name; | |
300 value = st->value; | |
301 | |
302 while (rev->ready) { | |
303 | |
304 /* XXX limit checks */ | |
305 /* XXX buffer input */ | |
306 | |
307 n = c->recv(c, &v, 1); | |
308 | |
309 if (n == NGX_ERROR || n == 0) { | |
310 goto failed; | |
311 } | |
312 | |
313 if (n != 1) { | |
314 break; | |
315 } | |
316 | |
317 /* XXX v -> ch */ | |
318 | |
319 switch (state) { | |
320 | |
321 case sw_start: | |
322 | |
323 if (v & 0x80) { | |
324 /* Insert With Name Reference */ | |
325 | |
326 dynamic = (v & 0x40) ? 0 : 1; | |
327 index = v & 0x3f; | |
328 | |
329 if (index != 0x3f) { | |
330 state = sw_inr_value_length; | |
331 break; | |
332 } | |
333 | |
334 index = 0; | |
335 state = sw_inr_name_index; | |
336 break; | |
337 } | |
338 | |
339 if (v & 0x40) { | |
340 /* Insert Without Name Reference */ | |
341 | |
342 huffman = (v & 0x20) ? 1 : 0; | |
343 name.len = v & 0x1f; | |
344 | |
345 if (name.len != 0x1f) { | |
346 offset = 0; | |
347 state = sw_iwnr_name; | |
348 break; | |
349 } | |
350 | |
351 name.len = 0; | |
352 state = sw_iwnr_name_length; | |
353 break; | |
354 } | |
355 | |
356 if (v & 0x20) { | |
357 /* Set Dynamic Table Capacity */ | |
358 | |
359 index = v & 0x1f; | |
360 | |
361 if (index != 0x1f) { | |
362 if (ngx_http_v3_set_capacity(c, index) != NGX_OK) { | |
363 goto failed; | |
364 } | |
365 | |
366 break; | |
367 } | |
368 | |
369 index = 0; | |
370 state = sw_capacity; | |
371 break; | |
372 } | |
373 | |
374 /* Duplicate */ | |
375 | |
376 index = v & 0x1f; | |
377 | |
378 if (index != 0x1f) { | |
379 if (ngx_http_v3_duplicate(c, index) != NGX_OK) { | |
380 goto failed; | |
381 } | |
382 | |
383 break; | |
384 } | |
385 | |
386 index = 0; | |
387 state = sw_duplicate; | |
388 break; | |
389 | |
390 case sw_inr_name_index: | |
391 | |
392 index = (index << 7) + (v & 0x7f); | |
393 if (v & 0x80) { | |
394 break; | |
395 } | |
396 | |
397 index += 0x3f; | |
398 state = sw_inr_value_length; | |
399 break; | |
400 | |
401 case sw_inr_value_length: | |
402 | |
403 huffman = (v & 0x80) ? 1 : 0; | |
404 value.len = v & 0x7f; | |
405 | |
406 if (value.len == 0) { | |
407 value.data = NULL; | |
408 | |
409 if (ngx_http_v3_ref_insert(c, dynamic, index, &value) != NGX_OK) | |
410 { | |
411 goto failed; | |
412 } | |
413 | |
414 state = sw_start; | |
415 break; | |
416 } | |
417 | |
418 if (value.len != 0x7f) { | |
419 value.data = ngx_pnalloc(pc->pool, value.len); | |
420 if (value.data == NULL) { | |
421 goto failed; | |
422 } | |
423 | |
424 state = sw_inr_value; | |
425 offset = 0; | |
426 break; | |
427 } | |
428 | |
429 value.len = 0; | |
430 state = sw_inr_read_value_length; | |
431 break; | |
432 | |
433 case sw_inr_read_value_length: | |
434 | |
435 value.len = (value.len << 7) + (v & 0x7f); | |
436 if (v & 0x80) { | |
437 break; | |
438 } | |
439 | |
440 value.len += 0x7f; | |
441 | |
442 value.data = ngx_pnalloc(pc->pool, value.len); | |
443 if (value.data == NULL) { | |
444 goto failed; | 286 goto failed; |
445 } | 287 } |
446 | 288 |
447 state = sw_inr_value; | 289 if (rc == NGX_DONE) { |
448 offset = 0; | 290 goto done; |
449 break; | |
450 | |
451 case sw_inr_value: | |
452 | |
453 value.data[offset++] = v; | |
454 if (offset != value.len) { | |
455 break; | |
456 } | 291 } |
457 | 292 |
458 if (huffman) { | 293 /* rc == NGX_AGAIN */ |
459 if (ngx_http_v3_decode_huffman(pc, &value) != NGX_OK) { | 294 } |
460 goto failed; | 295 } |
461 } | |
462 } | |
463 | |
464 if (ngx_http_v3_ref_insert(c, dynamic, index, &value) != NGX_OK) { | |
465 goto failed; | |
466 } | |
467 | |
468 state = sw_start; | |
469 break; | |
470 | |
471 case sw_iwnr_name_length: | |
472 | |
473 name.len = (name.len << 7) + (v & 0x7f); | |
474 if (v & 0x80) { | |
475 break; | |
476 } | |
477 | |
478 name.len += 0x1f; | |
479 | |
480 name.data = ngx_pnalloc(pc->pool, name.len); | |
481 if (name.data == NULL) { | |
482 goto failed; | |
483 } | |
484 | |
485 offset = 0; | |
486 state = sw_iwnr_name; | |
487 break; | |
488 | |
489 case sw_iwnr_name: | |
490 | |
491 name.data[offset++] = v; | |
492 if (offset != name.len) { | |
493 break; | |
494 } | |
495 | |
496 if (huffman) { | |
497 if (ngx_http_v3_decode_huffman(pc, &name) != NGX_OK) { | |
498 goto failed; | |
499 } | |
500 } | |
501 | |
502 state = sw_iwnr_value_length; | |
503 break; | |
504 | |
505 case sw_iwnr_value_length: | |
506 | |
507 huffman = (v & 0x80) ? 1 : 0; | |
508 value.len = v & 0x7f; | |
509 | |
510 if (value.len == 0) { | |
511 value.data = NULL; | |
512 | |
513 if (ngx_http_v3_insert(c, &name, &value) != NGX_OK) { | |
514 goto failed; | |
515 } | |
516 | |
517 state = sw_start; | |
518 break; | |
519 } | |
520 | |
521 if (value.len != 0x7f) { | |
522 value.data = ngx_pnalloc(pc->pool, value.len); | |
523 if (value.data == NULL) { | |
524 goto failed; | |
525 } | |
526 | |
527 offset = 0; | |
528 state = sw_iwnr_value; | |
529 break; | |
530 } | |
531 | |
532 state = sw_iwnr_read_value_length; | |
533 break; | |
534 | |
535 case sw_iwnr_read_value_length: | |
536 | |
537 value.len = (value.len << 7) + (v & 0x7f); | |
538 if (v & 0x80) { | |
539 break; | |
540 } | |
541 | |
542 value.data = ngx_pnalloc(pc->pool, value.len); | |
543 if (value.data == NULL) { | |
544 goto failed; | |
545 } | |
546 | |
547 offset = 0; | |
548 state = sw_iwnr_value; | |
549 break; | |
550 | |
551 case sw_iwnr_value: | |
552 | |
553 value.data[offset++] = v; | |
554 if (offset != value.len) { | |
555 break; | |
556 } | |
557 | |
558 if (huffman) { | |
559 if (ngx_http_v3_decode_huffman(pc, &value) != NGX_OK) { | |
560 goto failed; | |
561 } | |
562 } | |
563 | |
564 if (ngx_http_v3_insert(c, &name, &value) != NGX_OK) { | |
565 goto failed; | |
566 } | |
567 | |
568 state = sw_start; | |
569 break; | |
570 | |
571 | |
572 case sw_capacity: | |
573 | |
574 index = (index << 7) + (v & 0x7f); | |
575 if (v & 0x80) { | |
576 break; | |
577 } | |
578 | |
579 index += 0x1f; | |
580 | |
581 if (ngx_http_v3_set_capacity(c, index) != NGX_OK) { | |
582 goto failed; | |
583 } | |
584 | |
585 state = sw_start; | |
586 break; | |
587 | |
588 case sw_duplicate: | |
589 | |
590 index = (index << 7) + (v & 0x7f); | |
591 if (v & 0x80) { | |
592 break; | |
593 } | |
594 | |
595 index += 0x1f; | |
596 | |
597 if (ngx_http_v3_duplicate(c, index) != NGX_OK) { | |
598 goto failed; | |
599 } | |
600 | |
601 state = sw_start; | |
602 break; | |
603 } | |
604 } | |
605 | |
606 st->state = state; | |
607 st->dynamic = dynamic; | |
608 st->huffman = huffman; | |
609 st->index = index; | |
610 st->offset = offset; | |
611 st->name = name; | |
612 st->value = value; | |
613 | 296 |
614 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | 297 if (ngx_handle_read_event(rev, 0) != NGX_OK) { |
615 goto failed; | 298 goto failed; |
616 } | 299 } |
617 | 300 |
618 return; | 301 return; |
619 | 302 |
620 failed: | 303 done: |
621 | 304 |
622 ngx_http_v3_close_uni_stream(c); | 305 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read done"); |
623 } | |
624 | |
625 | |
626 static void | |
627 ngx_http_v3_client_decoder_handler(ngx_event_t *rev) | |
628 { | |
629 u_char v; | |
630 ssize_t n; | |
631 ngx_uint_t index; | |
632 ngx_connection_t *c; | |
633 ngx_http_v3_uni_stream_t *st; | |
634 enum { | |
635 sw_start = 0, | |
636 sw_ack_header, | |
637 sw_cancel_stream, | |
638 sw_inc_insert_count | |
639 } state; | |
640 | |
641 c = rev->data; | |
642 st = c->data; | |
643 | |
644 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client decoder"); | |
645 | |
646 state = st->state; | |
647 index = st->index; | |
648 | |
649 while (rev->ready) { | |
650 | |
651 /* XXX limit checks */ | |
652 /* XXX buffer input */ | |
653 | |
654 n = c->recv(c, &v, 1); | |
655 | |
656 if (n == NGX_ERROR || n == 0) { | |
657 goto failed; | |
658 } | |
659 | |
660 if (n != 1) { | |
661 break; | |
662 } | |
663 | |
664 switch (state) { | |
665 | |
666 case sw_start: | |
667 | |
668 if (v & 0x80) { | |
669 /* Header Acknowledgement */ | |
670 | |
671 index = v & 0x7f; | |
672 | |
673 if (index != 0x7f) { | |
674 if (ngx_http_v3_ack_header(c, index) != NGX_OK) { | |
675 goto failed; | |
676 } | |
677 | |
678 break; | |
679 } | |
680 | |
681 index = 0; | |
682 state = sw_ack_header; | |
683 break; | |
684 } | |
685 | |
686 if (v & 0x40) { | |
687 /* Stream Cancellation */ | |
688 | |
689 index = v & 0x3f; | |
690 | |
691 if (index != 0x3f) { | |
692 if (ngx_http_v3_cancel_stream(c, index) != NGX_OK) { | |
693 goto failed; | |
694 } | |
695 | |
696 break; | |
697 } | |
698 | |
699 index = 0; | |
700 state = sw_cancel_stream; | |
701 break; | |
702 } | |
703 | |
704 /* Insert Count Increment */ | |
705 | |
706 index = v & 0x3f; | |
707 | |
708 if (index != 0x3f) { | |
709 if (ngx_http_v3_inc_insert_count(c, index) != NGX_OK) { | |
710 goto failed; | |
711 } | |
712 | |
713 break; | |
714 } | |
715 | |
716 index = 0; | |
717 state = sw_inc_insert_count; | |
718 break; | |
719 | |
720 case sw_ack_header: | |
721 | |
722 index = (index << 7) + (v & 0x7f); | |
723 if (v & 0x80) { | |
724 break; | |
725 } | |
726 | |
727 index += 0x7f; | |
728 | |
729 if (ngx_http_v3_ack_header(c, index) != NGX_OK) { | |
730 goto failed; | |
731 } | |
732 | |
733 state = sw_start; | |
734 break; | |
735 | |
736 case sw_cancel_stream: | |
737 | |
738 index = (index << 7) + (v & 0x7f); | |
739 if (v & 0x80) { | |
740 break; | |
741 } | |
742 | |
743 index += 0x3f; | |
744 | |
745 if (ngx_http_v3_cancel_stream(c, index) != NGX_OK) { | |
746 goto failed; | |
747 } | |
748 | |
749 state = sw_start; | |
750 break; | |
751 | |
752 case sw_inc_insert_count: | |
753 | |
754 index = (index << 7) + (v & 0x7f); | |
755 if (v & 0x80) { | |
756 break; | |
757 } | |
758 | |
759 index += 0x3f; | |
760 | |
761 if (ngx_http_v3_inc_insert_count(c, index) != NGX_OK) { | |
762 goto failed; | |
763 } | |
764 | |
765 state = sw_start; | |
766 break; | |
767 } | |
768 } | |
769 | |
770 st->state = state; | |
771 st->index = index; | |
772 | |
773 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
774 goto failed; | |
775 } | |
776 | |
777 return; | |
778 | 306 |
779 failed: | 307 failed: |
780 | 308 |
781 ngx_http_v3_close_uni_stream(c); | 309 ngx_http_v3_close_uni_stream(c); |
782 } | 310 } |
833 return NULL; | 361 return NULL; |
834 } | 362 } |
835 | 363 |
836 | 364 |
837 static ngx_connection_t * | 365 static ngx_connection_t * |
838 ngx_http_v3_get_server_encoder(ngx_connection_t *c) | 366 ngx_http_v3_get_control(ngx_connection_t *c) |
839 { | 367 { |
840 ngx_http_v3_connection_t *h3c; | 368 ngx_http_v3_connection_t *h3c; |
841 | 369 |
842 h3c = c->qs->parent->data; | 370 h3c = c->qs->parent->data; |
843 | 371 |
844 if (h3c->server_encoder == NULL) { | 372 if (h3c->server_encoder == NULL) { |
845 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, | 373 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, |
846 NGX_HTTP_V3_ENCODER_STREAM); | 374 NGX_HTTP_V3_STREAM_CONTROL); |
847 } | 375 } |
848 | 376 |
849 return h3c->server_encoder; | 377 return h3c->server_encoder; |
850 } | 378 } |
851 | 379 |
852 | 380 |
853 static ngx_connection_t * | 381 static ngx_connection_t * |
854 ngx_http_v3_get_server_decoder(ngx_connection_t *c) | 382 ngx_http_v3_get_encoder(ngx_connection_t *c) |
855 { | 383 { |
856 ngx_http_v3_connection_t *h3c; | 384 ngx_http_v3_connection_t *h3c; |
857 | 385 |
858 h3c = c->qs->parent->data; | 386 h3c = c->qs->parent->data; |
859 | 387 |
860 if (h3c->server_decoder == NULL) { | 388 if (h3c->server_encoder == NULL) { |
861 h3c->server_decoder = ngx_http_v3_create_uni_stream(c, | 389 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, |
862 NGX_HTTP_V3_DECODER_STREAM); | 390 NGX_HTTP_V3_STREAM_ENCODER); |
863 } | 391 } |
864 | 392 |
865 return h3c->server_decoder; | 393 return h3c->server_encoder; |
394 } | |
395 | |
396 | |
397 static ngx_connection_t * | |
398 ngx_http_v3_get_decoder(ngx_connection_t *c) | |
399 { | |
400 ngx_http_v3_connection_t *h3c; | |
401 | |
402 h3c = c->qs->parent->data; | |
403 | |
404 if (h3c->server_encoder == NULL) { | |
405 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, | |
406 NGX_HTTP_V3_STREAM_DECODER); | |
407 } | |
408 | |
409 return h3c->server_encoder; | |
866 } | 410 } |
867 | 411 |
868 | 412 |
869 ngx_int_t | 413 ngx_int_t |
870 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, | 414 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, |
876 | 420 |
877 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | 421 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, |
878 "http3 client ref insert, %s[%ui] \"%V\"", | 422 "http3 client ref insert, %s[%ui] \"%V\"", |
879 dynamic ? "dynamic" : "static", index, value); | 423 dynamic ? "dynamic" : "static", index, value); |
880 | 424 |
881 ec = ngx_http_v3_get_server_encoder(c); | 425 ec = ngx_http_v3_get_encoder(c); |
882 if (ec == NULL) { | 426 if (ec == NULL) { |
883 return NGX_ERROR; | 427 return NGX_ERROR; |
884 } | 428 } |
885 | 429 |
886 p = buf; | 430 p = buf; |
921 ngx_connection_t *ec; | 465 ngx_connection_t *ec; |
922 | 466 |
923 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | 467 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
924 "http3 client insert \"%V\":\"%V\"", name, value); | 468 "http3 client insert \"%V\":\"%V\"", name, value); |
925 | 469 |
926 ec = ngx_http_v3_get_server_encoder(c); | 470 ec = ngx_http_v3_get_encoder(c); |
927 if (ec == NULL) { | 471 if (ec == NULL) { |
928 return NGX_ERROR; | 472 return NGX_ERROR; |
929 } | 473 } |
930 | 474 |
931 /* XXX option for huffman? */ | 475 /* XXX option for huffman? */ |
970 ngx_connection_t *ec; | 514 ngx_connection_t *ec; |
971 | 515 |
972 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 516 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
973 "http3 client set capacity %ui", capacity); | 517 "http3 client set capacity %ui", capacity); |
974 | 518 |
975 ec = ngx_http_v3_get_server_encoder(c); | 519 ec = ngx_http_v3_get_encoder(c); |
976 if (ec == NULL) { | 520 if (ec == NULL) { |
977 return NGX_ERROR; | 521 return NGX_ERROR; |
978 } | 522 } |
979 | 523 |
980 buf[0] = 0x20; | 524 buf[0] = 0x20; |
997 ngx_connection_t *ec; | 541 ngx_connection_t *ec; |
998 | 542 |
999 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 543 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1000 "http3 client duplicate %ui", index); | 544 "http3 client duplicate %ui", index); |
1001 | 545 |
1002 ec = ngx_http_v3_get_server_encoder(c); | 546 ec = ngx_http_v3_get_encoder(c); |
1003 if (ec == NULL) { | 547 if (ec == NULL) { |
1004 return NGX_ERROR; | 548 return NGX_ERROR; |
1005 } | 549 } |
1006 | 550 |
1007 buf[0] = 0; | 551 buf[0] = 0; |
1024 ngx_connection_t *dc; | 568 ngx_connection_t *dc; |
1025 | 569 |
1026 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 570 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1027 "http3 client ack header %ui", stream_id); | 571 "http3 client ack header %ui", stream_id); |
1028 | 572 |
1029 dc = ngx_http_v3_get_server_decoder(c); | 573 dc = ngx_http_v3_get_decoder(c); |
1030 if (dc == NULL) { | 574 if (dc == NULL) { |
1031 return NGX_ERROR; | 575 return NGX_ERROR; |
1032 } | 576 } |
1033 | 577 |
1034 buf[0] = 0x80; | 578 buf[0] = 0x80; |
1051 ngx_connection_t *dc; | 595 ngx_connection_t *dc; |
1052 | 596 |
1053 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 597 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1054 "http3 client cancel stream %ui", stream_id); | 598 "http3 client cancel stream %ui", stream_id); |
1055 | 599 |
1056 dc = ngx_http_v3_get_server_decoder(c); | 600 dc = ngx_http_v3_get_decoder(c); |
1057 if (dc == NULL) { | 601 if (dc == NULL) { |
1058 return NGX_ERROR; | 602 return NGX_ERROR; |
1059 } | 603 } |
1060 | 604 |
1061 buf[0] = 0x40; | 605 buf[0] = 0x40; |
1078 ngx_connection_t *dc; | 622 ngx_connection_t *dc; |
1079 | 623 |
1080 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 624 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1081 "http3 client increment insert count %ui", inc); | 625 "http3 client increment insert count %ui", inc); |
1082 | 626 |
1083 dc = ngx_http_v3_get_server_decoder(c); | 627 dc = ngx_http_v3_get_decoder(c); |
1084 if (dc == NULL) { | 628 if (dc == NULL) { |
1085 return NGX_ERROR; | 629 return NGX_ERROR; |
1086 } | 630 } |
1087 | 631 |
1088 buf[0] = 0; | 632 buf[0] = 0; |