W3C home > Mailing lists > Public > public-webrtc@w3.org > March 2014

WebRTC and backpressure (how to stop reading?)

From: Nicholas Wilson <nicholas@nicholaswilson.me.uk>
Date: Tue, 25 Mar 2014 18:16:38 +0000
Message-ID: <CAN+ZGEk8J-NJxi28zE=NzPw278iHN+MwLzfW7XJGqj9j5TSn_A@mail.gmail.com>
To: public-webrtc@w3.org
Dear all,

I've started writing a C++ application that uses WebRTC data channels,
but I'm running into a problem straight away:

How can I stop reading from the channel?

The JavaScript data channel API seems to have the same problem that
the JavaScript WebSocket API had, namely that it's not easy/possible
to stop reading and apply backpressure to the channel. For the
WebSocket spec, I made a request about this on the WHATWG list a
couple of years ago, but it was already too late for the spec to be
changed. Would it be possible to make sure that this key use-case is
supported for WebRTC?

WebRTC is meant to make things easy for developers of webapps: forcing
them to implement application-level flowcontrol on top of a perfectly
good flow-controlled channel seems harmful, and will result in lower
throughput performance than using the native SCTP buffering. We want
our RTCDataChannel-based apps to be as fast as possible!

The underlying SCTP channel fully supports applying backpressure, it's
only the webrtc::DataChannelInterface API which doesn't support it.
Similarly the WebRTC JavaScript API uses the same onmessage-style
handling of incoming data, making it impossible to punt the data to a
worker thread without risking overwhelming it.

The use-case is simple and clear: If I want to implement file transfer
to a WebRTC client (say), it's not possible for the browser to fully
buffer the data (it might be a 30GB disk image I'm sending, more than
my RAM). The WebRTC read end needs to have a way to stop reading (if
it plans to do any processing on the data). This would let the SCTP
recv buff fill up, so the window would shrink, and the send end would
start backing up data. The sending end in turn ideally needs to have
an onwrite callback, so that if the application sees the
bufferedAmount increasing, it can implement blocking semantics, and
resume sending when the bufferedAmount drops. Without an onwrite
callback, the application has to poll until the bufferedAmount goes
down; this stinks a bit but is just about acceptable.

I have the time to add the relevant code to the C++ WebRTC.org library
-- but is there interest? We need the JavaScript spec to be tweaked,
and changes to the glue in both Firefox and Chrome, for it to be
worthwhile. I really hope it's possible to get this change pushed
forward, or we'll be left in the same bad situation as for WebSockets,
where it's now too late to fix the problem!

The WHATWG streams interface is a clear example of a useful JavaScript
interface that simply can't be implemented on top of the current
WebRTC or WebSocket APIs (https://github.com/whatwg/streams). Please
correct me though if I'm wrong!

The required changes for the JavaScript spec would be the addition of
a single `setReadEnabled(bool)` method or a settable attribute on
RTCDataChannel. Polling makes programmers sad :(, so it would be
highly desirable also to add an onwrite attribute of type
EventHandler, for a callback when the write buffer clears.
Corresponding methods would need to be added to
webrtc::DataChannelObserver. The plumbing is essentially
straightforward, except for some threading shenanigans in libusrsctp
which doesn't exactly have an ideal external interface.

Thanks for any comments,
Nicholas

-----
Nicholas Wilson: nicholas@nicholaswilson.me.uk
Site and blog: www.nicholaswilson.me.uk
Received on Wednesday, 26 March 2014 08:33:29 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 15:19:38 UTC