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.
This commit is contained in:
Vladimir Homutov 2020-05-22 18:14:35 +03:00
parent 76605fa07a
commit 57696b56e9

View File

@ -1189,34 +1189,7 @@ ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
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, ngx_int_t rc)
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;