diff --git a/src/http/v3/ngx_http_v3.c b/src/http/v3/ngx_http_v3.c index 29b07e025..84bb8f601 100644 --- a/src/http/v3/ngx_http_v3.c +++ b/src/http/v3/ngx_http_v3.c @@ -47,6 +47,10 @@ ngx_http_v3_init_session(ngx_connection_t *c) h3c->keepalive.handler = ngx_http_v3_keepalive_handler; h3c->keepalive.cancelable = 1; + h3c->table.send_insert_count.log = pc->log; + h3c->table.send_insert_count.data = pc; + h3c->table.send_insert_count.handler = ngx_http_v3_inc_insert_count_handler; + cln = ngx_pool_cleanup_add(pc->pool, 0); if (cln == NULL) { goto failed; @@ -93,6 +97,10 @@ ngx_http_v3_cleanup_session(void *data) if (h3c->keepalive.timer_set) { ngx_del_timer(&h3c->keepalive); } + + if (h3c->table.send_insert_count.posted) { + ngx_delete_posted_event(&h3c->table.send_insert_count); + } } diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c index 25c1edf6d..cd70bd3bf 100644 --- a/src/http/v3/ngx_http_v3_parse.c +++ b/src/http/v3/ngx_http_v3_parse.c @@ -395,6 +395,8 @@ done: if (ngx_http_v3_send_ack_section(c, c->quic->id) != NGX_OK) { return NGX_ERROR; } + + ngx_http_v3_ack_insert_count(c, st->prefix.insert_count); } st->state = sw_start; diff --git a/src/http/v3/ngx_http_v3_table.c b/src/http/v3/ngx_http_v3_table.c index c6d543ac4..22dc37901 100644 --- a/src/http/v3/ngx_http_v3_table.c +++ b/src/http/v3/ngx_http_v3_table.c @@ -232,11 +232,9 @@ ngx_http_v3_insert(ngx_connection_t *c, ngx_str_t *name, ngx_str_t *value) dt->elts[dt->nelts++] = field; dt->size += size; - /* TODO increment can be sent less often */ + dt->insert_count++; - if (ngx_http_v3_send_inc_insert_count(c, 1) != NGX_OK) { - return NGX_ERROR; - } + ngx_post_event(&dt->send_insert_count, &ngx_posted_events); if (ngx_http_v3_new_entry(c) != NGX_OK) { return NGX_ERROR; @@ -246,6 +244,34 @@ ngx_http_v3_insert(ngx_connection_t *c, ngx_str_t *name, ngx_str_t *value) } +void +ngx_http_v3_inc_insert_count_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_v3_session_t *h3c; + ngx_http_v3_dynamic_table_t *dt; + + c = ev->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http3 inc insert count handler"); + + h3c = ngx_http_v3_get_session(c); + dt = &h3c->table; + + if (dt->insert_count > dt->ack_insert_count) { + if (ngx_http_v3_send_inc_insert_count(c, + dt->insert_count - dt->ack_insert_count) + != NGX_OK) + { + return; + } + + dt->ack_insert_count = dt->insert_count; + } +} + + ngx_int_t ngx_http_v3_set_capacity(ngx_connection_t *c, ngx_uint_t capacity) { @@ -607,6 +633,21 @@ ngx_http_v3_check_insert_count(ngx_connection_t *c, ngx_uint_t insert_count) } +void +ngx_http_v3_ack_insert_count(ngx_connection_t *c, uint64_t insert_count) +{ + ngx_http_v3_session_t *h3c; + ngx_http_v3_dynamic_table_t *dt; + + h3c = ngx_http_v3_get_session(c); + dt = &h3c->table; + + if (dt->ack_insert_count < insert_count) { + dt->ack_insert_count = insert_count; + } +} + + static void ngx_http_v3_unblock(void *data) { diff --git a/src/http/v3/ngx_http_v3_table.h b/src/http/v3/ngx_http_v3_table.h index 6f88b35b9..1c2fb17b9 100644 --- a/src/http/v3/ngx_http_v3_table.h +++ b/src/http/v3/ngx_http_v3_table.h @@ -26,9 +26,13 @@ typedef struct { ngx_uint_t base; size_t size; size_t capacity; + uint64_t insert_count; + uint64_t ack_insert_count; + ngx_event_t send_insert_count; } ngx_http_v3_dynamic_table_t; +void ngx_http_v3_inc_insert_count_handler(ngx_event_t *ev); void ngx_http_v3_cleanup_table(ngx_http_v3_session_t *h3c); ngx_int_t ngx_http_v3_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *value); @@ -46,6 +50,7 @@ ngx_int_t ngx_http_v3_decode_insert_count(ngx_connection_t *c, ngx_uint_t *insert_count); ngx_int_t ngx_http_v3_check_insert_count(ngx_connection_t *c, ngx_uint_t insert_count); +void ngx_http_v3_ack_insert_count(ngx_connection_t *c, uint64_t insert_count); ngx_int_t ngx_http_v3_set_param(ngx_connection_t *c, uint64_t id, uint64_t value);