W3C home > Mailing lists > Public > public-webrtc@w3.org > April 2012

RE: Data API symmetry

From: Jim Barnett <Jim.Barnett@genesyslab.com>
Date: Wed, 25 Apr 2012 07:58:47 -0700
Message-ID: <E17CAD772E76C742B645BD4DC602CD810616EC71@NAHALD.us.int.genesyslab.com>
To: "Adam Bergkvist" <adam.bergkvist@ericsson.com>, <public-webrtc@w3.org>
Your approach #2 (both sides create data channel with same label)
becomes tricky when the two parties aren't downloading their pages from
the same site. They're very unlikely to select the same label and
settings in this case. Overall, isn't it safer to have one side create
the channel and pass the label and the settings to the other side? (The
receiving side can accept/reject/modify, of course).  It is somewhat
asymmetrical, but so is the basic offer/answer paradigm for creating a
call/media connection. 

- Jim 

-----Original Message-----
From: Adam Bergkvist [mailto:adam.bergkvist@ericsson.com] 
Sent: Wednesday, April 25, 2012 10:04 AM
To: public-webrtc@w3.org
Subject: Data API symmetry

Hi

In a previous mail conversation we discussed the data channel setup
process; as a starting point we had the createDataChannel()@A ->
"datachannel event"@B. The question was if we also should support the
automatic label matching approach where each peer could call
createDataChannel("label") and if the labels were the same, the data
channels would be connected and the "open" event would trigger on each
side. The result of the discussion was that the two approaches were
tricky to combine since it wasn't straightforward to determine if a
"datachannel" event should be triggered at the other peer or if the
other peer may call createDataChannel() with a matching label in the
near future. In the recent discussions about the "open" event we have
talked about symmetry and our current API is a bit asymmetric in some
sense. Therefore I've done some coding where the current approach with a
createDataChannel() call and a "datachannel" event is compared to the
matching label approach, not combined with the first approach as in the
previous discussion, but on its own. This means that in the matching
label approach, a channel is not usable until a matching channel has
been created on the other side. I've come up with two cases (A and B
described below) and approaches #1 ("datachannel" event) and #2 (label
matching) are applied to both.

Case A demonstrates the two approaches when two data channels ("chat" 
and "extra") are set up as soon as the PeerConnection reaches the ACTIVE
state ("open" event is triggered). I think this is a common use case
when an application wants a set of data channels from the start.

The symmetry of #2 is really advantageous in this case - the channels
can simply be created and assigned to their corresponding variables. 
Both sides waits for the "open" event to get started. Approach #1 needs
to decide who will create the channels and the receiving side needs to
determine which dispatched channel that should go into which local
variable.

// Case A - #1

peerConn.onopen = function () {
     if (caller) {
         chatDataChan = peerConn.createDataChannel("chat",
chatSettings);
         chatDataChan.onopen = startChat;
         chatDataChan.onmessage = showChatMessage;

         extraDataChan = peerConn.createDataChannel("extra",
extraSettings);
         extraDataChan.onopen = startExtra;
         extraDataChan.onmessage = onExtraMessage;
     }

     peerConn.ondatachannel = function (evt) {
         var chan = evt.channel;
         if (chan.label == "chat") {
             chatDataChan = chan;
             startChat();
             chatDataChan.onmessage = showChatMessage;
         }
         else {
             extraDataChan = chan;
             startExtra();
             extraDataChan.onmessage = onExtraMessage;
         }
     };
};

//----------------------------------------------------------------------
--------

// Case A - #2

peerConn.onopen = function () {
     chatDataChan = peerConn.createDataChannel("chat", chatSettings);
     chatDataChan.onopen = startChat;
     chatDataChan.onmessage = showChatMessage;

     extraDataChan = peerConn.createDataChannel("extra", extraSettings);
     extraDataChan.onopen = startExtra;
     extraDataChan.onmessage = onExtraMessage; };

//======================================================================
========

In case B, one data channel is set up as the PeerConnection object
reaches the ACTIVE state (as in case A), and an "extra" channel is set
up as a response to a user action (button click in this case).

Approach #1 has an advantage in case B since the API is based around one
side initializing the data channel creation process. In approach #2, the
JavaScript needs to signal that the other side should create a data
channel with a specific label. However, in #1 there's a risk that two
parallel data channels with the same label are created if both users
clicks the add button simultaneously. In #2, the simultaneous clicks
would actually set up the channel and the manual creation signaling from
the other side can be discarded by both sides.

// Case B - #1

peerConn.onopen = function () {
     if (caller) {
         chatDataChan = peerConn.createDataChannel("chat",
chatSettings);
         chatDataChan.onopen = startChat;
         chatDataChan.onmessage = showChatMessage;
     }

     peerConn.ondatachannel = function (evt) {
         var chan = evt.channel;
         if (chan.label == "chat") {
             chatDataChan = chan;
             startChat();
             chatDataChan.onmessage = showChatMessage;
         }
         else {
             extraDataChan = chan;
             startExtra();
             extraDataChan.onmessage = onExtraMessage;
         }
     };
};


addButton.onclick = function () {
     if (extraDataChan)
         return;

     extraDataChan = peerConn.createDataChannel("extra", extraSettings);
     extraDataChan.onopen = startExtra;
     extraDataChan.onmessage = onExtraMessage; };

//----------------------------------------------------------------------
--------

// Case B - #2

peerConn.onopen = function () {
     chatDataChan = peerConn.createDataChannel("chat", chatSettings);
     chatDataChan.onopen = startChat;
     chatDataChan.onmessage = showChatMessage; };

addButton.onclick = function () {
     if (extraDataChan)
         return;

     viaWebServer.send("setup extra channel");
     setupExtraChannel();
};

function setupExtraChanel() {
     extraDataChan = peerConn.createDataChannel("extra", extraSettings);
     extraDataChan.onopen = startExtra;
     extraDataChan.onmessage = onExtraMessage; }

viaWebServer.onmessage = function (evt) {
     if (evt.data == "setup extra chanel" && !extraDataChannel)
         setupExtraChannel();
};

//======================================================================
========

Regarding the settings used when creating a new data channel, #2 does
introduce an extra risk of failure if the settings mismatches (not
possible in #1), but it's a programming error that will throw an
exception. In the example "Case B - #2" above, the settings for the
"extra" data channel is known to both sides since it's a symmetric
application, but in the case where the initiating side has modified or
created a new settings object, the settings needs to be transferred
along with the request to tell the other side to create a data channel
with a matching label.

Thanks for reading all the way here.

BR
Adam
Received on Wednesday, 25 April 2012 14:59:34 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Wednesday, 25 April 2012 14:59:35 GMT