bundle.https.html (5272B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <meta name="timeout" content="long"> 4 <title>RTCPeerConnection BUNDLE</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="../RTCPeerConnection-helper.js"></script> 8 <script> 9 'use strict'; 10 11 promise_test(async t => { 12 const caller = new RTCPeerConnection(); 13 t.add_cleanup(() => caller.close()); 14 const callee = new RTCPeerConnection(); 15 t.add_cleanup(() => callee.close()); 16 const stream = await getNoiseStream({audio: true, video: true}); 17 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 18 stream.getTracks().forEach(track => caller.addTrack(track, stream)); 19 20 21 exchangeIceCandidates(caller, callee); 22 const offer = await caller.createOffer(); 23 // remove the a=group:BUNDLE from the SDP when signaling. 24 const sdp = offer.sdp.replace(/a=group:BUNDLE (.*)\r\n/, ''); 25 const ontrack = new Promise(r => callee.ontrack = r); 26 27 await callee.setRemoteDescription({type: 'offer', sdp}); 28 await caller.setLocalDescription(offer); 29 30 const answer = await callee.createAnswer(); 31 await caller.setRemoteDescription(answer); 32 await callee.setLocalDescription(answer); 33 34 const {streams: [recvStream]} = await ontrack; 35 assert_equals(recvStream.getTracks().length, 2, "Tracks should be added to the stream before sRD resolves."); 36 const v = document.createElement('video'); 37 v.autoplay = true; 38 v.srcObject = recvStream; 39 v.id = recvStream.id; 40 await new Promise(r => v.onloadedmetadata = r); 41 42 const senders = caller.getSenders(); 43 const dtlsTransports = senders.map(s => s.transport); 44 assert_equals(dtlsTransports.length, 2); 45 assert_not_equals(dtlsTransports[0], dtlsTransports[1]); 46 47 const iceTransports = dtlsTransports.map(t => t.iceTransport); 48 assert_equals(iceTransports.length, 2); 49 assert_not_equals(iceTransports[0], iceTransports[1]); 50 }, 'not negotiating BUNDLE creates two separate ice and dtls transports'); 51 52 promise_test(async t => { 53 const caller = new RTCPeerConnection(); 54 t.add_cleanup(() => caller.close()); 55 const callee = new RTCPeerConnection(); 56 t.add_cleanup(() => callee.close()); 57 const stream = await getNoiseStream({audio: true, video: true}); 58 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 59 stream.getTracks().forEach(track => caller.addTrack(track, stream)); 60 61 exchangeIceCandidates(caller, callee); 62 const offer = await caller.createOffer(); 63 const ontrack = new Promise(r => callee.ontrack = r); 64 await callee.setRemoteDescription(offer); 65 await caller.setLocalDescription(offer); 66 const secondTransport = caller.getSenders()[1].transport; // Save a reference to this transport. 67 68 const answer = await callee.createAnswer(); 69 await caller.setRemoteDescription(answer); 70 await callee.setLocalDescription(answer); 71 72 const {streams: [recvStream]} = await ontrack; 73 assert_equals(recvStream.getTracks().length, 2, "Tracks should be added to the stream before sRD resolves."); 74 const v = document.createElement('video'); 75 v.autoplay = true; 76 v.srcObject = recvStream; 77 v.id = recvStream.id; 78 await new Promise(r => v.onloadedmetadata = r); 79 80 const senders = caller.getSenders(); 81 const dtlsTransports = senders.map(s => s.transport); 82 assert_equals(dtlsTransports.length, 2); 83 assert_equals(dtlsTransports[0], dtlsTransports[1]); 84 assert_not_equals(dtlsTransports[1], secondTransport); 85 assert_equals(secondTransport.state, 'closed'); 86 }, 'bundles on the first transport and closes the second'); 87 88 promise_test(async t => { 89 const sdp = `v=0 90 o=- 0 3 IN IP4 127.0.0.1 91 s=- 92 t=0 0 93 a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93 94 a=ice-ufrag:ETEn 95 a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l 96 m=audio 9 UDP/TLS/RTP/SAVPF 111 97 c=IN IP4 0.0.0.0 98 a=rtcp-mux 99 a=sendonly 100 a=mid:audio 101 a=rtpmap:111 opus/48000/2 102 a=setup:actpass 103 m=video 9 UDP/TLS/RTP/SAVPF 100 104 c=IN IP4 0.0.0.0 105 a=rtcp-mux 106 a=sendonly 107 a=mid:video 108 a=rtpmap:100 VP8/90000 109 a=fmtp:100 max-fr=30;max-fs=3600 110 a=setup:actpass 111 `; 112 const pc = new RTCPeerConnection({ bundlePolicy: 'max-bundle' }); 113 t.add_cleanup(() => pc.close()); 114 await pc.setRemoteDescription({ type: 'offer', sdp }); 115 await pc.setLocalDescription(); 116 const transceivers = pc.getTransceivers(); 117 assert_equals(transceivers.length, 2); 118 assert_false(transceivers[0].stopped); 119 assert_true(transceivers[1].stopped); 120 }, 'max-bundle with an offer without bundle only negotiates the first m-line'); 121 122 promise_test(async t => { 123 const sdp = `v=0 124 o=- 0 3 IN IP4 127.0.0.1 125 s=- 126 t=0 0 127 a=group:BUNDLE audio video 128 m=audio 9 UDP/TLS/RTP/SAVPF 111 129 c=IN IP4 0.0.0.0 130 a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93 131 a=ice-ufrag:ETEn 132 a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l 133 a=rtcp-mux 134 a=sendonly 135 a=mid:audio 136 a=rtpmap:111 opus/48000/2 137 a=setup:actpass 138 m=video 0 UDP/TLS/RTP/SAVPF 100 139 c=IN IP4 0.0.0.0 140 a=bundle-only 141 a=sendonly 142 a=mid:video 143 a=rtpmap:100 VP8/90000 144 a=fmtp:100 max-fr=30;max-fs=3600 145 `; 146 const pc = new RTCPeerConnection(); 147 t.add_cleanup(() => pc.close()); 148 await pc.setRemoteDescription({ type: 'offer', sdp }); 149 }, 'sRD(offer) works with no transport attributes in a bundle-only m-section'); 150 </script>