Почему в WebRTC не открывается DataChannel с третьим пользователем?

Здравствуйте, я пытаюсь сделать многопользовательский чат с использованием WebRTC. Все должно работать примерно так:
  1. Новый пользователь, используя WebSocket, отправляет широковещательное сообщение, так самым как бы анонсируя себя.
  2. Другие пользователи должны отправить новому SDP offer.
  3. Новый пользователь должен отправить SDP answer тем, от кого он получил offer.


Когда два пользователя подключены друг к другу, проблем не возникает. Когда же третий пользователь пытается подключиться, он отправляет анонс, два предыдущих пользователя отправляют ему offer, он отправляет им answer, но канал почему-то открывается только с одним из них. Помогите, пожалуйста, понять, что я делаю не так.

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>


Сигнальный сервер:

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);
        }
    });
});
  • Вопрос задан
  • 816 просмотров
Пригласить эксперта
Ответы на вопрос 1
ACCNCC
@ACCNCC
Делаю игры!
Все нормально работает! Но меня не работает в firefox!
Получаю в консоли:
ICE failed, see about:webrtc for more details
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы