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