Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial Reliability #30

Closed
aboba opened this issue Dec 3, 2018 · 16 comments
Closed

Partial Reliability #30

aboba opened this issue Dec 3, 2018 · 16 comments

Comments

@aboba
Copy link
Collaborator

aboba commented Dec 3, 2018

There are situations intermediate between the "reliable transport" and "no retransmissions" modes specified in the current document. As an example, a real-time communications application might want to support maxPacketLifetime or maxRetransmissions, so that real-time data would not be delivered after it had become stale. As an example, the rtx-time parameter in RTX could be emulated over QUIC via maxPacketLifetime applied to a QUIC stream.

There are ongoing discussions about how to support partial reliability in QUIC. Proposals include:

  1. DATAGRAM : https://tools.ietf.org/html/draft-pauly-quic-datagram
  2. Partially reliable streams: https://tools.ietf.org/html/draft-lubashev-quic-partial-reliability
  3. send message, and then RST_STREAM (if maxPacketLifetime or maxRetransmissions is exceeded):
    Explain emulation of partial reliability with one message per stream? quicwg/ops-drafts#15

However, from an API point of view, it doesn't appear difficult to extend createStream() for partial reliability:

partial dictionary RTCQuicStreamParameters {
unsigned short maxPacketLifetime ;
unsigned short maxRetransmissions;
};

@johnwason
Copy link

johnwason commented Dec 4, 2018

For the stream based messages, there is the option of combining opening, sending data, and then closing the stream in one operation. This operation should be available as a single function, ie "sendStreamMessage." On the receiver side there should be an option to receive the entire message in one callback, rather than having callbacks for open, data, and close. Does the QUIC protocol have a way to flag a "stream" as a single message so it can be combined into a single callback?

Nevermind, this design would require unlimited buffering before returning a message. Being able to set the reliability on stream creating should be sufficient.

@aboba
Copy link
Collaborator Author

aboba commented Apr 29, 2019

At this point, much of the discussion on unreliable and partially reliable transport in the IETF QUIC WG is focusing on the DATAGRAM approach outlined in 1 above, rather than approaches 2 or 3 which involve support for unreliable or partially reliable streams.

@johnwason
Copy link

The DATAGRAM approach and partially reliable streams have very different use cases. Having only the DATAGRAM option available would require significant effort to reconstruct messages that are larger than MTU. It would also require significant effort to detect if packets are lost. A partially reliable message that has some attempt to re-transmit such as what is available in DTLS is necessary for many applications. The people requesting the DATAGRAM are probably working on streaming applications like RTP rather than sending application data messages between peers.

@pthatcherg
Copy link
Contributor

