jiebi/TextFlow huggingface dataset:
Original text:
frame is the offset of the next byte that would be sent. The first byte in the stream has an offset of 0.  The largest offset <del> delivered on a stream - the sum of the offset and data length - MUST be less than 2^62. </del>  19.9.

Reviewer comments:
The text here had a MUST prohibiting data+offset from exceeding 2^62-1. But that is redundant with flow control, which can't express a limit greater than this anyway. So just point to FLOWCONTROLERROR.
Sec 19.8 says: The first byte in the stream has an offset of 0. The largest offset delivered on a stream - the sum of the offset and data length - MUST be less than 2^62. It certainly possible to express a STREAM frame that violates this rule. What action should we take?
I don't know if we ever wrote this down, but I think that we might say if you catch a peer violating the spec, then you can send an error of any type you like. But for this case, PROTOCOL_VIOLATION is entirely appropriate (as with many others of this sort).
Not just offset, but offset + content size of stream frame, otherwise there is no fixed limit on stream sizes, which is unfortunate.

Revised text:
frame is the offset of the next byte that would be sent. The first byte in the stream has an offset of 0.  The largest offset  <ins> delivered on a stream - the sum of the offset and data length - cannot exceed 2^62-1, as it is not possible to provide flow control credit for that data.  Receipt of a frame that exceeds this limit will be treated as a connection error of type FLOW_CONTROL_ERROR. </ins> 19.9.
Original text:
least 1200 bytes. The crypto retransmission timer is not set if the time threshold <del> time-threshold loss detection timer is set.  When the crypto retransmission timer is active, the probe timer (pto) is not active. </del>  6.2.1.

Reviewer comments:
Adds some explanation about why it's better to arm/fire the time threshold alarm before the crypto retransmission timeout. Hopefully clarifies comments from
Thanks for the explanation. It's much clearer. Can i ask for one more clarification? In DetectLostPackets, shouldn't the for-loop have been something like this:
Thanks for catching the pseudocode error in DetectLostPackets. PTAL.
lgtm. thank you!
In both SetLossDetectionTimer() and OnLossDetectionTimeout(), the losstime based timer setup and loss detection happens before the crypto loss recovery logics. That seems at the cross road with the idea that crypto packets having higher priority in loss recovery. In fact in OnLossDetectionTimerou(), if losstime is present and we go into DetectLostPackets(), then we will only decect loss of one packet number space between Initial and Handshake. Plus the losstime used to set the timer is the earliest among all possible values, which means even if only one of Initial and Handshake space has inflight packets, we may still not retransmit all the inflight packets when this timer fires. So this current code really doesn't follow the idea that when crypto is inflight and loss timer fires, all inflight crypto needs to be retransmitted. If we change the code so that crypto is handled first, we can also reduce the states need to be maintained and simplify some of the functions. In current draft there are 3 losstimes, one per packet number space. By always handling crypto first, we will need such loss_time for AppData space only, and no need to have the helper function to GetEarliestLossTime(). (I'm more than happy to cook up a PR if people think this makes sense.)
It's been a few days. I sent PR .
This was introduced as a fix to URL, and fixed in URL I don't think we should revert that fix.
+1 to NAME comment. Timers are necessary when you have no information about what might be lost, but if you do have information, there's no reason not to use that instead.
I sent out an editorial PR to clarify why time based loss detection has higher priority.

Revised text:
least 1200 bytes. The crypto retransmission timer is not set if the time threshold  <ins> time-threshold loss detection timer is set.  The time threshold loss detection timer is expected to both expire earlier than the crypto retransmission timeout and be less likely to spuriously retransmit data.  The Initial and Handshake packet number spaces will typically contain a small number of packets, so losses are less likely to be detected using packet-threshold loss detection. When the crypto retransmission timer is active, the probe timer (pto) is not active. </ins> 6.2.1.
Original text:
6.3.2. When a PTO timer expires, the sender MUST send one ack-eliciting <del> packet as a probe.  A sender MAY send up to two ack-eliciting packets, to avoid an expensive consecutive PTO expiration due to a single packet loss. </del>  Consecutive PTO periods increase exponentially, and as a result, connection recovery latency increases exponentially as packets

