Re: DataChannels API


Thanks for putting together this summary.

On 2012-08-31 23:05, Randell Jesup wrote:
> So, on a totally different topic:
> We discussed the DataChannels API at the Stockholm Interim.  I'd like to
> move this part of the spec forward, as Mozilla has an implementation in
> testing.
> The API, per the decisions at the Interim and mailing list is based
> closely on the WebSockets interface.  For example, you are supposed to
> wait for onopen to fire before calling send(), at both ends. (The
> low-level IETF protocol supports sending before onopen, but WebSockets
> doesn't.)  Currently I have no limit on send(DOMString); WebSockets
> limits DOMStrings to 123 characters.
> I should note that the immediately-following IETF Interim appeared to
> have the opposite conclusion on onopen and send(), and so the IETF
> protocol design allows sending immediately, while the API I propose for
> WebRTC DataChannels here does not.
> Supported channel types are reliable (and and out of order) channels,
> unreliable and partly-reliable channels.  (See the dictionary below.)

What role do partly-reliable channels have here? I don't see a natural 
way to expose such channels to JavaScript ATM since we put the transport 
properties on the channel and not on every package.

> I'd *REALLY* like to move forward on resolving the open issues listed
> below, as we're preparing to expose a preliminary DataChannels
> implementation.   Thanks.

Sounds great!

> Open Issues:
> ==========
> When can createDataChannel() be called?
> ----------------------------------------------------------
> Currently pc.createDataChannel() must be called after onconnected
> fires.  This was a point of discussion at the meeting and on the rtcweb
> list, since DataChannels need some RTTs to establish; allowing the
> application to pre-request data channels would allow them to be included
> in the signaling (and thus save 1 RTT off the setup time).

What triggers the onconnected callback?

> In order to allow pc.createDataChannel() to be called earlier the only
> difference at the offerer's JS API level would be whether you can do:
>      pc = new PeerConnection(...);
>      pc.addStream(...);
>      pc.createDataChannel("foo",{});
>      pc.createOffer(...);
> etc.  On the receive side, there's no way to reject a DataChannel (just
> as there's no way to reject one before it's created after the
> PeerConnection is connected).  You can avoid setting onDataChannel or
> respond to onDataChannel by closing it if you don't want it.  The
> receiver would be able to call pc.createDataChannel() before
> createAnswer().  In all cases the channel isn't usable until onopen fires.
> Do we need a DataConnection object?
> -----------------------------------------------------
> It was suggested that we have a DataConnection object, and hang
> createDataChannel off of that.  (see the thread "DataConnection objects"
> from June.)  Doing so would minorly reduce the number of methods on
> PeerConnection (by moving onconnection/onclosedconnection/ondatachannel
> to it, and maybe an attribute for initial number of streams).
> Pros:
> * It gives you a clear way to easily drop all DataChannels.
> * It gives you an easy point to query the association (mostly for
> maxstreams I'd guess, perhaps for total bytes queued across all
> DataChannels).
> * A spec for a DataConnection object might be useful in some other
> context in the future - but it always could be added later if needed.
> (You could even indicate that PeerConnection implements DataConnection
> if you wanted.)
> * It does give you a clear way to say "Don't bother to open an
> association" if you don't need one.
> * You could add more DataConnections to a PeerConnections (but what does
> that gain you?)
> * Allows future extension to allow other protocols to be used over the
> connection/association.
> * Gives you something to hang an application identifier off of - but the
> application can do that in other ways.
> Cons:
> * More objects, more code required to set up a call with little benefit
> to the current usecases.
> * If you want to add a DataConnection later, it will require a renegotiation
> * Answering requires a few extra steps to see if the offerer offered a
> DataConnection.
> Overall, I'm very mildly in favor of adding the DataConnection object,
> because it might be useful in some other contexts in the future.  I do
> think it complicates PeerConnection slightly, but only slightly  (less
> methods, but PeerConnection now needs to trigger renegotiation when
> createDataConnection is called.)

I'm still a bit hesitant to insert another object. However, if we need 
the extra state machine (onconnection and onclosedconnection) I'm, on 
the other hand, a bit hesitant to just add that to PeerConnection as 
well (since it already exposes two types of states).

