Draft: draft-ietf-masque-h3-datagram

Commentary: This PR attempts to meet the majority of requirements from the design team 's discussion on 2021 - 11 - 15 , while removing all other features . Note that this PR is against the design team consensus branch , not main . . . 
 High level comments : Do we need to be as generic about transparent and opaque now ? Perhaps we can strictly state how an intermediary can convert between native DATAGRAMs and Datagram Capsules in both directions , and must forward any other capsules unmodified unless otherwise specified in a capsule 's definition . If we are baking the Datagram Capsule into The Capsule Protocol ( TCP - sorry , could n't resist ) with a code point in this document , then is it safe to say that the intended usage is for conveying datagrams and optional request related information over a request stream ? Eg : can another document specify the use " Capsule Protocol " but forbid the transmission of Datagram capsules , or does it become a different protocol at that point ? Note that WebTransport over H3 may do exactly this , since that protocol requires QUIC DATAGRAMs . Can an application using WebTransport specify the use of Capsule Protocol for a non - request stream ? 
 IMO the use ( or prohibition ) of capsule types would be a job of a spec on top of this . The capsule protocol is still in effect even if you choose to allow only some types of capsules on it . The PR states " Note that use of the Capsule Protocol is not required to use HTTP Datagrams . " so your WT use case seems to be supported . Interesting , that might be a case where we can state something like " a future extension to the capsule protocol could describe how it can be applied to other stream types beyond client - initiated bidirectional streams " 
 I agree , I 've removed the concept of opaque vs transparent . I do n't think that 's right : WebTransport currently requires the QUIC DATAGRAM frame to be supported but it does n't require datagrams to be sent using it . I think that 's a fine place to be . As Lucas points out , WebTransport could decide to ban sending using DATAGRAM capsules while still using the capsule protocol . The capsule protocol is currently 1:1 tied to a request stream , so as specified I 'd say it ca n't be used on WebTransport streams other than the WebTransport CONNECT stream . I 'm not sure there 's a use case for that though . 
 I think we can make that even more explicit in the Section 4 intro . There 's a use case for framing on any unframed byte - stream , which WebTransport streams are . Capsule Protocol minus Datagram Capsule could serve this purpose . I 'm ok saying that 's out of scope though . 
 Agreed , some text . I 'd say that 's out of scope . Applications can decide to use " TLVs where T and L are varints " without saying it 's the capsule protocol . 
 Can we remove the " Creating a Demultiplexing Extension " section ? I find it really confusing and hard to follow and it 's unclear to me what its purpose is -- is " demultiplexing " the h3 - h2 - h3 problem , or the " identify different kinds of datagrams ( like context ID did before ) " problem ? 
 In , points out that Content - Type does n't make sense with the capsule protocol . Should we prohibit it ? 
 In , points out that status codes 204 , 205 , and 206 do n't make sense with the capsule protocol . Should we prohibit them ? 
 We 've been discussing this topic on the and on the , but rightly points out that this deserves its own issue . There is interest in deploying extensions to protocols that use HTTP Datagrams . Some of these extensions require the ability to send multiple types of HTTP datagrams associated with a single request stream . For example , an extension to CONNECT - UDP that allows measuring the HTTP Datagram MTU an extension to CONNECT - IP that allows compressing IP headers This means that when these extensions are in use , HTTP Datagrams carry an identifier that allows the receiver to know what kind of HTTP Datagram it 's receiving ( e.g. " is this a UDP payload or an MTU probe ? " or " is this a full IP packet or a compressed one ? " ) . One potential solution is to have CONNECT - UDP and CONNECT - IP require their HTTP Datagrams to always start with an identifier . This has the unfortunate downside of wasting a byte for requests that do not use extensions , and also precludes WebTransport from using extensions in the future . Alternatively , we could define an optional extension to HTTP Datagrams which has the advantage of not wasting bytes when not in use , and allows any protocol relying on HTTP Datagrams to use it if chooses to at any point in the future . This extension would be negotiated via an HTTP header . Let 's assume we are going with the model of an optional extension to HTTP Datagrams . Since this is optional , a client will not know whether it is supported by the server until it receives the response headers . " Zero - Latency Extensibility " is the ability for a client to send HTTP Datagrams ( both the " regular " datagram that 's the default one from the request , and the " extension " datagrams ) . Note that this does n't apply to the server because the server does n't send HTTP Datagrams until after it 's parsed the request headers . Let 's call the flight of frames and/or packets that go alongside the HTTP request headers the " first flight " . The requirement is for the client to be able to send both " regular " and " extension " HTTP datagrams with its first flight , and to have the server parse them as follows : if the server supports the extension , the server can correctly parse both " regular " and " extension " HTTP datagrams from the first flight ; if the server does n't support the extension , the server can correctly parse the " regular " datagrams and drop the " extension " ones . Intermediaries should n't have to know or care about this extension . All that intermediaries need to do is blindly convert between QUIC DATAGRAM frames and DATAGRAM capsules regardless of any extension being used . This puts one constraint on the solution : QUIC DATAGRAM frames and DATAGRAM capsules need to have the same semantics because they can get converted between one another by intermediaries . Solving this problem once the headers is exchanged is pretty straightforward : if both endpoints support the extension , then datagrams start with an identifier . Otherwise , they do n't contain the identifier . Getting this to work before the response headers are received is slightly more tricky : it requires having a way to distinguish between datagrams sent before the headers were received and ones sent after . The simplest way to distinguish them is to define two capsules and use the capsule type to tell us which is which . The datagram context extension works as follows : it is negotiated by adding a header to both request and response , and when both endpoints support it , it adds a context ID varint at the start of the HTTP Datagram Payload field . Now , in order to achieve zero - latency extensibility , the client needs to be able to send datagrams before receiving the server headers in such a way that the server can correctly parse them ( if you add the context ID and the server does n't support the extension , you do n't want the server to parse the context ID as part of the payload ) . So here 's my idea for how to accomplish that . The extension says the following : clients that support the extension are not allowed to send QUIC DATAGRAM frames nor DATAGRAM capsule before they 've received the server headers the extension defines a new RELIABLEDATAGRAMEXT capsule that can be sent before and after receiving server headersthe extension does not change the semantics of the RELIABLEDATAGRAM capsule , that still does not contain a Context IDwhen both endpoints support the extension ( after receiving headers ) the extension changes the semantics of both the QUIC DATAGRAM frame and DATAGRAM capsule to include a Context ID at the start : if the client wishes to use zero - latency extensibility , it can send RELIABLEDATAGRAM and RELIABLEDATAGRAMEXT before receiving the server headers . Both of these will be parsed correctly by servers , whether or not the server supports the extension . All of this relies on the fact that there is one bit that differentiates the DATAGRAM capsule from the RELIABLEDATAGRAM capsule ( the bit is in the capsule type ) , so that the extension can give the two capsules different semantics in a way that is backwards compatible . I 'm realizing that calling this RELIABLEDATAGRAM tied zero - latency extensibility to . This would work just as well if we renamed RELIABLEDATAGRAM to EARLYDATAGRAM or UNEXTENDED_DATAGRAM . 
 I do n't view it as waste . I view it as the ( extremely low ) cost of simple and performant 0 - RTT extensibility . When you make mechanisms complex , the may solve problems on paper , but no one will use them -- see HTTP/2 Priorities . Is there a more concrete argument for how this byte will cause performance problems for users of unextended CONNECT - UDP or CONNECT - IP ? If WebTransport might ever want to change the layout of H3 Datagrams , it should add an identifier now . 
 Yeah , I 'm with  on this . This design is considerably more complex and forces clients into using reliable , ordered transfer for ~1RTT if they want to use extensibility . Spending the byte or so on a type discriminator is far simpler . For WebTransport , I doubt we 'll need this . We hand off responsibility for the content of datagrams to applications . And then there is always the possibility of a WebTransport version 2 . ( Here , I am forced to acknowledge that protocol negotiation with extended CONNECT is likely a complete disaster , but now we 're far enough into speculative territory that I 'm OK with that risk . ) 
 Separately , That presumes that the negotiation of extensions that modify the payload of datagrams occurs atomically . If the extension is not negotiated atomically and uses capsules that are sent after the request , then a server might process a request and send DATAGRAM frames ignorant of the potential for extensions to be used . That creates an ambiguity at the client . The client can not know if the server has not understood the extension ( so that the datagram does n't include a context / type / usage field ) or whether it is using the extension ( so that it does ) when it receives the first DATAGRAM frame , which is likely to arrive before any negotiation signals . That means that the server also has to follow the pattern of sending datagrams as part of the stream , with the various markings you have , unless you bind the processing of extensions into the HTTP request header fields . There 's no mention of how these extensions are negotiated here , so I assume that you are planning to use HTTP header fields in order to get this . My thought would be that it is easier to do that sort of negotiation with capsules , which is what previous versions of the draft did . That this comes with this constraint on how extensions are negotiated or used makes it less appealing . 
 sorry for being unclear . Whether or not contexts are in use ( by which I mean " does the payload start with a context ID varint ? " ) is negotiated via an HTTP header . That occurs atomically . Subsequently , capsules are used to assign semantics to a given context . There 's no ambiguity on the receiver there , because if you receive a datagram for context 4 and you have n't received or understood what context 4 means you can just drop that datagram . 
 I agree that it 's much simpler to just always have the context ID be present for protocol that want to be able to tag different datagrams . This means there 's no complexity about when unreliable datagrams are allowed to be sent , or dealing with headers to try to guess how to interpret payloads . It 's much more deterministic and will be less prone to implementation bugs . 
 Since both  and Tommy specifically mentioned " Context ID " , I 'll point out that the identifier could be the context ID as currently specified in the drafts , but alternate designs are possible . 
 We should revisit . 
 A discussion of this has broken out . My understanding is that there are two major motivating reasons for this : desire for end - to - end finite - sized message . I think we resolved that capsules of any type provide this capability , so any attempt to add the capability to this draft is largely based on the desire to have a singular form . about . The latter is the interesting one . I admit that I do n't understand it well , especially the part that uses a RELIABLEDATAGRAM capsule . The desire to be able to negotiate different uses for QUIC DATAGRAM frames and for clients to be able to exercise those options prior to seeing any response from a server is very much context - specific . Lowering latency is interesting , but I do n't have a clear path from that requirement to this proposed mechanism . Low - latency extensibility for DATAGRAM frames is something that can be enabled for each protocol by defining a " usage " field in the DATAGRAM payload for that protocol . The goal here seems to be to be able to impose the use of this " usage " field on any protocol , even if that protocol did n't originally choose to allow that . That 's quite a narrow applicability : uses DATAGRAM frames ( unreliable , finite sized messages ) has multiple uses for those DATAGRAM frames has some potential uses that are unknown at the time the protocol is defined ( that naturally flows from the multiple uses scenario ) wants clients to be able to send DATAGRAM frames immediately ( which might well be a generic capability ) did n't want the overhead of an additional field in DATAGRAM frames in the original design It seems like this imposes a constraint on a client that wants to exercise this extensibility . Such a client ca n't send DATAGRAM frames immediately . It has to use RELIABLEDATAGRAM until the negotiation is complete . That seems like an undesirable property to me , but I can see some advantages to it . It 's also unclear whether a server is similarly constrained . It might answer a request without knowing that the client wants to support this extension , so it might also need to refrain from sending DATAGRAM frames until can perform the same negotiation . The simpler design alternative is to add a " usage " tag to every DATAGRAM for all protocols . That 's easy : unknown ( or unnegotiated ) usage labels are ignored . But that 's overhead and I 'm opposed to that . It says that someone defining a protocol ca n't know what they are doing ( which shows a great lack of faith , even if experience suggests that we often get this sort of thing wrong ) . No matter what path I plot , I ca n't see a path in which RELIABLE_DATAGRAM is useful . perhaps you can help us understand your vision better . That said , co - opting this issue might not be the right way to do that ; what you are talking about might be solved using other mechanisms . Perhaps we should discuss the low - latency extensibility requirement in its own issue . 
 So much this . I do n't know if I 'd call it usage , but I think any protocol that wants DATAGRAM extensibility should be using a varint at the beginning of the payload to facilitate it . Not all protocols need it . WebTransport does n't ( yet anyways ) . I do n't think we should require it in H3 Datagram . To refine the point about overhead though , I am OK with this overhead in CONNECT - UDP / CONNECT - IP if those protocols want extensibility . The < 0.1 % overhead there seems like a reasonable tradeoff . Given that I think there are better patterns for extensibility at higher layers , I do n't think RELIABLEDATAGRAM is useful at this layer . 
 I 've filed to discuss zero - latency extensibility , since RELIABLE_DATAGRAM is one potential solution but not the only possible one . 
  and I discussed this today , and came to the conclusion that , now that we 've merged the result of the design team , there is no need for this in the base HTTP Datagrams document and it can be implemented by a future extension . So I 'm closing this issue with no action . Please comment / reopen if you disagree . 
 LGTM minus figuring out what we want to do with RELIABLE_DATAGRAMS.Good direction ; some open issues to resolve , but I do n't think they block the main direction of the work . Design - wise : LGTM I made a bunch of editorial suggestions . These are non - blocking and we can consider them in follow - on work if nobody wants to change this PR up too much .
Note that use of the Capsule Protocol is not required to use HTTP
Datagrams.  Definitions of new HTTP Methods or of new HTTP Upgrade
Tokens can use HTTP Datagrams with their own data stream protocol.
This indicates that the context was closed to save resources.  The
recipient SHOULD limit its future registration of resource-
intensive contexts.
Note that while datagram capsules are sent on a stream,
intermediaries can reencode HTTP Datagrams into QUIC DATAGRAM frames
over the next hop, and those could be dropped.  Because of this,
applications have to always consider HTTP Datagrams to be unreliable,
even if they were initially sent in a capsule.
Capsules MUST be forwarded unmodified by intermediaries, with the
exception of the DATAGRAM capsule; see datagram-capsule.  An
intermediary that understands the request semantics enough to know
that capsules are in use MAY convert between QUIC DATAGRAM frames and
DATAGRAM capsules.  Definitions of new Capsule Types MAY specify
optional custom intermediary processing.
Note that while DATAGRAM capsules that are sent on a stream are
reliably delivered in order, intermediaries can reencode DATAGRAM
capsules into QUIC DATAGRAM frames when forwarding messages, which
could result in loss or reordering.
frames to datagram capsules allows HTTP Datagrams to be arbitrarily
large without suffering any loss; this can misrepresent the true path
properties, defeating methods such a DPLPMTUD.
frames to DATAGRAM capsules allows HTTP Datagrams to be arbitrarily
large without suffering any loss; this can misrepresent the true path
properties, defeating methods such as DPLPMTUD.
The value of the Datagram Format Type field (see datagram-formats)
is a 62-bit integer.
The value of the Close Code field (see close-capsule) is a 62-bit
integer.