Reviewer comments:
Editorial fix for This seems like the minimal fix for the existing text, though I wonder if it's the correct one.
I think this fix is fine, but it's inadequate. I'll take this in since it's useful.
Can you clarify why it's inadequate on the still open issue?
NAME primarily because it does not correct the pseudocode, but I've also made some textual adjustments in
As discussed with NAME 6.2.2.2 is awkward, because in the first paragraph it says And then the very last paragraph changes that by saying What is super unclear is that the final paragraph apparently means to imply that when there is no new or unACKed data to send, nothing should be send, i.e., it invalidates the SHOULD in the first paragraph. Related to that, the pseudo code still uses , which is also inaccurate, since it's really "at least one (unless you don't have new or unACKed data) but can also send two". Good luck finding a good name for that function :-)
The pseudocode now uses SendOneOrTwoPackets(), but the last paragraph pretty clearly violates the previous MUST, which is very bad. The simplest fix would be to change the MUST to a "SHOULD unless otherwise specified", but I'm increasingly thinking we should stick with the MUST and if you get into a situation you have nothing to send, require sending something ack-eliciting to ensure in-flight packets are removed from flight. Thoughts?

Revised text:
6.3.2. When a PTO timer expires, the sender MUST send one ack-eliciting  <ins> packet as a probe, unless there is nothing to send.  A sender MAY send up to two ack-eliciting packets, to avoid an expensive consecutive PTO expiration due to a single packet loss. </ins> Consecutive PTO periods increase exponentially, and as a result, connection recovery latency increases exponentially as packets
Original text:
PUSH_PROMISE frames are not part of the response; see server-push for more details.  The "chunked" transfer encoding defined in Section 4.1 of RFC7230 MUST NOT be used.

Reviewer comments:
This arises from a different discussion I had about the message exchange definition in section 5.1. The description is correct but glosses over the detail of QPACK, which is mentioned very briefly later in section 5.1.1. For complete accuracy, I would argue that a single message exchange may also contain one or more QPACK encoder instructions sent on the encoder stream.

Revised text:
PUSH_PROMISE frames are not part of the response; see server-push for more details. <ins> The HEADERS and PUSH_PROMISE frames might reference updates to the QPACK dynamic table.  While these updates are not directly part of the message exchange, they must be received and processed before the message can be consumed.  See header-formatting for more details. </ins> The "chunked" transfer encoding defined in Section 4.1 of RFC7230 MUST NOT be used.
Original text:
versions without retaining state.  Though either the Initial packet or the Version Negotiation packet that is sent in response could be lost, the client will send new packets until it successfully receives <del> a response or it abandons the connection attempt. </del>  A server MAY limit the number of Version Negotiation packets it sends.  For instance, a server that is able to recognize packets as

Reviewer comments:
Just in case it wasn't perfectly clear from the choice of words.
I know how you feel. We'll be defining "the" eventually. I don't know where the line is, but I think that it helps in this case to be doubly explicit.
I'm wondering how one could possibly misinterpret "abandoning" here. Furthermore, I don't think it's relevant for the server here if the client actually discarded the connection state, as long as it doesn't any more packets.
I don't think we need to spend a lot of energy here. I agree that this doesn't seem necessary, but I'm not going to fight it either.
The draft currently reads: "When a client receives a Version Negotiation packet, it MUST abandon the current connection attempt." However, it does not define what it is to abandon a connection attempt. Is it an abrupt termination without writing a connection close? That probably makes the most sense since the server is meant to be stateless at this stage.
Do we really need to define "abandon"? And if so, don't we need to define what "discarding" means?LGTM

