diff options
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html')
-rw-r--r-- | dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html new file mode 100644 index 0000000000..75f0d12463 --- /dev/null +++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html @@ -0,0 +1,134 @@ +<!DOCTYPE HTML> +<html> +<head> + <script type="application/javascript" src="pc.js"></script> +</head> +<body> +<pre id="test"> +<script type="application/javascript"> + createHTML({ + bug: "1342579", + title: "Unbundled PC connects to two different PCs", + visible: true + }); + + const fakeFingerPrint = "a=fingerprint:sha-256 11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11"; + + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + const pc3 = new RTCPeerConnection(); + + const add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed); + pc1.onicecandidate = e => { + if (e.candidate) { + if (e.candidate.sdpMid === "1") { + add(pc2, e.candidate, generateErrorCallback()) + } else { + add(pc3, e.candidate, generateErrorCallback()) + } + } + }; + pc2.onicecandidate = e => add(pc1, e.candidate, generateErrorCallback()); + pc3.onicecandidate = e => add(pc1, e.candidate, generateErrorCallback()); + + let ice1Finished, ice2Finished, ice3Finished; + const ice1Done = new Promise(r => ice1Finished = r); + const ice2Done = new Promise(r => ice2Finished = r); + const ice3Done = new Promise(r => ice3Finished = r); + + const icsc = (pc, str, resolve) => { + const state = pc.iceConnectionState; + info(str + " ICE connection state is: " + state); + if (state == "connected") { + ok(true, str + " ICE connected"); + resolve(); + } else if (state == "failed") { + ok(false, str + " ICE failed") + resolve(); + } + }; + + pc1.oniceconnectionstatechange = e => icsc(pc1, "PC1", ice1Finished); + pc2.oniceconnectionstatechange = e => icsc(pc2, "PC2", ice2Finished); + pc3.oniceconnectionstatechange = e => icsc(pc3, "PC3", ice3Finished); + + + function combineAnswer(origAnswer, answer) { + const sdplines = origAnswer.sdp.split('\r\n'); + const fpIndex = sdplines.findIndex(l => l.match('^a=fingerprint')); + const FP = sdplines[fpIndex]; + const audioIndex = sdplines.findIndex(l => l.match(/^m=audio [1-9]/)); + const videoIndex = sdplines.findIndex(l => l.match(/^m=video [1-9]/)); + if (audioIndex > -1) { + var ss = sdplines.slice(0, audioIndex); + ss.splice(fpIndex, 1); + answer.sessionSection = ss; + const rejectedVideoIndex = sdplines.findIndex(l => l.match('m=video 0')); + var ams = sdplines.slice(audioIndex, rejectedVideoIndex); + ams.push(FP); + ams.push(fakeFingerPrint); + answer.audioMsection = ams; + } + if (videoIndex > -1) { + var vms = sdplines.slice(videoIndex, sdplines.length -1); + vms.push(fakeFingerPrint); + vms.push(FP); + answer.videoMsection = vms; + } + return answer; + } + +runNetworkTest(async () => { + const v1 = createMediaElement('video', 'v1'); + const v2 = createMediaElement('video', 'v2'); + const v3 = createMediaElement('video', 'v3'); + + const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); + (v1.srcObject = stream).getTracks().forEach(t => pc1.addTrack(t, stream)); + + const stream2 = await navigator.mediaDevices.getUserMedia({ video: true }); + (v2.srcObject = stream2).getTracks().forEach(t => pc2.addTrack(t, stream2)); + + const stream3 = await navigator.mediaDevices.getUserMedia({ audio: true }); + (v3.srcObject = stream3).getTracks().forEach(t => pc3.addTrack(t, stream3)); + + const offer = await pc1.createOffer(); + await pc1.setLocalDescription(offer); + + //info("Original OFFER: " + JSON.stringify(offer)); + offer.sdp = sdputils.removeBundle(offer.sdp); + //info("OFFER w/o BUNDLE: " + JSON.stringify(offer)); + const offerAudio = new RTCSessionDescription(JSON.parse(JSON.stringify(offer))); + offerAudio.sdp = offerAudio.sdp.replace('m=video 9', 'm=video 0'); + //info("offerAudio: " + JSON.stringify(offerAudio)); + const offerVideo = new RTCSessionDescription(JSON.parse(JSON.stringify(offer))); + offerVideo.sdp = offerVideo.sdp.replace('m=audio 9', 'm=audio 0'); + //info("offerVideo: " + JSON.stringify(offerVideo)); + + // We need to do these in parallel, otherwise pc1 will start firing + // icecandidate events before pc3 is ready. + await Promise.all([pc2.setRemoteDescription(offerVideo), pc3.setRemoteDescription(offerAudio)]); + + const answerVideo = await pc2.createAnswer(); + const answerAudio = await pc3.createAnswer(); + + const answer = combineAnswer(answerAudio, combineAnswer(answerVideo, {})); + const fakeAnswer = answer.sessionSection.concat(answer.audioMsection, answer.videoMsection).join('\r\n'); + info("ANSWER: " + fakeAnswer); + + // We want to do these in parallel, because if we do them seqentially, by the + // time pc3.sLD completes pc2 could have fired icecandidate events, when we + // haven't called pc1.sRD yet. + await Promise.all( + [pc2.setLocalDescription(answerVideo), + pc3.setLocalDescription(answerAudio), + pc1.setRemoteDescription({type: 'answer', sdp: fakeAnswer})]); + + await Promise.all([ice1Done, ice2Done, ice3Done]); + + ok(true, "Connected."); + }); +</script> +</pre> +</body> +</html> |