diff --git a/draft-ietf-quic-recovery.md b/draft-ietf-quic-recovery.md index f50e92c5b5..0e70a56f8a 100644 --- a/draft-ietf-quic-recovery.md +++ b/draft-ietf-quic-recovery.md @@ -588,10 +588,17 @@ However, the client MUST send a new packet to allow the server to continue sending data. At this stage in the connection, when few to none RTT samples have been generated, it is possible that the probe timer expiration is due to an incorrect RTT estimate at the client. To allow the client to improve its RTT -estimate, the new packet that it sends MUST be ack-eliciting. If Handshake -keys are available to the client, it MUST send a Handshake packet, and -otherwise it MUST send an Initial packet in a UDP datagram of at least 1200 -bytes. +estimate, the new packet that it sends MUST be ack-eliciting. If Handshake keys +are available to the client, it MUST send a Handshake packet, and otherwise +it MUST send an Initial packet in a UDP datagram of at least 1200 bytes. + +If the handshake is complete, but not confirmed (see Section 4.1.1 and Section +4.1.2 of {{QUIC-TLS}}), in addition to sending unacknowledged CRYPTO data in a +probe packet, endpoints SHOULD send an ack-eliciting 1-RTT packet. This can be +coalesced with Handshake packets, even if there is sufficient unacknowledged +CRYPTO data outstanding to consume the entire PMTU. Sending an ack-eliciting +1-RTT packet provides a peer with the opportunity to confirm the handshake and +allow all state associated with Handshake packets to be discarded. Initial packets and Handshake packets may never be acknowledged, but they are removed from bytes in flight when the Initial and Handshake keys are discarded. @@ -1227,13 +1234,15 @@ OnLossDetectionTimeout(): return if (endpoint is client without 1-RTT keys): - // Client sends an anti-deadlock packet: Initial is padded - // to earn more anti-amplification credit, - // a Handshake packet proves address ownership. - if (has Handshake keys): - SendOneAckElicitingHandshakePacket() + // Client sends an anti-deadlock packet. + if (has only Initial keys): + // Pad Initial to earn more anti-amplification credit. + SendAckElicitingPaddedInitialPacket() + else if (has 1-RTT keys): + // Send Handshake coalesced with 1-RTT. + SendAckElicitingHandshakeAnd1RttPackets() else: - SendOneAckElicitingPaddedInitialPacket() + SendAckElicitingHandshakePacket() else: // PTO. Send new data if available, else retransmit old data. // If neither is available, send a single PING frame. diff --git a/draft-ietf-quic-tls.md b/draft-ietf-quic-tls.md index 031b1e2170..6e5d46c61a 100644 --- a/draft-ietf-quic-tls.md +++ b/draft-ietf-quic-tls.md @@ -391,6 +391,15 @@ sent with 1-RTT keys, and the highest value of the Largest Acknowledged field in any received 1-RTT ACK frame: once the latter is higher than or equal to the former, the handshake is confirmed. +Note: + +: Unless ack-eliciting packets protected by 1-RTT keys are sent by an endpoint, + the handshake might never be confirmed by an endpoint. If the peer does + confirm the handshake, this could result in perpetual transmission of + Handshake packets, which cannot be acknowledged. To avoid this problem, in + addition to retransmitting Handshake packets, endpoints can send ack-eliciting + packets after the handshake is complete until the handshake is confirmed. + ### Sending and Receiving Handshake Messages