jiebi/CodeConvo huggingface dataset:
Change:
Implementations can do this anyway, so we're not getting much from the recommendation. And we already have good limits on what can be sent (including PATH_RESPONSE) in the migration section.
This can lead to amplification attack if not careful.
NAME how can this lead to amplification?
If an endpoint seeing a challenge uses the opportunity to discover if its preferred MTU is supported by padding the response (as opposed to the challenge) even if the challenge packet is small. Since this might fail, it like will also send a small response after a delay or after a new challenge if it doesn't get an ACK before that. A defence could be to ensure that challenges are no larger than, say twice, response.
An endpoint may also optimistically bundle all kinds of other data in a response. Even with 1200 bytes, this can be much larger than a small challenge packet without considering PMTU discovery at all.
I think I raised this issue quite a while ago this is the reason the limit was introduced, although I didn't formulate the exact counter measure.
The counter measure we have against amplification is the initial congestion window. We won't send more than that. That's higher than the x3 we have during the handshake, but I think that's a reasonable balance, considering that the attacker in this context has to spend a considerable amount of effort. Yes, this is a policy question, but I'm happy with it. (Though we should probably highlight this when asking for review.)
It's pretty hard to understand what the normative force of this is, given that it doesn't explain what the limit is. I think there's actually a simple rule we should propose, which is one PATH_CHALLENGE frame per packet (with others to be ignored). Given that we require duplicate suppression at the packet level, that will have an amplification factor of 1:1, which you can get by a variety of other mechanisms.
The relevant existing guideline is the 3x limit we have on handshake amplification. Given that CHALLENGE/RESPONSE doesn't inherently include any amplification other than what might result from different connection ID lengths on packets, I don't think that we need to do much special. That is, the text in 9.3.1 is fine, even if the limits are different. I'm OK with striking everything from "However" onward here.

Discussion:
On receiving a PATH_CHALLENGE frame, an endpoint MUST respond immediately by echoing the data contained in the PATH_CHALLENGE frame <del> in a PATH_RESPONSE frame.  However, because a PATH_CHALLENGE might be sent from a spoofed address, an endpoint MUST limit the rate at which it sends PATH_RESPONSE frames and MAY silently discard PATH_CHALLENGE frames that would cause it to respond at a higher rate. </del> <ins> in a PATH_RESPONSE frame. </ins> To ensure that packets can be both sent to and received from the peer, the PATH_RESPONSE MUST be sent on the same path as the
Change:
Thanks everyone, this is much better.
From NAME I think that the advice here is that ranges are dropped when all ACKs for all packets in that range have been acknowledged. Or something along those lines. Maybe: Though that seems clumsy. Better words would be appreciated.
Maybe "Endpoints SHOULD not acknowledge packets for which it has already received acknowledgement of acknowledgements, except where this would create unnecessary gaps in the encoded ACK frame." Not ideal, I know/
I think this is connected to in an interesting way. The question that arises is if one MUST include all ACK state between highest received, and the lower PN that needs to be ACKed (as it is newly arrived due to reordering). An alternative would be to explicitly allow GAPs for packets that has been received and where the reception's ACKs has been ACKed. But, I guess that results in interesting bookkeeping chores in the implementations.
Agreed the wording is too strong. Take a look at PR

Discussion:
To limit ACK Blocks to those that have not yet been received by the sender, the receiver SHOULD track which ACK frames have been <del> acknowledged by its peer.  Once an ACK frame has been acknowledged, the packets it acknowledges SHOULD NOT be acknowledged again. </del> <ins> acknowledged.  The receiver SHOULD exclude already acknowledged packets from future ACK frames whenever these packets would unnecessarily contribute to the ACK frame size. </ins> Because ACK frames are not sent in response to ACK-only packets, a receiver that is only sending ACK frames will only receive
Change:
Section 2.3, paragraph 2 still uses "hq"
Good spot, PR fixes this
Whoops!

