]> git.kaiwu.me - nginx.git/commitdiff
Refactored ngx_quic_close_connection().
authorVladimir Homutov <vl@nginx.com>
Thu, 23 Apr 2020 08:15:44 +0000 (11:15 +0300)
committerVladimir Homutov <vl@nginx.com>
Thu, 23 Apr 2020 08:15:44 +0000 (11:15 +0300)
The function is split into three:
    ngx_quic_close_connection() itself cleans up all core nginx things
    ngx_quic_close_quic()  deals with everything inside c->quic
    ngx_quic_close_streams() deals with streams cleanup

The quic and streams cleanup functions may return NGX_AGAIN, thus signalling
that cleanup is not ready yet, and the close cannot continue to next step.

src/event/ngx_event_quic.c

index 1965ed907115c79d142a82f6660f6cce756e2445..5ef9cf47e5e85d975d8faf84df517d874cea0967 100644 (file)
@@ -141,7 +141,11 @@ static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
     ngx_connection_handler_pt handler);
 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
 static void ngx_quic_input_handler(ngx_event_t *rev);
+
 static void ngx_quic_close_connection(ngx_connection_t *c);
+static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c);
+static ngx_int_t ngx_quic_close_streams(ngx_connection_t *c,
+    ngx_quic_connection_t *qc);
 
 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b);
 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c,
@@ -760,95 +764,118 @@ ngx_quic_input_handler(ngx_event_t *rev)
 static void
 ngx_quic_close_connection(ngx_connection_t *c)
 {
-#if (NGX_DEBUG)
-    ngx_uint_t              ns;
-#endif
-    ngx_uint_t              i;
-    ngx_pool_t             *pool;
-    ngx_event_t            *rev;
-    ngx_rbtree_t           *tree;
-    ngx_rbtree_node_t      *node;
-    ngx_quic_stream_t      *qs;
-    ngx_quic_connection_t  *qc;
+    ngx_pool_t  *pool;
 
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "close quic connection");
 
-    qc = c->quic;
-
-    if (qc) {
+    if (c->quic && ngx_quic_close_quic(c) == NGX_AGAIN) {
+        return;
+    }
 
-        qc->closing = 1;
-        tree = &qc->streams.tree;
+    if (c->ssl) {
+        (void) ngx_ssl_shutdown(c);
+    }
 
-        if (tree->root != tree->sentinel) {
-            if (c->read->timer_set) {
-                ngx_del_timer(c->read);
-            }
+    if (c->read->timer_set) {
+        ngx_del_timer(c->read);
+    }
 
-#if (NGX_DEBUG)
-            ns = 0;
+#if (NGX_STAT_STUB)
+    (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
 #endif
 
-            for (node = ngx_rbtree_min(tree->root, tree->sentinel);
-                 node;
-                 node = ngx_rbtree_next(tree, node))
-            {
-                qs = (ngx_quic_stream_t *) node;
+    c->destroyed = 1;
 
-                rev = qs->c->read;
-                rev->ready = 1;
-                rev->pending_eof = 1;
+    pool = c->pool;
 
-                ngx_post_event(rev, &ngx_posted_events);
+    ngx_close_connection(c);
 
-                if (rev->timer_set) {
-                    ngx_del_timer(rev);
-                }
+    ngx_destroy_pool(pool);
+}
 
-#if (NGX_DEBUG)
-                ns++;
-#endif
-            }
 
-            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                           "quic connection has %ui active streams", ns);
+static ngx_int_t
+ngx_quic_close_quic(ngx_connection_t *c)
+{
+    ngx_uint_t              i;
+    ngx_quic_connection_t  *qc;
 
-            return;
-        }
+    qc = c->quic;
 
-        for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
-            ngx_quic_free_frames(c, &qc->crypto[i].frames);
-        }
+    qc->closing = 1;
 
-        for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
-            ngx_quic_free_frames(c, &qc->send_ctx[i].frames);
-            ngx_quic_free_frames(c, &qc->send_ctx[i].sent);
-        }
+    if (ngx_quic_close_streams(c, qc) == NGX_AGAIN) {
+        return NGX_AGAIN;
+    }
 
-        if (qc->push.timer_set) {
-            ngx_del_timer(&qc->push);
-        }
+    for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
+        ngx_quic_free_frames(c, &qc->crypto[i].frames);
+    }
 
-        if (qc->retry.timer_set) {
-            ngx_del_timer(&qc->retry);
-        }
+    for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
+        ngx_quic_free_frames(c, &qc->send_ctx[i].frames);
+        ngx_quic_free_frames(c, &qc->send_ctx[i].sent);
     }
 
-    if (c->ssl) {
-        (void) ngx_ssl_shutdown(c);
+    if (qc->push.timer_set) {
+        ngx_del_timer(&qc->push);
     }
 
-#if (NGX_STAT_STUB)
-    (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
+    if (qc->retry.timer_set) {
+        ngx_del_timer(&qc->retry);
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc)
+{
+    ngx_event_t        *rev;
+    ngx_rbtree_t       *tree;
+    ngx_rbtree_node_t  *node;
+    ngx_quic_stream_t  *qs;
+
+#if (NGX_DEBUG)
+    ngx_uint_t          ns;
 #endif
 
-    c->destroyed = 1;
+    tree = &qc->streams.tree;
 
-    pool = c->pool;
+    if (tree->root == tree->sentinel) {
+        return NGX_OK;
+    }
 
-    ngx_close_connection(c);
+#if (NGX_DEBUG)
+    ns = 0;
+#endif
 
-    ngx_destroy_pool(pool);
+    for (node = ngx_rbtree_min(tree->root, tree->sentinel);
+         node;
+         node = ngx_rbtree_next(tree, node))
+    {
+        qs = (ngx_quic_stream_t *) node;
+
+        rev = qs->c->read;
+        rev->ready = 1;
+        rev->pending_eof = 1;
+
+        ngx_post_event(rev, &ngx_posted_events);
+
+        if (rev->timer_set) {
+            ngx_del_timer(rev);
+        }
+
+#if (NGX_DEBUG)
+        ns++;
+#endif
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "quic connection has %ui active streams", ns);
+
+    return NGX_AGAIN;
 }