Skip to content

Commit 4dbc1b1

Browse files
committed
enable duvet for h3-datagrams
1 parent 778b6f4 commit 4dbc1b1

3 files changed

Lines changed: 180 additions & 7 deletions

File tree

.duvet/snapshot.txt

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,3 +865,161 @@ SPECIFICATION: https://www.rfc-editor.org/rfc/rfc9114
865865
TEXT[!MUST,exception]: values of N (that is, 0x21, 0x40, ..., through 0x3ffffffffffffffe)
866866
TEXT[!MUST,exception]: MUST NOT be assigned by IANA and MUST NOT appear in the listing of
867867
TEXT[!MUST,exception]: assigned values.
868+
869+
SPECIFICATION: https://www.rfc-editor.org/rfc/rfc9297
870+
SECTION: [HTTP Datagrams](#section-2)
871+
TEXT[!MUST]: HTTP Datagrams MUST only be sent with an association to an HTTP
872+
TEXT[!MUST]: request that explicitly supports them.
873+
TEXT[!MUST]: If an HTTP Datagram is received and it is associated with a request
874+
TEXT[!MUST]: that has no known semantics for HTTP Datagrams, the receiver MUST
875+
TEXT[!MUST]: terminate the request.
876+
TEXT[!MUST]: If HTTP/3 is in use, the request stream MUST
877+
TEXT[!MUST]: be aborted with H3_DATAGRAM_ERROR (0x33).
878+
TEXT[!MAY]: HTTP extensions MAY
879+
TEXT[!MAY]: override these requirements by defining a negotiation mechanism and
880+
TEXT[!MAY]: semantics for HTTP Datagrams.
881+
882+
SECTION: [HTTP/3 Datagrams](#section-2.1)
883+
TEXT[!MUST]: Receipt of an HTTP/3 Datagram that includes a larger value MUST be
884+
TEXT[!MUST]: treated as an HTTP/3 connection error of type H3_DATAGRAM_ERROR
885+
TEXT[!MUST]: (0x33).
886+
TEXT[!MUST]: Receipt of a QUIC DATAGRAM frame whose payload is too short to allow
887+
TEXT[!MUST]: parsing the Quarter Stream ID field MUST be treated as an HTTP/3
888+
TEXT[!MUST]: connection error of type H3_DATAGRAM_ERROR (0x33).
889+
TEXT[!MUST]: HTTP/3 Datagrams MUST NOT be sent unless the corresponding stream's
890+
TEXT[!MUST]: send side is open.
891+
TEXT[!MUST]: If a datagram is received after the corresponding
892+
TEXT[!MUST]: stream's receive side is closed, the received datagrams MUST be
893+
TEXT[!MUST]: silently dropped.
894+
TEXT[!MUST]: If an HTTP/3 Datagram is received and its Quarter Stream ID field
895+
TEXT[!MUST]: maps to a stream that has not yet been created, the receiver SHALL
896+
TEXT[!MUST]: either drop that datagram silently or buffer it temporarily (on the
897+
TEXT[!MUST]: order of a round trip) while awaiting the creation of the
898+
TEXT[!MUST]: corresponding stream.
899+
TEXT[!SHOULD]: If an HTTP/3 Datagram is received and its Quarter Stream ID field
900+
TEXT[!SHOULD]: maps to a stream that cannot be created due to client-initiated
901+
TEXT[!SHOULD]: bidirectional stream limits, it SHOULD be treated as an HTTP/3
902+
TEXT[!SHOULD]: connection error of type H3_ID_ERROR.
903+
TEXT[!MAY]: Future extensions MAY define how to prioritize datagrams and MAY
904+
TEXT[!MAY]: define signaling to allow communicating prioritization preferences.
905+
906+
SECTION: [The SETTINGS_H3_DATAGRAM HTTP/3 Setting](#section-2.1.1)
907+
TEXT[!MUST]: The value of the SETTINGS_H3_DATAGRAM setting MUST be either 0 or 1.
908+
TEXT[!MUST]: If the SETTINGS_H3_DATAGRAM setting is
909+
TEXT[!MUST]: received with a value that is neither 0 nor 1, the receiver MUST
910+
TEXT[!MUST]: terminate the connection with error H3_SETTINGS_ERROR.
911+
TEXT[!MUST,implementation]: QUIC DATAGRAM frames MUST NOT be sent until the SETTINGS_H3_DATAGRAM
912+
TEXT[!MUST,implementation]: setting has been both sent and received with a value of 1.
913+
TEXT[!MAY]: When clients use 0-RTT, they MAY store the value of the server's
914+
TEXT[!MAY]: SETTINGS_H3_DATAGRAM setting.
915+
TEXT[!MUST]: When servers decide to accept
916+
TEXT[!MUST]: 0-RTT data, they MUST send a SETTINGS_H3_DATAGRAM setting greater
917+
TEXT[!MUST]: than or equal to the value they sent to the client in the connection
918+
TEXT[!MUST]: where they sent them the NewSessionTicket message.
919+
TEXT[!MUST]: If a client
920+
TEXT[!MUST]: stores the value of the SETTINGS_H3_DATAGRAM setting with their 0-RTT
921+
TEXT[!MUST]: state, they MUST validate that the new value of the
922+
TEXT[!MUST]: SETTINGS_H3_DATAGRAM setting sent by the server in the handshake is
923+
TEXT[!MUST]: greater than or equal to the stored value; if not, the client MUST
924+
TEXT[!MUST]: terminate the connection with error H3_SETTINGS_ERROR.
925+
TEXT[!SHOULD]: It is RECOMMENDED that implementations that support receiving HTTP/3
926+
TEXT[!SHOULD]: Datagrams always send the SETTINGS_H3_DATAGRAM setting with a value
927+
TEXT[!SHOULD]: of 1, even if the application does not intend to use HTTP/3
928+
TEXT[!SHOULD]: Datagrams.
929+
930+
SECTION: [The Capsule Protocol](#section-3.2)
931+
TEXT[!SHOULD]: Because new protocols or extensions might define new Capsule Types,
932+
TEXT[!SHOULD]: intermediaries that wish to allow for future extensibility SHOULD
933+
TEXT[!SHOULD]: forward Capsules without modification unless the definition of the
934+
TEXT[!SHOULD]: Capsule Type in use specifies additional intermediary processing.
935+
TEXT[!SHOULD]: In
936+
TEXT[!SHOULD]: particular, intermediaries SHOULD forward Capsules with an unknown
937+
TEXT[!SHOULD]: Capsule Type without modification.
938+
TEXT[!MUST]: Endpoints that receive a Capsule with an unknown Capsule Type MUST
939+
TEXT[!MUST]: silently drop that Capsule and skip over it to parse the next
940+
TEXT[!MUST]: Capsule.
941+
TEXT[!MAY]: A future extension MAY
942+
TEXT[!MAY]: define a new Capsule Type to carry HTTP content.
943+
TEXT[!MUST]: The Capsule Protocol MUST NOT be used with messages that contain
944+
TEXT[!MUST]: Content-Length, Content-Type, or Transfer-Encoding header fields.
945+
TEXT[!MUST]: Additionally, HTTP status codes 204 (No Content), 205 (Reset
946+
TEXT[!MUST]: Content), and 206 (Partial Content) MUST NOT be sent on responses
947+
TEXT[!MUST]: that use the Capsule Protocol.
948+
TEXT[!MUST]: A receiver that observes a violation
949+
TEXT[!MUST]: of these requirements MUST treat the HTTP message as malformed.
950+
TEXT[!SHOULD]: This approach SHOULD be avoided because it can consume
951+
TEXT[!SHOULD]: flow control in underlying layers, and that might lead to deadlocks
952+
TEXT[!SHOULD]: if the Capsule data exhausts the flow control window.
953+
954+
SECTION: [Error Handling](#section-3.3)
955+
TEXT[!MUST]: When a receiver encounters an error processing the Capsule Protocol,
956+
TEXT[!MUST]: the receiver MUST treat it as if it had received a malformed or
957+
TEXT[!MUST]: incomplete HTTP message.
958+
TEXT[!MUST]: Each Capsule's payload MUST contain exactly the fields identified in
959+
TEXT[!MUST]: its description.
960+
TEXT[!MUST]: A Capsule payload that contains additional bytes
961+
TEXT[!MUST]: after the identified fields or a Capsule payload that terminates
962+
TEXT[!MUST]: before the end of the identified fields MUST be treated as it if were
963+
TEXT[!MUST]: a malformed or incomplete message.
964+
TEXT[!MUST]: In particular, redundant length
965+
TEXT[!MUST]: encodings MUST be verified to be self-consistent.
966+
TEXT[!MUST]: If the receive side of a stream carrying Capsules is terminated
967+
TEXT[!MUST]: cleanly (for example, in HTTP/3 this is defined as receiving a QUIC
968+
TEXT[!MUST]: STREAM frame with the FIN bit set) and the last Capsule on the stream
969+
TEXT[!MUST]: was truncated, this MUST be treated as if it were a malformed or
970+
TEXT[!MUST]: incomplete message.
971+
972+
SECTION: [The Capsule-Protocol Header Field](#section-3.4)
973+
TEXT[!MUST]: Its value MUST be a Boolean; any
974+
TEXT[!MUST]: other value type MUST be handled as if the field were not present by
975+
TEXT[!MUST]: recipients (for example, if this field is included multiple times,
976+
TEXT[!MUST]: its type will become a List and the field will be ignored).
977+
TEXT[!MUST]: Receivers MUST ignore unknown parameters.
978+
TEXT[!MAY]: Intermediaries MAY use this header field to allow processing of HTTP
979+
TEXT[!MAY]: Datagrams for unknown HTTP upgrade tokens.
980+
TEXT[!MUST]: The Capsule-Protocol header field MUST NOT be used on HTTP responses
981+
TEXT[!MUST]: with a status code that is both different from 101 (Switching
982+
TEXT[!MUST]: Protocols) and outside the 2xx (Successful) range.
983+
TEXT[!SHOULD]: When using the Capsule Protocol, HTTP endpoints SHOULD send the
984+
TEXT[!SHOULD]: Capsule-Protocol header field to simplify intermediary processing.
985+
TEXT[!MAY]: Definitions of new HTTP upgrade tokens that use the Capsule Protocol
986+
TEXT[!MAY]: MAY alter this recommendation.
987+
988+
SECTION: [The DATAGRAM Capsule](#section-3.5)
989+
TEXT[!MAY]: In
990+
TEXT[!MAY]: other words, an intermediary MAY send a DATAGRAM Capsule to forward
991+
TEXT[!MAY]: an HTTP Datagram that was received in a QUIC DATAGRAM frame and vice
992+
TEXT[!MAY]: versa.
993+
TEXT[!MUST]: Intermediaries MUST NOT perform this re-encoding unless they
994+
TEXT[!MUST]: have identified the use of the Capsule Protocol on the corresponding
995+
TEXT[!MUST]: request stream; see Section 3.2.
996+
TEXT[!SHOULD]: If an intermediary receives an HTTP Datagram in a QUIC DATAGRAM frame
997+
TEXT[!SHOULD]: and is forwarding it on a connection that supports QUIC DATAGRAM
998+
TEXT[!SHOULD]: frames, the intermediary SHOULD NOT convert that HTTP Datagram to a
999+
TEXT[!SHOULD]: DATAGRAM Capsule.
1000+
TEXT[!SHOULD]: If the HTTP Datagram is too large to fit in a
1001+
TEXT[!SHOULD]: DATAGRAM frame (for example, because the Path MTU (PMTU) of that QUIC
1002+
TEXT[!SHOULD]: connection is too low or if the maximum UDP payload size advertised
1003+
TEXT[!SHOULD]: on that connection is too low), the intermediary SHOULD drop the HTTP
1004+
TEXT[!SHOULD]: Datagram instead of converting it to a DATAGRAM Capsule.
1005+
TEXT[!SHOULD]: Implementations SHOULD take those limits into account when parsing
1006+
TEXT[!SHOULD]: DATAGRAM Capsules.
1007+
TEXT[!SHOULD]: If an incoming DATAGRAM Capsule has a length that
1008+
TEXT[!SHOULD]: is known to be so large as to not be usable, the implementation
1009+
TEXT[!SHOULD]: SHOULD discard the Capsule without buffering its contents into
1010+
TEXT[!SHOULD]: memory.
1011+
TEXT[!SHOULD]: This SHOULD be avoided, because it can
1012+
TEXT[!SHOULD]: cause flow control problems; see Section 3.2.
1013+
TEXT[!SHOULD]: However, new HTTP extensions that
1014+
TEXT[!SHOULD]: wish to use HTTP Datagrams SHOULD use the Capsule Protocol, as
1015+
TEXT[!SHOULD]: failing to do so will make it harder for the HTTP extension to
1016+
TEXT[!SHOULD]: support versions of HTTP other than HTTP/3 and will prevent
1017+
TEXT[!SHOULD]: interoperability with intermediaries that only support the Capsule
1018+
TEXT[!SHOULD]: Protocol.
1019+
1020+
SECTION: [Capsule Types](#section-5.4)
1021+
TEXT[!MUST]: In addition to those common fields, all
1022+
TEXT[!MUST]: registrations in this registry MUST include a "Capsule Type" field
1023+
TEXT[!MUST]: that contains a short name or label for the Capsule Type.
1024+
TEXT[!MUST]: These values MUST NOT be assigned by IANA
1025+
TEXT[!MUST]: and MUST NOT appear in the listing of assigned values.

h3-datagram/src/datagram.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,25 @@ where
3333

3434
/// Decodes a datagram frame from the QUIC datagram
3535
pub fn decode(mut buf: B) -> Result<Self, InternalConnectionError> {
36+
//= https://www.rfc-editor.org/rfc/rfc9297#section-2.1
37+
//# Receipt of a QUIC DATAGRAM frame whose payload is too short to allow
38+
//# parsing the Quarter Stream ID field MUST be treated as an HTTP/3
39+
//# connection error of type H3_DATAGRAM_ERROR (0x33).
3640
let q_stream_id = VarInt::decode(&mut buf).map_err(|_| {
3741
InternalConnectionError::new(Code::H3_DATAGRAM_ERROR, "invalid stream id".to_string())
3842
})?;
3943

4044
//= https://www.rfc-editor.org/rfc/rfc9297#section-2.1
41-
// Quarter Stream ID: A variable-length integer that contains the value of the client-initiated bidirectional
42-
// stream that this datagram is associated with divided by four (the division by four stems
43-
// from the fact that HTTP requests are sent on client-initiated bidirectional streams,
44-
// which have stream IDs that are divisible by four). The largest legal QUIC stream ID
45-
// value is 262-1, so the largest legal value of the Quarter Stream ID field is 260-1.
46-
// Receipt of an HTTP/3 Datagram that includes a larger value MUST be treated as an HTTP/3
47-
// connection error of type H3_DATAGRAM_ERROR (0x33).
45+
//# Quarter Stream ID: A variable-length integer that contains the value
46+
//# of the client-initiated bidirectional stream that this datagram is
47+
//# associated with divided by four (the division by four stems from
48+
//# the fact that HTTP requests are sent on client-initiated
49+
//# bidirectional streams, which have stream IDs that are divisible by
50+
//# four). The largest legal QUIC stream ID value is 2^62-1, so the
51+
//# largest legal value of the Quarter Stream ID field is 2^60-1.
52+
//# Receipt of an HTTP/3 Datagram that includes a larger value MUST be
53+
//# treated as an HTTP/3 connection error of type H3_DATAGRAM_ERROR
54+
//# (0x33).
4855
let stream_id = StreamId::try_from(u64::from(q_stream_id) * 4).map_err(|_| {
4956
InternalConnectionError::new(Code::H3_DATAGRAM_ERROR, "invalid stream id".to_string())
5057
})?;

h3-datagram/src/datagram_handler.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ mod tests {
185185
}
186186
}
187187

188+
//= https://www.rfc-editor.org/rfc/rfc9297#section-2.1.1
189+
//= type=test
190+
//# QUIC DATAGRAM frames MUST NOT be sent until the SETTINGS_H3_DATAGRAM
191+
//# setting has been both sent and received with a value of 1.
188192
#[test]
189193
fn refuses_send_when_datagrams_not_negotiated() {
190194
let mut s = sender::create(Arc::new(SharedState::default()));
@@ -195,6 +199,10 @@ mod tests {
195199
assert_eq!(s.handler.calls, 0);
196200
}
197201

202+
//= https://www.rfc-editor.org/rfc/rfc9297#section-2.1.1
203+
//= type=test
204+
//# QUIC DATAGRAM frames MUST NOT be sent until the SETTINGS_H3_DATAGRAM
205+
//# setting has been both sent and received with a value of 1.
198206
#[test]
199207
fn sends_when_datagrams_negotiated() {
200208
let mut s = {

0 commit comments

Comments
 (0)