Re: [rtcweb] Data Channel Negotiation

Randell Jesup <> Thu, 07 February 2013 15:49 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 6A45221F84D1 for <>; Thu, 7 Feb 2013 07:49:50 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.599
X-Spam-Status: No, score=-2.599 tagged_above=-999 required=5 tests=[BAYES_00=-2.599]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id dRTlVE+D6oSM for <>; Thu, 7 Feb 2013 07:49:48 -0800 (PST)
Received: from ( []) by (Postfix) with ESMTP id 8BCD621F84CA for <>; Thu, 7 Feb 2013 07:49:48 -0800 (PST)
Received: from ([]:64969 helo=[]) by with esmtpsa (TLSv1:DHE-RSA-AES256-SHA:256) (Exim 4.80) (envelope-from <>) id 1U3TjP-000BCV-IS for; Thu, 07 Feb 2013 09:49:47 -0600
Message-ID: <>
Date: Thu, 07 Feb 2013 10:49:42 -0500
From: Randell Jesup <>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20130117 Thunderbird/19.0
MIME-Version: 1.0
References: <>
In-Reply-To: <>
Content-Type: text/plain; charset="ISO-8859-1"; format="flowed"
Content-Transfer-Encoding: 7bit
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname -
X-AntiAbuse: Original Domain -
X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
X-AntiAbuse: Sender Address Domain -
Subject: Re: [rtcweb] Data Channel Negotiation
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: Real-Time Communication in WEB-browsers working group list <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Thu, 07 Feb 2013 15:49:50 -0000

On 2/7/2013 6:22 AM, Martin Thomson wrote:
> We're a fickle lot.  It seems that decisions can be unmade very easily.
> In any case, I promised a concrete proposal.  Here it is.  Beware:
> long post ahead.
> This proposal is progressive, I think that the best option would be to
> take all of it, but we could choose to not adopt the later parts.
> I'll start with the basics.
> ==Layer 1
> Negotiate all new data channels with SDP offer/answer.
> As I understand it, the 1.5 round trip cost for in-band channel
> creation was to prevent glare.  (Randell hinted that there might have
> been something else that was SCTP-specific, but this appears to reduce
> to a straightforward glare situation.)  Doing the negotiation in SDP
> lets us use the glare mitigation mechanisms we have built into SDP, so
> we save 0.5 round trips for every new channel.

The SCTP-specific thing requiring the ACK was to avoid an in-band issue 
(need to review mail archives with the SCTP authors to find it), so it 
wouldn't apply here.  I think it was only need to be able to tell the 
app for *sure* that the other side had processed the openresponse, but 
I'm not certain.

> This allows us to ditch the in-band signaling protocol almost entirely
> (see Option B below).
> Creating a new data channel triggers the onnegotiationneeded event.

This solution will work.  It means you're beholden to SDP and 
negotiation with the app involved.  I've always tried to avoid 
re-negotiation wherever possible; renegotiation is rife with 
hard-to-track-down timing and other issues.

> ==Layer 2
> Zero round trip channel establishment
> The only reason that we have for negotiation of each channel is to
> provide a consistent set of characteristics for each channel.  The
> peer that creates a channel decides the values for label,
> retransmission count (0, n, infinite), and subprotocol.  If you don't
> care about these values being consistent between peers, or you have
> another means of ensuring consistency, you don't need to negotiate new
> channels at all.

In fact, the current design (in-band protocol or the 'mixed' (2b) 
proposal) doesn't actually negotiate them - they're declarative. The 
response merely tells the creator what the opposite-direction stream 
number is (or if there was some failure).

