Git Product home page Git Product logo

draft-ietf-webtrans-http3's Introduction

draft-ietf-webtrans-http3's People

Contributors

afrind avatar bashi avatar davidschinazi avatar ekinnear avatar lpardue avatar marten-seemann avatar martinthomson avatar nidhijaju avatar vasilvv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

draft-ietf-webtrans-http3's Issues

Meaning of "Fallback"

The term "fallback" is not well enough defined. It might be helpful to define a list of requirements that "fallback" transport (and APIs) must satisfy.

As an example, if QUIC is not available, but HTTP/2 over TCP is, it may be possible to utilize RFC 8441 and/or potential extensions to provide for multiple streams over TCP. This would support a portion of the WebTransport API (e.g. reliable streams), but now loss on one stream will block other streams and some protocol functionality (e.g. datagrams) may not be available. Does that mean that some WebTransport methods operate differently or are not available? In some cases, developers might prefer to "fallback" to the existing WebSockets API with its message-orientation.

Define Error Code of WebTransport over QUIC

In WebTransport over QUIC, when an invalid Client Indication is received, the server treats the connection as an error(section 6).

This is an error that occurred in a layer above the QUIC, so I think the connection should be closed with CONNECTION_CLOSE (0x1d) indicating an error in the application using the QUIC.

I think it is valuable to define an error code for WebTransport over QUIC.
( draft-ietf-quic-transport-24 section 20.1 saids "the management of application error codes is left to application protocols." )

and, by specifying the error code that the endpoint uses when it close the connection, the specification becomes clear.

for example

- WQ_NO_ERROR 
- WQ_INVALID_CLIENT_INDICATION
- WQ_NOT_AUTHORITATIVE_ORGIN
- WQ_OTHER_ERROR
...

Bidirectional Stream Frame Ordering Requirements

The draft says:

WebTransport endpoints can initiate bidirectional streams by opening an HTTP/3 bidirectional stream and sending an HTTP/3 frame with type WEBTRANSPORT_STREAM (type=0x41).

It is unclear if it is allowed to send other frames before sending the WEBTRANSPORT_STREAM frame. I can't think of any currently defined HTTP/3 frame that would make sense to send here, but that might not be the case with future extensions. At the very least, it would be nice of grease frames could be sent.

Error codes for closing the session

Since the API was based off QuicTransport, the API document currently has a method to close the session, with both an error code and a reason string (modeled off QUIC CONNECTION_CLOSE): https://w3c.github.io/webtransport/#web-transport-close-info.

We could attempt to reset the CONNECT stream, but that would imply that it's always reset, and will not let us supply a reason string. I think the easiest way would be to send trailers on the CONNECT stream.

New Connection throttling

Porting w3c/webtransport#230 originally posted to W3C WT @ricea

New connections should be throttled to avoid being a DoS vector. Maybe we will just have some language in the standard to permit and encourage throttling, and leave the details to browsers.

Are Type-Value frames usable in WebTransport

I believe the QUIC WG decided that TV frames were fine in extensions, but that we weren't going to use them in the core spec? Others disagreed with my recollection/understanding.

Subsequent discussion from Lucas and Alan indicated that TV frames are not allowed in HTTP/3, but it is allowed to have a 0 length frame which indicated the rest of the stream was WebTransport data. I'm not sure it matters, since either way a peer which doesn't understand the frame is going to parse the stream. Those that skip the frame will start parsing another frame after it and the parser will enter an unknown state. Similarly, the behavior for TV is going to be unexpected/unknown.

Originally posted by @ianswett in #24 (comment)

closing streams when the session is closed

The draft says that all streams need to be closed when the WebTransport session is closed.

This makes me wonder:

  1. Which error code to use for that? Should we mandate using the same error code that the WebTransport session was closed with?
  2. Stream tracking: If it's the WebTransport implementation's responsibility to reset all the stream, this means that I need to keep another list / map of streams (outside of my QUIC stack). The interesting question is how to garbage collect closed streams from that list. It seems like the only way to do so is by introducing a callback for my QUIC stack to signal that a stream was closed / reset in both directions, so I can clean it up on the WebTransport layer.