Revised text:
versions without retaining state.  Though either the Initial packet or the Version Negotiation packet that is sent in response could be lost, the client will send new packets until it successfully receives  <ins> a response or it abandons the connection attempt.  As a result, the client discards all state for the connection and does not send any more packets on the connection. </ins> A server MAY limit the number of Version Negotiation packets it sends.  For instance, a server that is able to recognize packets as
Original text:
endpoint's RTT samples, and rttvar is the endpoint's estimated variance in the RTT samples. <del> smoothed_rtt uses path latency after adjusting RTT samples for peer- reported host delays (host-delay).  A peer limits any delay in </del>  sending an acknowledgement for an ack-eliciting packet to no greater <del> than the advertised max_ack_delay transport parameter.  Consequently, when a peer reports an Ack Delay that is greater than its max_ack_delay, the delay is attributed to reasons out of the peer's control, such as scheduler latency at the peer or loss of previous ACK frames.  Any delays beyond the peer's max_ack_delay are therefore considered effectively part of path delay and incorporated into the smoothed_rtt estimate. </del>  When adjusting an RTT sample using peer-reported acknowledgement delays, an endpoint:  MUST use the lesser of the value reported in Ack Delay field of the ACK frame and the peer's max_ack_delay transport parameter (host-delay).

Reviewer comments:
This should have been part of .
NAME I applied your suggestions. I think this PR should be marked as editorial.
The new "MUST" threw me, but it's not really new, is it?
That one was introduced in already.
Seems reasonable to me. Throughout here, should we be using "peer" or "receiver"? (The suggestions I make here are not issues with this change, but I'm sure that NAME or NAME will find them a home.)Thanks for fixing this.

Revised text:
endpoint's RTT samples, and rttvar is the endpoint's estimated variance in the RTT samples.  <ins> The calculation of smoothed_rtt uses path latency after adjusting RTT samples for host delays (host-delay).  For packets sent in the ApplicationData packet number space, a peer limits any delay in </ins> sending an acknowledgement for an ack-eliciting packet to no greater  <ins> than the value it advertised in the max_ack_delay transport parameter.  Consequently, when a peer reports an Ack Delay that is greater than its max_ack_delay, the delay is attributed to reasons out of the peer's control, such as scheduler latency at the peer or loss of previous ACK frames.  Any delays beyond the peer's max_ack_delay are therefore considered effectively part of path delay and incorporated into the smoothed_rtt estimate. </ins> When adjusting an RTT sample using peer-reported acknowledgement delays, an endpoint: <ins> MUST ignore the Ack Delay field of the ACK frame for packets sent in the Initial and Handshake packet number space. </ins> MUST use the lesser of the value reported in Ack Delay field of the ACK frame and the peer's max_ack_delay transport parameter (host-delay).
Original text:
number of TCP segments is not guaranteed to map predictably to the size and number of HTTP DATA or QUIC STREAM frames.  The TCP connection can be closed by either peer.  When the client ends the request stream (that is, the receive stream at the proxy enters the "Data Recvd" state), the proxy will set the FIN bit on its

Reviewer comments:
This still seems like a pointless restriction to me, but it's what we agreed in Tokyo, so here it is.
NAME I think I share the concern (though I am not sure how much I care). HTTP/3 is expected to allow extension frames to be used without coordination; this PR forbids that to happen on a stream that uses the CONNECT method.
S 5.2. Can you send anything other than DATA on a CONNECT stream? You don't say that I can't send anything else, but you don't say I can't either.
It doesn't mean anything (because we haven't assigned semantics), but we should probably just forbid the use of other frames (of those defined in this document). This is probably a shortcoming of 7540 as well.
Wouldn’t it be better to just prohibit the HEADERS frame? We might want to introduce a frame that changes a property of a stream (e.g., max bitrate). I do not think there’s a strong reason to forbid such kind of extensions only on CONNECT stream.
I don't want to prohibit extension frames, but the frames defined in the current spec don't serve any purpose. That is why I said "of those defined in this document".
Well, there's technically nothing preventing the use of push.... ;-) More seriously, I don't feel like the prohibition adds much. This maps the definition of the CONNECT method into H3 framing -- DATA frames == TCP payload. In any other respect, it's an HTTP request and frames mean what they otherwise mean. Is there a particular frame that needs to be prohibited? HEADERS would indicate a trailer block; it might be worth upstreaming to the updated semantic draft that a CONNECT tunnel can't have trailers.
Discussed in Tokyo; after the CONNECT takes effect, all frames other than DATA are prohibited unless an extension specifically provides otherwise.
nits

