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:04:58 UTC