Skip to content

Commit ca01c44

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

4 files changed

Lines changed: 193 additions & 7 deletions

File tree

.duvet/config.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ pattern = "h3/**/*.rs"
66
[[specification]]
77
source = "https://www.rfc-editor.org/rfc/rfc9114"
88

9+
[[source]]
10+
pattern = "h3-datagram/**/*.rs"
11+
12+
[[specification]]
13+
source = "https://www.rfc-editor.org/rfc/rfc9297"
14+
915
[report.html]
1016
enabled = true
1117
issue-link = "https://github.com/hyperium/h3/issues"

.duvet/snapshot.txt

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