Mercurial > hg > nginx
diff src/http/v3/ngx_http_v3_parse.c @ 8456: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 |
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3_parse.c +++ b/src/http/v3/ngx_http_v3_parse.c @@ -10,6 +10,10 @@ #include <ngx_http.h> +static ngx_int_t ngx_http_v3_parse_lookup(ngx_connection_t *c, + ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *name, ngx_str_t *value); + + ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c, ngx_http_v3_parse_varlen_int_t *st, u_char ch) @@ -144,6 +148,7 @@ ngx_http_v3_parse_headers(ngx_connection sw_start = 0, sw_length, sw_prefix, + sw_verify, sw_header_rep, sw_done }; @@ -195,8 +200,19 @@ ngx_http_v3_parse_headers(ngx_connection return NGX_ERROR; } + st->state = sw_verify; + break; + + case sw_verify: + + rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count); + if (rc != NGX_OK) { + return rc; + } + st->state = sw_header_rep; - break; + + /* fall through */ case sw_header_rep: @@ -228,6 +244,12 @@ done: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done"); + if (st->prefix.insert_count > 0) { + if (ngx_http_v3_client_ack_header(c, c->qs->id) != NGX_OK) { + return NGX_ERROR; + } + } + st->state = sw_start; return NGX_DONE; } @@ -286,6 +308,10 @@ ngx_http_v3_parse_header_block_prefix(ng done: + if (ngx_http_v3_decode_insert_count(c, &st->insert_count) != NGX_OK) { + return NGX_ERROR; + } + if (st->sign) { st->base = st->insert_count - st->delta_base - 1; } else { @@ -294,7 +320,7 @@ done: ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header block prefix done " - "i:%ui, s:%ui, d:%ui, base:%uL", + "insert_count:%ui, sign:%ui, delta_base:%ui, base:%uL", st->insert_count, st->sign, st->delta_base, st->base); st->state = sw_start; @@ -479,7 +505,6 @@ ngx_int_t ngx_http_v3_parse_header_ri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, u_char ch) { - ngx_http_v3_header_t *h; enum { sw_start = 0, sw_index @@ -518,15 +543,14 @@ done: st->index = st->base - st->index - 1; } - h = ngx_http_v3_lookup_table(c, st->dynamic, st->index); - if (h == NULL) { + if (ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, + &st->value) + != NGX_OK) + { return NGX_ERROR; } - st->name = h->name; - st->value = h->value; st->state = sw_start; - return NGX_DONE; } @@ -535,8 +559,7 @@ ngx_int_t ngx_http_v3_parse_header_lri(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, u_char ch) { - ngx_int_t rc; - ngx_http_v3_header_t *h; + ngx_int_t rc; enum { sw_start = 0, sw_index, @@ -616,12 +639,12 @@ done: st->index = st->base - st->index - 1; } - h = ngx_http_v3_lookup_table(c, st->dynamic, st->index); - if (h == NULL) { + if (ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, NULL) + != NGX_OK) + { return NGX_ERROR; } - st->name = h->name; st->state = sw_start; return NGX_DONE; } @@ -735,7 +758,6 @@ ngx_int_t ngx_http_v3_parse_header_pbi(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, u_char ch) { - ngx_http_v3_header_t *h; enum { sw_start = 0, sw_index @@ -768,13 +790,13 @@ done: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header pbi done dynamic[+%ui]", st->index); - h = ngx_http_v3_lookup_table(c, 1, st->base + st->index); - if (h == NULL) { + if (ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, + &st->value) + != NGX_OK) + { return NGX_ERROR; } - st->name = h->name; - st->value = h->value; st->state = sw_start; return NGX_DONE; } @@ -784,8 +806,7 @@ ngx_int_t ngx_http_v3_parse_header_lpbi(ngx_connection_t *c, ngx_http_v3_parse_header_t *st, u_char ch) { - ngx_int_t rc; - ngx_http_v3_header_t *h; + ngx_int_t rc; enum { sw_start = 0, sw_index, @@ -860,17 +881,57 @@ done: "http3 parse header lpbi done dynamic[+%ui] \"%V\"", st->index, &st->value); - h = ngx_http_v3_lookup_table(c, 1, st->base + st->index); - if (h == NULL) { + if (ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, NULL) + != NGX_OK) + { return NGX_ERROR; } - st->name = h->name; st->state = sw_start; return NGX_DONE; } +static ngx_int_t +ngx_http_v3_parse_lookup(ngx_connection_t *c, ngx_uint_t dynamic, + ngx_uint_t index, ngx_str_t *name, ngx_str_t *value) +{ + u_char *p; + + if (!dynamic) { + return ngx_http_v3_lookup_static(c, index, name, value); + } + + if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) { + return NGX_ERROR; + } + + if (name) { + p = ngx_pnalloc(c->pool, name->len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, name->data, name->len); + p[name->len] = '\0'; + name->data = p; + } + + if (value) { + p = ngx_pnalloc(c->pool, value->len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, value->data, value->len); + p[value->len] = '\0'; + value->data = p; + } + + return NGX_OK; +} + + ngx_int_t ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch) { @@ -1145,7 +1206,7 @@ done: "http3 parse encoder instruction done"); st->state = sw_start; - return NGX_DONE; + return NGX_AGAIN; } @@ -1429,7 +1490,7 @@ done: "http3 parse decoder instruction done"); st->state = sw_start; - return NGX_DONE; + return NGX_AGAIN; }