jiebi/TextFlow huggingface dataset:
Original text:
6.4. <del> Recovery is a period of time beginning with detection of a lost packet or an increase in the ECN-CE counter.  Because QUIC does not retransmit packets, it defines the end of recovery as a packet sent after the start of recovery being acknowledged.  This is slightly different from TCP's definition of recovery, which ends when the lost packet that started recovery is acknowledged. </del>  The recovery period limits congestion window reduction to once per round trip.  During recovery, the congestion window remains unchanged

Reviewer comments:
I'm happy to merge this as is, but I'll give it 24hrs in case others have comments.
This is weird in that it assumes some context that isn't provided: Perhaps instead: This "Because QUIC does not retransmit packets" thing is unnecessary. I'll open a PR.

Revised text:
6.4.  <ins> A recovery period is entered when loss or ECN-CE marking of a packet is detected.  A recovery period ends when a packet sent during the recovery period is acknowledged.  This is slightly different from TCP's definition of recovery, which ends when the lost packet that started recovery is acknowledged. </ins> The recovery period limits congestion window reduction to once per round trip.  During recovery, the congestion window remains unchanged
Original text:
HTTP/3 can either rely on transport-layer padding or employ the reserved frame and stream types discussed in frame-reserved and stream-grease.  These methods of padding produce different results in <del> terms of the granularity of padding, the effect of packet loss and recovery, and how an implementation might control padding. </del>  10.2.

Reviewer comments:
This text was pretty good and more or less covered the problem already, but I think that this might be slightly better. NAME if you don't like this, close this AND .
From a discussion on : We should probably have a conversation about the trade-offs with padding. Transport-layer padding is in some ways superior, like in how it can be granular to a single byte, which reserved streams and frames cannot do. But PADDING frames at the transport aren't retransmitted when lost, which could lead to some interesting attacks if packets can be suppressed by an attacker. If retransmissions aren't padded, boom. Originally posted by NAME in URL

Revised text:
HTTP/3 can either rely on transport-layer padding or employ the reserved frame and stream types discussed in frame-reserved and stream-grease.  These methods of padding produce different results in  <ins> terms of the granularity of padding, how padding is arranged in relation to the information that is being protected, whether padding is applied in the case of packet loss, and how an implementation might control padding. </ins> 10.2.
Original text:
receive one or more extension frame types with the one transport parameter.  Extension frames MUST be congestion controlled and MUST cause an ACK frame to be sent.  The exception is extension frames that replace or supplement the ACK frame.  Extension frames are not included in flow

