- From: Stefan Hakansson LK <stefan.lk.hakansson@ericsson.com>
- Date: Mon, 3 Sep 2012 15:27:24 +0200
- To: public-webrtc@w3.org
On 08/31/2012 11:05 PM, 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.) > > 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. > > 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). I think this makes sense. > > 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(...); or just (if you're only going to do data): pc = new PeerConnection(...); pc.createDataChannel("foo",{}); === "negotiationneeded" fires === pc.createOffer(...); I don't see a reason why you would need to create a PeerConnection, wait for onopen, and then createDataChannel. > > 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 don't have a strong view. > > > 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. +1, I also think #1 makes most sense. > > > 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? To me, the single "reliable" attribute seems enough for a first version, but if others want more it should be added (after all, a reason for using a dictionary was to enable the addition of more things as we see need). > > (My opinion: Probably no to all of these, though I can see exposing the > dict entries.) > > > > 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 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 Monday, 3 September 2012 13:27:54 UTC