Description
Hey folks,
I'm working on a proposed live media standard: Media over QUIC. I ported my library from quiche to quinn when I found the h3-webtransport
crate. Big thanks to @darioalessandro and @ten3roberts for implementing it!
One thing that got lost in my migration was the ability to prioritize streams. It's critically important for MoQ and it's the key functionality that allows QUIC to deliver live media over congested networks. I specifically want send order, which means streams are transmitted in a strict order based on an integer priority (basically a priority queue).
Quinn implements send order but it is not implemented in the h3::quic trait or the h3_webtransport::SendStream struct. One of the problems is that there's no official QUIC API and nothing is sent over the wire, so stream prioritization is up to the implementation. Here's a few I've seen in the wild:
- quinn uses an i32.
- quiche uses a u8 and an incremental flag.
- s2n-quic does not support stream priorities.
- W3C WebTransport uses a u64 (technically a float)
- HTTP/3 Priority uses 8 values and an incremental flag.
I think there's two routes to support stream prioritization.
1. Add set_priority
to the h3::quic
trait.
The debate would primarily be over the API. I'm a huge fan of a i32
(like Quinn) to match the JS API, but that would rule out other QUIC backends as they exist today.
I could work with a u8
like I did with quiche, but it's quite annoying. My application would maintain the stream priority queue and constantly update the stream priority with the index in the queue, limited to 256 streams outstanding at any time. Alternatively, I've discussed changing the quiche API with the authors and they're open to it.
I don't think an incremental flag is useful, even for the HTTP/3 Priorities. incremental=false
is a solid default.
2. Add a mechanism to access the underlying SendStream.
The h3::quic
trait makes a lot of sense for HTTP/3 since there's a set of core functionality required for HTTP/3. However, WebTransport models itself as QUIC on the web, which means exposing a nebulous "QUIC API". You can envision WebTransport as a thin layer on top of QUIC streams primarily for browser support.
I think it would be reasonable if the application could access the quinn::SendStream
directly. For those unaware, WebTransport streams involve a few bytes at the start to identify the session_id
. They behave like regular QUIC streams after that, although RESET_STREAM error codes use a special encoding to include the session_id
.
I haven't explored if this would work, but maybe h3_webtransport::SendStream
could implement inner(&mut self) &mut T
or just DerefMut
? It would be ideal if the application could not get access to the underlying quinn::SendStream.reset()
to avoid misuse, which is why overloading it and using Deref
might be better, but I think the h3::quic
trait gets in the way.