Revised text:
number of TCP segments is not guaranteed to map predictably to the size and number of HTTP DATA or QUIC STREAM frames. <ins> Once the CONNECT method has completed, only DATA frames are permitted to be sent on the stream.  Extension frames MAY be used if specifically permitted by the definition of the extension.  Receipt of any other frame type MUST be treated as a connection error of type HTTP_UNEXPECTED_FRAME. </ins> The TCP connection can be closed by either peer.  When the client ends the request stream (that is, the receive stream at the proxy enters the "Data Recvd" state), the proxy will set the FIN bit on its
Original text:
QUIC Stream ID for a client-initiated bidirectional stream encoded as a variable-length integer.  A client MUST treat receipt of a GOAWAY frame containing a Stream ID of any other type as a connection error <del> of type HTTP_WRONG_STREAM. </del>  Clients do not need to send GOAWAY to initiate a graceful shutdown; they simply stop making new requests.  A server MUST treat receipt of The GOAWAY frame applies to the connection, not a specific stream.  A client MUST treat a GOAWAY frame on a stream other than the control <del> stream as a connection error (errors) of type HTTP_UNEXPECTED_FRAME. </del>  See connection-shutdown for more information on the use of the GOAWAY frame.

Reviewer comments:
I'm pretty sure the intent of URL was correct but the wrong error was changed in the draft. This pr makes the change that I think was intended in URL
Just a note. If this is the right answer and the PR lands, then will need to replace the new instance of HTTPMALFORMEDFRAME with something, e.g. HTTPINVALIDGOAWAY or something
Yeah, that crossed my mind. :-) YAEC!
In , NAME correctly observed that I messed up , but he closed his PR and I'm not able to reopen it without more git wizardry than I'm interested in practicing today. Easier just to fix it in my own branch.

Revised text:
QUIC Stream ID for a client-initiated bidirectional stream encoded as a variable-length integer.  A client MUST treat receipt of a GOAWAY frame containing a Stream ID of any other type as a connection error  <ins> of type HTTP_MALFORMED_FRAME. </ins> Clients do not need to send GOAWAY to initiate a graceful shutdown; they simply stop making new requests.  A server MUST treat receipt of The GOAWAY frame applies to the connection, not a specific stream.  A client MUST treat a GOAWAY frame on a stream other than the control  <ins> stream as a connection error (errors) of type HTTP_WRONG_STREAM. </ins> See connection-shutdown for more information on the use of the GOAWAY frame.
Original text:
The HEADERS frame (type=0x1) is used to carry a header block, compressed using QPACK.  See QPACK for more details. <del> HEADERS frames can only be sent on request / push streams. </del>  7.2.3.

Reviewer comments:
Receiving a HEADERS frame on a control stream should result in a connection error of type HTTPWRONGSTREAM. The correct error is documented for all other frame types except for HEADERS. This pr specifies the error for HEADERS frames as well.
This inconsistency was bugging me the other day. So thanks for beating me to fixing it :) NAME iff gets traction, we'd need a sweep of all these If a HEADERS frame is received on either control stream phrases to cover all streams (exclusively or inclusively).
NAME was closed. Is there anything else that's blocking this pr from being merged?
NAME I added NAME so he can review and merge this.

Revised text:
The HEADERS frame (type=0x1) is used to carry a header block, compressed using QPACK.  See QPACK for more details.  <ins> HEADERS frames can only be sent on request / push streams.  If a HEADERS frame is received on a control stream, the recipient MUST respond with a connection error (errors) of type HTTP_WRONG_STREAM. </ins> 7.2.3.
Original text:
the client has advertised or a Push ID which has already been promised as a connection error of type HTTP_MALFORMED_FRAME. <del> If a PUSH_PROMISE frame is received on either control stream, the recipient MUST respond with a connection error (errors) of type </del>  HTTP_WRONG_STREAM.  See server-push for a description of the overall server push mechanism.

Reviewer comments:
This pr changes the server's error on receipt of a PUSHPROMISE frame. While the current draft implicitly suggests push promises can only be sent by the server, it doesn't explicitly disallow clients from sending PUSHPROMISE frames. This pr explicitly disallows clients from sending PUSHPROMISE frames and requires the server to treat each receipt of a PUSHPROMISE frame as a connection error of type HTTPUNEXPECTEDFRAME.