> Label glare:
> ---------------
> A previous discussion ("Data API symmetry", in April/May) covered this.
> This is the "what happens if both sides call createDataChannel("foo",{})
> at the same time" question.  You can:
> 1) Create two channels labelled "foo".  Each side would get an onopen to
> their createDataChannel, and each would get an onDataChannel and onopen
> for the one created by the other side. Handling the glare would be the
> application's domain.
> 2) Fail both (or find some agreed-on tiebreaker that lets you have one
> fail and the other succeed).
> 3) Create one channel labelled "foo", and each side would believe they
> created it.  Both would simply get "onopen", and it might even come
> faster than normal.  NOTE: if the two sides select different options for
> the channel, then you still may need to return errors! (or create
> channels with the same label)
> #3 is mildly appealing, until you think about how you handle errors with
> disagreement on reliability.  So I think I end up preferring #1.  #3
> also implies you should have a unique label for each channel, to avoid
> confusions with opening multiple channels with the same name at the same
> time when the other side tries to as well.

Since we want to support the "create at A, dispatch at B"-method I agree 
to #1.

#3 also comes with timing issues when channels can be created by both 
"label matching" and "create at A, dispatch at B"-methods. How long 
should you wait for a matching label before dispatching a channel on the 
B-side instead?

> Attributes:
> -------------
> Is the single "reliable" attribute enough?  Do we need to expose the
> dict entries?  Do we need a FindDataChannel(label) to get a reference to
> an existing channel?
> (My opinion: Probably no to all of these, though I can see exposing the
> dict entries.)

I think a reliable property is preferable since the developer doesn't 
have to derive what reliable is from a set of other properties. It 
shouldn't prevent us from exposing other properties (later) to tweak the 
transfer mode.

> This is the dictionary for RTCPeerConnection's createDataChannel()
> method: (xpidl)
> /* If either maxRetransmitTime or maxRetransmitNum are set, it's
>      unreliable, else it's a reliable channel.  If both are set it's an
>      error.  outOfOrderAllowed can be used with any type of channel.  The
>      equivalent of UDP is { outOfOrderAllowed: true, maxRetransmitNum: 0 }.
>      The TCP equivalent is {}. */
> dictionary DataChannelInit {
>     boolean outOfOrderAllowed;
>     unsigned short maxRetransmitTime; // in ms
>     unsigned short maxRetransmitNum;
> };
> And in PeerConnection: (xpidl)
>     /* Data channel */
>     nsIDOMDataChannel createDataChannel([optional] in ACString label,
>                                         /* DataChannelInit */ [optional] in jsval options);
>     attribute RTCPeerConnectionCallbackVoid onConnection;
>     attribute RTCPeerConnectionCallbackVoid onClosedConnection;
>     attribute RTCPeerConnectionCallback onDataChannel;

This is an EventHandler (not a callback) with an associated 
DataChannelEvent in the current specification. onConnection and 
onClosedConnection should also be EventHandlers for consistency with the 
rest of the spec.


> This is the webidl for DataChannel I have currently (note: it might have
> errors as we use xpidl internally, though we're switching to webidl).
> interface DataChannel : EventTarget {
>     [Infallible]
>     readonly attribute DOMString label;
>     [Infallible]
>     readonly attribute boolean reliable;
>     // ready state
>     const unsigned short CONNECTING = 0;
>     const unsigned short OPEN = 1;
>     const unsigned short CLOSING = 2;
>     const unsigned short CLOSED = 3;
>     [Infallible]
>     readonly attribute unsigned short readyState;
>     [Infallible]
>     readonly attribute unsigned long bufferedAmount;
>     [TreatNonCallableAsNull, GetterInfallible]
>     attribute Function? onopen;
>     [TreatNonCallableAsNull, GetterInfallible]
>     attribute Function? onerror;
>     [TreatNonCallableAsNull, GetterInfallible]
>     attribute Function? onclose;
>     [Infallible]
>     readonly attribute DOMString extensions;
>     [Infallible]
>     readonly attribute DOMString protocol;
>     void close();
>     // messaging
>     [TreatNonCallableAsNull, GetterInfallible]
>     attribute Function? onmessage;
>     [GetterInfallible]
>     attribute DOMString binaryType;
>     void send(DOMString data);
>     void send(Blob data);
>     void send(ArrayBuffer data);
> };

Received on Thursday, 6 September 2012 14:19:40 UTC