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.
This commit is contained in:
Vladimir Homutov 2020-04-23 11:15:44 +03:00
parent 37b95d545c
commit c8edca3137

View 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,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
@ -852,6 +794,91 @@ ngx_quic_close_connection(ngx_connection_t *c)
}
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)
{