Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8281:618a65de08b3 quic
When closing a QUIC connection, wait for all streams to finish.
Additionally, streams are now removed from the tree in cleanup handler.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 24 Mar 2020 18:05:45 +0300 |
parents | b364af7f9f3f |
children | 4cf00c14f11a |
comparison
equal
deleted
inserted
replaced
8280:b364af7f9f3f | 8281:618a65de08b3 |
---|---|
48 ngx_ssl_t *ssl; | 48 ngx_ssl_t *ssl; |
49 ngx_quic_frame_t *frames; | 49 ngx_quic_frame_t *frames; |
50 | 50 |
51 ngx_quic_streams_t streams; | 51 ngx_quic_streams_t streams; |
52 ngx_uint_t max_data; | 52 ngx_uint_t max_data; |
53 ngx_uint_t send_timer_set; | 53 |
54 /* unsigned send_timer_set:1 */ | 54 unsigned send_timer_set:1; |
55 unsigned closing:1; | |
55 | 56 |
56 #define SSL_ECRYPTION_LAST ((ssl_encryption_application) + 1) | 57 #define SSL_ECRYPTION_LAST ((ssl_encryption_application) + 1) |
57 uint64_t crypto_offset[SSL_ECRYPTION_LAST]; | 58 uint64_t crypto_offset[SSL_ECRYPTION_LAST]; |
58 }; | 59 }; |
59 | 60 |
306 ngx_connection_t *c; | 307 ngx_connection_t *c; |
307 ngx_quic_frame_t *frame; | 308 ngx_quic_frame_t *frame; |
308 | 309 |
309 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); | 310 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); |
310 | 311 |
312 if (c->quic->closing) { | |
313 return 1; | |
314 } | |
315 | |
311 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 316 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
312 "ngx_quic_send_alert(), lvl=%d, alert=%d", | 317 "ngx_quic_send_alert(), lvl=%d, alert=%d", |
313 (int) level, (int) alert); | 318 (int) level, (int) alert); |
314 | 319 |
315 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); | 320 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); |
534 b.start = buf; | 539 b.start = buf; |
535 b.end = buf + sizeof(buf); | 540 b.end = buf + sizeof(buf); |
536 b.pos = b.last = b.start; | 541 b.pos = b.last = b.start; |
537 | 542 |
538 c = rev->data; | 543 c = rev->data; |
544 qc = c->quic; | |
539 | 545 |
540 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "quic input handler"); | 546 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "quic input handler"); |
547 | |
548 if (qc->closing) { | |
549 ngx_quic_close_connection(c); | |
550 return; | |
551 } | |
541 | 552 |
542 if (rev->timedout) { | 553 if (rev->timedout) { |
543 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | 554 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); |
544 ngx_quic_close_connection(c); | 555 ngx_quic_close_connection(c); |
545 return; | 556 return; |
567 if (ngx_quic_input(c, &b) != NGX_OK) { | 578 if (ngx_quic_input(c, &b) != NGX_OK) { |
568 ngx_quic_close_connection(c); | 579 ngx_quic_close_connection(c); |
569 return; | 580 return; |
570 } | 581 } |
571 | 582 |
572 qc = c->quic; | |
573 | |
574 qc->send_timer_set = 0; | 583 qc->send_timer_set = 0; |
575 ngx_add_timer(rev, qc->tp.max_idle_timeout); | 584 ngx_add_timer(rev, qc->tp.max_idle_timeout); |
576 } | 585 } |
577 | 586 |
578 | 587 |
579 static void | 588 static void |
580 ngx_quic_close_connection(ngx_connection_t *c) | 589 ngx_quic_close_connection(ngx_connection_t *c) |
581 { | 590 { |
582 ngx_pool_t *pool; | 591 #if (NGX_DEBUG) |
583 | 592 ngx_uint_t ns; |
584 /* XXX wait for all streams to close */ | 593 #endif |
585 | 594 ngx_pool_t *pool; |
586 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 595 ngx_event_t *rev; |
587 "close quic connection: %d", c->fd); | 596 ngx_rbtree_t *tree; |
597 ngx_rbtree_node_t *node; | |
598 ngx_quic_stream_t *qs; | |
599 ngx_quic_connection_t *qc; | |
600 | |
601 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "close quic connection"); | |
602 | |
603 qc = c->quic; | |
604 | |
605 if (qc) { | |
606 tree = &qc->streams.tree; | |
607 | |
608 if (tree->root != tree->sentinel) { | |
609 if (c->read->timer_set) { | |
610 ngx_del_timer(c->read); | |
611 } | |
612 | |
613 #if (NGX_DEBUG) | |
614 ns = 0; | |
615 #endif | |
616 | |
617 for (node = ngx_rbtree_min(tree->root, tree->sentinel); | |
618 node; | |
619 node = ngx_rbtree_next(tree, node)) | |
620 { | |
621 qs = (ngx_quic_stream_t *) node; | |
622 | |
623 rev = qs->c->read; | |
624 rev->ready = 1; | |
625 rev->pending_eof = 1; | |
626 | |
627 ngx_post_event(rev, &ngx_posted_events); | |
628 | |
629 #if (NGX_DEBUG) | |
630 ns++; | |
631 #endif | |
632 } | |
633 | |
634 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
635 "quic connection has %ui active streams", ns); | |
636 | |
637 qc->closing = 1; | |
638 return; | |
639 } | |
640 } | |
588 | 641 |
589 if (c->ssl) { | 642 if (c->ssl) { |
590 (void) ngx_ssl_shutdown(c); | 643 (void) ngx_ssl_shutdown(c); |
591 } | 644 } |
592 | 645 |
1585 ngx_connection_t *pc; | 1638 ngx_connection_t *pc; |
1586 ngx_quic_frame_t *frame; | 1639 ngx_quic_frame_t *frame; |
1587 ngx_quic_stream_t *qs; | 1640 ngx_quic_stream_t *qs; |
1588 ngx_quic_connection_t *qc; | 1641 ngx_quic_connection_t *qc; |
1589 | 1642 |
1590 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size); | |
1591 | |
1592 qs = c->qs; | 1643 qs = c->qs; |
1593 pc = qs->parent; | 1644 pc = qs->parent; |
1594 qc = pc->quic; | 1645 qc = pc->quic; |
1646 | |
1647 if (qc->closing) { | |
1648 return NGX_ERROR; | |
1649 } | |
1650 | |
1651 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size); | |
1595 | 1652 |
1596 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t)); | 1653 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t)); |
1597 if (frame == NULL) { | 1654 if (frame == NULL) { |
1598 return 0; | 1655 return 0; |
1599 } | 1656 } |
1640 | 1697 |
1641 qs = c->qs; | 1698 qs = c->qs; |
1642 pc = qs->parent; | 1699 pc = qs->parent; |
1643 qc = pc->quic; | 1700 qc = pc->quic; |
1644 | 1701 |
1702 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic stream cleanup"); | |
1703 | |
1704 ngx_rbtree_delete(&qc->streams.tree, &qs->node); | |
1705 | |
1706 if (qc->closing) { | |
1707 ngx_post_event(pc->read, &ngx_posted_events); | |
1708 return; | |
1709 } | |
1710 | |
1645 if ((qs->id & 0x03) == NGX_QUIC_STREAM_UNIDIRECTIONAL) { | 1711 if ((qs->id & 0x03) == NGX_QUIC_STREAM_UNIDIRECTIONAL) { |
1646 /* do not send fin for client unidirectional streams */ | 1712 /* do not send fin for client unidirectional streams */ |
1647 return; | 1713 return; |
1648 } | 1714 } |
1649 | 1715 |