changeset 8354:d11bc25fc4c3 quic

Refactored ngx_quic_close_connection(). 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.
author Vladimir Homutov <vl@nginx.com>
date Thu, 23 Apr 2020 11:15:44 +0300
parents 036164360fa9
children ad3a6f069498
files src/event/ngx_event_quic.c
diffstat 1 files changed, 96 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -141,7 +141,11 @@ static ngx_int_t ngx_quic_new_connection
     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,84 +764,22 @@ 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) {
-
-        qc->closing = 1;
-        tree = &qc->streams.tree;
-
-        if (tree->root != tree->sentinel) {
-            if (c->read->timer_set) {
-                ngx_del_timer(c->read);
-            }
-
-#if (NGX_DEBUG)
-            ns = 0;
-#endif
-
-            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;
-        }
-
-        for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
-            ngx_quic_free_frames(c, &qc->crypto[i].frames);
-        }
-
-        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 (qc->push.timer_set) {
-            ngx_del_timer(&qc->push);
-        }
-
-        if (qc->retry.timer_set) {
-            ngx_del_timer(&qc->retry);
-        }
+    if (c->quic && ngx_quic_close_quic(c) == NGX_AGAIN) {
+        return;
     }
 
     if (c->ssl) {
         (void) ngx_ssl_shutdown(c);
     }
 
+    if (c->read->timer_set) {
+        ngx_del_timer(c->read);
+    }
+
 #if (NGX_STAT_STUB)
     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
 #endif
@@ -853,6 +795,91 @@ ngx_quic_close_connection(ngx_connection
 
 
 static ngx_int_t
+ngx_quic_close_quic(ngx_connection_t *c)
+{
+    ngx_uint_t              i;
+    ngx_quic_connection_t  *qc;
+
+    qc = c->quic;
+
+    qc->closing = 1;
+
+    if (ngx_quic_close_streams(c, qc) == NGX_AGAIN) {
+        return NGX_AGAIN;
+    }
+
+    for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
+        ngx_quic_free_frames(c, &qc->crypto[i].frames);
+    }
+
+    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 (qc->push.timer_set) {
+        ngx_del_timer(&qc->push);
+    }
+
+    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
+
+    tree = &qc->streams.tree;
+
+    if (tree->root == tree->sentinel) {
+        return NGX_OK;
+    }
+
+#if (NGX_DEBUG)
+    ns = 0;
+#endif
+
+    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;
+}
+
+
+static ngx_int_t
 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b)
 {
     u_char             *p;