Draft: draft-ietf-webtrans-http2

Commentary: Initial rewrite that uses WT frames on top of the HTTP flows Welcome Borrows heavily from draft - thomson - webtrans - hwtq-00 , rfc9000 , and draft - ietf - quic - datagram-02 , but tries to keep the same general document structure to parallel WT over H3 Initial outline of frame formats for WT frames , following closely along the lines of QUIC frames A few things that we 'll need to do and/or file issues for : More robust error instructions / WT connection - level errors Do we really want length in the frame header for all frames ? If so , we probably also want stream ID and to use stream 0 like h2 does . Alternately we could drop it back down like we do for QUIC , at the cost of being unable to delineate unknown frames on the underlying H2 stream ( which is a little different from the considerations at play for QUIC ) More decoupling from H2 , do we want to rename , all that sort of thing to be more purely HTTP semantics and not H/2 dependent . Did n't do that here because we are n't ( yet ) specifying any negation mechanism outside of HTTP/2 SETTINGS frames . Fix up the example for real and do some more useful examples Many more updates and general completeness 
 How does WTDATAGRAM compare to the Datagram capsule from masque ? Originally posted by in 
 Also 
 We should decide whether or not we want to use capsules in general , I think . If so , then we can use a datagram capsule and get rid of WT_DATAGRAM . ( See for more discussion ) 
 Ah , this is already covered by . 
 Since QUIC 's flow control credits work differently from H2 , it may be worth explicitly stating how this works here . Originally posted by in 
 Agreed this needs some text , has more details for flow control , closing in favor of that . 
 This field is n't necessary because of the in - order , reliable delivery of the underlying transport . That said , I 'm not opposed to leaving it here for symmetry with QUIC . We could also say - it 's unused , or what to do if this value is different from the value computed as the size of sent data on this stream ? Originally posted by in 
 I think that we should remove it . The frame format is not identical to QUIC as you have lengths to all of the frames . This is a good choice , I think , but it means that you do n't have an identical parser . As we have QUIC rules for  and we have in - order delivery , we can guarantee that there is no ambiguity about how much data was consumed from the " session " flow control limit , so the field is just another thing to check . 
 Should we make the length be first in every frame so we can strip it and use the same parser ? 
 That is an interesting suggestion . It is even ... Sort of ... Consistent with HTTP/2 . 
 I guess WebTransport frames are explicitly not capsules , but they are the same as capsules , I think ? Capsules are explicitly " TLV " . 
 Yeah , I 'm expecting we 'll have a slide at 112 about the lengths . QUIC has them for the frames where you have something that varies in length , and I put it in every frame here . Seems like the best choices are either ( a ) decide that was unnecessary and take them out or ( b ) move them to the front to make it easier . We also need to see if it would be a capsule or not . Seems like for this issue , we need to decide whether or not we 're okay keeping " useless " fields solely for the sake of looking like QUIC . If so , moving length to the front and then keeping the rest of the frame identical seems great . If not , then out with the extra and the position of length does n't matter nearly as much . Will raise at 112 so we can settle on " useless " fields . 
 Do we think that WT over H2 should be using  ? In particular it might seem silly to have two different ways to send a DATAGRAM . If we think that all WT Frames should be capsules , and we want length up front , we need to take that up in MASQUE . Besides Final Offset , are there any other " useless " fields ? 
 Chair notes from IETF 112 meeting : this is on hold pending which is itself on hold pending output of MASQUE HTTP Datagrams design team 
 Also from 112 : No strong desire to keep things exactly aligned with QUIC frames , so fine to have length in any position and to remove final length . 
 Do we talk about the stream ID numbering space here ? It could be completely scoped to the WebTransport session , which is different than H3 . Originally posted by in 
 Document how MAXDATA interacts with the enclosing HTTP/2 flow control scheme Originally posted by in 
 I tend to think we might want to have a section entirely on flow control since we 've now got several layers : HTTP/2 connection level HTTP/2 stream for the CONNECT stream WTMAXDATA for the WT session Noting that this is different than the HTTP/2 layer 's CONNECT stream , since we want to be able to indicate the sum of stream data separately from other control frames WTMAXSTREAMDATA for each WT stream And stream - count flow control HTTP/2 stream limits do n't really apply once you 've got the WT session up WTMAX_STREAMS limits stream counts within a WT session Just indicating the intended usage of each of these knobs would be helpful . 
 ( From : Since QUIC 's flow control credits work differently from H2 , it may be worth explicitly stating how this works here . ) 
 Chair notes from IETF 112 meeting : no one objected to proposal of resolving this by documenting how flow control works and pitfalls 
 Why do we need WTMAXDATA in first place ? I thought that since we have flow control from the HTTP/2 side , we do n't need it . 
 We want to be able to say " do n't send me any more data on this stream " while still allowing control frames on that stream 
 It 's possible that a WebTransport endpoint may wish to drain a session , such that the peer would know not to create new streams on that session , but existing sessions could complete before closing the session 's stream . We need something like GOAWAY , but scoped to a single session . This is useful when there are multiple sessions ( and possibly other HTTP traffic ) multiplexed on a single connection , which are routed to different upstream servers . If a single upstream server needs to restart ( and gracefully drain ) , it would be nice to not have to drain all the sessions / traffic from the client 's connection . 
 Could the Connect Stream be used for this ( since it is 1:1 a session already and the lifetime is tied to that connect stream ) ? I guess we 're already there a bit , but just resetting that stream loses the routing information you need to clean up , hence the need for something like GOAWAY , like you said . 
 I think we should let the design happen for H3 ( ) and then translate that here . 
 Done with , closing the CONNECT stream kills the session , but you can have other CONNECT streams ( and other sessions within them ) that are entirely unaffected . 
 From the : We had previously discussed that WebTransport should not be trying to reuse stream IDs that may already be present in the protocols that it 's mapped over , since those may not all have the same semantics and we wanted it to be consistent for clients . Make sure that we include explicit stream IDs in our HTTP/2 Transport description as well . 
 One interesting question here is whether or not we expect the Connect Stream to have a WebTransport Stream ID , since it 's not really intended to be used to exchange significant data . 
 makes this obsolete , we now have Stream IDs within WT_STREAMs since we 're multiplexing within a single HTTP/2 stream . Nice . 
 We should have a clear section that explains how Http2Transport fulfills the transport protocol requirements from the 
 Completed prior to 
 The contains the following text : We should consider documenting how it 's possible to send the connect frame and then the next stream , since we can guarantee in - order delivery ( and processing ? ) of the data . We can also note that this is orthogonal to 0 - RTT . 
 Will this only be possible with WT over H2 ? An HTTP request can be sent at any time over an existing connection , and it contains both information in the headers sufficient to route it to the proper destination AND potentially payload that can be acted upon as soon as it gets there . Because these are separate streams in HTTP/3 , they could arrive out of order at a proxy , which means sending independently routable messages ( which require a session and a stream ) from H3 have worse latency than H2 . It 's also strange because while the browser to edge hop may be H2 , subsequent hops may be H3 . 
 It 's possible that this would only work over HTTP/2 , which does provide an interesting inversion from the usual benefits that you get from HTTP/3 . It would be really nice if these were in a single stream in HTTP/3 as well , but I do n't really see that happening if we have CONNECT followed by other streams to which that CONNECT referred . 
 I do n't think that this is possible with any version of this design , because the client wo n't have server settings when it sends 0 - RTT . HTTP/2 assumes that default settings are in play , which makes 0 - RTT usable for regular requests , but the CONNECT here depends on a setting . That does n't seem like it is worth fixing for this mapping . I also have reservations about the value in making 0 - RTT work in the HTTP/3 mapping , but that should be taken up there . 
 This issue says that it is orthogonal to 0 - RTT . It 's about sending the CONNECT and one more WTSTREAM / WTDATAGRAMS in a single flight . The H3 draft was updated with a section saying this is allowed : 
 Yeah , the h3 draft can allow 0 - RTT , but I do n't see a way to have the h2 draft do that without taking a dependency on ALPS or some persistent settings concept . I mean , it could define its own persistent settings concept , but that seems worse than ALPS ( and I 'm not a big fan , at least for h2 ) . 
 Oops , I should have . I do n't see any reason to allow sending prior to session confirmation . You might , however , allow new streams to be created prior to getting a 200 response on the session . For that , it really depends on how you might plan to deal with resource management . Of course , if you could send data inside the primary stream , that makes this largely moot . 
 The H3 draft disallows 0 - RTT : 
 Just for clarity , we need to be able to take an already - established WT session and bring up a new stream + get data on that stream in either direction in a single roundtrip , hence the orthogonal - to-0 - RTT part . I think this is now obsolete with since it 's pretty clear that a WT_STREAM frame carries data and therefore we do n't need to say anything special to make it obvious that this is permitted . 
 Thanks for doing the heavy lifting here !
