Looking through the Chrome/Firefox bug trackers it looks like this issue has been identified and resolved, but only in Chrome Canary 33.0.1715.0 or higher.
If you're unwilling to require the Chrome Canary build mentioned above, you can detect the bad peer combination, and have your 'offer' button signal the other client to make an offer.
Pseudocode:
socket.onMessage(msg) {
if(msg == "request-offer"){
doOffer();
}
...
}
createDataChannelButton.onClick() {
if(!canCreateChannelBasedOnBrowser){
socket.send("request-offer");
}
else {
doOffer();
}
}
With your example code:
<!DOCTYPE html>
<html>
<head>
<title>WebRTC test</title>
<meta charset="utf-8">
</head>
<body>
<button id="create" disabled>Create data channel</button>
<script type="text/javascript">
// DOM
// CHANGE: Add basic browser detection based on google's adapter.js file.
var rtcBrowserVersion = 0;
var rtcCanInitiateDataOffer = false;
if (navigator.mozGetUserMedia) {
rtcBrowserVersion = parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
rtcCanInitiateDataOffer = true;
} else if (navigator.webkitGetUserMedia) {
// Chrome Canary reports major version 35 for me. Can't find a reliable resource to confirm
// canary versions.
rtcBrowserVersion = parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
rtcCanInitiateDataOffer = rtcBrowserVersion >= 35;
}
var create = document.getElementById('create');
// Compatibility
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate;
// Create a WebRTC object
var rtc = new RTCPeerConnection(null);
// Create a data channel
var sendChannel = rtc.createDataChannel('pingtest', {reliable: false});
var myMsg = 'ping';
function setRecvChannel(recvChannel) {
recvChannel.onmessage = function(event) {
if(event.data.indexOf('\x03\x00\x00\x00\x00\x00\x00\x00\x00') === 0) {
console.log('-> ' + window.btoa(event.data));
return; // Received channel's name, ignore
}
console.log('-> ' + event.data);
window.setTimeout(function() {
console.log('<- ' + myMsg);
sendChannel.send(myMsg);
}, 500);
};
}
// Chrome and Firefox
sendChannel.onopen = function(event) {
setRecvChannel(sendChannel);
if(myMsg === 'ping') {
console.log('<- ' + myMsg);
sendChannel.send(myMsg);
}
};
// Firefox
rtc.ondatachannel = function(event) {
setRecvChannel(event.channel);
};
// ICE
rtc.onicecandidate = function(event) {
if(event.candidate) {
console.log('<- ' + JSON.stringify(event.candidate));
ws.send(JSON.stringify(event.candidate));
}
};
// Signaling channel
var ws = new WebSocket('ws://127.0.0.1:49300/');
ws.onopen = function() {
create.disabled = false;
};
ws.onmessage = function(event) {
console.log('-> ' + event.data);
var data = JSON.parse(event.data);
if(data.sdp) {
rtc.setRemoteDescription(new RTCSessionDescription(data));
if(data.type === 'offer') {
myMsg = 'pong';
rtc.createAnswer(function(anwser) {
rtc.setLocalDescription(anwser, function () {
console.log('<- ' + JSON.stringify(anwser));
ws.send(JSON.stringify(anwser));
});
}, console.error);
}
}
// CHANGE: Chrome with offer bug asked to initiate the offer.
else if(data.initiate === true){
doOffer();
}
else {
rtc.addIceCandidate(new RTCIceCandidate(data));
}
};
ws.onclose = function() {
create.disabled = true;
};
// Create an offer
// CHANGE: Create function for offer, so that it may be called from ws.onmessage
function doOffer(){
rtc.createOffer(function(offer) {
rtc.setLocalDescription(offer, function () {
offer.sdp = offer.sdp;
console.log(offer.sdp);
console.log('<- ' + JSON.stringify(offer));
ws.send(JSON.stringify(offer));
});
}, console.error);
}
create.onclick = function() {
// CHANGE: If this client is not able to negotiate a data channel, send a
// message to the peer asking them to offer the channel.
if(rtcCanInitiateDataOffer){
doOffer();
}
else {
ws.send(JSON.stringify({initiate:true}));
}
};
Related Issues:
- WebRTC - Test SCTP data channel interop with Firefox Closed as Fixed 11/25/13
- Chromium - SCTP Data Channel fails to connect if Chrome offers and FF answers - Closed as Fixed 11/4/13
It is also worth noting that there is currently a max message buffer size of 16KB when sending data to a Chrome peer. If you are sending large data messages, you will need to break them into 16KB chunks before transmitting them over the data channel.