Revised text:
the client has advertised or a Push ID which has already been promised as a connection error of type HTTP_MALFORMED_FRAME.  <ins> If a PUSH_PROMISE frame is received on the control stream, the client MUST respond with a connection error (errors) of type </ins> HTTP_WRONG_STREAM. <ins> A client MUST NOT send a PUSH_PROMISE frame.  A server MUST treat the receipt of a PUSH_PROMISE frame as a connection error of type HTTP_UNEXPECTED_FRAME. </ins> See server-push for a description of the overall server push mechanism.
Original text:
SETTINGS frames always apply to a connection, never a single stream. A SETTINGS frame MUST be sent as the first frame of each control stream (see control-streams) by each peer, and MUST NOT be sent <del> subsequently or on any other stream.  If an endpoint receives a SETTINGS frame on a different stream, the endpoint MUST respond with a connection error of type HTTP_WRONG_STREAM.  If an endpoint receives a second SETTINGS frame, the endpoint MUST respond with a connection error of type HTTP_UNEXPECTED_FRAME. </del>  SETTINGS parameters are not negotiated; they describe characteristics of the sending peer, which can be used by the receiving peer.

Reviewer comments:
by clearly splitting the two different error cases.
Moves existing text to be clearer, but doesn't change the stated requirements. Editorial, and fine by me.
It's unclear which error should be reported if an endpoint receives a second SETTINGS frame on any stream that's not a control stream. Perhaps this should be explicitly defined in the draft?
Hey NAME I initially thought this was an editorial problem so created as an attempt to clarify things. However, I think the question is more philosophical. To analyse it a bit, what you're asking is how to handle an error after the occurrence of a critical connection error. First, a SETTINGS frame on a wrong stream type, then another SETTINGS frame on a wrong stream. After the first critical error, all bets are off. I'd expect a lot implementations to just give up at that stage as the peer is likely to be misbehaving.
I agree its an edge case but I do think it'd be useful to exactly specify which of the two errors should be reported, especially when thinking of automated testing of HTTP/3 implementations.
I'm sympathetic to that but I fear this could be a slippery slope towards adding lots of text for issues that occur after a critical close event. PRIORITY frames fall into a similar bucket, along with many of the server push frames and their validation rules.
I think the real unclarity in the spec is that both can happen simultaneously. After receiving a proper SETTINGS frame on the control channel, receiving a SETTINGS frame on some other stream would be both a second SETTINGS frame and a SETTINGS frame on the wrong stream. clarifies this reasonable. Thanks, both of you!

Revised text:
SETTINGS frames always apply to a connection, never a single stream. A SETTINGS frame MUST be sent as the first frame of each control stream (see control-streams) by each peer, and MUST NOT be sent  <ins> subsequently.  If an endpoint receives a second SETTINGS frame on the control stream, the endpoint MUST respond with a connection error of type HTTP_UNEXPECTED_FRAME. SETTINGS frames MUST NOT be sent on any steam other than the control stream.  If an endpoint receives a SETTINGS frame on a different stream, the endpoint MUST respond with a connection error of type HTTP_WRONG_STREAM. </ins> SETTINGS parameters are not negotiated; they describe characteristics of the sending peer, which can be used by the receiving peer.
Original text:
The "chunked" transfer encoding defined in Section 4.1 of RFC7230 MUST NOT be used.  Trailing header fields are carried in an additional HEADERS frame following the body.  Senders MUST send only one HEADERS frame in the trailers section; receivers MUST discard any subsequent HEADERS

Reviewer comments:
reincarnated, because I messed up. Sorry, NAME
LGTM but don't forget push

Revised text:
The "chunked" transfer encoding defined in Section 4.1 of RFC7230 MUST NOT be used. <ins> If a DATA frame is received before a HEADERS frame on a either a request or push stream, the recipient MUST respond with a connection error of type HTTP_UNEXPECTED_FRAME (errors). </ins> Trailing header fields are carried in an additional HEADERS frame following the body.  Senders MUST send only one HEADERS frame in the trailers section; receivers MUST discard any subsequent HEADERS