That's a good point about the MTU. It's rather cheap to keep the disableRetransmissions flag around (it's easy to implement), so if a lot of people want it, I think we could keep it.

But that's based on developer feedback, and the place we're trying to gather developer feedback is at https://discourse.wicg.io/t/webtransport-proposal/3508, so please consider taking your thoughts there. I think it would help a lot in driving forward the spec and prioritizing its implementation (to have lots of developers saying what API they want and why).

@johnwason
Copy link

Ok, I can write something up. Is that for the general QUIC protocol or just the browser bindings? My plan is to make my software work with both.

Another point to add to my previous one: the main goal for my use case is to avoid head of line blocking and have the ability to drop stale data if it fails to transmit. This is not a DATAGRAM use case where there is essentially just a raw network socket. The type of data I transmit is for instance the joint angles of a robot streaming to the client. I don't really care what the value was at a previous time sample, but I do need to know what the last value was if the streaming is stopped. If I only have raw DATAGRAM's, I will have to build an entire protocol on top of the DATAGRAM to handle the partial reliability and MTU reconstruction. This would defeat the purpose of using QUIC.

@aboba
Copy link
Collaborator Author

aboba commented Apr 30, 2019

I think it would be useful to write something up for the IETF QUIC WG in addition to weighing in on WICG. It's been nearly a year since submission of the last IETF draft on partially reliable streams and for the last few IETF meetings the discussion has focused on the DATAGRAM approach. Some notes from the DATAGRAM meeting at IETF 104 are here, and are consistent with your observation of an interest in RTP as well as other unreliable datagram uses. So evidence of continued interest in non-reliable streams might help avoid it falling out of sight.

@johnwason
Copy link

@aboba I can describe my use case and requirements but I do not have the technical expertise to do much more.

@aboba
Copy link
Collaborator Author

aboba commented Apr 30, 2019

Having your use cases and requirements posted to the IETF QUIC list can help jump start a discussion and also can serve as a useful reference for those of us whose job involves supporting developers. Both the IETF and W3C could do a better job of providing an hospitable environment for developers so getting more feedback is an important first step.

@johnwason
Copy link

I have sent a description of what I am working on and my requirements to the IETF QUIC WG mailing list.

@johnwason
Copy link

The discussion on the IETF QUIC mailing list was informative. Apparently the type of partial reliability I require can be implemented using RESET frames rather than the more complicated partial reliability proposals. Because each stream will contain one message, the RESET stream can be used to cancel the entire message. The Lubashev proposal involved being able to drop part of a data within a stream, which is unnecessary for my needs.

Will the ability to cancel the transmission of a stream by issuing a RESET and clearing the buffers be available in webrtc? Has there been any consideration of implementing a "SendMessageStream" command and possibly a "MessageReceived" event to handle the open, send/recv, and close of the stream in one operation?

@pthatcherg
Copy link
Contributor

The streams from QuicTransport do allow you to reset a stream in this way. That's what the abortWriting method does.

To send a message as a stream all in one go, it's just one line, as seen in one of the examples.

transport.createSendStream().write({data: msg, finished: true});

To receive that message is almost as simple if it's a very small message:

transport.onreceivestream = event => {
let buffer = new UInt8Array(event.stream.readableAmount);
event.stream.readInto(buffer);
}

For larger message, you need to do wait for the entire message to show up like so:

https://github.com/w3c/webrtc-quic/blob/master/examples/quic-ws.js#L191

We have considered using WHATWG streams to make this slightly more pleasant, but in general we've been favoring a low-level API that a few lines of JS can give a nicer API to if you want it.

By the way, could you take your comments to https://discourse.wicg.io/t/webtransport-proposal/3508?

@pthatcherg
Copy link
Contributor

Replying to your previous comment:

  1. The WICG link is for the Web API, but at the WICG discourse, Victor pointed to some IETF docs he's writing that go along with the Web APIs (although they are small; we don't need that much).

  2. It does sound like your use case matches the "one message per stream" model, which allows you to have arbitrary size and reliability and avoid head of line blocking. In other words, don't use datagrams for that; use streams.

@vasilvv
Copy link
Contributor

vasilvv commented May 9, 2019

I just realized that we should probably change the description of abortWriting(). It currently says to always send RST_STREAM. But really, if we sent an entire stream with a FIN, we only need to send RST_STREAM when we try to retransmit something; if the receiver acks the entire stream, including the FIN, nothing needs to be further done.

Also, what would you say about renaming abortWriting() to retire()? I feel it would do a better job at "I am done with this stream, but would still prefer it to be fully delivered".

@dontcallmedom dontcallmedom transferred this issue from w3c/p2p-webtransport Jun 28, 2019
@Atrius
Copy link

Atrius commented Jul 1, 2019

I've encountered some practical difficulties with the model of abortWriting()/retire() for partial reliability, and I think it's worth considering support for TTL and/or max retransmission count in the API.

I don't believe these feature require any special transport-layer support if they apply to an entire stream: the implementation simply resets the stream rather than retransmitting anything after the TTL or max retransmission count is exceeded.

I've found it far simpler to implement these kind of features inside a QUIC stream than above it. The implementation knows when it's about to retransmit data and can evaluate the TTL or max retransmission count at that moment. The user must keep some mapping of streams to deadlines and schedule callbacks to invoke abortWriting(). And the application needs to know how many retransmissions have happened and when that number changes in order to implement a max retransmission count.

@aboba
Copy link
Collaborator Author

aboba commented Jul 2, 2019

@Atrius I tend to agree with you. Both maxPacketLifeTime and maxRetransmissions are parameters in the RTCDataChannel API, and neither can be faithfully implemented with application timers.

@pthatcherg
Copy link
Contributor

We've gone with datagrams for now, and I don't think there is anything else on the horizon. If something does come up, we can reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants