RTCConfiguration-rtcpMuxPolicy.html (7448B)
1 <!doctype html> 2 <title>RTCConfiguration rtcpMuxPolicy</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="RTCConfiguration-helper.js"></script> 6 <script src="RTCPeerConnection-helper.js"></script> 7 <script> 8 'use strict'; 9 10 // Test is based on the following editor draft: 11 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html 12 13 // The following helper function is called from RTCConfiguration-helper.js: 14 // config_test 15 16 /* 17 [Constructor(optional RTCConfiguration configuration)] 18 interface RTCPeerConnection : EventTarget { 19 RTCConfiguration getConfiguration(); 20 void setConfiguration(RTCConfiguration configuration); 21 ... 22 }; 23 24 dictionary RTCConfiguration { 25 RTCRtcpMuxPolicy rtcpMuxPolicy = "require"; 26 ... 27 }; 28 29 enum RTCRtcpMuxPolicy { 30 "negotiate", 31 "require" 32 }; 33 */ 34 35 test(() => { 36 const pc = new RTCPeerConnection(); 37 assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require'); 38 }, `new RTCPeerConnection() should have default rtcpMuxPolicy require`); 39 40 test(() => { 41 const pc = new RTCPeerConnection({ rtcpMuxPolicy: undefined }); 42 assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require'); 43 }, `new RTCPeerConnection({ rtcpMuxPolicy: undefined }) should have default rtcpMuxPolicy require`); 44 45 test(() => { 46 const pc = new RTCPeerConnection({ rtcpMuxPolicy: 'require' }); 47 assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require'); 48 }, `new RTCPeerConnection({ rtcpMuxPolicy: 'require' }) should succeed`); 49 50 /* 51 4.3.1.1. Constructor 52 3. If configuration.rtcpMuxPolicy is negotiate, and the user agent does not 53 implement non-muxed RTCP, throw a NotSupportedError. 54 */ 55 test(() => { 56 let pc; 57 try { 58 pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' }); 59 } catch(err) { 60 // NotSupportedError is a DOMException with code 9 61 if(err.code === 9 && err.name === 'NotSupportedError') { 62 // ignore error and pass test if negotiate is not supported 63 return; 64 } else { 65 throw err; 66 } 67 } 68 69 assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'negotiate'); 70 71 }, `new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' }) may succeed or throw NotSupportedError`); 72 73 config_test(makePc => { 74 assert_throws_js(TypeError, () => 75 makePc({ rtcpMuxPolicy: null })); 76 }, `with { rtcpMuxPolicy: null } should throw TypeError`); 77 78 config_test(makePc => { 79 assert_throws_js(TypeError, () => 80 makePc({ rtcpMuxPolicy: 'invalid' })); 81 }, `with { rtcpMuxPolicy: 'invalid' } should throw TypeError`); 82 83 /* 84 4.3.2. Set a configuration 85 6. If configuration.rtcpMuxPolicy is set and its value differs from the 86 connection's rtcpMux policy, throw an InvalidModificationError. 87 */ 88 89 test(() => { 90 const pc = new RTCPeerConnection({ rtcpMuxPolicy: 'require' }); 91 assert_idl_attribute(pc, 'setConfiguration'); 92 assert_throws_dom('InvalidModificationError', () => 93 pc.setConfiguration({ rtcpMuxPolicy: 'negotiate' })); 94 95 }, `setConfiguration({ rtcpMuxPolicy: 'negotiate' }) with initial rtcpMuxPolicy require should throw InvalidModificationError`); 96 97 test(() => { 98 let pc; 99 try { 100 pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' }); 101 } catch(err) { 102 // NotSupportedError is a DOMException with code 9 103 if(err.code === 9 && err.name === 'NotSupportedError') { 104 // ignore error and pass test if negotiate is not supported 105 return; 106 } else { 107 throw err; 108 } 109 } 110 111 assert_idl_attribute(pc, 'setConfiguration'); 112 assert_throws_dom('InvalidModificationError', () => 113 pc.setConfiguration({ rtcpMuxPolicy: 'require' })); 114 115 }, `setConfiguration({ rtcpMuxPolicy: 'require' }) with initial rtcpMuxPolicy negotiate should throw InvalidModificationError`); 116 117 test(() => { 118 let pc; 119 pc = new RTCPeerConnection({ rtcpMuxPolicy: 'require' }); 120 // default rtcpMuxPolicy is 'require', so this is allowed 121 pc.setConfiguration({}); 122 assert_equals(pc.getConfiguration().rtcpMuxPolicy, 'require'); 123 }, `setConfiguration({}) with initial rtcpMuxPolicy require should leave rtcpMuxPolicy to require`); 124 125 test(() => { 126 let pc; 127 try { 128 pc = new RTCPeerConnection({ rtcpMuxPolicy: 'negotiate' }); 129 } catch(err) { 130 // NotSupportedError is a DOMException with code 9 131 if(err.code === 9 && err.name === 'NotSupportedError') { 132 // ignore error and pass test if negotiate is not supported 133 return; 134 } else { 135 throw err; 136 } 137 } 138 139 assert_idl_attribute(pc, 'setConfiguration'); 140 // default value for rtcpMuxPolicy is require 141 assert_throws_dom('InvalidModificationError', () => 142 pc.setConfiguration({})); 143 144 }, `setConfiguration({}) with initial rtcpMuxPolicy negotiate should throw InvalidModificationError`); 145 146 /* 147 Coverage Report 148 149 Tested 2 150 Total 2 151 */ 152 const FINGERPRINT_SHA256 = '00:00:00:00:00:00:00:00:00:00:00:00:00' + 153 ':00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00'; 154 const ICEUFRAG = 'someufrag'; 155 const ICEPWD = 'somelongpwdwithenoughrandomness'; 156 157 promise_test(async t => { 158 // audio-only SDP offer without BUNDLE and rtcp-mux. 159 const sdp = 'v=0\r\n' + 160 'o=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + 161 's=-\r\n' + 162 't=0 0\r\n' + 163 'm=audio 9 UDP/TLS/RTP/SAVPF 111\r\n' + 164 'c=IN IP4 0.0.0.0\r\n' + 165 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + 166 'a=ice-ufrag:' + ICEUFRAG + '\r\n' + 167 'a=ice-pwd:' + ICEPWD + '\r\n' + 168 'a=fingerprint:sha-256 ' + FINGERPRINT_SHA256 + '\r\n' + 169 'a=setup:actpass\r\n' + 170 'a=mid:audio1\r\n' + 171 'a=sendonly\r\n' + 172 'a=rtcp-rsize\r\n' + 173 'a=rtpmap:111 opus/48000/2\r\n'; 174 const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'}); 175 t.add_cleanup(() => pc.close()); 176 177 return promise_rejects_dom(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'offer', sdp})); 178 }, 'setRemoteDescription throws InvalidAccessError when called with an offer without rtcp-mux and rtcpMuxPolicy is set to require'); 179 180 promise_test(async t => { 181 // audio-only SDP answer without BUNDLE and rtcp-mux. 182 // Also omitting a=mid in order to avoid parsing it from the offer as this needs to match. 183 const sdp = 'v=0\r\n' + 184 'o=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' + 185 's=-\r\n' + 186 't=0 0\r\n' + 187 'm=audio 9 UDP/TLS/RTP/SAVPF 111\r\n' + 188 'c=IN IP4 0.0.0.0\r\n' + 189 'a=rtcp:9 IN IP4 0.0.0.0\r\n' + 190 'a=ice-ufrag:' + ICEUFRAG + '\r\n' + 191 'a=ice-pwd:' + ICEPWD + '\r\n' + 192 'a=fingerprint:sha-256 ' + FINGERPRINT_SHA256 + '\r\n' + 193 'a=setup:active\r\n' + 194 'a=sendonly\r\n' + 195 'a=rtcp-rsize\r\n' + 196 'a=rtpmap:111 opus/48000/2\r\n'; 197 const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'}); 198 t.add_cleanup(() => pc.close()); 199 200 const offer = await generateAudioReceiveOnlyOffer(pc); 201 await pc.setLocalDescription(offer); 202 return promise_rejects_dom(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'answer', sdp})); 203 }, 'setRemoteDescription throws InvalidAccessError when called with an answer without rtcp-mux and rtcpMuxPolicy is set to require'); 204 </script>