Discussion:
QUIC connections are established as described in QUIC-TRANSPORT. During connection establishment, HTTP/3 support is indicated by <del> selecting the ALPN token "hq" in the TLS handshake.  Support for </del> <ins> selecting the ALPN token "h3" in the TLS handshake.  Support for </ins> other application-layer protocols MAY be offered in the same handshake.
Change:
HTTP response headers are common across HTTP/1.1, HTTP/2 and HTTP/3. There seems no need to be so precise on what version of the protocol returns the example header.

Discussion:
ALTSVC frame (ALTSVC), using the ALPN token defined in connection- establishment. <del> For example, an origin could indicate in an HTTP/1.1 or HTTP/2 response that HTTP/3 was available on UDP port 50781 at the same hostname by including the following header field in any response: </del> <ins> For example, an origin could indicate in an HTTP response that HTTP/3 was available on UDP port 50781 at the same hostname by including the following header field: </ins> On receipt of an Alt-Svc record indicating HTTP/3 support, a client MAY attempt to establish a QUIC connection to the indicated host and
Change:
If connection for incoming packet cannot be found, check whether this is a stateless reset packet.
states: This only works for endpoints whose SCID is zero length. If SCID is not zero length, the connection corresponding to the stateless reset packet will not be found. This latter case should be included in the stateless reset detection algorithm.
OK with the requested changes.

Discussion:
10.4.1. <del> An endpoint detects a potential stateless reset when a packet with a short header either cannot be decrypted or is marked as a duplicate packet.  The endpoint then compares the last 16 bytes of the packet with the Stateless Reset Token provided by its peer, either in a </del> <ins> An endpoint detects a potential stateless reset when a incoming packet with a short header either cannot be associated with a connection, cannot be decrypted, or is marked as a duplicate packet. The endpoint then compares the last 16 bytes of the packet with the Stateless Reset Token provided by its peer, either in a </ins> NEW_CONNECTION_ID frame or the server's transport parameters.  If these values are identical, the endpoint MUST enter the draining period and not send any further packets on this connection.  If the
Change:
I think the text is a leftover from time before we introduced STOP_SENDING.
There was an earlier draft where RST could be used for both locally and peer initiated streams. Not sure if that is relevant here.

Discussion:
transmitted on a stream.  For a stream that is reset, the final offset is carried explicitly in a RESET_STREAM frame.  Otherwise, the final offset is the offset of the end of the data carried in a STREAM <del> frame marked with a FIN flag, or 0 in the case of incoming unidirectional streams. </del> <ins> frame marked with a FIN flag. </ins> An endpoint will know the final offset for a stream when the receiving part of the stream enters the "Size Known" or "Reset Recvd"
Change:
Quoted from draft 17, value specifying the initial flow control limit for unidirectional streams. This limit applies to newly created bidirectional streams It should be - This limit applies to newly created unidirectional...

Discussion:
This parameter is an integer value specifying the initial flow control limit for unidirectional streams.  This limit applies to <del> newly created bidirectional streams opened by the endpoint that </del> <ins> newly created unidirectional streams opened by the endpoint that </ins> receives the transport parameter.  In client transport parameters, this applies to streams with an identifier with the least significant two bits set to 0x3; in server transport parameters,
Change:
What exists is "earlydata" extension and its "maxearlydatasize" field.

Discussion:
4.5. In order to be usable for 0-RTT, TLS MUST provide a NewSessionTicket <del> message that contains the "max_early_data" extension with the value 0xffffffff; the amount of data which the client can send in 0-RTT is controlled by the "initial_max_data" transport parameter supplied by the server.  A client MUST treat receipt of a NewSessionTicket that contains a "max_early_data" extension with any other value as a connection error of type PROTOCOL_VIOLATION. </del> <ins> message that contains the "early_data" extension with a max_early_data_size of 0xffffffff; the amount of data which the client can send in 0-RTT is controlled by the "initial_max_data" transport parameter supplied by the server.  A client MUST treat receipt of a NewSessionTicket that contains an "early_data" extension with any other value as a connection error of type PROTOCOL_VIOLATION. </ins> Early data within the TLS connection MUST NOT be used.  As it is for other TLS application data, a server MUST treat receiving early data
Change:
Is this just a statement about this spec or a normative requirement on future specs?
It is not an invariant.
There's more to requirements on future specs than invariants.
It's a statement about the current version, but it would presumptively apply to extensions to the current version that don't redefine the base spec.
Perhaps it'd be better to use to avoid confusion like this.

