RTCIceCandidate role
by jib1
HTML
<video id="video1" width="160" height="120" autoplay muted></video>
<video id="video2" width="160" height="120" autoplay></video><br>
<div id="div"></div>
JavaScript
const console = {log: msg => div.innerHTML += `${msg}<br>`};
const dump = f => console.log(`${f.toString().slice(6)} = ${JSON.stringify(f(), null, 2)}`);
const wait = ms => new Promise(r => setTimeout(r, ms));
const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({video: true});
for (const track of stream.getTracks()) {
pc1.addTrack(track, stream);
}
await pc1.setLocalDescription();
console.log("PC1 after SLD(offer):");
const {iceTransport} = pc1.getTransceivers()[0].sender.transport;
dump(() => iceTransport);
dump(() => iceTransport.role);
dump(() => iceTransport.component);
dump(() => iceTransport.state);
dump(() => iceTransport.gatheringState);
await pc2.setRemoteDescription(pc1.localDescription);
console.log("PC2 after SRD(offer):");
dump(() => pc2.getTransceivers()[0].receiver.transport);
await pc2.setLocalDescription();
console.log("PC2 after SLD(answer):");
const iceTransport2 = pc2.getTransceivers()[0].receiver.transport.iceTransport;
dump(() => iceTransport2);
dump(() => iceTransport2.role);
dump(() => iceTransport2.component);
dump(() => iceTransport2.state);
dump(() => iceTransport2.gatheringState);
await pc1.setRemoteDescription(pc2.localDescription);
console.log("PC1:");
dump(() => iceTransport.role);
await wait(1000);
dump(() => iceTransport.role);
} catch (e) {
console.log(e);
}
})();
pc1.onicecandidate = ({candidate}) => pc2.addIceCandidate(candidate);
pc2.onicecandidate = ({candidate}) => pc1.addIceCandidate(candidate);
pc1.oniceconnectionstatechange = () => console.log(pc1.iceConnectionState);