jiebi/TextFlow huggingface dataset:
Original text:
If the server sends a Retry packet, it MUST use the original version. The client ignores Retry packets using other versions.  The client <del> MUST NOT use a different version in the subsequent Initial that contains the Retry token.  The server MAY encode the QUIC version in its Retry token to validate that the client did not switch versions, and drop the packet if it switched. </del>  QUIC version 2 uses the same transport parameters to authenticate the Retry as QUIC version 1.  After switching to a negotiated version

Reviewer comments:
here (URL) it is better that we call it QUIC version 1 not just QUIC. As later it is referred as QUIC version 1.here (URL) I would add reference to VN draft instead of calling it "that document"here (URL) i would add "packet" after "Initial" just to be clear, as we have now a initial version in VN draft.
Thanks, fixed here URL

Revised text:
If the server sends a Retry packet, it MUST use the original version. The client ignores Retry packets using other versions.  The client  <ins> MUST NOT use a different version in the subsequent Initial packet that contains the Retry token.  The server MAY encode the QUIC version in its Retry token to validate that the client did not switch versions, and drop the packet if it switched. </ins> QUIC version 2 uses the same transport parameters to authenticate the Retry as QUIC version 1.  After switching to a negotiated version
Original text:
3.1. <del> The Version field of long headers is 0x709a50c4.  This randomly chosen value is meant to avoid creating patterns in specified version numbers. </del>  This version number will not change in subsequent versions of this draft, unless there is a behavior change that breaks compatibility.

Reviewer comments:
As requested, all new version number, salts, etc. for QUICv2. Verification of the test vectors would be especially valuable.
Woof. Thank you very much for quickly checking, and sorry I botched every part of that. All fixed now, I hope.
The new test vectors works well with my QUIC implementation in Haskell.
Thanks Kazu!
WFM. Not validated with a real build, but a script. See URL for the script that I used.

Revised text:
3.1.  <ins> The Version field of long headers is 0x6b3343cf.  This was generated by taking the first four bytes of the sha256sum of "QUICv2 version number". </ins> This version number will not change in subsequent versions of this draft, unless there is a behavior change that breaks compatibility.
Original text:
The salt used to derive Initial keys in QUIC-TLS changes to:  3.3.2. The labels used in QUIC-TLS to derive packet protection keys

Reviewer comments:
As requested, all new version number, salts, etc. for QUICv2. Verification of the test vectors would be especially valuable.
Woof. Thank you very much for quickly checking, and sorry I botched every part of that. All fixed now, I hope.
The new test vectors works well with my QUIC implementation in Haskell.
Thanks Kazu!
WFM. Not validated with a real build, but a script. See URL for the script that I used.

Revised text:
The salt used to derive Initial keys in QUIC-TLS changes to: <ins> This is the first 20 bytes of the sha256sum of "QUICv2 salt". </ins> 3.3.2. The labels used in QUIC-TLS to derive packet protection keys
Original text:
The key and nonce used for the Retry Integrity Tag (QUIC-TLS) change to:  4. QUIC version 2 is not intended to deprecate version 1.  Endpoints

Reviewer comments:
As requested, all new version number, salts, etc. for QUICv2. Verification of the test vectors would be especially valuable.
Woof. Thank you very much for quickly checking, and sorry I botched every part of that. All fixed now, I hope.
The new test vectors works well with my QUIC implementation in Haskell.
Thanks Kazu!
WFM. Not validated with a real build, but a script. See URL for the script that I used.

Revised text:
The key and nonce used for the Retry Integrity Tag (QUIC-TLS) change to: <ins> The secret is the sha256sum of "QUICv2 retry secret".  The key and nonce are derived from this secret with the labels "quicv2 key" and "quicv2 iv", respectively. </ins> 4. QUIC version 2 is not intended to deprecate version 1.  Endpoints
Original text:
4.2.4. The CANCEL_PUSH frame (type=0x3) is used to request cancellation of a <del> server push prior to the push stream being created.  The CANCEL_PUSH </del>  frame identifies a server push by Push ID (see frame-push-promise), encoded as a variable-length integer.