> Here, we permit the use of additional channels immediately after
> creation, without negotiation.  This has several advantages...and
> ramifications.  And no real drawbacks.
> Firstly, the arrival of a packet on a stream that is not negotiated
> will require the creation of a data channel.  The properties of this
> data channel will be largely unknown. The browser can possibly detect
> that the channel is unreliable if the packet doesn't request
> acknowledgement, but that's something I'm not 100% clear on for
> partially reliable messages.  As a result, the browser will be
> required to leave these properties undefined or generate default
> values for them.
> It's perfectly OK to have default or undefined values for label,
> reliability and subprotocol as long as you let the application set new
> values.  This allows for another advantage: applications can, if they
> choose, set the reliability on a per-packet basis, consistent with all
> other SCTP APIs, but setting the property before sending each packet.
> This keeps the simplicity of the API design, ensures websocket
> compatibility for those that need it, but it exposes more SCTP
> capabilities to those that desire those features.
> This does have consequences for negotiation: Values for label,
> reliability and subprotocol need to be declarative in SDP, not
> negotiated.

The proposal I made yesterday (though I really didn't get a chance to 
present it) was purely declarative in the SDP (the mixed case I 
proposed).  They were stand-ins for the Open in-band messages and 
carried the same declarative info.

>   Both peers would be required to signal the values that
> they are using for each stream.  This would allow for the fact that
> peers could set different values for the same stream number, based on
> whatever values are set on their data channel object.  In the general
> case, it allows one peer to declare the use of a particular stream and
> the other peer to not advertise anything on the matching stream.
> This also makes the 'onopen' event useless for all but the first
> channel.  It should fire immediately for any channel that is created
> when the association is already active.
> Receipt of a message on a channel that has not already been created
> locally causes the following events, one after the other:
> ondatachannel, onopen, onmessage.

I'll note this is virtually the same as the original in-band protocol 
suggestion from Stockholm, with the loss of symmetry and labels.  The 
original proposal has the first message on a  stream be an Open message, 
but you can call Send() immediately.  We could fire onOpen immediately 
for WebSockets compatibility (without waiting for an OpenResponse); 
since we're declarative, this isn't unreasonable even semantically 
different than what causes onOpen in Websockets.

The downside(?) would be you have actual Open/OpenResponse/ACK(maybe).  
This also means there's no need to ever specify the channels in the SDP 
or renegotiate; all channel opens are 0 RTT effectively.

We previously had discussed exposing the full SCTP per-packet options, 
and generally people saw this as minimally useful and adding 
considerable confusion/complexity to web app authors.  Given you can 
open any number of channels with different characteristics the user 
isn't that constrained by this.

> In order to maintain the symmetrical usage pattern, and the
> websockets-compatible usage pattern, we would then require several
> things:
> 1. The browser MUST, by default, negotiate streams with values that
> match any in an offer if it does not already have a data channel for
> that stream number.  The browser MUST also create the corresponding
> data channels.
> 2. Applications that require perfect channel symmetry need to
> negotiate before using streams.
> 3. Applications that care about having their use of the API be
> interchangeable with websockets need to wait for the 'onopen' event
> before sending anything, lest they get errors when switching to
> websockets.
> On that last point: We could require that channels reject attempts to
> send() prior to the onopen event being processed, but that is
> unnecessarily mean.  Calling createDataChannel() followed immediately
> by send() should be OK as long as the association is active.

The wire protocol I've speced in draft-jesup-datachannel-protocol (sp) 
allows for send immediately after createDataChannel.  I agree and see no 
reason not to allow the JS to do this, though I think there was some 
disagreement last time from the W3 side.  However, this is not a real 
issue if you're going to fire onopen immediately on both sides.

>    Just
> because you haven't processed the 'onopen', doesn't mean that you
> should be prevented from using a perfectly usable channel.  Of course,
> waiting for onopen would be safest in the general case, and many
> applications would naturally do this, but I see no reason to constrain
> usage patterns unnecessarily.
> ===Option A
> Removing the in-band protocol makes the negotiation of the protocol
> that layers on top of SCTP less crucial ... it makes negotiation of
> the upper-layer protocol less crucial.  In the WebRTC case, we
> probably don't need to negotiate 'webrtc-datachannel', we could even
> let the application decide the value for that label.
> Personally, I don't think that we need to surface API to enable
> changing protocols.  However, it would be completely harmless in this
> configuration for an application to change the protocol label to
> something else by editing SDP, so that they could interoperate with a
> peer that expected another protocol.  That would enable CLUE usage, or
> BFCP, or whatever, as long as you can find someone who talks SCTP over
> DTLS over UDP.

