summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html')
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html134
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>