Queue ICE candidates until remoteDescription is set
This commit is contained in:
+55
-1
@@ -625,6 +625,33 @@ let chatDataChannels = {}; // keep track of our peer chat data channels
|
||||
let fileDataChannels = {}; // keep track of our peer file sharing data channels
|
||||
let allPeers = {}; // keep track of all peers in the room, indexed by peer_id == socket.io id
|
||||
|
||||
|
||||
let pendingIceCandidates = {};
|
||||
|
||||
function queueIceCandidate(peer_id, ice_candidate) {
|
||||
if (!peer_id || !ice_candidate) return;
|
||||
if (!pendingIceCandidates[peer_id]) pendingIceCandidates[peer_id] = [];
|
||||
pendingIceCandidates[peer_id].push(ice_candidate);
|
||||
}
|
||||
|
||||
async function flushIceCandidates(peer_id) {
|
||||
const pc = peerConnections[peer_id];
|
||||
const queued = pendingIceCandidates[peer_id];
|
||||
|
||||
if (!pc || !queued || queued.length === 0) return;
|
||||
if (!pc.remoteDescription || !pc.remoteDescription.type) return;
|
||||
|
||||
delete pendingIceCandidates[peer_id];
|
||||
|
||||
for (const ice of queued) {
|
||||
try {
|
||||
await pc.addIceCandidate(new RTCIceCandidate(ice));
|
||||
} catch (err) {
|
||||
console.error('[Error] addIceCandidate (queued)', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let lastStats = null;
|
||||
|
||||
// stream
|
||||
@@ -2715,6 +2742,9 @@ async function handleAddPeer(config) {
|
||||
const peerConnection = new RTCPeerConnection({ iceServers: iceServers });
|
||||
peerConnections[peer_id] = peerConnection;
|
||||
|
||||
// If ICE arrived before we processed addPeer, keep it and flush when ready.
|
||||
flushIceCandidates(peer_id).catch((err) => console.error('[Error] flushIceCandidates', err));
|
||||
|
||||
allPeers = peers;
|
||||
// Ensure extras object exists for every peer to avoid undefined checks later
|
||||
try {
|
||||
@@ -3115,10 +3145,19 @@ function handleSessionDescription(config) {
|
||||
|
||||
const pc = peerConnections[peer_id];
|
||||
|
||||
if (!pc) {
|
||||
console.warn('[RTCSessionDescription] peer connection missing, ignoring', { peer_id });
|
||||
return;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setRemoteDescription
|
||||
pc.setRemoteDescription(remote_description)
|
||||
.then(() => {
|
||||
console.log('setRemoteDescription done!');
|
||||
|
||||
// Drain any queued ICE now that remoteDescription is set.
|
||||
flushIceCandidates(peer_id).catch((err) => console.error('[Error] flushIceCandidates', err));
|
||||
|
||||
if (session_description.type == 'offer') {
|
||||
console.log('Creating answer');
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createAnswer
|
||||
@@ -3166,7 +3205,20 @@ function handleSessionDescription(config) {
|
||||
function handleIceCandidate(config) {
|
||||
const { peer_id, ice_candidate } = config;
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate
|
||||
peerConnections[peer_id].addIceCandidate(new RTCIceCandidate(ice_candidate)).catch((err) => {
|
||||
const pc = peerConnections[peer_id];
|
||||
|
||||
if (!pc) {
|
||||
queueIceCandidate(peer_id, ice_candidate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue until remoteDescription is set; otherwise addIceCandidate can fail and the candidate is lost.
|
||||
if (!pc.remoteDescription || !pc.remoteDescription.type) {
|
||||
queueIceCandidate(peer_id, ice_candidate);
|
||||
return;
|
||||
}
|
||||
|
||||
pc.addIceCandidate(new RTCIceCandidate(ice_candidate)).catch((err) => {
|
||||
console.error('[Error] addIceCandidate', err);
|
||||
});
|
||||
}
|
||||
@@ -3229,6 +3281,7 @@ function handleDisconnect(reason) {
|
||||
chatDataChannels = {};
|
||||
fileDataChannels = {};
|
||||
peerConnections = {};
|
||||
pendingIceCandidates = {};
|
||||
peerScreenMediaElements = {};
|
||||
peerVideoMediaElements = {};
|
||||
peerAudioMediaElements = {};
|
||||
@@ -3302,6 +3355,7 @@ function handleRemovePeer(config) {
|
||||
delete chatDataChannels[peer_id];
|
||||
delete fileDataChannels[peer_id];
|
||||
delete peerConnections[peer_id];
|
||||
delete pendingIceCandidates[peer_id];
|
||||
delete peerScreenMediaElements[peerScreenId];
|
||||
delete peerVideoMediaElements[peerVideoId];
|
||||
delete peerAudioMediaElements[peerAudioId];
|
||||
|
||||
Reference in New Issue
Block a user