RTCConfiguration-iceTransportPolicy.html (12018B)
1 <!doctype html> 2 <meta name="timeout" content="long"> 3 <title>RTCConfiguration iceTransportPolicy</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="RTCConfiguration-helper.js"></script> 7 <script src="RTCPeerConnection-helper.js"></script> 8 <script> 9 'use strict'; 10 11 // Test is based on the following editor draft: 12 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html 13 14 // The following helper function is called from RTCConfiguration-helper.js: 15 // config_test 16 17 /* 18 [Constructor(optional RTCConfiguration configuration)] 19 interface RTCPeerConnection : EventTarget { 20 RTCConfiguration getConfiguration(); 21 void setConfiguration(RTCConfiguration configuration); 22 ... 23 }; 24 25 dictionary RTCConfiguration { 26 sequence<RTCIceServer> iceServers; 27 RTCIceTransportPolicy iceTransportPolicy = "all"; 28 }; 29 30 enum RTCIceTransportPolicy { 31 "relay", 32 "all" 33 }; 34 */ 35 36 test(() => { 37 const pc = new RTCPeerConnection(); 38 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 39 }, `new RTCPeerConnection() should have default iceTransportPolicy all`); 40 41 test(() => { 42 const pc = new RTCPeerConnection({ iceTransportPolicy: undefined }); 43 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 44 }, `new RTCPeerConnection({ iceTransportPolicy: undefined }) should have default iceTransportPolicy all`); 45 46 test(() => { 47 const pc = new RTCPeerConnection({ iceTransportPolicy: 'all' }); 48 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 49 }, `new RTCPeerConnection({ iceTransportPolicy: 'all' }) should succeed`); 50 51 test(() => { 52 const pc = new RTCPeerConnection({ iceTransportPolicy: 'relay' }); 53 assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay'); 54 }, `new RTCPeerConnection({ iceTransportPolicy: 'relay' }) should succeed`); 55 56 /* 57 4.3.2. Set a configuration 58 8. Set the ICE Agent's ICE transports setting to the value of 59 configuration.iceTransportPolicy. As defined in [JSEP] (section 4.1.16.), 60 if the new ICE transports setting changes the existing setting, no action 61 will be taken until the next gathering phase. If a script wants this to 62 happen immediately, it should do an ICE restart. 63 */ 64 test(() => { 65 const pc = new RTCPeerConnection({ iceTransportPolicy: 'all' }); 66 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 67 68 pc.setConfiguration({ iceTransportPolicy: 'relay' }); 69 assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay'); 70 }, `setConfiguration({ iceTransportPolicy: 'relay' }) with initial iceTransportPolicy all should succeed`); 71 72 test(() => { 73 const pc = new RTCPeerConnection({ iceTransportPolicy: 'relay' }); 74 assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay'); 75 76 pc.setConfiguration({ iceTransportPolicy: 'all' }); 77 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 78 }, `setConfiguration({ iceTransportPolicy: 'all' }) with initial iceTransportPolicy relay should succeed`); 79 80 test(() => { 81 const pc = new RTCPeerConnection({ iceTransportPolicy: 'relay' }); 82 assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay'); 83 84 // default value for iceTransportPolicy is all 85 pc.setConfiguration({}); 86 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 87 }, `setConfiguration({}) with initial iceTransportPolicy relay should set new value to all`); 88 89 config_test(makePc => { 90 assert_throws_js(TypeError, () => 91 makePc({ iceTransportPolicy: 'invalid' })); 92 }, `with invalid iceTransportPolicy should throw TypeError`); 93 94 // "none" is in Blink and Gecko's IDL, but not in the spec. 95 config_test(makePc => { 96 assert_throws_js(TypeError, () => 97 makePc({ iceTransportPolicy: 'none' })); 98 }, `with none iceTransportPolicy should throw TypeError`); 99 100 config_test(makePc => { 101 assert_throws_js(TypeError, () => 102 makePc({ iceTransportPolicy: null })); 103 }, `with null iceTransportPolicy should throw TypeError`); 104 105 // iceTransportPolicy is called iceTransports in Blink. 106 test(() => { 107 const pc = new RTCPeerConnection({ iceTransports: 'relay' }); 108 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 109 }, `new RTCPeerConnection({ iceTransports: 'relay' }) should have no effect`); 110 111 test(() => { 112 const pc = new RTCPeerConnection({ iceTransports: 'invalid' }); 113 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 114 }, `new RTCPeerConnection({ iceTransports: 'invalid' }) should have no effect`); 115 116 test(() => { 117 const pc = new RTCPeerConnection({ iceTransports: null }); 118 assert_equals(pc.getConfiguration().iceTransportPolicy, 'all'); 119 }, `new RTCPeerConnection({ iceTransports: null }) should have no effect`); 120 121 const getLines = (sdp, startsWith) => 122 sdp.split('\r\n').filter(l => l.startsWith(startsWith)); 123 124 const getUfrags = ({sdp}) => getLines(sdp, 'a=ice-ufrag:'); 125 126 promise_test(async t => { 127 const offerer = new RTCPeerConnection({iceTransportPolicy: 'relay'}); 128 t.add_cleanup(() => offerer.close()); 129 130 offerer.addEventListener('icecandidate', 131 e => { 132 if (e.candidate) { 133 assert_equals(e.candidate.candidate, '', 'Should get no ICE candidates') 134 } 135 } 136 ); 137 138 offerer.addTransceiver('audio'); 139 await offerer.setLocalDescription(); 140 141 await waitForIceGatheringState(offerer, ['complete']); 142 }, `iceTransportPolicy "relay" on offerer should prevent candidate gathering`); 143 144 promise_test(async t => { 145 const offerer = new RTCPeerConnection(); 146 const answerer = new RTCPeerConnection({iceTransportPolicy: 'relay'}); 147 t.add_cleanup(() => offerer.close()); 148 t.add_cleanup(() => answerer.close()); 149 150 offerer.addEventListener('icecandidate', 151 e => { 152 if (e.candidate) { 153 assert_equals(e.candidate.candidate, '', 'Should get no ICE candidates') 154 } 155 } 156 ); 157 158 offerer.addTransceiver('audio'); 159 const offer = await offerer.createOffer(); 160 await answerer.setRemoteDescription(offer); 161 await answerer.setLocalDescription(await answerer.createAnswer()); 162 await waitForIceGatheringState(answerer, ['complete']); 163 }, `iceTransportPolicy "relay" on answerer should prevent candidate gathering`); 164 165 promise_test(async t => { 166 const offerer = new RTCPeerConnection(); 167 const answerer = new RTCPeerConnection(); 168 t.add_cleanup(() => offerer.close()); 169 t.add_cleanup(() => answerer.close()); 170 171 offerer.addTransceiver('audio'); 172 173 exchangeIceCandidates(offerer, answerer); 174 175 await Promise.all([ 176 exchangeOfferAnswer(offerer, answerer), 177 listenToIceConnected(offerer), 178 listenToIceConnected(answerer), 179 waitForIceGatheringState(offerer, ['complete']), 180 waitForIceGatheringState(answerer, ['complete']) 181 ]); 182 183 const [oldUfrag] = getUfrags(offerer.localDescription); 184 185 offerer.setConfiguration({iceTransportPolicy: 'relay'}); 186 187 offerer.addEventListener('icecandidate', 188 e => { 189 if (e.candidate) { 190 assert_equals(e.candidate.candidate, '', 'Should get no ICE candidates') 191 } 192 } 193 ); 194 195 await Promise.all([ 196 exchangeOfferAnswer(offerer, answerer), 197 waitForIceStateChange(offerer, ['failed']), 198 waitForIceStateChange(answerer, ['failed']), 199 waitForIceGatheringState(offerer, ['complete']), 200 waitForIceGatheringState(answerer, ['complete']) 201 ]); 202 203 const [newUfrag] = getUfrags(offerer.localDescription); 204 assert_not_equals(oldUfrag, newUfrag, 205 'Changing iceTransportPolicy should prompt an ICE restart'); 206 }, `Changing iceTransportPolicy from "all" to "relay" causes an ICE restart which should fail, with no new candidates`); 207 208 promise_test(async t => { 209 const offerer = new RTCPeerConnection({iceTransportPolicy: 'relay'}); 210 const answerer = new RTCPeerConnection(); 211 t.add_cleanup(() => offerer.close()); 212 t.add_cleanup(() => answerer.close()); 213 214 offerer.addTransceiver('audio'); 215 216 exchangeIceCandidates(offerer, answerer); 217 218 const checkNoCandidate = 219 e => { 220 if (e.candidate) { 221 assert_equals(e.candidate.candidate, '', 'Should get no ICE candidates') 222 } 223 }; 224 225 offerer.addEventListener('icecandidate', checkNoCandidate); 226 227 await Promise.all([ 228 exchangeOfferAnswer(offerer, answerer), 229 waitForIceStateChange(offerer, ['failed']), 230 waitForIceStateChange(answerer, ['failed']), 231 waitForIceGatheringState(offerer, ['complete']), 232 waitForIceGatheringState(answerer, ['complete']) 233 ]); 234 235 const [oldUfrag] = getUfrags(offerer.localDescription); 236 237 offerer.setConfiguration({iceTransportPolicy: 'all'}); 238 239 offerer.removeEventListener('icecandidate', checkNoCandidate); 240 241 await Promise.all([ 242 exchangeOfferAnswer(offerer, answerer), 243 listenToIceConnected(offerer), 244 listenToIceConnected(answerer), 245 waitForIceGatheringState(offerer, ['complete']), 246 waitForIceGatheringState(answerer, ['complete']) 247 ]); 248 249 const [newUfrag] = getUfrags(offerer.localDescription); 250 assert_not_equals(oldUfrag, newUfrag, 251 'Changing iceTransportPolicy should prompt an ICE restart'); 252 }, `Changing iceTransportPolicy from "relay" to "all" causes an ICE restart which should succeed`); 253 254 promise_test(async t => { 255 const offerer = new RTCPeerConnection(); 256 const answerer = new RTCPeerConnection(); 257 t.add_cleanup(() => offerer.close()); 258 t.add_cleanup(() => answerer.close()); 259 260 offerer.addTransceiver('audio'); 261 262 exchangeIceCandidates(offerer, answerer); 263 264 await Promise.all([ 265 exchangeOfferAnswer(offerer, answerer), 266 listenToIceConnected(offerer), 267 listenToIceConnected(answerer), 268 waitForIceGatheringState(offerer, ['complete']), 269 waitForIceGatheringState(answerer, ['complete']) 270 ]); 271 272 const [oldUfrag] = getUfrags(offerer.localDescription); 273 274 offerer.setConfiguration({iceTransportPolicy: 'relay'}); 275 offerer.setConfiguration({iceTransportPolicy: 'all'}); 276 277 await Promise.all([ 278 exchangeOfferAnswer(offerer, answerer), 279 listenToIceConnected(offerer), 280 listenToIceConnected(answerer), 281 waitForIceGatheringState(offerer, ['complete']), 282 waitForIceGatheringState(answerer, ['complete']) 283 ]); 284 285 const [newUfrag] = getUfrags(offerer.localDescription); 286 assert_not_equals(oldUfrag, newUfrag, 287 'Changing iceTransportPolicy should prompt an ICE restart'); 288 }, `Changing iceTransportPolicy from "all" to "relay", and back to "all" prompts an ICE restart`); 289 290 promise_test(async t => { 291 const offerer = new RTCPeerConnection(); 292 const answerer = new RTCPeerConnection(); 293 t.add_cleanup(() => offerer.close()); 294 t.add_cleanup(() => answerer.close()); 295 296 offerer.addTransceiver('audio'); 297 298 exchangeIceCandidates(offerer, answerer); 299 300 await Promise.all([ 301 exchangeOfferAnswer(offerer, answerer), 302 listenToIceConnected(offerer), 303 listenToIceConnected(answerer), 304 waitForIceGatheringState(offerer, ['complete']), 305 waitForIceGatheringState(answerer, ['complete']) 306 ]); 307 308 const [oldUfrag] = getUfrags(answerer.localDescription); 309 310 answerer.setConfiguration({iceTransportPolicy: 'relay'}); 311 312 await Promise.all([ 313 exchangeOfferAnswer(offerer, answerer), 314 listenToIceConnected(offerer), 315 listenToIceConnected(answerer), 316 waitForIceGatheringState(offerer, ['complete']), 317 waitForIceGatheringState(answerer, ['complete']) 318 ]); 319 320 const [newUfrag] = getUfrags(answerer.localDescription); 321 assert_equals(oldUfrag, newUfrag, 322 'Changing iceTransportPolicy on answerer should not effect ufrag'); 323 }, `Changing iceTransportPolicy from "all" to "relay" on the answerer has no effect on a subsequent offer/answer`); 324 325 </script>