- From: Adam Bergkvist <adam.bergkvist@ericsson.com>
- Date: Wed, 25 Apr 2012 16:04:25 +0200
- To: "public-webrtc@w3.org" <public-webrtc@w3.org>
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