# HG changeset patch # User Vladimir Homutov # Date 1590160475 -10800 # Node ID d96ddef458cd02f85bdf7805bd7495c9f43bf3c3 # Parent ffd362e87eb2ede6cccb224dd90e5c1ccdbfb1f4 Added sending of extra CONNECTION_CLOSE frames. According to quic-transport draft 28 section 10.3.1: When sending CONNECTION_CLOSE, the goal is to ensure that the peer will process the frame. Generally, this means sending the frame in a packet with the highest level of packet protection to avoid the packet being discarded. After the handshake is confirmed (see Section 4.1.2 of [QUIC-TLS]), an endpoint MUST send any CONNECTION_CLOSE frames in a 1-RTT packet. However, prior to confirming the handshake, it is possible that more advanced packet protection keys are not available to the peer, so another CONNECTION_CLOSE frame MAY be sent in a packet that uses a lower packet protection level. diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c --- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -1189,34 +1189,7 @@ ngx_quic_close_quic(ngx_connection_t *c, ngx_quic_free_frames(c, &ctx->sent); } - level = (qc->state == ssl_encryption_early_data) - ? ssl_encryption_application - : qc->state; - - if (rc == NGX_OK) { - - /* - * 10.3. Immediate Close - * - * An endpoint sends a CONNECTION_CLOSE frame (Section 19.19) to - * terminate the connection immediately. - */ - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic immediate close, drain = %d", qc->draining); - - if (ngx_quic_send_cc(c, level, NGX_QUIC_ERR_NO_ERROR, 0, NULL) - == NGX_OK) - { - - qc->close.log = c->log; - qc->close.data = c; - qc->close.handler = ngx_quic_close_timer_handler; - qc->close.cancelable = 1; - - ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO); - } - - } else if (rc == NGX_DONE) { + if (rc == NGX_DONE) { /* * 10.2. Idle Timeout @@ -1230,13 +1203,49 @@ ngx_quic_close_quic(ngx_connection_t *c, qc->draining ? "drained" : "idle"); } else { - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic immediate close due to fatal error: %ui", - qc->error); - - err = qc->error ? qc->error : NGX_QUIC_ERR_INTERNAL_ERROR; + + /* + * 10.3. Immediate Close + * + * An endpoint sends a CONNECTION_CLOSE frame (Section 19.19) + * to terminate the connection immediately. + */ + + if (rc == NGX_OK) { + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic immediate close, drain = %d", + qc->draining); + + qc->close.log = c->log; + qc->close.data = c; + qc->close.handler = ngx_quic_close_timer_handler; + qc->close.cancelable = 1; + + ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO); + + err = NGX_QUIC_ERR_NO_ERROR; + + } else { + err = qc->error ? qc->error : NGX_QUIC_ERR_INTERNAL_ERROR; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic immediate close due to error: %ui %s", + qc->error, + qc->error_reason ? qc->error_reason : ""); + } + + level = (qc->state == ssl_encryption_early_data) + ? ssl_encryption_handshake + : qc->state; + (void) ngx_quic_send_cc(c, level, err, qc->error_ftype, qc->error_reason); + + if (level == ssl_encryption_handshake) { + /* for clients that might not have handshake keys */ + (void) ngx_quic_send_cc(c, ssl_encryption_initial, err, + qc->error_ftype, qc->error_reason); + } } qc->closing = 1;