Mercurial > hg > nginx-quic
comparison src/http/v3/ngx_http_v3_parse.c @ 7951:c9538aef3211 quic
HTTP/3: refactored dynamic table implementation.
Previously dynamic table was not functional because of zero limit on its size
set by default. Now the following changes enable it:
- new directives to set SETTINGS_QPACK_MAX_TABLE_CAPACITY and
SETTINGS_QPACK_BLOCKED_STREAMS
- send settings with SETTINGS_QPACK_MAX_TABLE_CAPACITY and
SETTINGS_QPACK_BLOCKED_STREAMS to the client
- send Insert Count Increment to the client
- send Header Acknowledgement to the client
- evict old dynamic table entries on overflow
- decode Required Insert Count from client
- block stream if Required Insert Count is not reached
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 02 Jul 2020 15:34:05 +0300 |
parents | b0e81f49d7c0 |
children | a7f64438aa3c |
comparison
equal
deleted
inserted
replaced
7950:b0e81f49d7c0 | 7951:c9538aef3211 |
---|---|
6 | 6 |
7 | 7 |
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 | |
12 | |
13 static ngx_int_t ngx_http_v3_parse_lookup(ngx_connection_t *c, | |
14 ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *name, ngx_str_t *value); | |
11 | 15 |
12 | 16 |
13 ngx_int_t | 17 ngx_int_t |
14 ngx_http_v3_parse_varlen_int(ngx_connection_t *c, | 18 ngx_http_v3_parse_varlen_int(ngx_connection_t *c, |
15 ngx_http_v3_parse_varlen_int_t *st, u_char ch) | 19 ngx_http_v3_parse_varlen_int_t *st, u_char ch) |
142 ngx_int_t rc; | 146 ngx_int_t rc; |
143 enum { | 147 enum { |
144 sw_start = 0, | 148 sw_start = 0, |
145 sw_length, | 149 sw_length, |
146 sw_prefix, | 150 sw_prefix, |
151 sw_verify, | |
147 sw_header_rep, | 152 sw_header_rep, |
148 sw_done | 153 sw_done |
149 }; | 154 }; |
150 | 155 |
151 switch (st->state) { | 156 switch (st->state) { |
193 | 198 |
194 if (st->length == 0) { | 199 if (st->length == 0) { |
195 return NGX_ERROR; | 200 return NGX_ERROR; |
196 } | 201 } |
197 | 202 |
203 st->state = sw_verify; | |
204 break; | |
205 | |
206 case sw_verify: | |
207 | |
208 rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count); | |
209 if (rc != NGX_OK) { | |
210 return rc; | |
211 } | |
212 | |
198 st->state = sw_header_rep; | 213 st->state = sw_header_rep; |
199 break; | 214 |
215 /* fall through */ | |
200 | 216 |
201 case sw_header_rep: | 217 case sw_header_rep: |
202 | 218 |
203 rc = ngx_http_v3_parse_header_rep(c, &st->header_rep, st->prefix.base, | 219 rc = ngx_http_v3_parse_header_rep(c, &st->header_rep, st->prefix.base, |
204 ch); | 220 ch); |
226 | 242 |
227 done: | 243 done: |
228 | 244 |
229 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done"); | 245 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done"); |
230 | 246 |
247 if (st->prefix.insert_count > 0) { | |
248 if (ngx_http_v3_client_ack_header(c, c->qs->id) != NGX_OK) { | |
249 return NGX_ERROR; | |
250 } | |
251 } | |
252 | |
231 st->state = sw_start; | 253 st->state = sw_start; |
232 return NGX_DONE; | 254 return NGX_DONE; |
233 } | 255 } |
234 | 256 |
235 | 257 |
283 } | 305 } |
284 | 306 |
285 return NGX_AGAIN; | 307 return NGX_AGAIN; |
286 | 308 |
287 done: | 309 done: |
310 | |
311 if (ngx_http_v3_decode_insert_count(c, &st->insert_count) != NGX_OK) { | |
312 return NGX_ERROR; | |
313 } | |
288 | 314 |
289 if (st->sign) { | 315 if (st->sign) { |
290 st->base = st->insert_count - st->delta_base - 1; | 316 st->base = st->insert_count - st->delta_base - 1; |
291 } else { | 317 } else { |
292 st->base = st->insert_count + st->delta_base; | 318 st->base = st->insert_count + st->delta_base; |
293 } | 319 } |
294 | 320 |
295 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, | 321 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, |
296 "http3 parse header block prefix done " | 322 "http3 parse header block prefix done " |
297 "i:%ui, s:%ui, d:%ui, base:%uL", | 323 "insert_count:%ui, sign:%ui, delta_base:%ui, base:%uL", |
298 st->insert_count, st->sign, st->delta_base, st->base); | 324 st->insert_count, st->sign, st->delta_base, st->base); |
299 | 325 |
300 st->state = sw_start; | 326 st->state = sw_start; |
301 return NGX_DONE; | 327 return NGX_DONE; |
302 } | 328 } |
477 | 503 |
478 ngx_int_t | 504 ngx_int_t |
479 ngx_http_v3_parse_header_ri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, | 505 ngx_http_v3_parse_header_ri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, |
480 u_char ch) | 506 u_char ch) |
481 { | 507 { |
482 ngx_http_v3_header_t *h; | |
483 enum { | 508 enum { |
484 sw_start = 0, | 509 sw_start = 0, |
485 sw_index | 510 sw_index |
486 }; | 511 }; |
487 | 512 |
516 | 541 |
517 if (st->dynamic) { | 542 if (st->dynamic) { |
518 st->index = st->base - st->index - 1; | 543 st->index = st->base - st->index - 1; |
519 } | 544 } |
520 | 545 |
521 h = ngx_http_v3_lookup_table(c, st->dynamic, st->index); | 546 if (ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, |
522 if (h == NULL) { | 547 &st->value) |
548 != NGX_OK) | |
549 { | |
523 return NGX_ERROR; | 550 return NGX_ERROR; |
524 } | 551 } |
525 | 552 |
526 st->name = h->name; | 553 st->state = sw_start; |
527 st->value = h->value; | |
528 st->state = sw_start; | |
529 | |
530 return NGX_DONE; | 554 return NGX_DONE; |
531 } | 555 } |
532 | 556 |
533 | 557 |
534 ngx_int_t | 558 ngx_int_t |
535 ngx_http_v3_parse_header_lri(ngx_connection_t *c, | 559 ngx_http_v3_parse_header_lri(ngx_connection_t *c, |
536 ngx_http_v3_parse_header_t *st, u_char ch) | 560 ngx_http_v3_parse_header_t *st, u_char ch) |
537 { | 561 { |
538 ngx_int_t rc; | 562 ngx_int_t rc; |
539 ngx_http_v3_header_t *h; | |
540 enum { | 563 enum { |
541 sw_start = 0, | 564 sw_start = 0, |
542 sw_index, | 565 sw_index, |
543 sw_value_len, | 566 sw_value_len, |
544 sw_read_value_len, | 567 sw_read_value_len, |
614 | 637 |
615 if (st->dynamic) { | 638 if (st->dynamic) { |
616 st->index = st->base - st->index - 1; | 639 st->index = st->base - st->index - 1; |
617 } | 640 } |
618 | 641 |
619 h = ngx_http_v3_lookup_table(c, st->dynamic, st->index); | 642 if (ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, NULL) |
620 if (h == NULL) { | 643 != NGX_OK) |
644 { | |
621 return NGX_ERROR; | 645 return NGX_ERROR; |
622 } | 646 } |
623 | 647 |
624 st->name = h->name; | |
625 st->state = sw_start; | 648 st->state = sw_start; |
626 return NGX_DONE; | 649 return NGX_DONE; |
627 } | 650 } |
628 | 651 |
629 | 652 |
733 | 756 |
734 ngx_int_t | 757 ngx_int_t |
735 ngx_http_v3_parse_header_pbi(ngx_connection_t *c, | 758 ngx_http_v3_parse_header_pbi(ngx_connection_t *c, |
736 ngx_http_v3_parse_header_t *st, u_char ch) | 759 ngx_http_v3_parse_header_t *st, u_char ch) |
737 { | 760 { |
738 ngx_http_v3_header_t *h; | |
739 enum { | 761 enum { |
740 sw_start = 0, | 762 sw_start = 0, |
741 sw_index | 763 sw_index |
742 }; | 764 }; |
743 | 765 |
766 done: | 788 done: |
767 | 789 |
768 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 790 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
769 "http3 parse header pbi done dynamic[+%ui]", st->index); | 791 "http3 parse header pbi done dynamic[+%ui]", st->index); |
770 | 792 |
771 h = ngx_http_v3_lookup_table(c, 1, st->base + st->index); | 793 if (ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, |
772 if (h == NULL) { | 794 &st->value) |
795 != NGX_OK) | |
796 { | |
773 return NGX_ERROR; | 797 return NGX_ERROR; |
774 } | 798 } |
775 | 799 |
776 st->name = h->name; | |
777 st->value = h->value; | |
778 st->state = sw_start; | 800 st->state = sw_start; |
779 return NGX_DONE; | 801 return NGX_DONE; |
780 } | 802 } |
781 | 803 |
782 | 804 |
783 ngx_int_t | 805 ngx_int_t |
784 ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, | 806 ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, |
785 ngx_http_v3_parse_header_t *st, u_char ch) | 807 ngx_http_v3_parse_header_t *st, u_char ch) |
786 { | 808 { |
787 ngx_int_t rc; | 809 ngx_int_t rc; |
788 ngx_http_v3_header_t *h; | |
789 enum { | 810 enum { |
790 sw_start = 0, | 811 sw_start = 0, |
791 sw_index, | 812 sw_index, |
792 sw_value_len, | 813 sw_value_len, |
793 sw_read_value_len, | 814 sw_read_value_len, |
858 | 879 |
859 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | 880 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
860 "http3 parse header lpbi done dynamic[+%ui] \"%V\"", | 881 "http3 parse header lpbi done dynamic[+%ui] \"%V\"", |
861 st->index, &st->value); | 882 st->index, &st->value); |
862 | 883 |
863 h = ngx_http_v3_lookup_table(c, 1, st->base + st->index); | 884 if (ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, NULL) |
864 if (h == NULL) { | 885 != NGX_OK) |
886 { | |
865 return NGX_ERROR; | 887 return NGX_ERROR; |
866 } | 888 } |
867 | 889 |
868 st->name = h->name; | |
869 st->state = sw_start; | 890 st->state = sw_start; |
870 return NGX_DONE; | 891 return NGX_DONE; |
892 } | |
893 | |
894 | |
895 static ngx_int_t | |
896 ngx_http_v3_parse_lookup(ngx_connection_t *c, ngx_uint_t dynamic, | |
897 ngx_uint_t index, ngx_str_t *name, ngx_str_t *value) | |
898 { | |
899 u_char *p; | |
900 | |
901 if (!dynamic) { | |
902 return ngx_http_v3_lookup_static(c, index, name, value); | |
903 } | |
904 | |
905 if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) { | |
906 return NGX_ERROR; | |
907 } | |
908 | |
909 if (name) { | |
910 p = ngx_pnalloc(c->pool, name->len + 1); | |
911 if (p == NULL) { | |
912 return NGX_ERROR; | |
913 } | |
914 | |
915 ngx_memcpy(p, name->data, name->len); | |
916 p[name->len] = '\0'; | |
917 name->data = p; | |
918 } | |
919 | |
920 if (value) { | |
921 p = ngx_pnalloc(c->pool, value->len + 1); | |
922 if (p == NULL) { | |
923 return NGX_ERROR; | |
924 } | |
925 | |
926 ngx_memcpy(p, value->data, value->len); | |
927 p[value->len] = '\0'; | |
928 value->data = p; | |
929 } | |
930 | |
931 return NGX_OK; | |
871 } | 932 } |
872 | 933 |
873 | 934 |
874 ngx_int_t | 935 ngx_int_t |
875 ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch) | 936 ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch) |
1143 | 1204 |
1144 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | 1205 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1145 "http3 parse encoder instruction done"); | 1206 "http3 parse encoder instruction done"); |
1146 | 1207 |
1147 st->state = sw_start; | 1208 st->state = sw_start; |
1148 return NGX_DONE; | 1209 return NGX_AGAIN; |
1149 } | 1210 } |
1150 | 1211 |
1151 | 1212 |
1152 ngx_int_t | 1213 ngx_int_t |
1153 ngx_http_v3_parse_header_inr(ngx_connection_t *c, | 1214 ngx_http_v3_parse_header_inr(ngx_connection_t *c, |
1427 | 1488 |
1428 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | 1489 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
1429 "http3 parse decoder instruction done"); | 1490 "http3 parse decoder instruction done"); |
1430 | 1491 |
1431 st->state = sw_start; | 1492 st->state = sw_start; |
1432 return NGX_DONE; | 1493 return NGX_AGAIN; |
1433 } | 1494 } |
1434 | 1495 |
1435 | 1496 |
1436 ngx_int_t | 1497 ngx_int_t |
1437 ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st, | 1498 ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st, |