Reviewer comments:
The SHOULD is guidance for future extensions; if we'd like to downgrade that to non-normative, that's also fine.
I'm going to merge this.
Resolution of was to have no design change, but consider a "here be dragons" warning in the extension section paralleling what was added to HTTP/3 in . (The reasons, and therefore the guidance, are different at the transport layer -- we can't directly steal the text.)

Revised text:
receive one or more extension frame types with the one transport parameter. <ins> Extensions that modify or replace core protocol functionality (including frame types) will be difficult to combine with other extensions which modify or replace the same functionality unless the behavior of the combination is explicitly defined.  Such extensions SHOULD define their interaction with previously-defined extensions modifying the same protocol components. </ins> Extension frames MUST be congestion controlled and MUST cause an ACK frame to be sent.  The exception is extension frames that replace or supplement the ACK frame.  Extension frames are not included in flow
Original text:
An HTTP/3 implementation can immediately close the QUIC connection at any time.  This results in sending a QUIC CONNECTION_CLOSE frame to <del> the peer; the error code in this frame indicates to the peer why the connection is being closed.  See errors for error codes which can be used when closing a connection. </del>  Before closing the connection, a GOAWAY MAY be sent to allow the client to retry some requests.  Including the GOAWAY frame in the

Reviewer comments:
This goes most of the way to solving my perceived problem. I do wonder if we should also add a little bit more text to section 8 in this paragraph under certain circumstances. Implementations need to consider the impact on outstanding requests before making this choice. Perhaps just a reference e.g. "Implementations need to consider the impact on outstanding requests before making this choice, see {immediate-application-closure}."
But that section doesn't discuss the impact on outstanding requests, and it seems irrelevant to this topic. Can you expand on the connection you see?
to me, the choice to promote a stream error to a connection error is the choice to promote it to an immediate application close. Therefore the present statement about "impact on outstanding requests" is really about how to do/decide on graceful close with GOAWAY. If that is not the case, then I don't understand what other consierations my endpoint should make
That text was added as a compromise, basically reminding implementations that choosing to blow up their connection will lose any requests in flight, so you should have a good reason.
NAME I'm going to go ahead and merge this, since it addresses the original issue and stands by itself. If you think we need additional text elsewhere, can you open a separate issue?
Sure thing, I'll review again
Draft 25 section 5.3 says: any time. This results in sending a QUIC CONNECTIONCLOSE frame to the peer; the error code in this frame indicates to the peer why the connection is being closed. This doesn't specifically tie down H3-initiated closure to only use the application variant of CONNECTIONCLOSE (0x1d). This gets a bit strange when combined with later guidance to use H3 error codes or treat unknown error codes as

Revised text:
An HTTP/3 implementation can immediately close the QUIC connection at any time.  This results in sending a QUIC CONNECTION_CLOSE frame to  <ins> the peer indicating that the application layer has terminated the connection.  The application error code in this frame indicates to the peer why the connection is being closed.  See errors for error codes which can be used when closing a connection in HTTP/3. </ins> Before closing the connection, a GOAWAY MAY be sent to allow the client to retry some requests.  Including the GOAWAY frame in the
Original text:
An endpoint restarts its idle timer when a packet from its peer is received and processed successfully.  The idle timer is also <del> restarted when sending an ack-eliciting packet (see QUIC-RECOVERY), but only if no other ack-eliciting packets have been sent since last receiving a packet.  Restarting when sending packets ensures that connections do not prematurely time out when initiating new activity. An endpoint might need to send packets to avoid an idle timeout if it is unable to send application data due to being blocked on flow control limits; see flow-control. </del>  An endpoint that sends packets near the end of the idle timeout period risks having those packets discarded if its peer enters the draining state before the packets arrive.  If a peer could time out within a Probe Timeout (PTO; see Section 6.6 of QUIC-RECOVERY), it is <del> advisable to test for liveness before sending any data that cannot be retried safely.  Note that it is likely that only applications or application protocols will know what information can be retried. </del>  10.3.

Reviewer comments:
From NAME and NAME comments on
In I received a number of comments on the existing text from NAME and NAME . This is an issue to track improving that text in a separate PR. One suggestion was to introduce an ITO(Idle Timeout) acronym.
NAME thinks cognitive load is increased by ITO and it's not that much shorter, so let's not do that.

Revised text:
An endpoint restarts its idle timer when a packet from its peer is received and processed successfully.  The idle timer is also  <ins> restarted when sending the first ack-eliciting packet (see QUIC- RECOVERY) after receiving a packet.  Restarting when sending packets ensures that connections do not prematurely time out when initiating new activity.  Only restarting when sending after receipt of a packet ensures the idle timeout is not excessively lengthened past the time the peer's timeout has expired.  An endpoint might need to send packets to avoid an idle timeout if it is unable to send application data due to being blocked on flow control limits; see flow-control. </ins> An endpoint that sends packets near the end of the idle timeout period risks having those packets discarded if its peer enters the draining state before the packets arrive.  If a peer could time out within a Probe Timeout (PTO; see Section 6.6 of QUIC-RECOVERY), it is  <ins> advisable to probe the path with an ack-eliciting packet to ensure the connection is still responsive before sending any data that cannot be retried safely.  Note that it is likely that only applications or application protocols will know what information can be retried. </ins> 10.3.
Original text:
2.1.4.  The Known Received Count is the total number of dynamic table insertions and duplications acknowledged by the decoder.  The encoder tracks the Known Received Count in order to identify which dynamic

Reviewer comments:
Much belated, this attempts to address the concerns about deadlocking. Basically, this says that you should avoid instructions that don't have flow control credit. It doesn't say how an encoder might learn what limits are, but we've seen a range of tactics being used in implementations and I don't want to get into transport API debates. This doesn't cover the memory exhaustion attack that NAME suggests on the issue; I think that is better covered more generally by the connection-level flow control limits.
I debated adding another paragraph:
Thanks for adding this!

Revised text:
2.1.4. <ins> Writing instructions on streams that are limited by flow control can produce deadlocks. A decoder might stop issuing flow control credit on the stream that carries a header block until the necessary updates are received on the encoder stream.  If the granting of flow control credit on the encoder stream (or the connection as a whole) depends on the consumption and release of data on the stream carrying the header block, a deadlock might result. More generally, a stream containing a large instruction can become deadlocked if the decoder withholds flow control credit until the instruction is completely received. To avoid these deadlocks, an encoder SHOULD avoid writing an instruction unless sufficient stream and connection flow control credit is available for the entire instruction. 2.1.5. </ins> The Known Received Count is the total number of dynamic table insertions and duplications acknowledged by the decoder.  The encoder tracks the Known Received Count in order to identify which dynamic
Original text:
estimate (4*rttvar), and max_ack_delay, to account for the maximum time by which a receiver might delay sending an acknowledgement. When the PTO is armed for Initial or Handshake packet number spaces, <del> the max_ack_delay is 0, as specified in 13.2.5 of QUIC-TRANSPORT. </del>  The PTO value MUST be set to at least kGranularity, to avoid the timer expiring immediately.

Reviewer comments:
In recovery for maxackdelay of 0.
Section 5.2.1 of -recovery-25 says: However, Section 13.2.5 of -transport-25 doesn't actually say that (anymore?) Section 13.2.1 says so I guess at least the reference is incorrect. But since Section 19.3 only has a SHOULD for encoding zero and the pseudo code simply uses the encoded ACK delay, if the ACK sender doesn't encode zero, the ACK receiver will compute its RTT based on the encoded ACK delay.
The intent is to use 0 as a peer maxackdelay for the Initial and Handshake packet number spaces. The pseudocode says: ackdelay = min(Ack Delay in ACK Frame, maxack_delay) So for Initial and Handshake, min(Ack Delay, 0) = 0 The text in the "Estimating smoothed RTT and RTTVar" section is fairly clear I think? I fixed the section reference in
I understood the in the to be the value of the transport parameter?
Not for Initial and Handshake PN spaces. Would it be helpful to have a comment above the min() in the pseudocode?
That would at least help me (pointing out it is NOT the value of the TP, although the name is the same.)
I noticed the pseudocode before UpdateRtt() already makes this fairly clear. I can fold the pn_space check into UpdateRtt if you think it would read more clearly?
Ah, so we are not limiting , we are overwriting .

Revised text:
estimate (4*rttvar), and max_ack_delay, to account for the maximum time by which a receiver might delay sending an acknowledgement. When the PTO is armed for Initial or Handshake packet number spaces,  <ins> the max_ack_delay is 0, as specified in 13.2.1 of QUIC-TRANSPORT. </ins> The PTO value MUST be set to at least kGranularity, to avoid the timer expiring immediately.
Original text:
Spuriously declaring packets as lost leads to unnecessary retransmissions and may result in degraded performance due to the actions of the congestion controller upon detecting loss. <del> Implementations that detect spurious retransmissions and increase the reordering threshold in packets or time MAY choose to start with smaller initial reordering thresholds to minimize recovery latency. </del>  5.1.1.

Reviewer comments:
by clarifying that one may start with a smaller time threshold, not a smaller packet threshold.
The doc says: "Implementations that detect spurious retransmissions and increase the reordering threshold in packets or time MAY choose to start with smaller initial reordering thresholds to minimize recovery latency." For the packet based threshold does that this say that a smaller initial value than 3 packets could be used? Is that really sensible? And for a time based threshold I don't really understand what this means because the threshold is anyway calculated dynamically based on the RTT, so there is no real initial value. I guess there was a time when the threshold was a fixed value and this sentence is maybe a left-over?
Given the current guidance to never use packet thresholds below 3, I think this text should be changed to be clear that you can start with a smaller fraction of RTT and it only applies to time threshold.
I think the fix will be editorial, but once a PR is out we'll know for sure.
If it's only about time-based threshold, any advise should be moved in the respective subsection. However, I would also be okay to just remove this sentence/paragraph...

Revised text:
Spuriously declaring packets as lost leads to unnecessary retransmissions and may result in degraded performance due to the actions of the congestion controller upon detecting loss.  <ins> Implementations can detect spurious retransmissions and increase the reordering threshold in packets or time to reduce future spurious retransmissions and loss events.  Implementations with adaptive time thresholds MAY choose to start with smaller initial reordering thresholds to minimize recovery latency. </ins> 5.1.1.
Original text:
target host to the server during the TLS handshake.  If the server is identified by a DNS name, clients MUST send the Server Name Indication (SNI) RFC6066 TLS extension unless an alternative <del> mechanism for indicate the target host is used. </del>  QUIC connections are established as described in QUIC-TRANSPORT. During connection establishment, HTTP/3 support is indicated by

Reviewer comments:
Follow-up to URL
Or "for indicating" :man_shrugging: not sure what the most appropriate one is.

Revised text:
target host to the server during the TLS handshake.  If the server is identified by a DNS name, clients MUST send the Server Name Indication (SNI) RFC6066 TLS extension unless an alternative  <ins> mechanism to indicate the target host is used. </ins> QUIC connections are established as described in QUIC-TRANSPORT. During connection establishment, HTTP/3 support is indicated by
Original text:
its peer invalidates the connection ID via a RETIRE_CONNECTION_ID frame (frame-retire-connection-id).  Connection IDs that are issued and not retired are considered active; any active connection ID is <del> valid for use at any time, in any packet type.  This includes the connection ID issued by the server via the preferred_address transport parameter. </del>  An endpoint SHOULD ensure that its peer has a sufficient number of available and unused connection IDs.  Endpoints store received

Reviewer comments:
This isn't strictly necessary, as it might be implied by the definition of a connection ID. I tried tweaking the connection ID definition, but it is hard to say anything concrete because of the way that addressing can also be used in combination with connection IDs to identify a connection at an endpoint. So I left that alone.
I agree that a connection ID identifies one session, and due to forbidden correlation, it is clear that a connection ID in use cannot proliferate. However, this is not implied for newly issued connection IDs. There is precedence for new tokens which do apply to new connections, so I think it is worth being precise here.
added the text " Connection IDs that are issued and not retired are considered active; any active connection ID is valid for use at any time, in any packet type. " As far as I can tell there is no text specifying that an issued connection ID cannot be used with subsequent connections. The introduction to connection IDs state that there must not be correlation across connections, but if an issued connection ID was never consumed, there would be no correlation because it was transmitted encrypted.
Not really sure if this is necessary. The text around this sentence implies that connection IDs identify one connection (which shouldn't be too surprising in the first place). It's only when you take this one sentence out of context, that the "problem" of occurs.

Revised text:
its peer invalidates the connection ID via a RETIRE_CONNECTION_ID frame (frame-retire-connection-id).  Connection IDs that are issued and not retired are considered active; any active connection ID is  <ins> valid for use with the current connection at any time, in any packet type.  This includes the connection ID issued by the server via the preferred_address transport parameter. </ins> An endpoint SHOULD ensure that its peer has a sufficient number of available and unused connection IDs.  Endpoints store received
Original text:
number spaces, the timer MUST be set for the packet number space with the earliest timeout, except for ApplicationData, which MUST be ignored until the handshake completes; see Section 4.1.1 of QUIC-TLS. <del> Not arming the PTO for ApplicationData prioritizes completing the handshake and prevents the server from sending a 1-RTT packet on a PTO before before it has the keys to process a 1-RTT packet. </del>  When a PTO timer expires, the PTO period MUST be set to twice its current value.  This exponential reduction in the sender's rate is

Reviewer comments:
Clarifies exactly what the implications of not arming PTO for ApplicationData prior to handshake complete. This came from a discussion with a coworker who read the transport and recovery drafts, but not TLS.
Thanks! I think this is much clearer from implementation perspective.

Revised text:
number spaces, the timer MUST be set for the packet number space with the earliest timeout, except for ApplicationData, which MUST be ignored until the handshake completes; see Section 4.1.1 of QUIC-TLS.  <ins> Not arming the PTO for ApplicationData prevents a client from retransmitting a 0-RTT packet on a PTO expiration before confirming that the server is able to decrypt 0-RTT packets, and prevents a server from sending a 1-RTT packet on a PTO expiration before it has the keys to process an acknowledgement. </ins> When a PTO timer expires, the PTO period MUST be set to twice its current value.  This exponential reduction in the sender's rate is
Original text:
congestion window, or a pacer might pace out packets handed to it by the congestion controller.  Timely delivery of ACK frames is important for efficient loss recovery.  Packets containing only ACK <del> frames should therefore not be paced, to avoid delaying their </del>  delivery to the peer. Sending multiple packets into the network without any delay between A sender that paces packets (see pacing) might delay sending packets and not fully utilize the congestion window due to this delay.  A <del> sender should not consider itself application limited if it would </del>  have fully utilized the congestion window without pacing delay. A sender MAY implement alternative mechanisms to update its

Reviewer comments:
This my need a design issue because I suggest to use two SHOULDs instead of should. However, I would first like to get some feedback if people agree.
I think this is editorial, because it fixes an error. I always intended these to be normative SHOULD/SHOULD NOT
I'm going with editorial also.
Yup, this is editorial.
Thanks, this is certainly what I meant when I wrote this text.

Revised text:
congestion window, or a pacer might pace out packets handed to it by the congestion controller.  Timely delivery of ACK frames is important for efficient loss recovery.  Packets containing only ACK  <ins> frames SHOULD therefore not be paced, to avoid delaying their </ins> delivery to the peer. Sending multiple packets into the network without any delay between A sender that paces packets (see pacing) might delay sending packets and not fully utilize the congestion window due to this delay.  A  <ins> sender SHOULD NOT consider itself application limited if it would </ins> have fully utilized the congestion window without pacing delay. A sender MAY implement alternative mechanisms to update its
Original text:
The initial probe timeout for a new connection or new path SHOULD be set to twice the initial RTT.  Resumed connections over the same <del> network SHOULD use the previous connection's final smoothed RTT value as the resumed connection's initial RTT.  If no previous RTT is </del>  available, the initial RTT SHOULD be set to 500ms, resulting in a 1 second initial timeout as recommended in RFC6298.

Reviewer comments:
The recovery draft says: "Resumed connections over the same network SHOULD use the previous connection's final smoothed RTT value as the resumed connection's initial RTT." I wonder if we should change this to a MAY, as there is also a temporal aspect. Or maybe we should say more about this? Also note that draft-ietf-tcpm-2140bis is probably related.
I would agree with switching to MAY. Even mentioning this leads to some incentive to implement, so the effect on implementation is similar. But we really don't need to recommend something like this.

Revised text:
The initial probe timeout for a new connection or new path SHOULD be set to twice the initial RTT.  Resumed connections over the same  <ins> network MAY use the previous connection's final smoothed RTT value as the resumed connection's initial RTT.  If no previous RTT is </ins> available, the initial RTT SHOULD be set to 500ms, resulting in a 1 second initial timeout as recommended in RFC6298.