Stale references to a transport parameter in security consideration?

https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3-01#section-6 states

WebTransport over HTTP/3 requires explicit opt-in through the use of
a QUIC transport parameter; this avoids potential protocol confusion
attacks by ensuring the HTTP/3 server explicitly supports it.

I can't tell if that is stale text or if it still true.

There is a SETTING - SETTINGS_ENABLE_WEBTRANSPORT - for extended CONNECT. Maybe that applies instead?

HTTP/3 Transport and Alt-Svc

Moving an issue from W3C w3c/webtransport#78 as we felt it is better handled here at IETF. OP by @LPardue.

During the WEBTRANS BoF at IETF Singapore 106 I made a comment at the microphone about the relationship between WebTransport over HTTP/3 and Alt-Svc. I was asked to open an issue here.

Simple Problem
The following are requirements from https://tools.ietf.org/html/draft-vvv-webtransport-http3-01#section-4.1:

  • In order to indicate support for Http3Transport, both the client and
    server MUST send an empty "http3_transport_support" transport
    parameter. Endpoints MUST NOT use any Http3Transport-related
    functionality unless the parameter has been negotiated.

  • If "http3_transport_support" is negotiated, support for the QUIC
    DATAGRAM extension MUST be negotiated.

For any given HTTP/3 connection with a value of "h3-draft" that meets the following above criteria, what happens if an Alt-Svc advert on that connection incorrectly causes a client to attempt a new connection that cannot meet the same requirements? I think marking the alternative as broken is probably good enough.

Broader problem
An HTTP/3 connection that coalesces connections might trip up if some of the traffic to origin is intended to be Http3Transport and some is not. An alternative for a non-Http3Transport-using authority might cause a complete changeover to fail.

HTTP/2 defines the 421 status code that can be used to mitigate such problems but it doesn't apply to all possible error cases (only the one where extended CONNECT fails).

I think in reality, an Http3Transport server will likely want to be smart about the Alt-Svc values it produces.

Broader broader problem
How does a client discover an Http3Transport service?

We're also talking about putting Alt-Svc in the DNS. How does a client learn of the availability of Http3Transport providing server based on its name, should it even be able to?

I wrote an I-D about a related problem in https://tools.ietf.org/html/draft-pardue-alt-svc-ext-unsupported-00.

Session layer resource management

QUIC manages resources, specifically streams and flow control, at the transport layer. Since the H3 draft allows pooling, those mechanisms may be inadequate in cases where WT sessions are multiplexed with each other or standard H3.