Discussion:
identifies the frame.  These frames are explained in more detail in frame-formats. <del> All QUIC frames are idempotent.  That is, a valid frame does not cause undesirable side effects or errors when received more than once. </del> <ins> All QUIC frames are idempotent in this version of QUIC.  That is, a valid frame does not cause undesirable side effects or errors when received more than once. </ins> The Frame Type field uses a variable length integer encoding (see integer-encoding) with one exception.  To ensure simple and efficient
Change:
Maybe takes things too far, please discuss.
Draft 17 says If I understand H3 Placeholders correctly, the PRIORITY frame would be used to set their priority too. Perhaps we can say: .
To me it seems that the current text is more accurate. While a PRIORITY frame might use a placeholder to designate the target, what is actually prioritized is the stream that carries the response. The transmission of the placeholder itself is never prioritized.
But the PRIORITY frame contains the Prioritized Element ID field, that allows us to set the priority of Placeholder type.
Yeah, my view is that it is an act of prioritizing a stream by specifying a placeholder ID that maps to the stream. Section 5.3 talks about prioritizing "streams".
That's a good observation, so I'd go further to say that IMO the textual description of H3 prioritisation is not completely aligned with the protocol mechanisms. Cue NAME to tell me I am completely off the mark :)
Also, the table of prioritized element types in seems to be duplicated
The two tables in section 4.2.3 are slightly different.
Correct, I just independently spotted that. Its logical but a bit annoying
makes some basic edits to section 4.2.3, adding Table captions and linking to them from the paragraph above. It reworks 5.3 slightly to reframe the language toward describing a tree of abstract elements but still provides concrete examples of request prioritisation.
Yeah, there was originally one table and I had to split it to accommodate the current design. If anyone sees an elegant way to recombine them, I'm fully supportive.
I thought perhaps make the labels multi line and then combine the last two columns of the second table onto the first. So there would be two colums containing two sub columns each, plus the left most bits column. I don't know the Markdown foo to make that happen though.
NAME My bad. I was confused. I now understand the issue and think that the PR will provide us the necessary fixes.
A comment on this text: we should be prioritizing requests and maybe pushes, not streams.
That's a fair point I'll see if I can incorporate that into the PR
Yes, I like this formulation better.

Discussion:
which is not yet in the tree.  Such elements are added to the tree with the requested priority. <del> When a prioritized element is first created it has a default inital </del> <ins> When a prioritized element is first created, it has a default initial </ins> weight of 16 and a default dependency.  Requests and placeholders are <del> dependent on the root of the priority tree, pushes are dependent on </del> <ins> dependent on the root of the priority tree; pushes are dependent on </ins> the client request on which the PUSH_PROMISE frame was sent. Requests may override the default intial values by including a PRIORTIY frame (see frame-priority) at the beginning of the stream. <del> Pushes and placeholders may be later updated by sending a PRIORITY frame on the control stream. </del> <ins> These priorities can be updated by sending a PRIORITY frame on the control stream. </ins> 5.3.1.
Change:
All other frame types in section 4 explicitly call out which stream types are allowed. For example DATA: If a DATA frame is received on either control stream, the recipient MUST respond with a connection error (Section 8) of type HTTPWRONGSTREAM.
FWIW this is explained in section 5. But I agree that conistency in the frame descriptions could help.

Discussion:
4.2.6. The PUSH_PROMISE frame (type=0x05) is used to carry a promised <del> request header set from server to client, as in HTTP/2. </del> <ins> request header set from server to client on a request stream, as in HTTP/2. </ins> The payload consists of:

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 either control stream, the recipient MUST respond with a connection error (errors) of type HTTP_WRONG_STREAM. </ins> See server-push for a description of the overall server push mechanism.
Change:
The transport Draft states: This guidance was added to the HTTP Draft in , but was subsequently removed.
I guess that something to discuss in the applicability draft as well
Looks like made this text more generic, leaving the specifics of how to keep a connection alive (e.g. with PING frames) to the transport implementation. The text in question is now in Section 5.1: It's possible the transport draft needs a similar generalization, to recommend implementations expose a way for the application layer to control whether an connection is idle.
Actually there is a section on "Session resumption versus Keep-alive" in the applicability draft already. Do we need to say more? Is that needed in the transport draft as well?
In , the direction of the discussion is that PING frames are an application-layer concept that won't necessarily be directly under the application-layer's control. The HTTP draft currently says: This should be reworded in terms of requesting the transport stack to keep the connection from idling out, rather than directly discussing PING frames.
Or maybe we just need to kinds of PING?
Gah! Not more types of PING please!
KEEPTHECARRUNNING frame (ID=0xAF)

Discussion:
than the server's advertised idle timeout, and SHOULD do so if approaching the idle timeout. <del> HTTP clients are expected to use QUIC PING frames to keep connections open while there are responses outstanding for requests or server pushes.  If the client is not expecting a response from the server, allowing an idle connection to time out is preferred over expending effort maintaining a connection that might not be needed.  A gateway MAY use PING to maintain connections in anticipation of need rather than incur the latency cost of connection establishment to servers. Servers SHOULD NOT use PING frames to keep a connection open. </del> <ins> HTTP clients are expected to request that the transport keep connections open while there are responses outstanding for requests or server pushes, as described in Section 19.2 of QUIC-TRANSPORT.  If the client is not expecting a response from the server, allowing an idle connection to time out is preferred over expending effort maintaining a connection that might not be needed.  A gateway MAY maintain connections in anticipation of need rather than incur the latency cost of connection establishment to servers.  Servers SHOULD NOT actively keep connections open. </ins> 6.2.
Change:
Editorial because it now says what we originally thought it said, but design because it is changing normative language. Does not interact with .
The following text is kind of hard to track: I'm not really following what's going on here. The server knows that it has two addresses and it wants to use its preferred address. Why does it have to probe from its preferred address. Also, I don't understand how these two paragraphs work together. The first one says you have to send probing packets from your original address but the second paragraph tells you to probe from the preferrd address.
You're right, that last restriction in the first paragraph looks backwards. IIRC, it's supposed to be a reiteration of the fact that the client decides when to actually cut over, so the server shouldn't be sending non-probing packets from the preferred address until the client starts sending them there. This is section 9.6.2 of Transport.
I think that the first paragraph is just missing "... until it receives a non-probing packet from the client at its preferred address." Then maybe a simple: "The server MUST probe on the path toward its preferred address before sending non-probing packets."

Discussion:
A server might receive a packet addressed to its preferred IP address at any time after it accepts a connection.  If this packet contains a PATH_CHALLENGE frame, the server sends a PATH_RESPONSE frame as per <del> migrate-validate.  The server MAY send other non-probing frames from its preferred address, but MUST continue sending all probing packets from its original IP address. </del> <ins> migrate-validate.  The server MUST send other non-probing frames from its original address until it receives a non-probing packet from the client at its preferred address and until the server has validated the new path. </ins> <del> The server SHOULD also initiate path validation of the client using its preferred address and the address from which it received the client probe.  This helps to guard against spurious migration </del> <ins> The server MUST probe on the path toward the client from its preferred address.  This helps to guard against spurious migration </ins> initiated by an attacker. Once the server has completed its path validation and has received a
Change:
Explicitly state that round trip time is abbreviated as RTT
In the recovery draft, RTT is briefly spelled out in section 5 but is used in several earlier sections. SRTT and PTO are not explained at all, it seems. TLP is spelled out. RTO has a section of its own but it referenced before that. The recovery doc cannot be a tutorial on transmission theory, but it would be helpful to list the key acronyms and possibly reference an RFC with more details. There are already sections summarising key variables in pseudocode. There are references at the end, but the reader would have to go through them all.
Yes, thanks for the note. I'm planning to do a cleanup of that doc soon.
I fixed defined RTT earlier in .

