/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// This is mostly so test_peerConnection_gatherWithStun300.html and // test_peerConnection_gatherWithStun300IPv6 can share this code. I would have // put the ipv6 test code in the same file, but our ipv6 tester support is // inconsistent enough that we need to be able to track the ipv6 test // separately.
async function gatherWithTimeout(pc, timeout, context) { const throwOnTimeout = async () => {
await wait(timeout); thrownew Error(
`Gathering did not complete within ${timeout} ms with ${context}`
);
};
// Set up trickle, but does not wait for it to complete. Can be used by itself // in cases where we do not expect any new candidates, but want to still set up // the signal handling in case new candidates _do_ show up.
async function connectNoTrickleWait(offerer, answerer, timeout, context) { return connect(offerer, answerer, timeout, context, true);
}
const throwOnTimeout = async () => { if (timeout) {
await wait(timeout); thrownew Error(
`ICE did not complete within ${timeout} ms with ${context}`
);
}
};
await Promise.race([
Promise.all(connectionPromises),
throwOnTimeout(timeout, context),
]);
} finally { if (!noTrickleWait) { // TODO(bug 1751509): For now, we need to let gathering finish before we // proceed, because there are races in ICE restart wrt gathering state.
await Promise.all([trickle1, trickle2]);
}
}
}
function isV6HostCandidate(candidate) { const fields = candidate.candidate.split(" "); const type = fields[7]; const ipAddress = fields[4]; return type == "host" && ipAddress.includes(":");
}
async function ipv6Supported() { const pc = new RTCPeerConnection(); const candidates = await gatherWithTimeout(pc, 8000);
info(`baseline candidates: ${JSON.stringify(candidates)}`);
pc.close(); return candidates.some(isV6HostCandidate);
}
async function checkSrflx(iceServers) { const context = makeContextString(iceServers);
info(`checkSrflx ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const srflxCandidates = candidates.filter(c => c.candidate.includes("srflx"));
info(`candidates: ${JSON.stringify(srflxCandidates)}`); // TODO(bug 1339203): Once we support rtcpMuxPolicy, set it to "require" to // result in a single srflx candidate
is(
srflxCandidates.length,
2,
`Should have two srflx candidates with ${context}`
);
pc.close();
}
async function checkNoSrflx(iceServers) { const context = makeContextString(iceServers);
info(`checkNoSrflx ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const srflxCandidates = candidates.filter(c => c.candidate.includes("srflx"));
info(`candidates: ${JSON.stringify(srflxCandidates)}`);
is(
srflxCandidates.length,
0,
`Should have no srflx candidates with ${context}`
);
pc.close();
}
async function checkRelayUdp(iceServers) { const context = makeContextString(iceServers);
info(`checkRelayUdp ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const relayCandidates = candidates.filter(c => c.candidate.includes("relay"));
info(`candidates: ${JSON.stringify(relayCandidates)}`); // TODO(bug 1339203): Once we support rtcpMuxPolicy, set it to "require" to // result in a single relay candidate
is(
relayCandidates.length,
2,
`Should have two relay candidates with ${context}`
); // It would be nice if RTCIceCandidate had a field telling us what the // "related protocol" is (similar to relatedAddress and relatedPort). // Because there is no such thing, we need to go through the stats API, // which _does_ have that information.
is(
(await findStatsRelayCandidates(pc, "tcp")).length,
0,
`No TCP relay candidates should be present with ${context}`
);
pc.close();
}
async function checkRelayTcp(iceServers) { const context = makeContextString(iceServers);
info(`checkRelayTcp ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const relayCandidates = candidates.filter(c => c.candidate.includes("relay"));
info(`candidates: ${JSON.stringify(relayCandidates)}`); // TODO(bug 1339203): Once we support rtcpMuxPolicy, set it to "require" to // result in a single relay candidate
is(
relayCandidates.length,
2,
`Should have two relay candidates with ${context}`
); // It would be nice if RTCIceCandidate had a field telling us what the // "related protocol" is (similar to relatedAddress and relatedPort). // Because there is no such thing, we need to go through the stats API, // which _does_ have that information.
is(
(await findStatsRelayCandidates(pc, "udp")).length,
0,
`No UDP relay candidates should be present with ${context}`
);
pc.close();
}
async function checkRelayUdpTcp(iceServers) { const context = makeContextString(iceServers);
info(`checkRelayUdpTcp ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const relayCandidates = candidates.filter(c => c.candidate.includes("relay"));
info(`candidates: ${JSON.stringify(relayCandidates)}`); // TODO(bug 1339203): Once we support rtcpMuxPolicy, set it to "require" to // result in a single relay candidate each for UDP and TCP
is(
relayCandidates.length,
4,
`Should have two relay candidates for each protocol with ${context}`
); // It would be nice if RTCIceCandidate had a field telling us what the // "related protocol" is (similar to relatedAddress and relatedPort). // Because there is no such thing, we need to go through the stats API, // which _does_ have that information.
is(
(await findStatsRelayCandidates(pc, "udp")).length,
2,
`Two UDP relay candidates should be present with ${context}`
); // TODO(bug 1705563): This is 1 because of bug 1705563
is(
(await findStatsRelayCandidates(pc, "tcp")).length,
1,
`One TCP relay candidates should be present with ${context}`
);
pc.close();
}
async function checkNoRelay(iceServers) { const context = makeContextString(iceServers);
info(`checkNoRelay ${context}`); const pc = new RTCPeerConnection({
iceServers,
bundlePolicy: "max-bundle", // Avoids extra candidates
}); const candidates = await gatherWithTimeout(pc, 8000, context); const relayCandidates = candidates.filter(c => c.candidate.includes("relay"));
info(`candidates: ${JSON.stringify(relayCandidates)}`);
is(
relayCandidates.length,
0,
`Should have no relay candidates with ${context}`
);
pc.close();
}
function gatheringStateReached(object, state) { if (object instanceof RTCIceTransport) { returnnew Promise(r =>
object.addEventListener("gatheringstatechange", function listener() { if (object.gatheringState == state) {
object.removeEventListener("gatheringstatechange", listener);
r(state);
}
})
);
} elseif (object instanceof RTCPeerConnection) { returnnew Promise(r =>
object.addEventListener("icegatheringstatechange", function listener() { if (object.iceGatheringState == state) {
object.removeEventListener("icegatheringstatechange", listener);
r(state);
}
})
);
} else { throw"First parameter is neither an RTCIceTransport nor an RTCPeerConnection";
}
}
function nextGatheringState(object) { if (object instanceof RTCIceTransport) { returnnew Promise(resolve =>
object.addEventListener( "gatheringstatechange",
() => resolve(object.gatheringState),
{ once: true }
)
);
} elseif (object instanceof RTCPeerConnection) { returnnew Promise(resolve =>
object.addEventListener( "icegatheringstatechange",
() => resolve(object.iceGatheringState),
{ once: true }
)
);
} else { throw"First parameter is neither an RTCIceTransport nor an RTCPeerConnection";
}
}
function emptyCandidate(pc) { returnnew Promise(r =>
pc.addEventListener("icecandidate", function listener(e) { if (e.candidate && e.candidate.candidate == "") {
pc.removeEventListener("icecandidate", listener);
r(e);
}
})
);
}
function nullCandidate(pc) { returnnew Promise(r =>
pc.addEventListener("icecandidate", function listener(e) { if (!e.candidate) {
pc.removeEventListener("icecandidate", listener);
r(e);
}
})
);
}
function connectionStateReached(object, state) { if (object instanceof RTCIceTransport || object instanceof RTCDtlsTransport) { returnnew Promise(resolve =>
object.addEventListener("statechange", function listener() { if (object.state == state) {
object.removeEventListener("statechange", listener);
resolve(state);
}
})
);
} elseif (object instanceof RTCPeerConnection) { returnnew Promise(resolve =>
object.addEventListener("connectionstatechange", function listener() { if (object.connectionState == state) {
object.removeEventListener("connectionstatechange", listener);
resolve(state);
}
})
);
} else { throw"First parameter is neither an RTCIceTransport, an RTCDtlsTransport, nor an RTCPeerConnection";
}
}
function nextConnectionState(object) { if (object instanceof RTCIceTransport || object instanceof RTCDtlsTransport) { returnnew Promise(resolve =>
object.addEventListener("statechange", () => resolve(object.state), {
once: true,
})
);
} elseif (object instanceof RTCPeerConnection) { returnnew Promise(resolve =>
object.addEventListener( "connectionstatechange",
() => resolve(object.connectionState),
{ once: true }
)
);
} else { throw"First parameter is neither an RTCIceTransport, an RTCDtlsTransport, nor an RTCPeerConnection";
}
}
function nextIceConnectionState(pc) { if (pc instanceof RTCPeerConnection) { returnnew Promise(resolve =>
pc.addEventListener( "iceconnectionstatechange",
() => resolve(pc.iceConnectionState),
{ once: true }
)
);
} else { throw"First parameter is not an RTCPeerConnection";
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.