# HG changeset patch # User Roman Arutyunyan <a...@nginx.com> # Date 1661169774 -14400 # Mon Aug 22 16:02:54 2022 +0400 # Branch quic # Node ID 6d444d4add98478c92a2ca84dde86005394ae0ea # Parent 923c0352912d80b224332c508379e047ec08dc4e QUIC: reusable mode for main connection.
The mode is controlled by application layer. For HTTP/3, it is enabled when there are no active request streams. diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -416,7 +416,7 @@ ngx_quic_input_handler(ngx_event_t *rev) if (c->close) { qc->error = NGX_QUIC_ERR_NO_ERROR; qc->error_reason = "graceful shutdown"; - ngx_quic_close_connection(c, NGX_OK); + ngx_quic_close_connection(c, NGX_ERROR); return; } diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c --- a/src/event/quic/ngx_event_quic_streams.c +++ b/src/event/quic/ngx_event_quic_streams.c @@ -161,13 +161,10 @@ ngx_quic_close_streams(ngx_connection_t ngx_pool_t *pool; ngx_queue_t *q; ngx_rbtree_t *tree; + ngx_connection_t *sc; ngx_rbtree_node_t *node; ngx_quic_stream_t *qs; -#if (NGX_DEBUG) - ngx_uint_t ns; -#endif - while (!ngx_queue_empty(&qc->streams.uninitialized)) { q = ngx_queue_head(&qc->streams.uninitialized); ngx_queue_remove(q); @@ -185,34 +182,31 @@ ngx_quic_close_streams(ngx_connection_t return NGX_OK; } -#if (NGX_DEBUG) - ns = 0; -#endif - node = ngx_rbtree_min(tree->root, tree->sentinel); while (node) { qs = (ngx_quic_stream_t *) node; node = ngx_rbtree_next(tree, node); + sc = qs->connection; - qs->recv_state = NGX_QUIC_STREAM_RECV_RESET_RECVD; - qs->send_state = NGX_QUIC_STREAM_SEND_RESET_SENT; - - if (qs->connection == NULL) { + if (sc == NULL) { ngx_quic_close_stream(qs); continue; } - ngx_quic_set_event(qs->connection->read); - ngx_quic_set_event(qs->connection->write); + ngx_quic_set_event(sc->read); + ngx_quic_set_event(sc->write); -#if (NGX_DEBUG) - ns++; -#endif + sc->close = 1; + sc->read->handler(sc->read); } - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic connection has %ui active streams", ns); + if (tree->root == tree->sentinel) { + return NGX_OK; + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic connection has active streams"); return NGX_AGAIN; } @@ -587,6 +581,7 @@ ngx_quic_create_stream(ngx_connection_t { ngx_log_t *log; ngx_pool_t *pool; + ngx_uint_t reusable; ngx_queue_t *q; ngx_connection_t *sc; ngx_quic_stream_t *qs; @@ -639,7 +634,13 @@ ngx_quic_create_stream(ngx_connection_t *log = *c->log; pool->log = log; + reusable = c->reusable; + ngx_reusable_connection(c, 0); + sc = ngx_get_connection(c->fd, log); + + ngx_reusable_connection(c, reusable); + if (sc == NULL) { ngx_destroy_pool(pool); ngx_queue_insert_tail(&qc->streams.free, &qs->queue); @@ -733,15 +734,22 @@ ngx_quic_empty_handler(ngx_event_t *ev) static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size) { - ssize_t len; - ngx_buf_t *b; - ngx_chain_t *cl, *in; - ngx_event_t *rev; - ngx_connection_t *pc; - ngx_quic_stream_t *qs; + ssize_t len; + ngx_buf_t *b; + ngx_chain_t *cl, *in; + ngx_event_t *rev; + ngx_connection_t *pc; + ngx_quic_stream_t *qs; + ngx_quic_connection_t *qc; qs = c->quic; pc = qs->parent; + qc = ngx_quic_get_connection(pc); + + if (qc->closing) { + return NGX_ERROR; + } + rev = c->read; if (qs->recv_state == NGX_QUIC_STREAM_RECV_RESET_RECVD @@ -807,8 +815,17 @@ ngx_quic_stream_recv(ngx_connection_t *c static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size) { - ngx_buf_t b; - ngx_chain_t cl; + ngx_buf_t b; + ngx_chain_t cl; + ngx_connection_t *pc; + ngx_quic_connection_t *qc; + + pc = c->quic->parent; + qc = ngx_quic_get_connection(pc); + + if (qc->closing) { + return NGX_ERROR; + } ngx_memzero(&b, sizeof(ngx_buf_t)); @@ -843,6 +860,11 @@ ngx_quic_stream_send_chain(ngx_connectio qs = c->quic; pc = qs->parent; qc = ngx_quic_get_connection(pc); + + if (qc->closing) { + return NGX_CHAIN_ERROR; + } + wev = c->write; if (qs->send_state != NGX_QUIC_STREAM_SEND_READY diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -258,7 +258,7 @@ ngx_http_v3_wait_request_handler(ngx_eve size_t size; ssize_t n; ngx_buf_t *b; - ngx_connection_t *c; + ngx_connection_t *c, *pc; ngx_pool_cleanup_t *cln; ngx_http_request_t *r; ngx_http_connection_t *hc; @@ -385,6 +385,9 @@ ngx_http_v3_wait_request_handler(ngx_eve h3c = ngx_http_v3_get_session(c); h3c->nrequests++; + pc = c->quic->parent; + ngx_reusable_connection(pc, 0); + if (h3c->keepalive.timer_set) { ngx_del_timer(&h3c->keepalive); } @@ -430,7 +433,7 @@ ngx_http_v3_cleanup_request(void *data) { ngx_http_request_t *r = data; - ngx_connection_t *c; + ngx_connection_t *c, *pc; ngx_http_v3_session_t *h3c; ngx_http_core_loc_conf_t *clcf; @@ -443,6 +446,9 @@ ngx_http_v3_cleanup_request(void *data) h3c = ngx_http_v3_get_session(c); if (--h3c->nrequests == 0) { + pc = c->quic->parent; + ngx_reusable_connection(pc, 1); + clcf = ngx_http_v3_get_module_loc_conf(c, ngx_http_core_module); ngx_add_timer(&h3c->keepalive, clcf->keepalive_timeout); } diff --git a/src/http/v3/ngx_http_v3_uni.c b/src/http/v3/ngx_http_v3_uni.c --- a/src/http/v3/ngx_http_v3_uni.c +++ b/src/http/v3/ngx_http_v3_uni.c @@ -182,6 +182,11 @@ ngx_http_v3_uni_read_handler(ngx_event_t ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); + if (c->close) { + ngx_http_v3_close_uni_stream(c); + return; + } + ngx_memzero(&b, sizeof(ngx_buf_t)); while (rev->ready) { @@ -262,6 +267,11 @@ ngx_http_v3_uni_dummy_read_handler(ngx_e ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy read handler"); + if (c->close) { + ngx_http_v3_close_uni_stream(c); + return; + } + if (rev->ready) { if (c->recv(c, &ch, 1) != 0) { ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, NULL); _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org