Subject: [rtcweb] What happens to buffered data when closing a DataChannel?

From: Taylor Brandstetter <[email-masked]>
Date: Tue, 10 Apr 2018 12:34:46 -0700

Recently on a chromium bug
<https://bugs.chromium.org/p/chromium/issues/detail?id=559394#c56>, there's
been some discussion about the data channel closing procedure.

The main question seems to be: what happens to messages that have been
enqueued but not yet sent?

rtcweb-data-protocol says:

   [RFC6525] also guarantees that all the messages are delivered (or
>    abandoned) before the stream is reset.
>
>
Which I believe refers to this step for performing a reset:

   C2:  The sender has either no outstanding TSNs or considers all
>         outstanding TSNs abandoned.
>
>
However: what about messages that have been enqueued but haven't yet
generated TSNs? Is their delivery guaranteed?

Or from the perspective of the JS API: can an application assume that after
calling "close", *all* buffered data will be sent? Or does it need to wait
until bufferedAmount goes to 0 to be safe?

And a secondary question, if we decide "buffered data must be sent": does
this apply to both sides, or only the side initiating the closure?

Note that implementations are currently inconsistent on this point; Chrome
ensures all buffered data is sent (from the side initiating the closure)
while Firefox doesn't.

---

From: Michael Tuexen <[email-masked]>
Date: Tue, 10 Apr 2018 21:55:58 +0200

> On 10. Apr 2018, at 21:34, Taylor Brandstetter <deadbeef=[email-masked]> wrote:
> 
> Recently on a chromium bug, there's been some discussion about the data channel closing procedure.
> 
> The main question seems to be: what happens to messages that have been enqueued but not yet sent?
> 
>    [RFC6525
> ] also guarantees that all the messages are delivered (or
That is correct.
>         outstanding TSNs abandoned.
No, this refers to the resetting of the SSN and TSN. This is not used by WebRTC.
WebRTC only resets outgoing streams, which is described by
https://tools.ietf.org/html/rfc6525#section-5.1.2
> 
> 
> However: what about messages that have been enqueued but haven't yet generated TSNs? Is their delivery guaranteed?
The above text doesn't apply to any procedure used in WebRTC>
> 
> Or from the perspective of the JS API: can an application assume that after calling "close", all buffered data will be sent? Or does it need to wait until bufferedAmount goes to 0 to be safe?

> 
> And a secondary question, if we decide "buffered data must be sent": does this apply to both sides, or only the side initiating the closure?
This has never been clear to me. When I asked people, most of the times I got a response indicating
that it should do the same as WebSockets...

You should also consider the backwards direction, since a data channel is bidirectional.

So A calls close on a data channel. If you want to provide a reliable shutdown procedure, you would
make sure all messages buffered above the SCTP stack would be provided to the SCTP stack and then
you  would reset the outgoing stream. Once this stream reset is received by B you would trigger
the onclose() callback, I guess. Now you would not accept any send() calls on B anymore, I guess.
But you might have messages buffered above SCTP, which you should provide to the SCTP stack and
then reset the corresponding outgoing stream. This would imply that you still call ondata()
on side A, even after close until the stream reset has been received and you would call onclose().

But this is not as defined for WebSockets. I think you discard messages received after close()
has been called...

Best regards
Michael
> 
> Note that implementations are currently inconsistent on this point; Chrome ensures all buffered data is sent (from the side initiating the closure) while Firefox doesn't.
> _______________________________________________
> rtcweb mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/rtcweb

---

From: Michael Tuexen <[email-masked]>
Date: Tue, 10 Apr 2018 21:55:58 +0200

That is correct.

Best regards
Michael

---

From: Lennart Grahl <[email-masked]>
Date: Wed, 11 Apr 2018 13:58:11 +0200

> The above text doesn't apply to any procedure used in WebRTC>

May I first point out that I've opened an issue on the W3C spec for this
topic before: https://github.com/w3c/webrtc-pc/issues/1825
I don't have a strong opinion where to discuss this but it's getting
hard to follow. ;)

>> Or from the perspective of the JS API: can an application assume that after calling "close", all buffered data will be sent? Or does it need to wait until bufferedAmount goes to 0 to be safe?

To compare it with WebSocket: WS ensures that all pending messages are
being sent before the WS is closed. And there are undoubtedly common use
cases for it, so we should follow that, too. It's pretty clear to me in
the draft, so I made a PR to clarify it in the W3C spec as well a week
ago: https://github.com/w3c/webrtc-pc/pull/1822

> But this is not as defined for WebSockets. I think you discard messages received after close()

Indeed. To quote:

"When a WebSocket message has been received with type type and data
data, the user agent must queue a task to follow these steps: [WSP]

1. If the readyState attribute's value is not OPEN (1), then return."

Source:
https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol

A WS whose closing procedure has been started will be in the 'closing'
state (the same applies to data channels).

My opinion: I think we should follow WS and not raise the 'message'
event as soon as the channel is not in the 'open' state any more. That
leaves whether to send or to discard (if possible - some data may be in
flight) pending data on the peer whose channel got closed by the other
peer up to the implementation (since all of the messages will be ignored
anyway). And it's a very simple clarification in the W3C spec.

>> Note that implementations are currently inconsistent on this point; Chrome ensures all buffered data is sent (from the side initiating the closure) while Firefox doesn't.

FYI regarding Firefox: People I've spoken to generally agree that
Firefox got it wrong but they're waiting for clarification on the spec
side, see https://bugzilla.mozilla.org/show_bug.cgi?id=1413198

Cheers
Lennart