1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title>RTCPeerConnection Failed State</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../RTCPeerConnection-helper.js"></script>
<script>
'use strict';
// Tests for correct behavior of ICE state.
// SDP copied from JSEP Example 7.1
// It contains two media streams with different ufrags, and bundle
// turned on.
const kSdp = `v=0
o=- 4962303333179871722 1 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle
a=group:BUNDLE a1 v1
a=group:LS a1 v1
m=audio 10100 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 203.0.113.100
a=mid:a1
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=msid:47017fee-b6c1-4162-929c-a25110252400 f83006c5-a0ff-4e0a-9ed9-d3e6747be7d9
a=ice-ufrag:ETEn
a=ice-pwd:OtSK0WpNtpUjkY4+86js7ZQl
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=dtls-id:1
a=rtcp:10101 IN IP4 203.0.113.100
a=rtcp-mux
a=rtcp-rsize
m=video 10102 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 203.0.113.100
a=mid:v1
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=msid:47017fee-b6c1-4162-929c-a25110252400 f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0
a=ice-ufrag:BGKk
a=ice-pwd:mqyWsAjvtKwTGnvhPztQ9mIf
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04:BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=dtls-id:1
a=rtcp:10103 IN IP4 203.0.113.100
a=rtcp-mux
a=rtcp-rsize
`;
// Returns a promise that resolves when |pc.iceConnectionState| is in one of the
// wanted states, and rejects if it is in one of the unwanted states.
// This is a variant of the function in RTCPeerConnection-helper.js.
function waitForIceStateChange(pc, wantedStates, unwantedStates=[]) {
return new Promise((resolve, reject) => {
if (wantedStates.includes(pc.iceConnectionState)) {
resolve();
return;
} else if (unwantedStates.includes(pc.iceConnectionState)) {
reject('Unexpected state encountered: ' + pc.iceConnectionState);
return;
}
pc.addEventListener('iceconnectionstatechange', () => {
if (wantedStates.includes(pc.iceConnectionState)) {
resolve();
} else if (unwantedStates.includes(pc.iceConnectionState)) {
reject('Unexpected state encountered: ' + pc.iceConnectionState);
}
});
});
}
promise_test(async t => {
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
t.add_cleanup(() => pc2.close());
let [track, streams] = await getTrackFromUserMedia('video');
const sender = pc1.addTrack(track);
exchangeIceCandidates(pc1, pc2);
await exchangeOfferAnswer(pc1, pc2);
await waitForIceStateChange(pc1, ['connected', 'completed']);
}, 'PC should enter connected (or completed) state when candidates are sent');
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
let [track, streams] = await getTrackFromUserMedia('video');
const sender = pc1.addTrack(track);
const offer = await pc1.createOffer();
assert_greater_than_equal(offer.sdp.search('a=ice-options:trickle'), 0);
}, 'PC should generate offer with a=ice-options:trickle');
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
await pc1.setRemoteDescription({type: 'offer', sdp: kSdp});
const answer = await pc1.createAnswer();
await pc1.setLocalDescription(answer);
assert_greater_than_equal(answer.sdp.search('a=ice-options:trickle'), 0);
// When we use trickle ICE, and don't signal end-of-caniddates, we
// expect failure to result in 'disconnected' state rather than 'failed'.
const stateWaiter = waitForIceStateChange(pc1, ['disconnected'],
['failed']);
// Add a bogus candidate. The candidate is drawn from the
// IANA "test-net-3" pool (RFC5737), so is guaranteed not to respond.
const candidateStr1 =
'candidate:1 1 udp 2113929471 203.0.113.100 10100 typ host';
await pc1.addIceCandidate({candidate: candidateStr1,
sdpMid: 'a1',
usernameFragment: 'ETEn'});
await stateWaiter;
}, 'PC should enter disconnected state when a failing candidate is sent');
</script>
|