Reviewer comments:
Not sure if this is enough, but it enacts Brad's suggested fix.
Yup, that's what I had in mind.
Why is this limited to being prior to the push stream being created, given that you specify how the server handles it if it has created the stream.
I don't read this as saying that you have to avoid it. The point is that you also have to reset/STOPSENDING on the stream if it exists, so there is no real point to using CANCELPUSH in addition.
Sounds like the intent is that CANCELPUSH should be used between the client receiving a PUSHPROMISE and before receiving the stream (i.e. when it is ambiguous as to whether the stream has been created by the server from the clients perspective). I think replacing "created" with "received" would make this more clear.

Revised text:
4.2.4. The CANCEL_PUSH frame (type=0x3) is used to request cancellation of a  <ins> server push prior to the push stream being received.  The CANCEL_PUSH </ins> frame identifies a server push by Push ID (see frame-push-promise), encoded as a variable-length integer.
Original text:
4. <del> As discussed above, frames are carried on QUIC streams and used on control streams, request streams, and push streams.  This section describes HTTP framing in QUIC.  For a comparison with HTTP/2 frames, see h2-frames. </del>  4.1.

Reviewer comments:
So a friendly pointer to detail that could be easily misinterpreted or missed? It seems like a table footnote is required but I'm not sure how to do that in Markdown.
While each frame's description indicates the stream type(s) on which it is allowed, there isn't one unified place to indicate which frames are expected on which streams. QPACK subdivides the instruction space per stream, which has the nice property that you can't put something on the wrong stream. While that's overkill for H3 (too dramatic a departure from H2, multiple IANA registries, etc.), having a table to indicate which frames are permitted on which streams would be helpful.
I like the table idea for both. Want a PR?
Text always welcome.
I'll submit two PRs in next day or so.
Minor nit; otherwise good. Given that we have two frames that fall into this camp, might it be worth doing something like "(*) = only as the first frame"?

Revised text:
4.  <ins> HTTP frames are carried on QUIC streams, as described in stream- mapping.  HTTP/3 defines three stream types: control stream, request stream, and push stream.  This section describes HTTP/3 frame formats and the streams types on which they are permitted; see stream-frame- mapping for an overiew.  A comparison between HTTP/2 and HTTP/3 frames is provided in h2-frames. </ins> 4.1.
Original text:
mapping for an overiew.  A comparison between HTTP/2 and HTTP/3 frames is provided in h2-frames.  4.1. All frames have the following format:

Reviewer comments:
This is my stab at adding the indication discussed in .
Lgtm. An minor Improvement might be to highlight in the new sentence that "specific guidance is provided in the relevant section" but that might be obvious. I'm happy without anything further.

Revised text:
mapping for an overiew.  A comparison between HTTP/2 and HTTP/3 frames is provided in h2-frames. <ins> Certain frames can only occur as the first frame of a particular stream type; these are indicated in stream-frame-mapping with a (1). Specific guidance is provided in the relevant section. </ins> 4.1. All frames have the following format:
Original text:
packets arrive.  If a peer could timeout within an Probe Timeout (PTO, see Section 6.2.2 of QUIC-RECOVERY), it is advisable to test for liveness before sending any data that cannot be retried safely.  10.3.

