IETF 110 WEBTRANS WG Minutes Monday, March 8, 2021 08:00 - 10:00 Pacific Time Session III, Room 3 Chairs: Bernard Aboba and David Schinazi IETF 110 Info: https://www.ietf.org/how/meetings/110/ Meeting URL: https://gce.conf.meetecho.com/conference/?group=webtrans Etherpad: https://codimd.ietf.org/notes-ietf-110-webtrans Slides: https://docs.google.com/presentation/d/15u9F-YgP8mpE7gUYhfM5Bn7ZGa3AiG6GQIo2wFZgC_Y/ ## Preliminaries, Chairs (10 minutes) Note WellJabber Scribe, Etherpad Note Takers Speaking Queue Manager (David Schinazi) Agenda Bash ## W3C WebTransport Update, Will Law (10 minutes) [Slide 7 onwards] (https://datatracker.ietf.org/meeting/110/materials/slides-110-webtrans-ietf-110-webtrans-wg-01) Summary of changes from W3C since November 16 Issues currently under debate Request for the IETF: please finalize a scheme to be used, some preference was expressed for "https" ## WebTransport over HTTP/3, Victor Vasiliev (40 minutes) https://tools.ietf.org/html/draft-ietf-webtrans-http3 Goal: Resolve issues blocking shipping interoperable version of WebTransport ### [Issue 23](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/23) Proposal: use the same syntax as client-initiated bidirectional streams Alan Frindell: Aren't client-initiated bidirectional streams identified by being a CONNECT request? Ah, they have a frame type. Martin Thomson: Client ones look like they have a frame type, but don't. They have a frame "type", would this be the same? Victor Vasiliev: The proposal here is that they should behave the same, will be modifying how they work in the next slides Martin Thomson: Sounds reasonable Alan: Do we want/need a way for everyone who wants to extend server-initiated bidirectional streams to solve this? Do we want all extensions to follow the same thing so that different extensions can be demultiplexed in the same way? Should there be guidance for extension writers so that we don't need to do this over and over for each HTTP extension. David Schinazi: (as individual) Similar to how we have a document for how to use datagrams in HTTP/3, maybe what we need here is an incredibly short document that describes how you use server-initiated bidirectional streams in HTTP/3. Victor: Not entirely sure a separate draft is required as long as we pick an approach that is compatible with further extensibility. David: Makes sense, works if we tie it to a different setting from the WebTransport setting. Don't want others to need WebTransport to use their own extensions. Ian Swett: I'm not completely sure you need to talk about Settings in all circumstances, this is more about how does one extend HTTP/3. If we do this, other folks will want to make a similar decision both because it's extensible and to be consistent with this. This is more about "it's best practice not to hog all the server-initiated bidirectional streams" and this is the obvious way to do so. If HTTP/3 wasn't already so far along, I'd suggest we shove it in right there. I don't think it really matters though, I think we can just move forward with a consistent design. Martin: We don't really own HTTP/3 and we'd have to talk to the people who do, probably best for httpbis to define a generic document that says this. Would also describe what it means to use a client initiated bidirectional stream. David: Doesn't the core HTTP/3 document describe how client-initiated bidirectional streams work? They carry frames and others can extend frames. Martin: I think it currently says "carries requests" which are made of frames, so we'd want something to make it clear how general usage should work. David: (as chair) I can take an action item to reach out to httpbis chairs to understand where this should live. Alan: One more point that I raised on issue 23, has to do with the fact that unidirectional streams are identified by stream type and bidirectional streams are identified by a frame time. If you ignore that difference, they look the same at the beginning of the stream, and I take advantage of that. If anyone ever added a new frame type (?), that would break a nice symmetric implementation. It might be nice to reserve the unidirectional stream type number in the frame type space to allow for that sort of implementation. That could also be done in a separate issue. David: Thanks, Alan. Let's have Bernard and myself circle back after talking with other chairs and that will be a great issue for that document wherever it lands. ### [Issue 26](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/26) Victor: Previously said that you could have a datagram frame that went to the end of the stream (i.e. use Type-Value without Length) and avoid additional framing. Issue discussion highlighted that people don't agree that it can be omitted. Question here, if we don't have length, should we add it? David: (as individual) Personally, I think this would be a useful HTTP/3 feature to have a frame length of zero mean that it goes to the end of the stream. Got turned down when adding it to HTTP/3 at some point, but we'd need to see if people were okay with doing that in HTTP/3 or if that's specific to WebTransport. Ian: Not that strong of an opinion, although I thought we were going to use the Type Value form for this. Would be nice to put best practices in an httpbis document if we were doing it. This is a special case because if you don't understand what the type is your parser will immediately fail, so these are already special frames that are non-standard HTTP/3 frames. Alan: Recognizing that either is possible, I do have an implementation where I had to go write code that handled frames without length. Was about 3 lines, not ridiculous. Might be a reason why you could start it with length zero. Pick one or decide on best practice. Lucas Pardue: I'm kind of confused by this because if my implementation saw an extension frame that it doesn't recognize, it will try to skip that frame, but I'm not sure how I can ignore a frame where I don't know what it is if it doesn't have a length. Victor: That's why we'd define a setting, you can't send the frame without the setting. Lucas: If I don't set the setting and you send me one, then my connection is dead? The current HTTP/3 extension story is that we just ignore extension frames. Victor: Fatal error to send the frame when both parties aren't sure that it's webtransport Martin: To answer Lucas, there's provision for settings that change the way the protocol behaves. Here, you'd be saying that everything after that frame is something other than frames, etc. can bake that meaning into the setting. Seems workable.Alan's point about stream types and frame types is relevant here, as the bidirectional streams will be just stream types and not frame types. Victor: I assume that speaks in favor of not using length here. Martin: I don't think length gives you anything at this point. A length of zero doesn't help, since your parser is going to choke there anyways. Result is undefined either way, so you have to rely on the setting here. Eric Kinnear: Having something that extends-until-it-doesn't is annoying when trying to implement some of these things, probably fine here, but wouldn't want to do this generically in all cases. Alan: I like the idea that this is a different thing and that we don't overload having zero length since that can have other meaning for other frames. David: My earlier comment about trying to do something generic doesn't work based on this conversation, so I'd support doing something WebTransport specific that works via the setting. Martin: I don't think it's something we can avoid generically for bidirectional streams, but aside from that the frame stuff I think that's going to be on a per-frame type basis. ### [Issue 38](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/38) Victor: Pick a URI scheme, please. Proposal: Use "https"No real reason to make a new one, as far as we can tell they're just HTTP resources, they do require a specific HTTP method but that's not new to some HTTP resources. The main objection was that there were subtle differences in how it behaves around things like cookies and HTTP auth, specifically that it does not, but that's different from the concern around how these resources are identified. Martin: I'd support "https", this seems pretty reasonable. Jonathan Lennox asked in Jabber why "ws" was a separate stream. "ws" and "wss" are examples of what not to do in this case. We should probably just treat it as a different method on the same HTTPS resource. That would be different if it were QuicTransport, but now that we've taken this path that's a much easier decision. David: (as chair) Not seeing any opposition to going with "https" here, so unless someone wants to speak up now or on the list, I think we can assume consensus on this one and move forward. ### [Issue 10](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/10) Victor: These are less critical for interop, but still important. Stream IDs -- reconfirming what we already have. We made a decision that WebTransport would not expose the stream IDs from QUIC. In QuicTransport it might have been okay, but for HTTP and especially if there are proxies in the middle, that makes no sense whatsoever.  Wanted to reconfirm that we're not going to expose QUIC stream IDs as part of the protocol.  Luke Curley: We made the original ticket, for context we wanted to know the ordering/creation date. That's not necessarily possible with HTTP/3 transport or pooling. We might need a custom way of doing that within WebTransport. Victor: I was thinking if it was possible to preserve ordering without preserving the idea of the exact stream IDs, one question I have: when you're interested in ordering do you care about relative ordering or does this ordering need to have no gaps.  Luke: Initially we did odd/even ones for different types of streams, and we used the fact that QUIC streams are increasing. Again, that's not possible because if there's a gap we won't know if it's an HTTP request. There's no way of knowing how many streams may have been created. We can just add a header on top of the request, and that may be acceptable, tell applications to assign their own stream IDs. Jan-Ivar Bruaroey: I just wanted to make sure I understood that, I think ordering is going to be important in the API since I think framing is going to be hard for javascript developers to get right. One thing we get asked a lot is how to wrap websocket-like API onto WebTransport. Two ways: either wrap on transport itself or introduce head of line blocking on a request stream. It seems that preserving the ordering of what was sent is critical. I wanted to clarify if we were able to guarantee that order. Victor: If you send on explicit streams, you're guaranteed that order will not be preserved, preserving ordering introduces head of line blocking. Jan-Ivar: I was happy to find in the QUIC spec that stream IDs are always increasing. If we can carry that forward to the API, if you await a stream then the appearance is going to be in the order that they were sent. Victor: I don't think this is true, you don't know if the ones in the middle are even related to you. Doesn't really make sense to assume that they're going to show up in the same order. Jan-Ivar: It won't be blocking, if you get one that's newer than expected, then the receiver can create the underlying streams for the missing numbers and then populate them later. David: If packets get lost, you can't assume that the ordering is enforced. I think you'd really diminish the benefits from QUIC if you had the API enforce the order, as that introduces head of line blocking, I'm sure there are applications that don't want that.  Jan-Ivar: We're talking about API now, I think the API doesn't force the application to choose, you can choose what you want to do here. You can create dummy streams for any gaps that you see. David: Given that we're not over HTTP/3 which is a multiplexed protocol, we're going to need a new namespace, as we're not going to expose that raw stream ID from QUIC to the application as that leaks information. So the question becomes, do we introduce a new thing into WebTransport and make a new namespace, or do we ask applications to make their own header and number them according to their requirements. Martin: I think David covered most of it, unless you want to make the application aware of things that are not for it. You can't use the presence of stream 16 to assume that 12 exists and is for you. The other way around it is a notion of dedicated connection for the purposes of that application, then you can expose it because it knows that it's going to be a WebTransport stream for it. Let's push this onto the application for the header. Bernard Aboba: I think it's worth having an issue, there's a number of cases where it's the application's responsibility. Another example, we decided to not make ACKs visible in the application, since people were unclear about whether or not they need to handle their own reliability (note: if you asked for unreliable, then yes you need to handle it yourself) David: Who is going to document this? Bernard: Victor willVictor: Sure, I've got the action item Jan-Ivar: The language that I found in the QUIC spec about streams of lower numbers meaning they're opened, is that not true? Victor: They're opened but we don't know which WebTransport stream they'll be, or even if they're a WebTransport stream at all. Jan-Ivar: Once you've received data and know what it is, an application could decide to open lower numbered streams. Victor: If you do this, then you've introduced head of line blocking.If we require streams to go in order, then all future streams would be blocked. David: It sounds like the feature you're asking for is "hey I received the client initiated stream and that stream told me that there's some other stream that I want to send on". If you want to send something without the client having spoken first, why not use a server-initiated stream? Jan-Ivar: The model here is that when you create a stream, all the data inside it, then that data  has guaranteed ordering. If I split it across two streams, then I'm not guaranteed the ordered delivery of those streams. But it would be beneficial if we could surface them in creation order and I don't see how that would block anything. Framing is hard in javascript and stream IDs is an implementation of framing that we could benefit from. I'll work on clarifying how I don't consider that head of line blocking, but it would be nice to look at that in WebTransport. David: This sounds interesting, can you write something up that we can discuss offline. Luke: I think at a higher level this also applies to the next issue. In my use case, we're using QUIC for mobile platforms and then for Web support we're going to use WebTransport. There are a few QUIC features that we've been using which don't map well into WebTransport. Stream IDs and Reset are two of those things that don't map particularly well. Are we looking for QUIC or a subset of QUIC API-wise?  Victor: My intuition is that it has to be a subset, I don't think we can do a 1:1 perfect mapping. Or if we could, I'm not sure it's worth it. QUIC has a lot of semantics and some of those semantics are dictated by the fact that QUIC is a transport protocol that has to handle transport issues. Our goal is to implement as much of QUIC as possible and expose as many of the semantics of QUIC, especially those that relate to unreliability and avoidance of head of line blocking. Alan: Folks are telling us what they want from the transport, we are ignoring them and trying to build a batteries-not-included simplest version that's possible. If applications are saying that more things are possible if we tell them about the ordering that things were created, then I would be in support of building that into the protocol.  Timothy Panton: I just wanted to say in the WebRTC world we came across the same problem and we solved it by introducing a lightweight protocol that slots in a header and allows the API to label a stream. That's turned out to be super useful, if something like that is possible without having too big an overhead, then I'd be in support of that. Victor: It sounds like it's worth discussing this one more, not for the most immediate interop draft. ### [Issue 31](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/31) Victor: Issue 31 is very similar. Do we want to expose RESET_STREAM? Martin: I'd argue for the first option, declare that RESET_STREAM is not reliable. The only issue is that if someone is mixing WebTransport streams and request streams and one of them gets reset and the other one doesn't get through, then you have a weird stream that appeared and it can't tell what to do with it, but that's fine. In those cases, the endpoint that created the stream and reset it too quickly would have meant that the other side never heard about it. Luke: From an application level, if I'm using WebTransport and I create a stream to write a bunch of data and then close it with an error code. It's a reasonable expectation that the error code will make it to the other side, especially if data was sent. It seems like an invitation to future problems if people expect those codes to be reliable but they aren't due to packet loss. Victor: Is this specifically about the error code being reliable?  Luke: I think so, the fact that a stream existed and the error code both would want to be reliable. Do we need the receiver to know that the stream ever existed if it never got data? If it didn't know what protocol it was for? Martin: This is physics, if you use RESET_STREAM for this purpose, you don't get to learn about the code sometimes. The question is whether we build an additional facility into the protocol to support it, or the only way I can see of getting these through reliably is having a dedicated connection. Victor: I would say that it is possible to just make it so that reset stream error codes always arrive, and that to some extent is a solution. Martin: There is an option here that does work, that is to reserve RESET_STREAM error codes for WebTransport. There is some ambiguity if you have two tabs sharing a transport, and then each has its own WebTransport you still can't tell what's going on, but otherwise you'd be able to tell that it was for the WebTransport in question. Victor: I feel like we should reserve some space for error codes just so we can distinguish from HTTP error codes regardless.  Jan-Ivar: Yeah I just wanted to echo that I think we're going to have to find some way to make these APIs a little bit more predictable. I'm hopeful that we might be able to do so at the API leve, but it seems like this particular one, once you get a newer stream you might know that there was an earlier one that could have been reset that never existed. It sounds like the semantics are embedded in the protocol. David: I think just conceptually and fundamentally, QUIC streams are not ordered. The fact that they have IDs that are sequential is an implementation detail. Neither QUIC nor WebTransport provide this capability to upper layers. If there's a need, it would be nice to have the use cases identified. ### [Issue 28](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/28), [29](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/29) Bernard: I agree, we've encountered this in other things such as WebRTC, but you might want to have limits on the buffer. Victor: Agreed. Need to limit the state required. ### [Issue 27](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/27) Victor: Assume reverse proxy with backend that sends GOAWAY, how should this be indicated to the application/client that the session is being drained and will go away soon. Do we want to support this in WebTransport?  Alan: I just want to say that it's very important that we find a solution to this problem, we have something very similar to WebTransport today and the application that uses it has a sequence of streams and we need a way to signal "please don't start any new work, but don't prevent the creation of new streams that are required to complete the transaction associated with that session". I could see using the CONNECT stream associated with that session to signal that. Martin: I agree with Alan. The way that we've been conceptualizing GOAWAY is about requests, this is the next level down. I would imagine it would work such that GOAWAY at H3 layer says "no more requests, please", but within a WebTransport session you can still make new streams (not new sessions). Within a session you'd need a similar way to say "stop making new streams" and that could be on CONNECT. Not sure if that's needed or application can do it without additional support. ### [Issue 33](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/33) Alan: I raised this issue after I implemented a lot of this last week, I found that in my implementation this was the only reason I had to track which streams belonged to which session within the transport stack. This meant that I had to keep an extra list of things, if the higher level already has that then it can handle it. Victor: I can kind of see that argument. I definitely agree that the browser should reset the connect stream if the tab goes away. It's unclear if we should relax the requirement for non-browser implementations. Luke: Only the creator of the stream knows that it's associated to the connection, it seems like however created it should close it when the connect stream is closed.  Victor: Lucas makes a good observation that if you allow them to continue, it makes us less able to rely on CONNECT for control-stream semantics like GOAWAY, etc. ### [Issue 34](https://github.com/ietf-wg-webtrans/draft-ietf-webtrans-http3/issues/34) Victor: How does the server let the client know that pooling WebTransports is not supported? Alan: (missed this) Bernard: I'd like to speak to option 2. Option 1 would be awkward especially if linked to other things like what stats you get. Yutaka Hirano: I don't understand why the client needs to send the indiciation to the server, the client needs to wait for the first settings frame just to find out that the server supports WebTransport. I don't know that we'd need to have settings from the client to the server. Victor: I think I agree with you, but this is something we need to think about more. We might be able to get rid of the client signal. Dragana Damjanovic: You will need a client indication if it wants to use that transport or separate HTTP/3 connections and WebTransport connections to the same origin. If you don't indicate from the application that you want a separate connection, then you can pool them. If the server only wants to support one, it seems complicated to have a server that listens on the same port on the same origin but requires separate connections. Victor: The reason I want to add a dedicated from the signal is that there are developers who want to allow that sort of thing. Dragana: Then you'd need to indicate that you want to open that connection for HTTP/3 or WebTransport so the browser knows what to do. I can try to explain further on the issue. Martin: Firmly against having a dedicated flag. The decision to use HTTP/3 means you're making an HTTP connection and there are a number of other ways for a server to say that it doesn't want other requests to happen. For example, we've got 421 to say "I've got a certificate but I'm not willing to answer requests for this origin", you could also put them on their own origin. I'd also second Yutaka's point about not needing this on the client side. Victor: Sure, if you're sending HTTP requests you already know where you're sending them. But what about having two WebTransport sessions for the same client. Martin: Key point here is resource management from a server perspective, having max sessions and maybe max streams per session would be a useful control here. Eric: So this isn't even really QUIC vs. HTTP isn't more about controlling that endpoint and being able to choose what requests you respond to. Martin: Can use 406 (405?) to say "method not supported", respond to what you want to handle. ### Datagram Flows How to encode them? Come to MASQUE tomorrow. ## WebTransport using HTTP/2, Eric Kinnear (30 minutes) https://tools.ietf.org/html/draft-kinnear-webtransport-http2 Some networks don't support QUIC (nee UDP) - what is a fallback? Web traffic can go back to TCP, what does WebTransport do? Choices: fail, build your own fallback (on top of WebSockets?), or WebTransport over HTTP/2. So lets think about what WebTransport over HTTP/2 looks like. It looks similar but TCP/TLS means we lose some features or capabilities. Is this worth pursuing even if there is not feature parity? Principle 1: it's okay to require an optional feature, make it clear when creating a session via the API. It might fail and you might need to provide your own alternative. Principle 2: application needs to know what features are available in a given session. Adjust what you do based on features Principle 3: Wherever possible WebTransport over H2, should be equivalent to WebTransport over H3. Draft has been updated now that we've adopted the single draft. So is this something worth doing, are the principles sound, is modelling it after HTTP/3 transport reasonable. Bernard: WebTransport over H2 is the best solution for developers. TCP fallback is important because UDP blocking is particularly prevalent in Enterprise Networks (affecting as much as 15 percent of enterprise usage). The question is how to support fallback. Without WebTransport over H2, WebSocketStreams API (which provides a WHATWG Streams-based interface to WebSockets) could be the fallback. Unlike WebTransport over H2, which would allow an application to support fallback with a single API (WebTransport), two APIs would be needed. There are differences between WebTransport API and WebSocketStream API, so developers would need to create their own wrappers to support both APIs. So this is not as clean as WebTransport over H2, but it can work whenever WebSockets is supported, and at least both APIs are based on Streams. However, my understanding that WebSocketStream API, which was in Origin Trial, is not moving forward. If the only alternative to WebTransport over H2 is to require developers to write to two very different APIs (WebTransport and WebSockets API) that is difficult and will present challenges. For example, WebSockets API has known issues with backpressure. MT: Requirements are spot on. Bernard's point is similar to points that myself and colleagues have made. Have reservations about technical aspects of approach; can probably simplify things. Maybe pack all of it in one H2 stream, rather than intermixing with HTTP request streams. This is the right work to be doing but I'd like to see more discussion on the technical side of things. David: From comments here and W3C there seems to be interest in this work. We want to reserve some time each session to discuss WebTransport over H2 (or TCP) at the end of each session, with a view to some future adoption. We want people to respond to gauge interest in this approach. Yutaka: We're still working on WebSocketStream. Jonathan: a little concerned that the failure rate of QUIC is low and that this code might not get well exercised. W3C probably need to help keep an eye on things. David: my understanding that this is oriented more towards networks that don't support UDP rather than servers that don't want to support a UDP-baed WebTransport Jonathan: web developers using their dev environment might not have traffic that is reflective of the Internet, there may be unanticipated surprising behavior David: interest and no opposition to discussing this. Too early to judge whether to adopt. Please continue discusion on [GitHub](https://github.com/ekinnear/draft-webtransport-http2/) and future session. We'll probably have an interim session before the net IETF meeting, please look out for information on the list. ## Hums, Wrap up and Summary, Chairs & ADs (30 minutes)