WebTransport OVERVIEW is a protocol framework that enables clients
constrained by the Web security model to communicate with a remote
server using a secure multiplexed transport.  This document describes
a WebTransport protocol that is based on HTTP/2 RFC7540 and provides
support for unidirectional streams, bidirectional streams and
datagrams, all multiplexed within the same HTTP/2 connection.
WebTransport OVERVIEW is a protocol framework that enables clients
constrained by the Web security model to communicate with a remote
server using a secure multiplexed transport.  This document describes
a WebTransport protocol that uses HTTP semantics to provide support
for unidirectional streams, bidirectional streams, and datagrams.
This protocol can be used with any HTTP version, however this
document focuses on TCP-based HTTP versions, specifically providing
examples of these capabilities when multiplexed within the same
HTTP/2 RFC7540 connection.
The repository tracking the issues for this draft can be found at
<https://github.com/ietf-wg-webtrans/draft-webtransport-http2>.  The
web API draft corresponding to this document can be found at
<https://w3c.github.io/webtransport/>.
The repository tracking the issues for this draft can be found at[]
(https://github.com/ietf-wg-webtrans/draft-webtransport-http2).  The
web API draft corresponding to this document can be found at[]
(https://w3c.github.io/webtransport/).
This protocol satisfies the WebTransport protocol framework's
requirements using HTTP semantics to provide support for
unidirectional streams, bidirectional streams, and datagrams.
By using HTTP semantics, this protocol allows deployment using any
HTTP version, although this document in particular focuses on HTTP/2
as the current most common TCP-based fallback to HTTP/3 running over
QUIC RFC9000.
This document defines a mechanism for multiplexing non-HTTP data with
HTTP/2 in a manner that conforms with the WebTransport protocol
requirements and semantics OVERVIEW.  Using the mechanism described
here, multiple WebTransport instances can be multiplexed
simultaneously with regular HTTP traffic on the same HTTP/2
connection.
This document defines a mechanism for establishing bidirectional
communication using HTTP semantics in a manner that conforms with the
WebTransport protocol requirements and semantics OVERVIEW.  When
running with HTTP/2, multiple WebTransport instances can be
multiplexed simultaneously with regular HTTP traffic on the same
HTTP/2 connection.
It is important to note that, while it is possible to have the
WebTransport session remain entirely "self contained" within a given
HTTP flow, certain HTTP versions may provide native features, such as
datagram support, which can allow for a better performing
implementation of the WebTransport client's requirements.
A datagram can be sent using a new HTTP/2 extension frame
WT_DATAGRAM.
A WebTransport session is terminated when the CONNECT stream that
created it is closed.
Both client and server can create a bidirectional or
unidirectional WebTransport stream within the WebTransport session
using a WT_STREAM frame.
A datagram can be sent using a WT_DATAGRAM frame.
Data flow on these streams is controlled via a flow control mechanism
very similar to the one provided by QUIC using WT_MAX_DATA,
WT_MAX_STREAM_DATA, WT_MAX_STREAMS, WT_DATA_BLOCKED,
WT_STREAM_DATA_BLOCKED, and WT_STREAMS_BLOCKED frames.
WebTransport streams can be closed via a WT_RESET_STREAM frame and a
receiver can request that a sender stop sending with a
WT_STOP_SENDING frame.
A WebTransport session is terminated when the CONNECT stream that
created it is closed.  This implicitly closes all WebTransport
streams that were multiplexed over that CONNECT stream.
As WebTransport sessions are established over HTTP/2, they are
identified using the "https" URI scheme RFC7230.
As WebTransport sessions are established over HTTP, they are
identified using the "https" URI scheme RFC7230.
In order to create a new WebTransport session, a client can send an
HTTP CONNECT request.  The ":protocol" pseudo-header field (RFC8441)
MUST be set to "webtransport" (Section 7.1 of WEBTRANSPORT-H3).  The
":scheme" field MUST be "https".  Both the ":authority" and the
":path" value MUST be set; those fields indicate the desired
WebTransport server.  An "Origin" header RFC6454 MUST be provided
within the request.
Upon receiving an extended CONNECT request with a ":protocol" field
set to "webtransport", the HTTP/2 server can check if it has a
WebTransport server associated with the specified ":authority" and
":path" values.  If it does not, it SHOULD reply with status code 404
(Section 6.5.4, RFC7231).  If it does, it MAY accept the session by
replying with status code 200.  The WebTransport server MUST verify
the "Origin" header to ensure that the specified origin is allowed to
access the server in question.
In order to create a new WebTransport session, a client can send an
HTTP CONNECT request.  The ":protocol" pseudo-header field (RFC8441)
MUST be set to "webtransport" (Section 7.1 of WEBTRANSPORT-H3).  The
":scheme" field MUST be "https".  Both the ":authority" and the
":path" value MUST be set; those fields indicate the desired
WebTransport server.  An "Origin" header { {!RFC6454}} MUST be
provided within the request.
Upon receiving an extended CONNECT request with a ":protocol" field
set to "webtransport", the HTTP server can check if it has a
WebTransport server associated with the specified ":authority" and
":path" values.  If it does not, it SHOULD reply with status code 404
(Section 6.5.4,RFC7231).  If it does, it MAY accept the session by
replying with status code 200.  The WebTransport server MUST verify
the "Origin" header to ensure that the specified origin is allowed to
access the server in question.
From the client's perspective, a WebTransport session is established
when the client receives a 200 response.  From the server's
perspective, a session is established once it sends a 200 response.
Both endpoints MUST NOT open any streams or send any datagrams on a
given session before that session is established.
From the client's perspective, a WebTransport session is established
when the client receives a 200 response.  From the server's
perspective, a session is established once it sends a 200 response.
Both endpoints MUST NOT send any WebTransport frames on a given
session before that session is established.
WebTransport over HTTP/2 provides the following features described in
OVERVIEW: unidirectional streams, bidirectional streams and
datagrams, initiated by either endpoint.
Session IDs are used to demultiplex streams and datagrams belonging
to different WebTransport sessions.  On the wire, session IDs are
encoded using a 31-bit integer field.
A new HTTP/2 frame called WT_STREAM is introduced for either endpoint
to establish WebTransport streams.  WT_STREAM frames can be sent on a
stream in the "idle", "reserved (local)", "open", or "half-closed
(remote)" state.
UNIDIRECTIONAL (0x1): When set, the stream begins in the "half-closed
(remote)" state at the sender, and in the "half-closed (local)" state
at the receiver.
As with all HTTP/2 streams, WebTransport streams initiated by a
client have odd stream IDs and those initiated by a server have even
stream IDs.
The recipient MUST respond with a stream error of type
WT_STREAM_ERROR if the specified WebTransport Connect Stream does not
exist, is not a stream established via extended CONNECT to use the
"webtransport" protocol, or if it is in the "closed" or "half-closed
(remote)" stream state.
The RST_STREAM frame defined in HTTP/2 moves a stream to the "closed"
state, but WebTransport streams can be reset unidirectionally, as in
QUIC and HTTP/3.  A new HTTP/2 frame called WT_RST_STREAM is
introduced for an endpoint to unidirectionally reset a stream for
writing.  WT_RST_STREAM frames can be sent on a stream in the "open",
or "half-closed (remote)" state.
The WT_RST_STREAM frame contains a single unsigned, 32-bit integer
identifying the error code.  The error code indicates why the stream
is being abruptly terminated for writing.
The WT_RST_STREAM frame does not define any flags.
The WT_RST_STREAM frame half-closes the referenced stream and effects
the same state machine transitions as sending or receiving the
END_STREAM flag.  If the sender is in the "open" state, it
transitions to "half-closed (local)".  If the sender is in the "half-
closed (remote)" state, it transitions to "closed".  If the receiver
is in the "open" state, it transitions to "half-closed (remote)".  If
the receiver is in the "half-closed (local)" state, it transitions to
"closed".
After sending a WT_RST_STREAM on a stream, the sender MUST NOT send
additional DATA frames for that stream.  If another frame is received
on a stream after receiving a WT_RST_STREAM, the recipient MUST treat
this as a connection error of type PROTOCOL_ERROR.
WT_RST_STREAM frames MUST be associated with a WebTransport stream.
If a WT_RST_STREAM frame is received with a stream identifier of 0x0,
or a request or push stream, the recipient MUST treat this as a
connection error of type PROTOCOL_ERROR.
WT_RST_STREAM frames MUST NOT be sent for a stream in any state other
than "open" or "half-closed (remote)".  If a WT_RST_STREAM frame
identifying a stream in the "idle", "reserved (local)", "reserved
(remote)" state is received, the recipient MUST treat this as a
connection error (Section 5.4.1) of type PROTOCOL_ERROR.  Because of
race conditions with WT_STOP_SENDING, it is possible to receive a
WT_RST_STREAM in the "half-closed (remote)" or "closed" state.  The
recipient should ignore the frame in this case.
A WT_RST_STREAM frame with a length other than 4 octets MUST be
treated as a connection error (Section 5.4.1) of type
FRAME_SIZE_ERROR.
The RST_STREAM frame defined in HTTP/2 moves a stream to the "closed"
state, but WebTransport streams can be reset unidirectionally, as in
QUIC and HTTP/3.  A new HTTP/2 frame called WT_STOP_SENDING is
introduced for an endpoint to unidirectionally reset a stream for
reading.  WT_STOP_SENDING frames can be sent on a stream in the
"open", or "half-closed (local)" state.
The WT_STOP_SENDING frame contains a single unsigned, 32-bit integer
identifying the error code.  The error code indicates why the reading
the stream is being abandoned.
The WT_STOP_SENDING frame does not define any flags.
The WT_STOP_SENDING frame half-closes the referenced stream and
effects the same state machine transitions as sending or receiving
the END_STREAM flag.  If the sender is in the open state, it
transitions to "half-closed (remote)".  If the sender is in the
"half-closed (local)" state, it transitions to "closed".  If the
receiver is in the "open" state, it transitions to "half-closed
(local)".  If the receiver is in the "half-closed (remote)" state, it
transitions to "closed".
After receiving a WT_STOP_SENDING on a stream, the sender MUST NOT
send additional frames for that stream.  After sending the
WT_STOP_SENDING, the sending endpoint MUST be prepared to receive and
handle additional frames sent on the stream that might have been sent
by the peer prior to the arrival of the WT_STOP_SENDING.
WT_STOP_SENDING frames MUST be associated with a WebTransport stream.
If a WT_STOP_SENDING frame is received with a stream identifier of
0x0, or a request or push stream, the recipient MUST treat this as a
connection error of type PROTOCOL_ERROR.
WT_STOP_SENDING frames MUST NOT be sent for a stream in any state
other than "open" or "half-closed (local)".  It is possible to
receive a WT_STOP_SENDING in another state however, because the
sender might have closed or reset the stream while the
WT_STOP_SENDING was in flight.  If a WT_STOP_SENDING frame
identifying a stream that is already "closed" or "half-closed
(local)", the recipient SHOULD ignore the frame.
It is also possible to receive DATA frames on a WebTransport stream
in the "half-closed (remote)" or "closed" states if the stream
transitioned there via WT_STOP_SENDING.  If a DATA frame is received
on a WebTransport stream in one of these states, the recipient MUST
account for its contribution against the connection flow-control
window and MUST NOT treat it as an error.
A WT_STOP_SENDING frame with a length other than 4 octets MUST be
treated as a connection error (Section 5.4.1) of type
FRAME_SIZE_ERROR.
A new HTTP/2 frame called WT_DATAGRAM is introduced for either
endpoint to transmit a datagram.  WT_DATAGRAM frames are sent with
Stream Identifier 0.
Data: Application data.  The amount of data is the remainder of the
frame payload after subtracting the length of the other fields that
are present.
The WT_DATAGRAM frame does not define any flags.
The recipient MAY respond with a stream error of type WT_STREAM_ERROR
if the specified WebTransport Connect Stream does not exist, is not a
stream established via extended CONNECT to use the "webtransport"
protocol, or if it is in the "closed" or "half-closed (remote)"
stream state.
WebTransport over TCP-based HTTP semantics provides the following
features described in OVERVIEW: unidirectional streams, bidirectional
streams, and datagrams, initiated by either endpoint.
WebTransport streams and datagrams that belong to different
WebTransport sessions are identified by the CONNECT stream on which
they are transmitted, with one WebTransport session consuming one
CONNECT stream.
Because WebTransport over TCP-based HTTP semantics relies on the
underlying protocols to provide in order and reliable delivery, there
are some notable differences from the way in which QUIC handles
application data.
Endpoints MUST send stream data in order.  As there is no ordering
mechanism available for the receiver to reassemble incoming data,
receivers assume that all data arriving in STREAM frames is
contiguous and in order.
DATAGRAM frames are delivered to the remote WebTransport endpoint
reliably, however this does not require that the receiving
implementation deliver that data to the application in a reliable
manner.
WebTransport streams have states that mirror the states of QUIC
streams (Section 3 of RFC9000) as closely as possible to aid in ease
of implementation.
Because WebTransport does not provide an acknowledgement mechanism
for WebTransport frames, it relies on the underlying transport's in
order delivery to inform stream state transitions.  Wherever QUIC
relies on receiving an ack for a packet to transition between stream
states, WebTransport performs that transition immediately.
WebTransport frames mirror their QUIC counterparts as closely as
possible to enable maximal reuse of any applicable QUIC
infrastructure by implementors.
A WebTransport frame begins with a Frame Type and Frame Length which
are followed by zero or more fields that are type-dependent.
The Frame Type field indicates the type of the frame, defining what
type-dependent fields will be present.
The Frame Length field indicates the length of the WebTransport
frame, including all type-dependent fields and other information.  It
does not include the size of the Frame Type or Frame Length fields
themselves.
Both of these fields use a variable-length integer encoding (see
Section 16 of RFC9000), with one exception.  To ensure simple and
efficient implementations of frame parsing, the frame type and length
MUST use the shortest possible encoding.  For example, for the frame
types defined in this document, this means a single-byte encoding,
even though it is possible to encode these values as a two-, four-,
or eight-byte variable-length integer.
A WT_PADDING frame (type=0x00) has no semantic value.  PADDING frames
can be used to introduce additional data between other WebTransport
frames and can also be used to provide protection against traffic
analysis or for other reasons.
The padding extends to the end of the WT_PADDING frame and that many
bytes can be discarded by the recipient.
A WebTransport frame called WT_RESET_STREAM is introduced for either
endpoint to abruptly terminate the sending part of a WebTransport
stream.
An endpoint uses a WT_RESET_STREAM frame (type=0x04) to abruptly
terminate the sending part of a stream.
After sending a WT_RESET_STREAM, an endpoint ceases transmission and
retransmission of WT_STREAM frames on the identified stream.  A
receiver of WT_RESET_STREAM can discard any data that it already
received on that stream.
Stream ID: A variable-length integer encoding of the WebTransport
stream ID of the stream being terminated.
Application Protocol Error Code: A variable-length integer containing
the application protocol error code that indicates why the stream is
being closed.
Final Size: A variable-length integer indicating the final size of
the stream by the WT_RESET_STREAM sender, in units of bytes.  This is
the amount of flow control credit that is consumed by a stream, see
Section 4.5 of RFC9000.
A WebTransport frame called WT_STOP_SENDING is introduced to
communicate that incoming data is being discarded on receipt per
application request.  WT_STOP_SENDING requests that a peer cease
transmission on a stream.
Stream ID: A variable-length integer carrying the WebTransport stream
ID of the stream being ignored.
Application Protocol Error Code: A variable-length integer containing
the application-specified reason the sender is ignoring the stream.
The FIN bit (0x01) indicates that the frame marks the end of the
stream.  The final size of the stream is the sum of the length, in
bytes, of all data previously sent on this stream and the length of
this frame without the length of the Stream ID.
A WebTransport frame called WT_MAX_DATA is introduced to inform the
peer of the maximum amount of data that can be sent on the
WebTransport session as a whole.
Maximum Data: A variable-length integer indicating the maximum amount
of data that can be sent on the entire connection, in units of bytes.
All data sent in WT_STREAM frames counts toward this limit.  The sum
of the final sizes on all streams, including streams in terminal
states, MUST NOT exceed the value advertised by a receiver.
A WebTransport frame called WT_MAX_STREAM_DATA is introduced to
inform a peer of the maximum amount of data that can be sent on a
stream.
Stream ID: The stream ID of the affected WebTransport stream, encoded
as a variable-length integer.
Maximum Stream Data: A variable-length integer indicating the maximum
amount of data that can be sent on the identified stream, in units of
bytes.
When counting data toward this limit, an endpoint accounts for the
largest amount of data that is sent or received on the stream.  The
data sent on a stream MUST NOT exceed the largest maximum stream data
value advertised by the receiver.
A WebTransport frame called WT_MAX_STREAMS is introduced to inform
the peer of the cumulative number of streams of a given type it is
permitted to open.  A WT_MAX_STREAMS frame with a type of 0x12
applies to bidirectional streams, and a WT_MAX_STREAMS frame with a
type of 0x13 applies to unidirectional streams.
Maximum Streams: A count of the cumulative number of streams of the
corresponding type that can be opened over the lifetime of the
connection.  This value cannot exceed 2^60, as it is not possible to
encode stream IDs larger than 2^(62-1).
An endpoint MUST NOT open more streams than permitted by the current
stream limit set by its peer.  For instance, a server that receives a
unidirectional stream limit of 3 is permitted to open streams 3, 7,
and 11, but not stream 15.
Note that this limit includes streams that have been closed as well
as those that are open.
A sender SHOULD send a WT_DATA_BLOCKED frame (type=0x14) when it
wishes to send data but is unable to do so due to WebTransport
session-level flow control.  WT_DATA_BLOCKED frames can be used as
input to tuning of flow control algorithms.
Maximum Data: A variable-length integer indicating the session-level
limit at which blocking occurred.
A sender SHOULD send a WT_STREAM_DATA_BLOCKED frame (type=0x15) when
it wishes to send data but is unable to do so due to stream-level
flow control.  This frame is analogous to WT_DATA_BLOCKED.
Stream ID: A variable-length integer indicating the WebTransport
stream that is blocked due to flow control.
Maximum Stream Data: A variable-length integer indicating the offset
of the stream at which the blocking occurred.
A sender SHOULD send a WT_STREAMS_BLOCKED frame (type=0x16 or 0x17)
when it wishes to open a stream but is unable to do so due to the
maximum stream limit set by its peer.  A WT_STREAMS_BLOCKED frame of
type 0x16 is used to indicate reaching the bidirectional stream
limit, and a STREAMS_BLOCKED frame of type 0x17 is used to indicate
reaching the unidirectional stream limit.
A WT_STREAMS_BLOCKED frame does not open the stream, but informs the
peer that a new stream was needed and the stream limit prevented the
creation of the stream.
Maximum Streams: A variable-length integer indicating the maximum
number of streams allowed at the time the frame was sent.  This value
cannot exceed 2^60, as it is not possible to encode stream IDs larger
than 2^(62-1).
The WT_DATAGRAM frame type (0x31) is used to carry datagram traffic.
Frame type 0x30 is also reserved to maintain parity with QUIC, but
unused, as all WebTransport frames MUST contain a length field.
Length: A variable-length integer specifying the length of the
Datagram Data in bytes.  Note that empty (i.e., zero-length)
datagrams are allowed.
Datagram Data: The content of the datagram to be delivered.
The following entries are added to the "HTTP/2 Error Code" registry
that was established by Section 11.2 of RFC7540.