S
S
saferif2015-04-08 17:02:20
JavaScript
saferif, 2015-04-08 17:02:20

Why doesn't a DataChannel with a third user open in WebRTC?

Hello, I'm trying to make a multiplayer chat using WebRTC. Everything should work like this:

  1. The new user, using WebSocket, sends a broadcast message, as if announcing himself.
  2. Other users must send the new SDP offer.
  3. The new user must send an SDP answer to those from whom he received the offer.

When two users are connected to each other, there is no problem. When the third user tries to connect, he sends an announcement, two previous users send him an offer, he sends them an answer, but for some reason the channel opens with only one of them. Please help me understand what I'm doing wrong.
HTML + JS:
<html>
<head>
    <title>WebRTC Chat Demo</title>
    <script src="/socket.io/socket.io.js"></script>
</head>
<body>

<textarea id="message"></textarea><button onclick="connect();">Connect</button><button onclick="sendMessage();">Send</button>
<div id="chatlog"></div>

<script>

var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;

function id () {
    return (Math.random() * 10000 + 10000 | 0).toString();
}

var ROOM = location.hash.substr(1);

// no room number specified, so create one
// which makes us the offerer
if (!ROOM) {
    ROOM = id();
    document.write("<a href='#"+ROOM+"'>Send link to other peer</a>");
}

var ME = id();

var socket = io.connect('', {port: 3000});
socket.on('webrtc', socketReceived);
socket.on('new', socketNewPeer);
socket.emit('room', JSON.stringify({id: ME, room: ROOM}));

// get references to the document tags
var chatlog = document.getElementById("chatlog");
var message = document.getElementById("message");

// options for the PeerConnection
var server = {
    iceServers: [
        {url: "stun:23.21.150.121"},
        {url: "stun:stun.l.google.com:19302"},
        {url: "turn:numb.viagenie.ca", credential: "webrtcdemo", username: "******"}
    ]
};
var options = {
    optional: [
        {DtlsSrtpKeyAgreement: true},
        {RtpDataChannels: true} 
    ]
}

var peers = {};

function bindEvents (channel) {
    channel.onopen = function () { console.log("Channel Open"); }
    channel.onmessage = function (e) {

        console.log(e);
        chatlog.innerHTML += "<div>Peer says: " + e.data + "</div>";
    };
}

function sendMessage () {
    var msg = message.value;
    for (var peer in peers) {
        if (peers.hasOwnProperty(peer)) {
            if (peers[peer].channel !== undefined) {
                peers[peer].channel.send(msg);
            }
        }
    }
    message.value = "";
}

function sendViaSocket(type, message, to) {
    socket.emit("webrtc", JSON.stringify({id: ME, to: to, type: type, data: message}));
}

function socketNewPeer(data) {
    peers[data] = {
        candidateCache: []
    };

    var pc = new PeerConnection(server, options);
    pc.onicecandidate = function(event) {
        if (event.candidate) {
            peers[data].candidateCache.push(event.candidate);
        }
        if (!event.candidate) {
            sendViaSocket('offer', pc.localDescription, data);
            for (var i = 0; i < peers[data].candidateCache.length; i++) {
                sendViaSocket('candidate', peers[data].candidateCache[i], data);
            }
        }
    };
    peers[data].connection = pc;

    var channel = pc.createDataChannel('mychannel', {});
    channel.owner = data;
    peers[data].channel = channel;

    bindEvents(channel);

    pc.createOffer(function(offer) {
        pc.setLocalDescription(offer);
    });
}

function socketReceived(data) {
    var json = JSON.parse(data);
    switch (json.type) {
        case "candidate": 
            remoteCandidateReceived(json.id, json.data);
            break;
        case "offer":
            remoteOfferReceived(json.id, json.data);
            break;
        case "answer":
            remoteAnswerReceived(json.id, json.data);
            break;
    }
}

function createConnection(id) {
    if (peers[id] === undefined) {
        peers[id] = {
            candidateCache: []
        };
        pc = new PeerConnection(server, options);
        pc.onicecandidate = function(event) {
            if (event.candidate) {
                peers[id].candidateCache.push(event.candidate);
            }
            if (!event.candidate) {
                sendViaSocket('answer', pc.localDescription, id);
                for (var i = 0; i < peers[id].candidateCache.length; i++) {
                    sendViaSocket('candidate', peers[id].candidateCache[i], id);
                }
            }
        };
        peers[id].connection = pc;
        pc.ondatachannel = function(e) {
            peers[id].channel = e.channel;
            peers[id].channel.owner = id;
            bindEvents(peers[id].channel);
        }
    }
}

function remoteCandidateReceived(id, data) {
    createConnection(id);
    var pc = peers[id].connection;
    pc.addIceCandidate(new IceCandidate(data));
    console.log('CANDIDATE RECEIVED');
}

function remoteOfferReceived(id, data) {
    createConnection(id);
    var pc = peers[id].connection;

    pc.setRemoteDescription(new SessionDescription(data));
    pc.createAnswer(function(answer) {
        pc.setLocalDescription(answer);
    });
    console.log('OFFER RECEIVED');
}

function remoteAnswerReceived(id, data) {
    createConnection(id);
    var pc = peers[id].connection;

    pc.setRemoteDescription(new SessionDescription(data));
    console.log('ANSWER RECEIVED');
}
</script>

</body>
</html>

Signal server:
var users = {};
var io = socket_io(server);
io.on('connection', function(socket) {
    socket.on('room', function(message) {
        console.log(message);
        var json = JSON.parse(message);
        users[json.id] = socket;
        if (socket.room !== undefined) {
            socket.leave(socket.room);
        }
        socket.room = json.room;
        socket.join(socket.room);
        socket.broadcast.to(socket.room).emit('new', json.id);
    });
    socket.on('webrtc', function(message) {
        console.log(message);
        var json = JSON.parse(message);
        if (json.to !== undefined && users[json.to] !== undefined) {
            users[json.to].emit('webrtc', message);
        } else {
            socket.broadcast.to(socket.room).emit('webrtc', message);
        }
    });
});

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Nicholas, 2015-10-01
@ACCNCC

Everything works fine! But it doesn't work for me in firefox!
I get in the console:
ICE failed, see about: webrtc for more details

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question