diff options
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_peerConnection_extmapRenegotiation.html')
-rw-r--r-- | dom/media/webrtc/tests/mochitests/test_peerConnection_extmapRenegotiation.html | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_extmapRenegotiation.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_extmapRenegotiation.html new file mode 100644 index 0000000000..78c6bb986c --- /dev/null +++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_extmapRenegotiation.html @@ -0,0 +1,325 @@ +<!DOCTYPE HTML> +<html> +<head> + <script type="application/javascript" src="pc.js"></script> + <script type="application/javascript" src="iceTestUtils.js"></script> +</head> +<body> +<pre id="test"> +<script type="application/javascript"> + createHTML({ + bug: "1799932", + title: "RTCPeerConnection check renegotiation of extmap" + }); + + function setExtmap(sdp, uri, id) { + const regex = new RegExp(`a=extmap:[0-9]+(\/[a-z]+)? ${uri}`, 'g'); + if (id) { + return sdp.replaceAll(regex, `a=extmap:${id}$1 ${uri}`); + } else { + return sdp.replaceAll(regex, `a=unknownattr`); + } + } + + function getExtmap(sdp, uri) { + const regex = new RegExp(`a=extmap:([0-9]+)(\/[a-z]+)? ${uri}`); + return sdp.match(regex)[1]; + } + + function replaceExtUri(sdp, oldUri, newUri) { + const regex = new RegExp(`(a=extmap:[0-9]+\/[a-z]+)? ${oldUri}`, 'g'); + return sdp.replaceAll(regex, `$1 ${newUri}`); + } + + const tests = [ + async function checkAudioMidChange() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", 14); + info(`New reoffer: ${reoffer.sdp}`); + await pc2.setRemoteDescription(reoffer); + await pc2.setLocalDescription(); + await wait(2000); + }, + + async function checkVideoMidChange() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({video: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", 14); + info(`New reoffer: ${reoffer.sdp}`); + await pc2.setRemoteDescription(reoffer); + await pc2.setLocalDescription(); + await wait(2000); + }, + + async function checkAudioMidSwap() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + const midId = getExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid"); + const ssrcLevelId = getExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level"); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", ssrcLevelId); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", midId); + info(`New reoffer: ${reoffer.sdp}`); + try { + await pc2.setRemoteDescription(reoffer); + ok(false, "sRD should fail when it attempts extension id remapping"); + } catch (e) { + ok(true, "sRD should fail when it attempts extension id remapping"); + } + }, + + async function checkVideoMidSwap() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({video: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + const midId = getExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid"); + const toffsetId = getExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:toffset"); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", toffsetId); + reoffer.sdp = setExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:toffset", midId); + info(`New reoffer: ${reoffer.sdp}`); + try { + await pc2.setRemoteDescription(reoffer); + ok(false, "sRD should fail when it attempts extension id remapping"); + } catch (e) { + ok(true, "sRD should fail when it attempts extension id remapping"); + } + }, + + async function checkAudioIdReuse() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + // Change uri, but not the id, so the id now refers to foo. + reoffer.sdp = replaceExtUri(reoffer.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", "foo"); + info(`New reoffer: ${reoffer.sdp}`); + try { + await pc2.setRemoteDescription(reoffer); + ok(false, "sRD should fail when it attempts extension id remapping"); + } catch (e) { + ok(true, "sRD should fail when it attempts extension id remapping"); + } + }, + + async function checkVideoIdReuse() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({video: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + // Sadly, there's no way to tell the offerer to change the extmap. Other + // types of endpoint could conceivably do this, so we at least don't want + // to crash. + // TODO: Would be nice to be able to test this with an endpoint that + // actually changes the ids it uses. + const reoffer = await pc1.createOffer(); + // Change uri, but not the id, so the id now refers to foo. + reoffer.sdp = replaceExtUri(reoffer.sdp, "urn:ietf:params:rtp-hdrext:toffset", "foo"); + info(`New reoffer: ${reoffer.sdp}`); + try { + await pc2.setRemoteDescription(reoffer); + ok(false, "sRD should fail when it attempts extension id remapping"); + } catch (e) { + ok(true, "sRD should fail when it attempts extension id remapping"); + } + }, + + // What happens when remote answer uses an extmap id, and then a remote + // reoffer tries to use the same id for something else? + async function checkAudioIdReuseOffererThenAnswerer() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + await connect(pc1, pc2, 32000, "Initial connection"); + + const reoffer = await pc2.createOffer(); + // Change uri, but not the id, so the id now refers to foo. + reoffer.sdp = replaceExtUri(reoffer.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", "foo"); + info(`New reoffer: ${reoffer.sdp}`); + try { + await pc1.setRemoteDescription(reoffer); + ok(false, "sRD should fail when it attempts extension id remapping"); + } catch (e) { + ok(true, "sRD should fail when it attempts extension id remapping"); + } + }, + + // What happens when a remote offer uses a different extmap id than the + // default? Does the answerer remember the new id in reoffers? + async function checkAudioIdReuseOffererThenAnswerer() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + // Negotiate, but change id for ssrc-audio-level to something pc2 would + // not typically use. + await pc1.setLocalDescription(); + const mungedOffer = setExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12); + await pc2.setRemoteDescription({sdp: mungedOffer, type: "offer"}); + await pc2.setLocalDescription(); + + const reoffer = await pc2.createOffer(); + is(getExtmap(reoffer.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level"), "12"); + }, + + async function checkAudioUnnegotiatedIdReuse1() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + // Negotiate, but remove ssrc-audio-level from answer + await pc1.setLocalDescription(); + const levelId = getExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level"); + await pc2.setRemoteDescription(pc1.localDescription); + await pc2.setLocalDescription(); + const answerNoExt = setExtmap(pc2.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", undefined); + await pc1.setRemoteDescription({sdp: answerNoExt, type: "answer"}); + + // Renegotiate, and use the id that offerer used for ssrc-audio-level for + // something different (while making sure we don't use it twice) + await pc2.setLocalDescription(); + const mungedReoffer = setExtmap(pc2.localDescription.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", levelId); + const twiceMungedReoffer = setExtmap(mungedReoffer, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", undefined); + await pc1.setRemoteDescription({sdp: twiceMungedReoffer, type: "offer"}); + }, + + async function checkAudioUnnegotiatedIdReuse2() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + // Negotiate, but remove ssrc-audio-level from offer. pc2 has never seen + // |levelId| in extmap yet, but internally probably wants to use that for + // ssrc-audio-level + await pc1.setLocalDescription(); + const levelId = getExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level"); + const offerNoExt = setExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", undefined); + await pc2.setRemoteDescription({sdp: offerNoExt, type: "offer"}); + await pc2.setLocalDescription(); + await pc1.setRemoteDescription(pc2.localDescription); + + // Renegotiate, but use |levelId| for something other than + // ssrc-audio-level. pc2 should not throw. + await pc1.setLocalDescription(); + const mungedReoffer = setExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", levelId); + const twiceMungedReoffer = setExtmap(mungedReoffer, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", undefined); + await pc2.setRemoteDescription({sdp: twiceMungedReoffer, type: "offer"}); + }, + + async function checkAudioUnnegotiatedIdReuse3() { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + + const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + pc1.addTrack(stream.getTracks()[0]); + pc2.addTrack(stream.getTracks()[0]); + + // Negotiate, but replace ssrc-audio-level with something pc2 won't + // support in offer. + await pc1.setLocalDescription(); + const levelId = getExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level"); + const mungedOffer = replaceExtUri(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", "fooba"); + await pc2.setRemoteDescription({sdp: mungedOffer, type: "offer"}); + await pc2.setLocalDescription(); + await pc1.setRemoteDescription(pc2.localDescription); + + // Renegotiate, and use levelId for something pc2 _will_ support. + await pc1.setLocalDescription(); + const mungedReoffer = setExtmap(pc1.localDescription.sdp, "urn:ietf:params:rtp-hdrext:sdes:mid", levelId); + const twiceMungedReoffer = setExtmap(mungedReoffer, "urn:ietf:params:rtp-hdrext:ssrc-audio-level", undefined); + await pc2.setRemoteDescription({sdp: twiceMungedReoffer, type: "offer"}); + }, + + ]; + + runNetworkTest(async () => { + for (const test of tests) { + info(`Running test: ${test.name}`); + await test(); + info(`Done running test: ${test.name}`); + } + }); + +</script> +</pre> +</body> +</html> |