RTCPeerConnection-iceConnectionState-disconnected.https.html (3119B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <meta name="timeout" content="long"> 4 <title>RTCPeerConnection.prototype.iceConnectionState - disconnection</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 promise_test(async t => { 11 const caller = new RTCPeerConnection(); 12 t.add_cleanup(() => caller.close()); 13 const callee = new RTCPeerConnection(); 14 t.add_cleanup(() => callee.close()); 15 16 const stream = await getNoiseStream({audio:true}); 17 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 18 const [track] = stream.getTracks(); 19 caller.addTrack(track, stream); 20 exchangeIceCandidates(caller, callee); 21 await exchangeOfferAnswer(caller, callee); 22 23 await listenToIceConnected(caller); 24 25 callee.close(); 26 await waitForIceStateChange(caller, ['disconnected', 'failed']); 27 // TODO: this should eventually transition to failed but that takes 28 // somewhat long (15-30s) so is not testable. 29 }, 'ICE goes to disconnected if the other side goes away'); 30 31 promise_test(async t => { 32 const caller = new RTCPeerConnection(); 33 t.add_cleanup(() => caller.close()); 34 const callee = new RTCPeerConnection(); 35 t.add_cleanup(() => callee.close()); 36 caller.addTransceiver('audio', {direction: 'sendrecv'}); 37 exchangeIceCandidates(caller, callee); 38 await exchangeOfferAnswer(caller, callee); 39 await listenToIceConnected(caller); 40 41 // Now, we pull a fast one, and convince callee to abandon the transport 42 // without telling caller. 43 await caller.setLocalDescription(); 44 await callee.setRemoteDescription(caller.localDescription); 45 const staleAnswer = await callee.createAnswer(); 46 await callee.setRemoteDescription({type: 'rollback', sdp: ''}); 47 48 const mlineRegex = /m=audio [0-9]+ /; 49 const mungedOfferSdp = caller.localDescription.sdp 50 .replace(mlineRegex, 'm=audio 0 ') 51 .replace('BUNDLE', 'BUNGLE'); // Avoid "But that mid is rejected!" errors 52 53 // callee gets the munged reoffer with a rejected m-section, caller gets a 54 // stale answer that was made before callee saw the rejected m-section. 55 await callee.setRemoteDescription({type: 'offer', sdp: mungedOfferSdp}); 56 await callee.setLocalDescription(); 57 await caller.setRemoteDescription(staleAnswer); 58 assert_equals(await nextIceConnectionState(caller), 'disconnected'); 59 60 // Now, let's fix this with an ICE restart! callee has already negotiated 61 // a rejection of the first m-section, so it will tolerate it being 62 // revived. 63 caller.restartIce(); 64 await caller.setLocalDescription(); 65 await callee.setRemoteDescription(caller.localDescription); 66 await callee.setLocalDescription(); 67 await caller.setRemoteDescription(callee.localDescription); 68 assert_equals(await nextIceConnectionState(caller), 'checking'); 69 assert_equals(await nextIceConnectionState(caller), 'connected'); 70 }, 'ICE restart when ICE is disconnected results in checking, then connected'); 71 72 </script>