There are two issues open tracking some different bits of this (#22/Flow Control) and (#31/~Streams), this issue is tracking whether we need to solve that by adding functionality at the WT session layer. #27 tracks the interpretation of GOAWAY and this could also be a session level concept.

This might look like a set of frames for granting stream and flow control credit, which would presumably be a subset of the QUIC transport credit.

Some arguments against this:

  1. Endpoints that require the resource management features of the transport can disable pooling and fall back to the transport for these.
  2. These problems already exist in clients that pool HTTP connections to the same server between different applications (eg: browser tabs) that are generally unaware of each other.
  3. "complexity"

Request forgery

When we built thewebsocketprotocol, masking was added to protect intermediaries from carefully crafted messages that were controlled by web sites. No such mechanism exists in this protocol and we should be certain that this is the right answer.

The threat model here is similar to websockets. The attacker is given complete control over the server and the ability to determine the content of QUIC datagrams or streams that are sent by the client. This doesn't give the attacker complete control over the content of UDP datagrams, but the level of control can be very good. As the attacker knows the keys that will be used and they can probably guess the offset into the packet at which data will be placed, they have fine control over the resulting ciphertext.

The result being than an attacker controls most of the content of the UDP datagrams sent by the browser. They choose connection IDs and with the exception of a small number of bytes toward the start of a packet and the authentication tag at the end of a packet, they have nearly complete control over the payload of UDP datagrams.

An attacker might also control the destination address if the client supports the use of preferred addresses. (Though they need to control this address if the client is going to send any meaningful data toward it.)

What an attacker can do with this control is hard to estimate. The attacks that used thewebsocketprotocol relied on having an intermediary that looked at TCP segments and applied some fairly loose parsing. Attackers could then exploit that intermediary. Cache poisoning was the demonstrated example, but we've since seen how bad logic in other intermediaries can be exploited in other ways.

How much intermediaries make decisions based on the content of random UDP packets they see is still unclear. There are a few protocols for which we might want to avoid the risk. For that, blocking traffic to a destination port of 68, 69 or 53 seems like it might provide an easy win. The fetch port blocklist is TCP-specific, but we could just use that for now and work on a UDP version.

Adding something like masking is possible, but far more disruptive. We do not apply masking to HTTP requests, but we allow sites similar levels of control over the content of packets. In a sense we're already accepting some risk of request forgery.

No matter what we decide, the specification needs to address this risk.

Reconsider the design around header block size limit

Reviewing #18, @LPardue wrote:

It seems unfortunate if a client can force a server to buffer up to 1,048,576 bytes. Yes the server can hangup, but it would have to wait until the application-imposed limit was reached. It might be healthier for the block to begin with a total length field. That allows a server to early abort.

I do agree that this is annoying, but at the same time adding a field that's redundant 90% of the time feels... weird? We should think more seriously about how to make header size limits work at some point (maybe using ALPS or something like that).

WebTransport and 0-RTT

There is this sentence about 0-RTT:

WebTransport over HTTP/3 does not support 0-RTT.

I think this needs a better explanation. I expect that CONNECT requests can be sent during 0-RTT period, but WebTranpsort
streams cannot be open before response to the CONNECT requests is received.
Clients may remember that WebTransport was supported by a server and may try to negotiate sessions during 0-RTT.

QuicTransport: Rejecting a path

The spec defines a way to reject an unsupported origin with a CONNECTION_CLOSE (which has its own problems) but it does not define a way to reject an unsupported path. It's left up to the application, presumably to send a custom message or custom CONNECTION_CLOSE error code.

I think that origin and path rejection should use the same rejection mechanism. Consistency will be important as new fields are added, potentially including user-defined fields. There are a few options:

  1. Path and origin rejection uses CONNECTION_CLOSE with reserved codes.
  2. Path and origin rejection uses a custom message containing an error code/message, sending CONNECTION_CLOSE upon receipt.
  3. Path and origin rejection is handled by the application.
  4. Path and origin rejection use RESET_STREAM, sending CONNECTION_CLOSE upon receipt.

I'm actually in favor of 3.

The browser still needs to populate the origin for security reasons. However, the server can terminate the connection however it sees fit; the reason why does not need to be communicated to QuicTransport or the browser. It's much simpler than defining error codes and is the minimal work to allow QUIC in a web environment.

WEBTRANSPORT_STREAM payload length?

Hi folks! Thanks for your efforts on this project. I’m really excited about what WT will enable.

I’m working on a WT3 implementation and had a question about WEBTRANSPORT_STREAM frames.

Why doesn’t a WEBTRANSPORT_STREAM header include a payload length value following the 0x41 frame type, before the session ID? (I saw this comment but curious for more context.)

From what I can tell, this exception forces a WT3-capable H3 server to be WT3-aware—or at least aware of H3 frames that don’t conform to the frame layout spec.

I’ve modified an existing H3 implementation to pass unknown frame types and streams to an extension. Right now, in order to accommodate WEBTRANSPORT_STREAM frames, a receiver has to stop parsing the frame after reading the frame type, and pass the stream to an extension that could either process or skip the unknown frame.

Given that the Session ID occupies the same place where a payload length varint would be, the frame parser could parse the second varint as a "length" and the WT3 extension could interpret it as a Session ID. Workable, but seems like a kludge.

It seems like one additional byte per bidi stream seems reasonable to align these.

Could WEBTRANSPORT_STREAM conform to the H3 frame layout spec with a zero-length payload, and have the payload start with the Stream ID?

Ambiguous RESET_STREAM

If a peer receives a RESET_STREAM message before it receives the first few bytes of the stream, then it is unable associate the RESET_STREAM with a protocol or session. This can occur if the STREAM packet is lost but the RESET_STREAM is not.

As a consequence, if a WebTransport client closes a stream with an error code, then it's not guaranteed to be received by the server. Worse yet, a reset client-initiated bidirectional stream may be confused for a HTTP/3 request and cause intended consequences.

QUIC Transport "path" seems underspecified

As discussed in Singapore BoF, the "path" of the URI for QUIC transport needs further specification. It isn't clear if it's a location, an application indication, or something else.

QUIC DATAGRAM vs H3 DATAGRAM

WT currently uses QUIC DATAGRAMS (eg: no Flow-Id), and does it's own demultiplexing via the session ID. This is incompatible with multiplexing other applications that use H3 DATAGRAMs, since the Flow-ID could collide with the session ID, depending on how it is chosen.

There was some discussion of this already in a PR on victor's repo: #21 (comment)

Specify behavior when receiving a bad session ID

The H3 draft is light on error handling guidance. There are number of cases for bad session IDs:

  1. The session ID is not a client initiated bidirectional stream ID
  2. The session ID refers to a stream that did not perform a WebTransport handshake
  3. The session ID refers to a stream that has been closed or reset

Presumably there is no error when a DATAGRAM arrives with a bad session id -- you just drop it?

For streams, perhaps HTTP_ID_ERROR is appropriate?

Issues #28 and #29 both refer to cases where you receive a session ID that has not been created yet. Best to keep the discussion there, but it's likely we want to allow clients/servers to buffer some of these at their own discretion rather than require an error.

Add WEBTRANS WG Charter and Agenda files

It'll be easier to iterate on the WEBTRANS WG Charter proposal as well as the BOF Agenda if we store these in github.

Current BOF Agenda is as follows:

WEBTRANS BOF Agenda
Applications and Real-Time Area (ART)
Wednesday, November 20, 2019
13:30 - 15:00
Room: Canning
Mailing list: [email protected]

13:30 - 13:35 PM Preliminaries (5 minutes)
Agenda Bash
Bluesheets
Minute takers
Jabber scribe

13:35 - 13:55 PM Use Cases and Requirements (20 minutes)
https://tools.ietf.org/html/draft-vvv-webtransport-overview

Machine Learning APIs
Communications Platform APIs
Web Gaming
Requirements/Summary

13:55 - 14:35 Relevant Drafts (40 minutes)

An Unreliable Datagram Extension to QUIC (Tommy Pauly, 10 minutes)
https://tools.ietf.org/html/draft-pauly-quic-datagram

Using QUIC Datagrams with HTTP/3 (David Schinazi, 5 minutes)
https://tools.ietf.org/html/draft-schinazi-quic-h3-datagram

WebTransport over QUIC (Victor, Vailiev, 5 minutes)
https://tools.ietf.org/html/draft-vvv-webtransport-quic

HTTP/2 as a Transport for Arbitrary Bytestreams (Eric Kinnear & Tommy Pauly, 10 minutes)
https://tools.ietf.org/html/draft-kinnear-httpbis-http2-transport

WebTransport over HTTP/3 (Victor Vasiliev, 10 minutes)
https://tools.ietf.org/html/draft-vvv-webtransport-http3

14:35 - 14:45 Potential Charter (10 minutes)

14:45 PM - 15:00 PM Wrapup and Summary (15 minutes)

The current WEBTRANS charter proposal is as follows:

WebTransport (WEBTRANS)

Charter

Chairs:
TBD

Applications and Real-Time Area Directors:
Barry Leiba [email protected];
Alexey Melnikov [email protected];
Adam Roach [email protected];

Applications and Real-Time Area Advisor:
Barry Leiba [email protected];

Mailing Lists:
General Discussion: [email protected]
To Subscribe: https://www.ietf.org/mailman/listinfo/webtransport
Archive:
https://mailarchive.ietf.org/arch/browse/webtransport/

Description of Working Group:

The WebTransport working group will define new protocols or
protocol extensions in order to support the development of the
W3C WebTransport API https://wicg.github.io/web-transport;.

These protocols will support:

  • Reliable bidirectional and unidirectional communication
    that provides greater efficiency than Websockets
    (e.g. removal of head-of-line blocking).
  • Unreliable datagram communication, functionality not
    available in Websockets.
  • Origin checks to allow supporting the Web's origin-based
    security model.

The WebTransport working group will define three variants:

  • A protocol directly running over QUIC with its own ALPN.
  • A protocol that runs multiplexed with HTTP/3.
  • Fallback protocols that can be used when QUIC or UDP
    are not available.

The group will pay attention to security issues arising from
the above scenarios so as to ensure against creation of new
modes of attack, as well as to ensure that security issues
addressed in the design of Websockets remain addressed
in the new work.

To assist in the coordination with W3C, the group will
initially develop an overview document containing use cases
and requirements in order to clarify the goals of the effort.
Feedback will also be solicited at various points along the way
in order to ensure the best possible match between the protocol
extensions and the needs of the W3C WebTransport API. The clarity
and interoperability of specifications will be confirmed via test
events and hackathons.

The group will also coordinate with other working groups within
the IETF (e.g. QUIC, HTTPBIS) as appropriate.

Goals and Milestones:

March 2020 - Adopt a WebTransport Overview draft as a WG work item
March 2020 - Adopt a draft on WebTransport over QUIC as a WG work item
March 2020 - Adopt a draft on WebTransport over HTTP/3 as a WG work
item
March 2020 - Adopt a draft on HTTP/2 fallback mechanism as a WG work
item
March 2020 - Adopt a draft on a QUIC fallback mechanism as a WG work
item
August 2020 - Issue WG last call of the WebTransport Overview
document.
November 2020 - Issue WG last call on WebTransport over QUIC
November 2020 - Issue WG last call on QUIC fallback mechanism
February 2021 - Issue WG last call on WebTransport over HTTP/3
February 2021 - Issue WG last call on HTTP/2 fallback mechanism

Consider using a stream prefix in QuicTransport

In QuicTransport, instead of having the client send the origin on stream 2, we could have all unidirectional streams carry a prefix and use that. This would map closely with HTTP/3 and HttpTransport, and would therefore allow code reuse

Remove implicit SETTINGS_ENABLE_CONNECT_PROTOCOL

Section 3.2 currently states:

the SETTINGS_ENABLE_WEBTRANSPORT setting implies that an endpoint supports extended CONNECT

That is not well-defined: it relies on RFC 8441 which only discusses HTTP/2, and the relevant changes between HTTP/2 and HTTP/3 are subtle.

Since we have a draft for extended CONNECT for HTTP/3 that is now in the RFC Editor Queue, WebTransport needs to instead refer to that and require servers to send SETTINGS_ENABLE_CONNECT_PROTOCOL.

Http3Transport server-initiated bidirectional stream future proofing

Http3Transport currently assumes that server-initiated bidirectional streams and datagrams can only be used for WebTransport.

I suggest we prefix each server-initiated bidirectional stream and datagram with a new HTTP/3 frame type for WebTransport. This way, a future standard could define it's own frame type to run alongside WebTransport.

Negotiation of pooling support

The H3 draft by its nature allows for the parallel processing of multiple WT sessions and also the intermixing of normal H3 request with WT. Server endpoints may wish to negotiate or disable this behavior. Clients can simply choose not to do either kind of pooling if they don't want to.

There's already a PR open (#25) with a design idea.

What to do with datagram context IDs?

h3-datagram provides an ability to multiplex multiple datagram contexts over a single flow of datagrams associated with a stream. This feature is optional; an endpoint can disable contexts by sending a register-without-context capsule.

We currently do not have a use for multiple contexts; there are potential extensions that could utilize those (e.g. multiple datagram queues with different priorities), but those would not make it into the first version of the spec.

There are roughly two approaches we could potentially take here:

  1. Require WebTransport servers to handle multiple contexts correctly even if we don't use those currently.
  2. Allow WebTransport servers to reject any kind of context registration other than register-without-context, unless there's an extension negotiated via a header.

The first option has the drawback of complexity that would not benefit most server implementers. The downside of the second option is that if we go with it, we would need to wait for the headers from the server before sending any datagrams.

cc @DavidSchinazi who can probably add more

Folding datagrams/streams into the CONNECT stream

Should the protocol share framing semantics with the HTTP/2 draft so that it is easy/easier to take datagrams or streams and put them on the CONNECT stream?

Should it be possible to use that mechanism, or should it instead be forbidden?

As much as possible, it would be desirable to have the forwarding logic be fairly uniform across different protocol versions. Right now, we have two almost completely different protocols.

Draining WebTransport Sessions

An HTTP/3 server needs the ability to gracefully drain existing connections. For HTTP/3, this involves sending a GOAWAY frame indicating that future requests should use a new HTTP/3 connection. However, the behavior of GOAWAY is partially undefined with WebTransport sessions.

After receiving a GOAWAY, the client is no longer able to make new CONNECT requests. This means that any new WebTransport sessions will need to use a new HTTP/3 connection. This is great.

However, it's not clear how existing sessions should behave after receiving a GOAWAY frame. Are they prohibited from creating new streams? How does this interact with the stream ID sent in the GOAWAY frame? Should the application expose the receipt of a GOAWAY to start a shutdown process?

SETTINGS_ENABLE_WEBTRANSPORT from the client

How necessary is to wait for SETTINGS_ENABLE_WEBTRANSPORT from the client? If we are a server, and we receive a request with :protocol set to webtransport, this seems like a pretty solid indication of support. From the current language in the draft, though, the server has to pause the processing of the request in question until the SETTINGS are there (which is really annoying to implement).

One counterpoint I can see is that we could use settings to negotiate a specific version of WebTransport over HTTP/3, and in that case we do need to wait for settings from both parties.

Session Establishment Round Trips

For a simple application that wants to send "hello world" over a WebTransport stream, it would take a minimum of 2.5 round trips for the data to arrive on the server. This is still an improvement over WebSockets but I'm wondering if we could do better.

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.

If the client is able to create streams prior to receiving the CONNECT response, then it would remove a round trip. The server would need to buffer any data received on streams associated with an unknown WebTransport session. If the server responds with a non-200 status code, then these streams are discarded.

WebTransport over HTTP/3 does not support 0-RTT.

I believe 0-RTT is disabled for WebTransport because CONNECT is not idempotent and would be subject to replay attacks. An idempotent CONNECT would remove a round trip when 0-RTT is used... although I'm not sure this is a good idea.

Session Establishment Race

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.

After the client initiates the WebTransport session by sending a CONNECT request, the server sends a 200 response and is free to create streams. This means that a server-initiated stream may arrive prior to the CONNECT response. Is the client able to infer that the session was successfully established, or does the client need to buffer this stream until it receives a proper response?

Alignment with MASQUE/CONNECT-UDP

If you ignore WebTransport streams, then the base functionality of WebTransport and CONNECT-UDP+H3 DATAGRAM is virtually identical:

  1. Client sends a HTTP/3 CONNECT(-UDP) request to establish a session, with a unique identifier
  2. The lifetime of that stream establishes the lifetime of the session
  3. The endpoints can exchange DATAGRAMS using the session ID as the flow ID

Granted there are important differences -- CONNECT-UDP has particular semantics for the receiver, and needs mechanisms for transport level extensions. I don't think they can be completely consolidated or factored out.

Negotiation and pooling support look different at this point -- there doesn't seem to be active discussion that a server endpoint should limit the number of open CONNECT-UDP sessions, or how they can be multiplexed with standard H3, but in WT it's more controversial.

Are there any opportunities for better alignment here?

Http3Transport does not have a consistent stream ID view if proxies are involved

In -overview, we require that "The client and the server have to agree on the numbering, so it can be referenced in the application payload.". However, if an Http3Transport session is relayed through a proxy, it is not feasible to make the stream IDs to match on client-to-proxy and proxy-to-server, so we would have to encode a separate ID inside the stream ourselves or come up with a scheme for numbering those.

Http3Transport connection flow control

Note that all of the below works when you swap "server" and "client". I wanted to focus on a poor Javascript client implementation, but it's equally possible to run into these cases with a poor server implementation.

Let's say that you have a Http3Transport session that shares a connection with HTTP/3 or another Http3Transport session. 

MAX_DATA

The client has limited buffer space and hypothetically advertises MAX_DATA of 1MB for the connection. If the server pushes 1MB of unprocessed data over a Http3Transport session, then it will prevent the server from sending data over the connection, including HTTP/3 responses and other Http3Transport sessions.

This can occur if the application does not accept all remote-created streams or does not fully read every stream. This will be VERY easy for a developer to mess up. It can also occur if the application can not process data faster than it is received.

In my case, the server creates unidirectional streams and pushes a large amount of media over them. The flow control limit would be hit if the Javascript application:

  • Only accepts bidirectional streams (ex. initialization)
  • Does not accept a unidirectional stream (ex. error or teardown)
  • Does not fully read or abort every stream (ex. parsing error)
  • Is not able to parse the media fast enough (ex. underpowered).

This is mostly intended behavior, otherwise these "bugs" would cause unbounded memory usage. However, the blast radius is bigger when sharing a connection. 

In my use-case, hitting the flow control limit would also block any HTTP/3 RPC calls or unrelated traffic on the connection. This introduces more scenarios for the connection to become deadlocked or generally stalled.

MAX_STREAMS

HTTP/3 implementations use MAX_STREAMS to limit the number of simultaneous requests. This use-case no longer works when sharing a connection with a Http3Transport session, and HTTP/3 implementations must instead return explicit error status codes when this threshold is reached.

The same issues with MAX_DATA also apply to MAX_STREAMS. A Javascript application that fails to accept or read/abort every stream will consume flow control resources. This can manifest itself in strange ways, such as HTTP/3 being unable to create control streams, or simply being unable to create new request streams.

Confirm the URL scheme name

The draft currently says quic-transport:, however, we'd still need to confirm this with the working group once we actually have one.

Stream Limits

Moving this to HTTP/3 since it's no longer an issue for HTTP/2:

From @martinthomson:

This is likely shared with the HTTP/3 mapping also, but I'm here first.

Web applications will want some degree of certainty about the streams they are able to access. As they also operate servers, this is probably not so bad in the client-to-server direction. The main concern for client-to-server is the potential for the connection to be used for HTTP requests that consume these limits. In the server-to-client direction clients might need to provide some number of streams that it would guarantee that a server can use for a given session.

As multiple sessions are involved, this gets harder, because the web security model might prevent us from exposing information about what other origins are using a shared connection for. That said, it's not clear that there is any value in withholding this information either (see ietf-wg-webtrans/draft-ietf-webtrans-http2#23) as the security boundary is essentially already gone once coalescing is involved.

(I'm deliberately not considering isolation of state by top-level browsing context; I expect that no coalescing or connection sharing would occur for different top-level sites.)

Describe what is allowed after sending or receiving a GOAWAY

If a connection carrying WebTransport sessions receives a GOAWAY, is the sender allowed to continue

  1. sending datagrams
  2. creating new WT streams
  3. receiving new WT streams

I assume it's ok to continue sending data on already open WT streams and the CONNECT stream, but clarification would be good.

Also, are the rules any different after sending a GOAWAY? Can the sender continue doing the above?

Unidirectional stream framing

WT uni streams are currently defined as

Stream Type | Preface (Session ID) | Unframed

This was awkward to implement, and asymmetric with how client-initiated bidi WT streams are implemented (and now server-initiated bidi -- with a frame).

I'd like to propose we change WT uni streams to

Stream Type | TV Frame

or perhaps

Stream Type | Preface | TV Frame

Should WT streams be reset when the CONNECT stream terminates

The draft currently states:

Upon learning about the session being terminated, the endpoint MUST stop sending new datagrams and reset all of the streams associated with the session.

It's clear that without a CONNECT stream that new streams cannot be created and datagrams cannot be sent, but WT streams that were opened for that session could continue operating normally. This is how push streams are handled in H2 and H3 -- the push stream continues even if the associated stream is terminated.

An endpoint always has the option to reset/stop sending WT streams when the session terminates.

This is somewhat related to the graceful drain issue (#27)

QuicTransport: 0-RTT and Origin Indication

QuicTransport optionally supports 0-RTT if there's a corresponding API for early data.

The WICG draft does not define any way to enable early data, and it probably shouldn't anyway. Early data complicates the API and exposes the user to potential security vulnerabilities if they misunderstand the risks.

However, one thing worth clarifying in relation to 0-RTT is the origin indication message. It must be safe to send the origin indication in 0-RTT for any API to support early data. I don't fully understand if this is true but my impression is that it would be safe.

As for APIs that only send application data in 1-RTT space, sending the origin indication message in 0-RTT would be a slight improvement. The server must buffer all streams until the origin indication has been processed, so sending the origin indication early would reduce that initial head-of-line blocking.

Could we clarify that origin indication CAN or SHOULD be sent in 0-RTT?

opening WebTransport streams before the WebTransport session is established

In order to save a round-trip on connection establishment, a client could optimistically open streams just after sending the CONNECT request, before it has received a reply from the server.

As both unidirectional and bidirectional streams are identified by the session ID, the server will be able to associate these streams with the WebTransport session as soon as it has processed the CONNECT request.

In case the server rejects the CONNECT request, the client should probably reset / cancel these streams. Note that this doesn't require any additional logic on the server side, as the server needs to be prepared to receive streams for sessions that it didn't establish anyway (a malicious client might open streams with arbitrary session IDs, and a server should better be prepared for that).

Currently, the spec forbids opening unidirectional streams before the session is established:

Once established, both endpoints can open unidirectional streams.

There's no such restriction for bidirectional stream.

RESET_STREAM error codes

If we are going to let the API users supply their own stream reset code, we should figure out how this is represented on the wire. We could potentially use the error codes as-is and say they mean different things for WebTransport streams than what they mean for normal streams, but I am not sure this is sound as we don't always know that a stream is a WebTransport stream at the time we process the reset (also this sounds like a pain to implement).

One possibility would be to reserve a block within HTTP/3 error code space. However, since HTTP/3 error codes contain GREASE code-points throughout, we might end up having to "de-grease" and "re-grease" them as the largest continuous block only has 255 codepoints available.

Alternatively, if we decide to just send RESET_STREAM as a part of CONNECT stream due to issues in #31, we could just send the error code there, and keep one single code for user-initiated termination.

Whatever we decide here should probably work for H/2 as well.

cc @martinthomson

QuicTransport: origin indication via transport parameters

QuicTransport identifies itself using an ALPN and both peers agree to transfer additional configuration via a client-initiated stream (ID 2).

I think it would be an improvement if this origin indication was moved into the QUIC transport parameters and exchanged via the TLS ClientHello.

There would be a few benefits (in no particular order):

  1. A server can terminate an invalid origin/path prior to performing the expensive TLS handshake.
  2. A server does not need to buffer stream data (inbound and outbound) waiting until stream 2 has arrived.
  3. A load balancer can route new connections to the correct server based on the path in the ClientHello. Currently, a load balancer must terminate TLS and buffer all streams until it can parse stream 2 prior to making a routing decision.
  4. QUIC stream IDs could be exposed to the application without the asterisks that stream 2 has already been used.
  5. The first client packet (ClientHello) must already be padded to 1200 bytes. The origin and path parameters would replace some of that padding and overall reduce the bandwidth for a new connection.

There would be a few downsides:

  1. Long paths and origins could cause fragment the ClientHello message into multiple packets.
  2. Requires registering webtransport_path and webtransport_origin.
  3. QUIC libraries need to expose or support the new transport parameters.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.