Reviewer comments:
What data can and cannot be retried safely?
That's not something that QUIC knows. HTTP does though. As advice, I don't think that this needs much more expansion, but I'd be happy to take a PR.
I'm not so sure this is a HTTP-only issue. Unlike TLS 1.3, there is QUIC data being sent under encryption, and that might have side effects.
LGTM, one nit. ("using applications" is fine, it's just a bit awkward.)

Revised text:
packets arrive.  If a peer could timeout within an Probe Timeout (PTO, see Section 6.2.2 of QUIC-RECOVERY), it is advisable to test for liveness before sending any data that cannot be retried safely. <ins> Note that it is likely that only applications or application protocols will know what information can be retried. </ins> 10.3.
Original text:
19.4. An endpoint uses a RESET_STREAM frame (type=0x04) to abruptly <del> terminate a stream. </del>  After sending a RESET_STREAM, an endpoint ceases transmission and retransmission of STREAM frames on the identified stream.  A receiver

Reviewer comments:
Saying it "terminates a stream" dangerously makes it sound like it has the same meaning as HTTP/2, which is false.
Thanks for all these little patches Martin, they are a real help.

Revised text:
19.4. An endpoint uses a RESET_STREAM frame (type=0x04) to abruptly  <ins> terminate the sending part of a stream. </ins> After sending a RESET_STREAM, an endpoint ceases transmission and retransmission of STREAM frames on the identified stream.  A receiver
Original text:
The final size is the amount of flow control credit that is consumed by a stream.  Assuming that every contiguous byte on the stream was sent once, the final size is the number of bytes sent.  More <del> generally, this is one higher than the largest byte offset sent on the stream. </del>  For a stream that is reset, the final size is carried explicitly in a RESET_STREAM frame.  Otherwise, the final size is the offset plus the

Reviewer comments:
The transport draft states the following (Section 4.4): This verbiage, introduced in PR , is ambiguous. Byte offset may refer to the Offset field in the STREAM frame; in this case, the definition above is incorrect. What we want to say is that the final size is one higher than the offset of the byte with the largest offset sent on the stream. If no bytes were sent, the final size is zero.

Revised text:
The final size is the amount of flow control credit that is consumed by a stream.  Assuming that every contiguous byte on the stream was sent once, the final size is the number of bytes sent.  More  <ins> generally, this is one higher than the offset of the byte with the largest offset sent on the stream, or zero if no bytes were sent. </ins> For a stream that is reset, the final size is carried explicitly in a RESET_STREAM frame.  Otherwise, the final size is the offset plus the
Original text:
Endpoints MUST NOT send this extension in a TLS connection that does not use QUIC (such as the use of TLS with TCP defined in TLS13).  A <del> fatal unsupported_extension alert MUST be sent if this extension is received when the transport is not QUIC. </del>  8.3.

Reviewer comments:
No point in levying requirements on them.
Section 8.2 says: However, this directly contradicts TLS 1.3 URL, which says: In order to say this, this document would need to Update 8446, and even then it doesn't make sense because the presumptive point of this rule is to detect attempts to negotiate QUIC with non-QUIC TLS endpoints, which don't need to conform to this RFC (and may predate it).
I don't think QUIC can tell anyone what do with regard to any protocol that is not QUIC. And since QUIC v1 carries its own TLS record wrapping it makes even less sense.
I agree with the problem statement, however I wonder if this opens a session ticket obtained using TLS13-over-TCP to be used in QUIC. Is that what we want?
NAME why would this text have an impact on that? Couldn't I negotiate TLS 1.3 over TCP w/o extension and then send the resume over QUIC w/ extension?
The point here is to insist on the alert if the extension is understood. This wasn't intended to supersede 8446.
NAME My bad. I was confused with the earlier versions of the QUIC-TLS draft that had the transport_parameters extension in the session tickets.
NAME I think you could phrase that, but is it useful, given that we can't rely on it?
Probably not. I'm OK with culling the text.
This might not be possible if a cloud load balancer only forwards QUIC with TLS and terminates TLS otherwise.

Revised text:
Endpoints MUST NOT send this extension in a TLS connection that does not use QUIC (such as the use of TLS with TCP defined in TLS13).  A  <ins> fatal unsupported_extension alert MUST be sent by an implementation that supports this extension if the extension is received when the transport is not QUIC. </ins> 8.3.
Original text:
maximum value for a Push ID that the server can use in a PUSH_PROMISE frame.  Consequently, this also limits the number of push streams that the server can initiate in addition to the limit set by the QUIC <del> MAX_STREAM_ID frame. </del>  The MAX_PUSH_ID frame is always sent on the control stream.  Receipt of a MAX_PUSH_ID frame on any other stream MUST be treated as a

Reviewer comments:
Makes two minor fixes in the GOAWAY text, both editorial: Correctly references the MAXSTREAMS frame instead of the MAXSTREAM_ID frame Notes that servers need not (and cannot) send a GOAWAY if the client has used up all the possible stream IDs; the client simply won't be making any more requests.
This is a whatever...

Revised text:
maximum value for a Push ID that the server can use in a PUSH_PROMISE frame.  Consequently, this also limits the number of push streams that the server can initiate in addition to the limit set by the QUIC  <ins> MAX_STREAMS frame. </ins> The MAX_PUSH_ID frame is always sent on the control stream.  Receipt of a MAX_PUSH_ID frame on any other stream MUST be treated as a
Original text:
of the connection.  An endpoint that completes a graceful shutdown SHOULD use the HTTP_NO_ERROR code when closing the connection.  6.3. An HTTP/3 implementation can immediately close the QUIC connection at

Reviewer comments:
Makes two minor fixes in the GOAWAY text, both editorial: Correctly references the MAXSTREAMS frame instead of the MAXSTREAM_ID frame Notes that servers need not (and cannot) send a GOAWAY if the client has used up all the possible stream IDs; the client simply won't be making any more requests.
This is a whatever...

Revised text:
of the connection.  An endpoint that completes a graceful shutdown SHOULD use the HTTP_NO_ERROR code when closing the connection. <ins> If a client has consumed all available bidirectional stream IDs with requests, the server need not send a GOAWAY frame, since the client is unable to make further requests. </ins> 6.3. An HTTP/3 implementation can immediately close the QUIC connection at
Original text:
permitted; receipt of a second stream which claims to be a control stream MUST be treated as a connection error of type HTTP_WRONG_STREAM_COUNT.  The sender MUST NOT close the control <del> stream.  If the control stream is closed at any point, this MUST be treated as a connection error of type HTTP_CLOSED_CRITICAL_STREAM. </del>  A pair of unidirectional streams is used rather than a single bidirectional stream.  This allows either peer to send data as soon

Reviewer comments:
Technically design, but barely.
Originally posted by NAME in URL There are three reasonable places to blow up: When you decide to stop reading a critical stream (i.e. when STOPSENDING is sent) When you discover the peer has stopped reading a critical stream (i.e. when STOPSENDING is received) When you discover the peer has closed a critical stream (when RESETSTREAM or FIN is received) My inclination would be to advise against FIN/SS/R_S on a critical stream and mandate connection termination on receipt of any of them.
Completely agree. This seems like the simplest and most obvious solution.
SGTM mike
Note that this PR does NOT address , just a comment that came up there.
Re-reading this, I think the existing text is pretty good; it just needs a little reframing. The existing requirement is to error out "If the control stream is closed at any point," without reference to whether it was closed because the peer send a FIN/RESET on their control stream or you obeyed a STOP_SENDING on yours. I think I'll add a requirement not to request closure of a control stream; do you think we need more elucidation here?
nits, but LGTM

Revised text:
permitted; receipt of a second stream which claims to be a control stream MUST be treated as a connection error of type HTTP_WRONG_STREAM_COUNT.  The sender MUST NOT close the control  <ins> stream, and the receiver MUST NOT request that the sender close the control stream.  If either control stream is closed at any point, this MUST be treated as a connection error of type HTTP_CLOSED_CRITICAL_STREAM. </ins> A pair of unidirectional streams is used rather than a single bidirectional stream.  This allows either peer to send data as soon
Original text:
The DUPLICATE_PUSH frame carries a single variable-length integer that identifies the Push ID of a resource that the server has <del> previously promised (see frame-push-promise). </del>  This frame allows the server to use the same server push in response to multiple concurrent requests.  Referencing the same server push

Reviewer comments:
Skirts the editorial/design line. Previously, DUPLICATEPUSH referred to a Push ID in a previously-sent PUSHPROMISE frame; that frame would have caused a connection error on arrival. This says that the error should be sent regardless of which frame arrives first. May need reconciling with .
Two questions: Should DUPLICATEPUSH respect max push ID limit? PUSHPROMISE says the following: provided in a MAXPUSHID frame (Section 4.2.8) and MUST NOT use the same Push ID in multiple PUSHPROMISE frames What should a client do if it sees a DUPLICATEPUSH for an ID of a PUSHPROMISE that it never received? This could be caused by a race condition, so it seems sensible to allow this to clients to support this without error. We should probably document that like we did for other racy things. E.g. a Push ID that has not yet been mentioned by a PUSHPROMISE frame.
(2) is covered in : For (1), yes it should -- the DUPLICATE might show up first, but the implication is that the ID has already been used in a PUSHPROMISE frame. If that would be invalid, we should be explicit that the DUPLICATEPUSH is also invalid.
SGTM
I think that we have a frame name problem, otherwise, this is fine.I think some wires got crossed in the suggested changes. Your comment points out that this might need reconciliation with but it seems to borrow the text directly from that PR. The outcome is that this PR is inconsistent with itself because at line the same error with PUSHPROMISE causes a MALFORMEDFRAME. I think the best path is to make this change be a MALFORMED_FRAME error and reconcile on if the group want that change.

Revised text:
The DUPLICATE_PUSH frame carries a single variable-length integer that identifies the Push ID of a resource that the server has  <ins> previously promised (see frame-push-promise), though that promise might not be received before this frame.  A server MUST NOT use a Push ID that is larger than the client has provided in a MAX_PUSH_ID frame (frame-max-push-id).  A client MUST treat receipt of a DUPLICATE_PUSH that contains a larger Push ID than the client has advertised as a connection error of type HTTP_MALFORMED_FRAME. </ins> This frame allows the server to use the same server push in response to multiple concurrent requests.  Referencing the same server push
Original text:
A TCP connection error is signaled with QUIC RESET_STREAM frame.  A proxy treats any error in the TCP connection, which includes receiving a TCP segment with the RST bit set, as a stream error of <del> type HTTP_CONNECT_ERROR (http-error-codes).  Correspondingly, a proxy MUST send a TCP segment with the RST bit set if it detects an error with the stream or the QUIC connection. </del>  4.3.

Reviewer comments:
LGTM
S 5.2. I don't believe this is possible on UNIX. What system call do I use to generate RST? Neither close() nor shutdown() does it.
You set SO_LINGER to {1, 0}, then close.
I don't think there's a question here about the -http draft, is there?
The question is if it's possible on standard OSes. Sounds like it is on Unix. How about Windows? NAME
This is the same requirement as in HTTP/2. A "MUST (but we know you probably won't)" ?
Well, that was a joke in 6919, so probably we shouldn't do that.
This is not that. We know that some implementations use TCP half-closed in HTTP. Some even rely on it to the point that things break if you don't do it. Not that things don't break for those people, but they have a narrow set of peers that they interact with. Of course, whether that set of endpoints is ALSO the same set of endpoints using CONNECT is hard to know.
Note that this particular issue is not about half-closed. In half-closed, you generate a FIN and then keep receiving data. This is about sending an RST.
Perhaps the text should be "SHOULD", and if the platform doesn't allow it, to "close the connection".
There's risk with that too, though. We encountered issues where the TCP connection was closed cleanly instead of aborted, and the client interpreted a truncated response as the (cacheable) response. It gets ugly. If you can't force a RST on the other side, you perhaps shouldn't be implementing CONNECT.
Discussed in Tokyo; MUST close the connection, SHOULD close with a RST.

Revised text:
A TCP connection error is signaled with QUIC RESET_STREAM frame.  A proxy treats any error in the TCP connection, which includes receiving a TCP segment with the RST bit set, as a stream error of  <ins> type HTTP_CONNECT_ERROR (http-error-codes).  Correspondingly, if a proxy detects an error with the stream or the QUIC connection, it MUST close the TCP connection.  If the underlying TCP implementation permits it, the proxy SHOULD send a TCP segment with the RST bit set. </ins> 4.3.
Original text:
bytes associated with an HTTP request or response payload. DATA frames MUST be associated with an HTTP request or response.  If <del> a DATA frame is received on either control stream, the recipient MUST </del>  respond with a connection error (errors) of type HTTP_WRONG_STREAM. 7.2.2.

Reviewer comments:
Use 'on a control stream' instead of 'on either control stream'. This is consistent with the changes made by .

Revised text:
bytes associated with an HTTP request or response payload. DATA frames MUST be associated with an HTTP request or response.  If  <ins> a DATA frame is received on a control stream, the recipient MUST </ins> respond with a connection error (errors) of type HTTP_WRONG_STREAM. 7.2.2.
Original text:
An optional reference to a specification that describes the use of the setting.  The entries in the following table are registered by this document. Additionally, each code of the format "0x1f * N + 0x21" for integer

Reviewer comments:
I went with "Default" because that and "Initial Value" now have specific, related (but distinct) usages in the context of pre-SETTINGS settings. Swapping them seems like it would create unnecessary confusion.
Yeah that makes sense on a reread of section 7.2.5.2
Not a new issue but: RFC 7540 has a column for . I think it makes sense that HTTP/3 does similar. Originally posted by NAME in URL

Revised text:
An optional reference to a specification that describes the use of the setting. <ins> The value of the setting unless otherwise indicated.  SHOULD be the most restrictive possible value. </ins> The entries in the following table are registered by this document. Additionally, each code of the format "0x1f * N + 0x21" for integer