450 lines
21 KiB
HTML
450 lines
21 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<script type="application/javascript" src="pc.js"></script>
|
|
<script type="application/javascript" src="iceTestUtils.js"></script>
|
|
<script type="application/javascript" src="helpers_from_wpt/sdp.js"></script></head>
|
|
<body>
|
|
<pre id="test">
|
|
<script type="application/javascript">
|
|
createHTML({
|
|
bug: "1253706",
|
|
title: "Test ICE gathering when setConfiguration is used to change the ICE config"
|
|
});
|
|
|
|
const tests = [
|
|
async function baselineV4Cases() {
|
|
await checkSrflx([{urls:[`stun:${turnAddressV4}`]}]);
|
|
await checkRelayUdp([{urls:[`turn:${turnAddressV4}`], username, credential}]);
|
|
await checkRelayTcp([{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]);
|
|
await checkRelayUdpTcp([{urls:[`turn:${turnAddressV4}`, `turn:${turnAddressV4}?transport=tcp`], username, credential}]);
|
|
await checkNoSrflx();
|
|
await checkNoRelay();
|
|
},
|
|
|
|
async function addStunServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
pc.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `just a stun server`);
|
|
ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
|
|
ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnTcpServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addStunServerAfterOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `just a stun server`);
|
|
ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnServerAfterOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
|
|
ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnTcpServerAfterOffer() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
|
|
ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should get no srflx candidates");
|
|
ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeStunServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
pc.setConfiguration({});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeTurnServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
try {
|
|
pc.setConfiguration({});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeTurnTcpServerBeforeOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
try {
|
|
pc.setConfiguration({});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeStunServerAfterOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `just a stun server`);
|
|
ok(candidates1.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeTurnServerAfterOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
|
|
ok(candidates1.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(candidates1.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function removeTurnTcpServerAfterOffer() {
|
|
const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
try {
|
|
const candidates1 = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
|
|
ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should get no srflx candidates");
|
|
ok(candidates1.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
await pc.setLocalDescription({type: "rollback"});
|
|
|
|
pc.setConfiguration({});
|
|
const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
|
|
ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addStunServerAfterNegotiation() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
const candidatePromise = trickleIce(offerer);
|
|
await connect(offerer, answerer, 32000, `no ICE servers`);
|
|
const candidates = await candidatePromise;
|
|
const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
|
|
is(ufrags.length, 1, "Should have one ufrag in candidate set");
|
|
|
|
offerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
const candidates2 = await gatherWithTimeout(offerer, 32000, `just a stun server`);
|
|
ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
|
|
is(ufrags2.length, 1, "Should have one ufrag in candidate set");
|
|
isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnServerAfterNegotiation() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
const candidatePromise = trickleIce(offerer);
|
|
await connect(offerer, answerer, 32000, `no ICE servers`);
|
|
const candidates = await candidatePromise;
|
|
const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
|
|
is(ufrags.length, 1, "Should have one ufrag in candidate set");
|
|
|
|
offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
const candidates2 = await gatherWithTimeout(offerer, 32000, `a turn (udp) server`);
|
|
ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
|
|
is(ufrags2.length, 1, "Should have one ufrag in candidate set");
|
|
isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnTcpServerAfterNegotiation() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
const candidatePromise = trickleIce(offerer);
|
|
await connect(offerer, answerer, 32000, `no ICE servers`);
|
|
const candidates = await candidatePromise;
|
|
const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
|
|
is(ufrags.length, 1, "Should have one ufrag in candidate set");
|
|
|
|
offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
const candidates2 = await gatherWithTimeout(offerer, 32000, `a turn (tcp) server`);
|
|
ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
|
|
is(ufrags2.length, 1, "Should have one ufrag in candidate set");
|
|
isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addStunServerBeforeCreateAnswer() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection();
|
|
|
|
try {
|
|
await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
|
|
|
|
answerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
const candidates = await gatherWithTimeout(answerer, 32000, `just a stun server`);
|
|
ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnServerBeforeCreateAnswer() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection();
|
|
|
|
try {
|
|
await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
|
|
|
|
answerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
const candidates = await gatherWithTimeout(answerer, 32000, `a turn (udp) server`);
|
|
ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
|
|
ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addTurnTcpServerBeforeCreateAnswer() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection();
|
|
|
|
try {
|
|
await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
|
|
|
|
answerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
|
|
const candidates = await gatherWithTimeout(answerer, 32000, `a turn (tcp) server`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
|
|
ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function relayPolicyPreventsSrflx() {
|
|
const pc = new RTCPeerConnection();
|
|
try {
|
|
pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}], iceTransportPolicy: "relay"});
|
|
const candidates = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
|
|
ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get a srflx candidate");
|
|
ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
|
|
} finally {
|
|
pc.close();
|
|
}
|
|
},
|
|
|
|
async function addOffererStunServerAllowsIceToConnect() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection();
|
|
|
|
try {
|
|
try {
|
|
// Both ends are behind a simulated endpoint-independent NAT, which
|
|
// requires at least one side to have a srflx candidate to work.
|
|
await connect(offerer, answerer, 2000, `no ICE servers`);
|
|
ok(false, "ICE should either have failed, or timed out!");
|
|
} catch (e) {
|
|
if (!(e instanceof Error)) throw e;
|
|
ok(true, "ICE should either have failed, or timed out!");
|
|
}
|
|
|
|
offerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
await connect(offerer, answerer, 32000, `just a STUN server`);
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addAnswererStunServerDoesNotAllowIceToConnect() {
|
|
const offerer = new RTCPeerConnection();
|
|
const answerer = new RTCPeerConnection();
|
|
|
|
try {
|
|
try {
|
|
// Both ends are behind a simulated endpoint-independent NAT, which
|
|
// requires at least one side to have a srflx candidate to work.
|
|
await connect(offerer, answerer, 2000, `no ICE servers`);
|
|
ok(false, "ICE should either have failed, or timed out!");
|
|
} catch (e) {
|
|
if (!(e instanceof Error)) throw e;
|
|
ok(true, "ICE should either have failed, or timed out!");
|
|
}
|
|
|
|
// This _won't_ help, because the answerer does not get to decide to
|
|
// trigger an ICE restart.
|
|
answerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
try {
|
|
await connectNoTrickleWait(offerer, answerer, 2000, `no ICE servers`);
|
|
ok(false, "ICE should either have failed, or timed out!");
|
|
} catch (e) {
|
|
if (!(e instanceof Error)) throw e;
|
|
ok(true, "ICE should either have failed, or timed out!");
|
|
}
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
}
|
|
},
|
|
|
|
async function addOffererTurnServerAllowsIceToConnect() {
|
|
await pushPrefs(
|
|
['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
|
|
['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT']);
|
|
|
|
const offerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
|
|
|
|
try {
|
|
try {
|
|
// Both ends are behind a simulated port-dependent NAT, which
|
|
// requires at least one side to have a relay candidate to work.
|
|
await connect(offerer, answerer, 2000, `just a STUN server`);
|
|
ok(false, "ICE should either have failed, or timed out!");
|
|
} catch (e) {
|
|
if (!(e instanceof Error)) throw e;
|
|
ok(true, "ICE should either have failed, or timed out!");
|
|
}
|
|
|
|
offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
|
|
await connect(offerer, answerer, 32000, `a TURN (udp) server`);
|
|
} finally {
|
|
offerer.close();
|
|
answerer.close();
|
|
await SpecialPowers.popPrefEnv();
|
|
}
|
|
},
|
|
|
|
];
|
|
|
|
runNetworkTest(async () => {
|
|
const turnServer = iceServersArray.find(server => "username" in server);
|
|
username = turnServer.username;
|
|
credential = turnServer.credential;
|
|
// Just use the first url. It might make sense to look for TURNS first,
|
|
// since that will always use a hostname, but on CI we don't have TURNS
|
|
// support anyway (see bug 1323439).
|
|
const turnHostname = getTurnHostname(turnServer.urls[0]);
|
|
turnAddressV4 = await dnsLookupV4(turnHostname);
|
|
|
|
await pushPrefs(
|
|
['media.peerconnection.ice.obfuscate_host_addresses', false],
|
|
['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
|
|
['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
|
|
['media.peerconnection.ice.loopback', true],
|
|
['media.getusermedia.insecure.enabled', true]);
|
|
|
|
for (const test of tests) {
|
|
info(`Running test: ${test.name}`);
|
|
try {
|
|
await test();
|
|
} catch (e) {
|
|
ok(false, `Caught ${e.name}: ${e.message} ${e.stack}`);
|
|
}
|
|
info(`Done running test: ${test.name}`);
|
|
// Make sure we don't build up a pile of GC work, and also get PCImpl to
|
|
// print their timecards.
|
|
await new Promise(r => SpecialPowers.exactGC(r));
|
|
}
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
}, { useIceServer: true });
|
|
</script>
|
|
</pre>
|
|
</body>
|
|
</html>
|