Discussion:
number space.  Separate packet number spaces ensures acknowledgement of packets sent with one level of encryption will not cause spurious retransmission of packets sent with a different encryption level. <del> Congestion control and RTT measurement are unified across packet number spaces. </del> <ins> Congestion control and round-trip time (RTT) measurement are unified across packet number spaces. </ins> 3.1.2.

5. <del> RTT is calculated when an ACK frame arrives by computing the difference between the current time and the time the largest acked packet was sent.  An RTT sample MUST NOT be taken for a packet that is not newly acknowledged or not ack-eliciting. </del> <ins> Round-trip time (RTT) is calculated when an ACK frame arrives by computing the difference between the current time and the time the largest acked packet was sent.  An RTT sample MUST NOT be taken for a packet that is not newly acknowledged or not ack-eliciting. </ins> When RTT is calculated, the ack delay field from the ACK frame SHOULD be limited to the max_ack_delay specified by the peer.  Limiting

QUIC senders use both ack information and timeouts to detect lost packets, and this section provides a description of these algorithms. <del> Estimating the network round-trip time (RTT) is critical to these algorithms and is described first. </del> If a packet is lost, the QUIC transport needs to recover from that loss, such as by retransmitting the data, sending an updated frame,
Change:
This makes the encoding and decoding pseudo-code more symmetric. "Alternatively" might not be the best word here, because it might imply that the implementation has a choice. In a section about encoding Required Insert Count, it is more pure to talk about Required Insert Count being zero than to talk about whether references are made to the dynamic table.
Also, CI failed because the line is too long

Discussion:
Required Insert Count to determine when it is safe to process the rest of the block. <del> If no references are made to the dynamic table, a value of 0 is encoded.  Alternatively, where the Required Insert Count is greater than zero, the encoder transforms it as follows before encoding: </del> <ins> The encoder transforms the Required Insert Count as follows before encoding: </ins> Here "MaxEntries" is the maximum number of entries that the dynamic table can have.  The smallest entry has empty name and value strings
Change:
Currently the draft is inconsistent: if the Required Insert Count value in a header block is smaller than dictated by the referenced dynamic table entries, {{overview-hol-avoidance}} says the decoder MAY treat this as a stream error, while {{invalid-references}} says it MUST. This PR seeks to clarify this.

Discussion:
Each header block contains a Required Insert Count, the lowest possible value for the Insert Count with which the header block can <del> be decoded.  For a header block with no references to the dynamic table, the Required Insert Count is zero. </del> <ins> be decoded.  For a header block with references to the dynamic table, the Required Insert Count is one larger than the largest Absolute Index of all referenced dynamic table entries.  For a header block with no references to the dynamic table, the Required Insert Count is zero. If the decoder encounters a header block with a Required Insert Count value larger than defined above, it MAY treat this as a stream error of type HTTP_QPACK_DECOMPRESSION_FAILED.  If the decoder encounters a header block with a Required Insert Count value smaller than defined above, it MUST treat this as a stream error of type HTTP_QPACK_DECOMPRESSION_FAILED as prescribed in invalid-references. </ins> When the Required Insert Count is zero, the frame contains no references to the dynamic table and can always be processed

becomes greater than or equal to the Required Insert Count for all header blocks the decoder has started reading from the stream. <del> If the decoder encounters a header block where the largest Absolute Index used is not equal to the largest value permitted by the Required Insert Count, it MAY treat this as a stream error of type HTTP_QPACK_DECOMPRESSION_FAILED. </del> The SETTINGS_QPACK_BLOCKED_STREAMS setting (see configuration) specifies an upper bound on the number of streams which can be blocked.  An encoder MUST limit the number of streams which could