They'd need to support SCTP over DTLS over ICE, and they'd need to 
support JSEP (or you'd need to somehow fake a response)
Is this an actual usecase?  If so, it hasn't been really surfaced 
before; could you expand on what this really means and how it would work?

If this is an important usecase (examples!), then we can move Open 
notifications over to a control channel.  This could be a wireline 
protocol in the browser (basically the same as the current wireline 
protocol with a field or two added).  Or as you say you push it all off 
into the application - but that means simple uses need a lot more 
boilerplate or JS-implement network protocol that many of these authors 
aren't familiar with.

> ===Option B
> The one remnant of the in-band protocol that remains is the parts that
> apply to the data payloads.  The in-band protocol is required to
> provide two features:
> 1. the ability to distinguish between textual data and binary data
> 2. the ability to send messages of arbitrary length
> I am sorely tempted to suggest that the first feature can instead be
> part of channel configuration, such that it is negotiated (with a
> default of binary).  This would mean that negotiation is needed if you
> want to use text and you can't handle the conversion of binary to
> text.  (Sadly, this isn't made easy and the top answer at
> stackoverflow doesn't work for UTF-8:

this would introduce a significant incompatibility with Websockets I 

> For the second, draft-jesup-rtcweb-data-protocol indicates that 2Gb is
> the limit, but my reading of RFC 4920 indicates that there is no limit
> to message size.  I'm far from expert in this area, but is it possible
> that this is an implementation limitation rather than a protocol one?
> Either way, I'm tempted to suggest that fragmentation can be pushed to
> the application.

This limit probably can be relaxed; Websockets allows IIRC 71-bit 
lengths ...  just in case you need them.

The practical limit is likely lower in that it returns a single 
arraybuffer/blob.  Right now Firefox limits Websockets to 2Gb.

> This would allow for direct access to SCTP, rather than an
> encapsulated layer.  This is good for several reasons.  Firstly, we
> don't need to specify a protocol at all.  We avoid all the arguments
> about what byte goes where.  More importantly, it leaves the SCTP
> clean, allowing WebRTC applications to use SCTP without ornamentation.

Sure, we can expose raw (or virtually raw) SCTP.  This was my original 
proposal over a year ago.  For what I think are good reasons, we pretty 
definitively decided on a simpler API for the JS programming API and in 
the wireline, and had left that decision lie since then.

> ===Option C
> If you care about reconciling the values for label, reliability, and
> subprotocol, it might be necessary to surface the values declared by
> your peer in the API.  You can get this information from the SDP, but
> if you don't like the idea of SDP spelunking you have two choices:
> provide an 'on(re)negotiated' event that carries the values declared
> by the remote peer; or, provide read-only accessors for these.
> I'm not certain that reconciliation of these values is important.
> Applications can even build their own mechanisms if it is.  If we must
> build more mechanisms, then I tend to favor the 'on(re)negotiated'
> event.
> _____________________________________________

I like (a lot) the declarative approach, and all the complications were 
due to needing to fulfill glare considerations (now resolved by not 
requiring resolving of label glare and not requiring bidirectional 
stream pairs have the same number), and due to the requirement for 
websockets compatibility with onOpen (and to not fire it until you have 
positive notification from the other side). If you drop that last part, 
you have immediate declarative 0-RTT opening time DataChannels.  I would 
propose keeping things simpler for users and to use the wireline 
protocol for the declaration/response, and avoid all the weirdnesses 
around labels, protocols and modes caused by dropping it.

I like your Layer 2, but with the wireline protocol previously speced.  
It gets you all the label/mode/etc sync stuff, and merely rules out 
option A (or requires you to dedicate a control stream).

Randell Jesup