Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 9156:36b59521a41c
QUIC: refined sending CONNECTION_CLOSE in various packet types.
As per RFC 9000, section 10.2.3, to ensure that peer successfully removed
packet protection, CONNECTION_CLOSE can be sent in multiple packets using
different packet protection levels.
Now it is sent in all protection levels available.
This roughly corresponds to the following paragraph:
* Prior to confirming the handshake, a peer might be unable to process 1-RTT
packets, so an endpoint SHOULD send a CONNECTION_CLOSE frame in both Handshake
and 1-RTT packets. A server SHOULD also send a CONNECTION_CLOSE frame in an
Initial packet.
In practice, this change allows to avoid sending an Initial packet when we know
the client has handshake keys, by checking if we have discarded initial keys.
Also, this fixes sending CONNECTION_CLOSE when using QuicTLS with old QUIC API,
where TLS stack releases application read keys before handshake confirmation;
it is fixed by sending CONNECTION_CLOSE additionally in a Handshake packet.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 01 Sep 2023 20:31:46 +0400 |
parents | 8f7e6d8c061e |
children | daf8f5ba23d8 |
comparison
equal
deleted
inserted
replaced
9155:35bb47f65cab | 9156:36b59521a41c |
---|---|
507 * | 507 * |
508 * An endpoint sends a CONNECTION_CLOSE frame (Section 19.19) | 508 * An endpoint sends a CONNECTION_CLOSE frame (Section 19.19) |
509 * to terminate the connection immediately. | 509 * to terminate the connection immediately. |
510 */ | 510 */ |
511 | 511 |
512 qc->error_level = c->ssl ? SSL_quic_read_level(c->ssl->connection) | |
513 : ssl_encryption_initial; | |
514 | |
515 if (qc->error == (ngx_uint_t) -1) { | 512 if (qc->error == (ngx_uint_t) -1) { |
516 qc->error = NGX_QUIC_ERR_INTERNAL_ERROR; | 513 qc->error = NGX_QUIC_ERR_INTERNAL_ERROR; |
517 qc->error_app = 0; | 514 qc->error_app = 0; |
518 } | 515 } |
519 | 516 |
522 "%serror:%ui \"%s\"", | 519 "%serror:%ui \"%s\"", |
523 rc == NGX_ERROR ? 1 : 0, qc->draining, | 520 rc == NGX_ERROR ? 1 : 0, qc->draining, |
524 qc->error_app ? "app " : "", qc->error, | 521 qc->error_app ? "app " : "", qc->error, |
525 qc->error_reason ? qc->error_reason : ""); | 522 qc->error_reason ? qc->error_reason : ""); |
526 | 523 |
527 if (rc == NGX_OK) { | 524 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { |
528 ctx = ngx_quic_get_send_ctx(qc, qc->error_level); | 525 ctx = &qc->send_ctx[i]; |
529 ngx_add_timer(&qc->close, 3 * ngx_quic_pto(c, ctx)); | 526 |
530 } | 527 if (!ngx_quic_keys_available(qc->keys, ctx->level)) { |
531 | 528 continue; |
532 (void) ngx_quic_send_cc(c); | 529 } |
533 | 530 |
534 if (qc->error_level == ssl_encryption_handshake) { | 531 qc->error_level = ctx->level; |
535 /* for clients that might not have handshake keys */ | |
536 qc->error_level = ssl_encryption_initial; | |
537 (void) ngx_quic_send_cc(c); | 532 (void) ngx_quic_send_cc(c); |
533 | |
534 if (rc == NGX_OK && !qc->close.timer_set) { | |
535 ngx_add_timer(&qc->close, 3 * ngx_quic_pto(c, ctx)); | |
536 } | |
538 } | 537 } |
539 } | 538 } |
540 | 539 |
541 qc->closing = 1; | 540 qc->closing = 1; |
542 } | 541 } |