Index: webrtc/api/peerconnectioninterface_unittest.cc |
diff --git a/webrtc/api/peerconnectioninterface_unittest.cc b/webrtc/api/peerconnectioninterface_unittest.cc |
index d673b4174a93a7a46aa2771477073b4c0b22ffe1..eb094b863f0e17ebcb82afe827f73d01d743c2b3 100644 |
--- a/webrtc/api/peerconnectioninterface_unittest.cc |
+++ b/webrtc/api/peerconnectioninterface_unittest.cc |
@@ -72,11 +72,11 @@ static const char kSdpStringWithStream1[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -85,6 +85,10 @@ static const char kSdpStringWithStream1[] = |
"a=ssrc:1 mslabel:stream1\r\n" |
"a=ssrc:1 label:audiotrack0\r\n" |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -100,11 +104,11 @@ static const char kSdpStringWithStream1AudioTrackOnly[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtpmap:103 ISAC/16000\r\n" |
@@ -121,12 +125,12 @@ static const char kSdpStringWithStream1And2[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "a=msid-semantic: WMS stream1 stream2\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "a=msid-semantic: WMS stream1 stream2\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -136,6 +140,10 @@ static const char kSdpStringWithStream1And2[] = |
"a=ssrc:3 cname:stream2\r\n" |
"a=ssrc:3 msid:stream2 audiotrack1\r\n" |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -151,16 +159,20 @@ static const char kSdpStringWithoutStreams[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
"a=rtpmap:103 ISAC/16000\r\n" |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -172,17 +184,21 @@ static const char kSdpStringWithMsidWithoutStreams[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "a=msid-semantic: WMS\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "a=msid-semantic: WMS\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
"a=rtpmap:103 ISAC/16000\r\n" |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -194,11 +210,11 @@ static const char kSdpStringWithoutStreamsAudioOnly[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -210,17 +226,21 @@ static const char kSdpStringSendOnlyWithoutStreams[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
+ "m=audio 1 RTP/AVPF 103\r\n" |
"a=ice-ufrag:e5785931\r\n" |
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
"a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
"BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
- "m=audio 1 RTP/AVPF 103\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=sendonly\r\n" |
"a=rtcp-mux\r\n" |
"a=rtpmap:103 ISAC/16000\r\n" |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=sendonly\r\n" |
@@ -232,14 +252,14 @@ static const char kSdpStringInit[] = |
"o=- 0 0 IN IP4 127.0.0.1\r\n" |
"s=-\r\n" |
"t=0 0\r\n" |
- "a=ice-ufrag:e5785931\r\n" |
- "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
- "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
- "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=msid-semantic: WMS\r\n"; |
static const char kSdpStringAudio[] = |
"m=audio 1 RTP/AVPF 103\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:audio\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -247,6 +267,10 @@ static const char kSdpStringAudio[] = |
static const char kSdpStringVideo[] = |
"m=video 1 RTP/AVPF 120\r\n" |
+ "a=ice-ufrag:e5785931\r\n" |
+ "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" |
+ "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" |
+ "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" |
"a=mid:video\r\n" |
"a=sendrecv\r\n" |
"a=rtcp-mux\r\n" |
@@ -325,6 +349,18 @@ bool GetFirstSsrc(const cricket::ContentInfo* content_info, int* ssrc) { |
return true; |
} |
+// Get the ufrags out of an SDP blob. Useful for testing ICE restart |
+// behavior. |
+std::vector<std::string> GetUfrags( |
+ const webrtc::SessionDescriptionInterface* desc) { |
+ std::vector<std::string> ufrags; |
+ for (const cricket::TransportInfo& info : |
+ desc->description()->transport_infos()) { |
+ ufrags.push_back(info.description.ice_ufrag); |
+ } |
+ return ufrags; |
+} |
+ |
void SetSsrcToZero(std::string* sdp) { |
const char kSdpSsrcAtribute[] = "a=ssrc:"; |
const char kSdpSsrcAtributeZero[] = "a=ssrc:0"; |
@@ -2726,6 +2762,116 @@ TEST_F(PeerConnectionInterfaceTest, OnAddTrackCallback) { |
EXPECT_EQ(observer_.last_added_track_label_, kVideoTracks[0]); |
} |
+// Test that when SetConfiguration is called and the configuration is |
+// changing, the next offer causes an ICE restart. |
+TEST_F(PeerConnectionInterfaceTest, SetConfigurationCausingIceRetart) { |
+ PeerConnectionInterface::RTCConfiguration config; |
+ config.type = PeerConnectionInterface::kRelay; |
+ // Need to pass default constraints to prevent disabling of DTLS... |
+ FakeConstraints default_constraints; |
+ CreatePeerConnection(config, &default_constraints); |
+ AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label"); |
+ |
+ // Do initial offer/answer so there's something to restart. |
+ CreateOfferAsLocalDescription(); |
+ CreateAnswerAsRemoteDescription(kSdpStringWithStream1); |
+ |
+ // Grab the ufrags. |
+ std::vector<std::string> initial_ufrags = GetUfrags(pc_->local_description()); |
+ |
+ // Change ICE policy, which should trigger an ICE restart on the next offer. |
+ config.type = PeerConnectionInterface::kAll; |
+ EXPECT_TRUE(pc_->SetConfiguration(config)); |
+ CreateOfferAsLocalDescription(); |
+ |
+ // Grab the new ufrags. |
+ std::vector<std::string> subsequent_ufrags = |
+ GetUfrags(pc_->local_description()); |
+ |
+ // Sanity check. |
+ EXPECT_EQ(initial_ufrags.size(), subsequent_ufrags.size()); |
+ // Check that each ufrag is different. |
+ for (int i = 0; i < static_cast<int>(initial_ufrags.size()); ++i) { |
+ EXPECT_NE(initial_ufrags[i], subsequent_ufrags[i]); |
+ } |
+} |
+ |
+// Test that when SetConfiguration is called and the configuration *isn't* |
+// changing, the next offer does *not* cause an ICE restart. |
+TEST_F(PeerConnectionInterfaceTest, SetConfigurationNotCausingIceRetart) { |
+ PeerConnectionInterface::RTCConfiguration config; |
+ config.type = PeerConnectionInterface::kRelay; |
+ // Need to pass default constraints to prevent disabling of DTLS... |
+ FakeConstraints default_constraints; |
+ CreatePeerConnection(config, &default_constraints); |
+ AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label"); |
+ |
+ // Do initial offer/answer so there's something to restart. |
+ CreateOfferAsLocalDescription(); |
+ CreateAnswerAsRemoteDescription(kSdpStringWithStream1); |
+ |
+ // Grab the ufrags. |
+ std::vector<std::string> initial_ufrags = GetUfrags(pc_->local_description()); |
+ |
+ // Call SetConfiguration with a config identical to what the PC was |
+ // constructed with. |
+ EXPECT_TRUE(pc_->SetConfiguration(config)); |
+ CreateOfferAsLocalDescription(); |
+ |
+ // Grab the new ufrags. |
+ std::vector<std::string> subsequent_ufrags = |
+ GetUfrags(pc_->local_description()); |
+ |
+ EXPECT_EQ(initial_ufrags, subsequent_ufrags); |
+} |
+ |
+// Test for a weird corner case scenario: |
+// 1. Audio/video session established. |
+// 2. SetConfiguration changes ICE config; ICE restart needed. |
+// 3. ICE restart initiated by remote peer, but only for one m= section. |
+// 4. Next createOffer should initiate an ICE restart, but only for the other |
+// m= section; it would be pointless to do an ICE restart for the m= section |
+// that was already restarted. |
+TEST_F(PeerConnectionInterfaceTest, SetConfigurationCausingPartialIceRestart) { |
+ PeerConnectionInterface::RTCConfiguration config; |
+ config.type = PeerConnectionInterface::kRelay; |
+ // Need to pass default constraints to prevent disabling of DTLS... |
+ FakeConstraints default_constraints; |
+ CreatePeerConnection(config, &default_constraints); |
+ AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label"); |
+ |
+ // Do initial offer/answer so there's something to restart. |
+ CreateOfferAsLocalDescription(); |
+ CreateAnswerAsRemoteDescription(kSdpStringWithStream1); |
+ |
+ // Change ICE policy, which should set the "needs-ice-restart" flag. |
+ config.type = PeerConnectionInterface::kAll; |
+ EXPECT_TRUE(pc_->SetConfiguration(config)); |
+ |
+ // Do ICE restart for the first m= section, initiated by remote peer. |
+ webrtc::JsepSessionDescription* remote_offer = |
+ new webrtc::JsepSessionDescription(SessionDescriptionInterface::kOffer); |
+ EXPECT_TRUE(remote_offer->Initialize(kSdpStringWithStream1, nullptr)); |
+ remote_offer->description()->transport_infos()[0].description.ice_ufrag = |
+ "modified"; |
+ EXPECT_TRUE(DoSetRemoteDescription(remote_offer)); |
+ CreateAnswerAsLocalDescription(); |
+ |
+ // Grab the ufrags. |
+ std::vector<std::string> initial_ufrags = GetUfrags(pc_->local_description()); |
+ ASSERT_EQ(2, initial_ufrags.size()); |
+ |
+ // Create offer and grab the new ufrags. |
+ CreateOfferAsLocalDescription(); |
+ std::vector<std::string> subsequent_ufrags = |
+ GetUfrags(pc_->local_description()); |
+ ASSERT_EQ(2, subsequent_ufrags.size()); |
+ |
+ // Ensure that only the ufrag for the second m= section changed. |
+ EXPECT_EQ(initial_ufrags[0], subsequent_ufrags[0]); |
+ EXPECT_NE(initial_ufrags[1], subsequent_ufrags[1]); |
+} |
+ |
class PeerConnectionMediaConfigTest : public testing::Test { |
protected: |
void SetUp() override { |