blob: 656ff224970eb5765fbe770526dd151e7f6caf3c [file] [log] [blame]
Steve Antonf1c6db12017-10-13 11:13:35 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "p2p/base/fakeportallocator.h"
12#include "p2p/base/teststunserver.h"
13#include "p2p/client/basicportallocator.h"
14#include "pc/mediasession.h"
Qingsi Wange1692722017-11-29 13:27:20 -080015#include "pc/peerconnection.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070016#include "pc/peerconnectionwrapper.h"
17#include "pc/sdputils.h"
18#ifdef WEBRTC_ANDROID
19#include "pc/test/androidtestinitializer.h"
20#endif
Karl Wiberg918f50c2018-07-05 11:40:33 +020021#include "absl/memory/memory.h"
Karl Wiberg1b0eae32017-10-17 14:48:54 +020022#include "api/audio_codecs/builtin_audio_decoder_factory.h"
23#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Qingsi Wange1692722017-11-29 13:27:20 -080024#include "api/peerconnectionproxy.h"
Anders Carlsson67537952018-05-03 11:28:29 +020025#include "api/video_codecs/builtin_video_decoder_factory.h"
26#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070027#include "pc/test/fakeaudiocapturemodule.h"
28#include "rtc_base/fakenetwork.h"
29#include "rtc_base/gunit.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070030#include "rtc_base/virtualsocketserver.h"
Harald Alvestrand76829d72018-07-18 23:24:36 +020031#include "system_wrappers/include/metrics_default.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070032
33namespace webrtc {
34
35using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
36using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
37using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080038using ::testing::Combine;
Steve Antonf1c6db12017-10-13 11:13:35 -070039using ::testing::Values;
40
41constexpr int kIceCandidatesTimeout = 10000;
42
Steve Anton46d926a2018-01-23 10:23:06 -080043class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070044 public:
45 using PeerConnectionWrapper::PeerConnectionWrapper;
46
47 // Adds a new ICE candidate to the first transport.
48 bool AddIceCandidate(cricket::Candidate* candidate) {
49 RTC_DCHECK(pc()->remote_description());
50 const auto* desc = pc()->remote_description()->description();
51 RTC_DCHECK(desc->contents().size() > 0);
52 const auto& first_content = desc->contents()[0];
53 candidate->set_transport_name(first_content.name);
54 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
55 return pc()->AddIceCandidate(&jsep_candidate);
56 }
57
58 // Returns ICE candidates from the remote session description.
59 std::vector<const IceCandidateInterface*>
60 GetIceCandidatesFromRemoteDescription() {
61 const SessionDescriptionInterface* sdesc = pc()->remote_description();
62 RTC_DCHECK(sdesc);
63 std::vector<const IceCandidateInterface*> candidates;
64 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
65 mline_index++) {
66 const auto* candidate_collection = sdesc->candidates(mline_index);
67 for (size_t i = 0; i < candidate_collection->count(); i++) {
68 candidates.push_back(candidate_collection->at(i));
69 }
70 }
71 return candidates;
72 }
73
74 rtc::FakeNetworkManager* network() { return network_; }
75
76 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
77
78 private:
79 rtc::FakeNetworkManager* network_;
80};
81
Steve Anton46d926a2018-01-23 10:23:06 -080082class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070083 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080084 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070085
Steve Anton46d926a2018-01-23 10:23:06 -080086 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
87 : vss_(new rtc::VirtualSocketServer()),
88 main_(vss_.get()),
89 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -070090#ifdef WEBRTC_ANDROID
91 InitializeAndroidObjects();
92#endif
93 pc_factory_ = CreatePeerConnectionFactory(
94 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +020095 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
96 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
97 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
98 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -070099 }
100
101 WrapperPtr CreatePeerConnection() {
102 return CreatePeerConnection(RTCConfiguration());
103 }
104
105 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
106 auto* fake_network = NewFakeNetwork();
107 auto port_allocator =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200108 absl::make_unique<cricket::BasicPortAllocator>(fake_network);
Steve Antonf1c6db12017-10-13 11:13:35 -0700109 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
110 cricket::PORTALLOCATOR_DISABLE_RELAY);
111 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800112 RTCConfiguration modified_config = config;
113 modified_config.sdp_semantics = sdp_semantics_;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200114 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Steve Antonf1c6db12017-10-13 11:13:35 -0700115 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800116 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700117 if (!pc) {
118 return nullptr;
119 }
120
Karl Wiberg918f50c2018-07-05 11:40:33 +0200121 auto wrapper = absl::make_unique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700122 pc_factory_, pc, std::move(observer));
123 wrapper->set_network(fake_network);
124 return wrapper;
125 }
126
127 // Accepts the same arguments as CreatePeerConnection and adds default audio
128 // and video tracks.
129 template <typename... Args>
130 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
131 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
132 if (!wrapper) {
133 return nullptr;
134 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700135 wrapper->AddAudioTrack("a");
136 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700137 return wrapper;
138 }
139
140 cricket::Candidate CreateLocalUdpCandidate(
141 const rtc::SocketAddress& address) {
142 cricket::Candidate candidate;
143 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
144 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
145 candidate.set_address(address);
146 candidate.set_type(cricket::LOCAL_PORT_TYPE);
147 return candidate;
148 }
149
150 // Remove all ICE ufrag/pwd lines from the given session description.
151 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
152 SetIceUfragPwd(sdesc, "", "");
153 }
154
155 // Sets all ICE ufrag/pwds on the given session description.
156 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
157 const std::string& ufrag,
158 const std::string& pwd) {
159 auto* desc = sdesc->description();
160 for (const auto& content : desc->contents()) {
161 auto* transport_info = desc->GetTransportInfoByName(content.name);
162 transport_info->description.ice_ufrag = ufrag;
163 transport_info->description.ice_pwd = pwd;
164 }
165 }
166
Qingsi Wange1692722017-11-29 13:27:20 -0800167 // Set ICE mode on the given session description.
168 void SetIceMode(SessionDescriptionInterface* sdesc,
169 const cricket::IceMode ice_mode) {
170 auto* desc = sdesc->description();
171 for (const auto& content : desc->contents()) {
172 auto* transport_info = desc->GetTransportInfoByName(content.name);
173 transport_info->description.ice_mode = ice_mode;
174 }
175 }
176
Steve Antonf1c6db12017-10-13 11:13:35 -0700177 cricket::TransportDescription* GetFirstTransportDescription(
178 SessionDescriptionInterface* sdesc) {
179 auto* desc = sdesc->description();
180 RTC_DCHECK(desc->contents().size() > 0);
181 auto* transport_info =
182 desc->GetTransportInfoByName(desc->contents()[0].name);
183 RTC_DCHECK(transport_info);
184 return &transport_info->description;
185 }
186
187 const cricket::TransportDescription* GetFirstTransportDescription(
188 const SessionDescriptionInterface* sdesc) {
189 auto* desc = sdesc->description();
190 RTC_DCHECK(desc->contents().size() > 0);
191 auto* transport_info =
192 desc->GetTransportInfoByName(desc->contents()[0].name);
193 RTC_DCHECK(transport_info);
194 return &transport_info->description;
195 }
196
Qingsi Wange1692722017-11-29 13:27:20 -0800197 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
198 // after it is implemented.
199 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100200 auto* pc_proxy =
201 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
202 pc_wrapper_ptr->pc());
203 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Steve Antonb8867112018-02-13 10:07:54 -0800204 for (auto transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800205 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton46d926a2018-01-23 10:23:06 -0800206 cricket::BaseChannel* channel = transceiver->internal()->channel();
207 if (channel) {
Zhi Huange830e682018-03-30 10:48:35 -0700208 auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
209 channel->rtp_packet_transport());
210 return dtls_transport->ice_transport()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800211 }
212 }
213 }
214 RTC_NOTREACHED();
215 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800216 }
217
Steve Antonf1c6db12017-10-13 11:13:35 -0700218 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
219 SessionDescriptionInterface* sdesc) {
220 auto* desc = sdesc->description();
221 RTC_DCHECK(desc->contents().size() > 0);
222 const auto& first_content = desc->contents()[0];
223 candidate->set_transport_name(first_content.name);
224 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
225 return sdesc->AddCandidate(&jsep_candidate);
226 }
227
228 rtc::FakeNetworkManager* NewFakeNetwork() {
229 // The PeerConnection's port allocator is tied to the PeerConnection's
230 // lifetime and expects the underlying NetworkManager to outlive it. That
231 // prevents us from having the PeerConnectionWrapper own the fake network.
232 // Therefore, the test fixture will own all the fake networks even though
233 // tests should access the fake network through the PeerConnectionWrapper.
234 auto* fake_network = new rtc::FakeNetworkManager();
235 fake_networks_.emplace_back(fake_network);
236 return fake_network;
237 }
238
239 std::unique_ptr<rtc::VirtualSocketServer> vss_;
240 rtc::AutoSocketServerThread main_;
241 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
242 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800243 const SdpSemantics sdp_semantics_;
244};
245
246class PeerConnectionIceTest
247 : public PeerConnectionIceBaseTest,
248 public ::testing::WithParamInterface<SdpSemantics> {
249 protected:
Harald Alvestrand76829d72018-07-18 23:24:36 +0200250 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
251 webrtc::metrics::Reset();
252 }
Steve Antonf1c6db12017-10-13 11:13:35 -0700253};
254
255::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
256 const char* b_expr,
257 const cricket::Candidate& a,
258 const cricket::Candidate& b) {
259 std::stringstream failure_info;
260 if (a.component() != b.component()) {
261 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
262 }
263 if (a.protocol() != b.protocol()) {
264 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
265 }
266 if (a.address() != b.address()) {
267 failure_info << "\naddress: " << a.address().ToString()
268 << " != " << b.address().ToString();
269 }
270 if (a.type() != b.type()) {
271 failure_info << "\ntype: " << a.type() << " != " << b.type();
272 }
273 std::string failure_info_str = failure_info.str();
274 if (failure_info_str.empty()) {
275 return ::testing::AssertionSuccess();
276 } else {
277 return ::testing::AssertionFailure()
278 << a_expr << " and " << b_expr << " are not equal"
279 << failure_info_str;
280 }
281}
282
Steve Anton46d926a2018-01-23 10:23:06 -0800283TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700284 const SocketAddress kLocalAddress("1.1.1.1", 0);
285
286 auto caller = CreatePeerConnectionWithAudioVideo();
287 caller->network()->AddInterface(kLocalAddress);
288
289 // Start ICE candidate gathering by setting the local offer.
290 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
291
292 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
293
294 auto offer = caller->CreateOffer();
295 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
296 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
297 offer->candidates(0)->count());
298 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
299 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
300 offer->candidates(1)->count());
301}
302
Steve Anton46d926a2018-01-23 10:23:06 -0800303TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700304 const SocketAddress kCallerAddress("1.1.1.1", 0);
305
306 auto caller = CreatePeerConnectionWithAudioVideo();
307 auto callee = CreatePeerConnectionWithAudioVideo();
308 caller->network()->AddInterface(kCallerAddress);
309
310 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
311 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
312
313 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
314
Steve Antondffead82018-02-06 10:31:29 -0800315 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700316 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
317 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
318 answer->candidates(0)->count());
319 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
320 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
321 answer->candidates(1)->count());
322}
323
Steve Anton46d926a2018-01-23 10:23:06 -0800324TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700325 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
326 const SocketAddress kCallerAddress("1.1.1.1", 1111);
327
328 auto caller = CreatePeerConnectionWithAudioVideo();
329 auto callee = CreatePeerConnectionWithAudioVideo();
330
331 auto offer = caller->CreateOfferAndSetAsLocal();
332 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
333 AddCandidateToFirstTransport(&candidate, offer.get());
334
335 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
336 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
337 ASSERT_EQ(1u, remote_candidates.size());
338 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
339 remote_candidates[0]->candidate());
340}
341
Steve Anton46d926a2018-01-23 10:23:06 -0800342TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700343 auto caller = CreatePeerConnectionWithAudioVideo();
344
345 auto offer = caller->CreateOffer();
346 RemoveIceUfragPwd(offer.get());
347
348 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
349}
350
Steve Anton46d926a2018-01-23 10:23:06 -0800351TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700352 auto caller = CreatePeerConnectionWithAudioVideo();
353 auto callee = CreatePeerConnectionWithAudioVideo();
354
355 auto offer = caller->CreateOfferAndSetAsLocal();
356 RemoveIceUfragPwd(offer.get());
357
358 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
359}
360
Steve Antonf764cf42018-05-01 14:32:17 -0700361// Test that doing an offer/answer exchange with no transport (i.e., no data
362// channel or media) results in the ICE connection state staying at New.
363TEST_P(PeerConnectionIceTest,
364 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
365 auto caller = CreatePeerConnection();
366 auto callee = CreatePeerConnection();
367
368 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
369
370 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
371 caller->pc()->ice_connection_state());
372 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
373 callee->pc()->ice_connection_state());
374}
375
Steve Antonf1c6db12017-10-13 11:13:35 -0700376// The following group tests that ICE candidates are not generated before
377// SetLocalDescription is called on a PeerConnection.
378
Steve Anton46d926a2018-01-23 10:23:06 -0800379TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700380 const SocketAddress kLocalAddress("1.1.1.1", 0);
381
382 auto caller = CreatePeerConnectionWithAudioVideo();
383 caller->network()->AddInterface(kLocalAddress);
384
385 // Pump for 1 second and verify that no candidates are generated.
386 rtc::Thread::Current()->ProcessMessages(1000);
387
388 EXPECT_EQ(0u, caller->observer()->candidates_.size());
389}
Steve Anton46d926a2018-01-23 10:23:06 -0800390TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700391 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
392 const SocketAddress kCallerAddress("1.1.1.1", 1111);
393
394 auto caller = CreatePeerConnectionWithAudioVideo();
395 auto callee = CreatePeerConnectionWithAudioVideo();
396 caller->network()->AddInterface(kCallerAddress);
397
398 auto offer = caller->CreateOfferAndSetAsLocal();
399 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
400 AddCandidateToFirstTransport(&candidate, offer.get());
401 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
402
403 // Pump for 1 second and verify that no candidates are generated.
404 rtc::Thread::Current()->ProcessMessages(1000);
405
406 EXPECT_EQ(0u, callee->observer()->candidates_.size());
407}
408
Steve Anton46d926a2018-01-23 10:23:06 -0800409TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700410 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
411
412 auto caller = CreatePeerConnectionWithAudioVideo();
413 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
414 JsepIceCandidate jsep_candidate(cricket::CN_AUDIO, 0, candidate);
415
416 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
417
418 caller->CreateOfferAndSetAsLocal();
419
420 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
Harald Alvestrand76829d72018-07-18 23:24:36 +0200421 EXPECT_EQ(
422 2, webrtc::metrics::NumSamples("WebRTC.PeerConnection.AddIceCandidate"));
423 EXPECT_EQ(
424 2, webrtc::metrics::NumEvents("WebRTC.PeerConnection.AddIceCandidate",
425 kAddIceCandidateFailNoRemoteDescription));
Steve Antonf1c6db12017-10-13 11:13:35 -0700426}
427
Steve Antonc79268f2018-04-24 09:54:10 -0700428TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
429 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
430
431 auto caller = CreatePeerConnectionWithAudioVideo();
432 auto callee = CreatePeerConnectionWithAudioVideo();
433
434 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
435
436 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
437 auto* audio_content = cricket::GetFirstAudioContent(
438 caller->pc()->local_description()->description());
439 JsepIceCandidate jsep_candidate(audio_content->name, 0, candidate);
440
441 caller->pc()->Close();
442
443 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
444}
445
Steve Anton46d926a2018-01-23 10:23:06 -0800446TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700447 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
448
449 auto caller = CreatePeerConnectionWithAudioVideo();
450 auto callee = CreatePeerConnectionWithAudioVideo();
451
452 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
453 ASSERT_TRUE(
454 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
455
456 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
457 caller->AddIceCandidate(&candidate);
458 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
459 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
460}
461
Steve Anton46d926a2018-01-23 10:23:06 -0800462TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700463 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
464 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
465
466 auto caller = CreatePeerConnectionWithAudioVideo();
467 auto callee = CreatePeerConnectionWithAudioVideo();
468
469 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
470
471 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
472 auto* audio_content = cricket::GetFirstAudioContent(
473 caller->pc()->local_description()->description());
474 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
475
476 ASSERT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
477
478 caller->pc()->Close();
479
480 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
481}
482
483TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700484 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
485 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
486
487 auto caller = CreatePeerConnectionWithAudioVideo();
488 auto callee = CreatePeerConnectionWithAudioVideo();
489
490 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
491 ASSERT_TRUE(
492 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
493
494 // |candidate.transport_name()| is empty.
495 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800496 auto* audio_content = cricket::GetFirstAudioContent(
497 caller->pc()->local_description()->description());
498 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700499 EXPECT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
500 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
501}
502
Steve Anton46d926a2018-01-23 10:23:06 -0800503TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700504 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
505
506 auto caller = CreatePeerConnectionWithAudioVideo();
507 auto callee = CreatePeerConnectionWithAudioVideo();
508
509 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
510 ASSERT_TRUE(
511 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
512
513 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
514 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
515 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
516 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
517}
518
519// Test that if a candidate is added via AddIceCandidate and via an updated
520// remote description, then both candidates appear in the stored remote
521// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800522TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700523 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
524 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
525 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
526
527 auto caller = CreatePeerConnectionWithAudioVideo();
528 auto callee = CreatePeerConnectionWithAudioVideo();
529
530 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
531 ASSERT_TRUE(
532 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
533
534 // Add one candidate via |AddIceCandidate|.
535 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
536 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
537
538 // Add the second candidate via a reoffer.
539 auto offer = caller->CreateOffer();
540 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
541 AddCandidateToFirstTransport(&candidate2, offer.get());
542
543 // Expect both candidates to appear in the callee's remote description.
544 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
545 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
546}
547
548// The follow test verifies that SetLocal/RemoteDescription fails when an offer
549// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
550// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
551// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800552TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Yves Gerey665174f2018-06-19 15:03:05 +0200553 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
554 int pwd_len) {
555 auto pc = CreatePeerConnectionWithAudioVideo();
556 auto offer = pc->CreateOffer();
557 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
558 std::string(pwd_len, 'x'));
559 return pc->SetLocalDescription(std::move(offer));
560 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700561
Yves Gerey665174f2018-06-19 15:03:05 +0200562 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
563 int pwd_len) {
564 auto pc = CreatePeerConnectionWithAudioVideo();
565 auto offer = pc->CreateOffer();
566 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
567 std::string(pwd_len, 'x'));
568 return pc->SetRemoteDescription(std::move(offer));
569 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700570
571 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
572 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
573 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
574 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
575 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
576 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
577 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
578 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
579 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
580 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
581 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
582 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
583}
584
585::testing::AssertionResult AssertIpInCandidates(
586 const char* address_expr,
587 const char* candidates_expr,
588 const SocketAddress& address,
589 const std::vector<IceCandidateInterface*> candidates) {
590 std::stringstream candidate_hosts;
591 for (const auto* candidate : candidates) {
592 const auto& candidate_ip = candidate->candidate().address().ipaddr();
593 if (candidate_ip == address.ipaddr()) {
594 return ::testing::AssertionSuccess();
595 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200596 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700597 }
598 return ::testing::AssertionFailure()
599 << address_expr << " (host " << address.HostAsURIString()
600 << ") not in " << candidates_expr
601 << " which have the following address hosts:" << candidate_hosts.str();
602}
603
Steve Anton46d926a2018-01-23 10:23:06 -0800604TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700605 const SocketAddress kLocalAddress1("1.1.1.1", 0);
606 const SocketAddress kLocalAddress2("2.2.2.2", 0);
607
608 auto caller = CreatePeerConnectionWithAudioVideo();
609 caller->network()->AddInterface(kLocalAddress1);
610 caller->network()->AddInterface(kLocalAddress2);
611
612 caller->CreateOfferAndSetAsLocal();
613 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
614
615 auto candidates = caller->observer()->GetCandidatesByMline(0);
616 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
617 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
618}
619
Steve Anton46d926a2018-01-23 10:23:06 -0800620TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700621 const SocketAddress kCallerAddress("1.1.1.1", 1111);
622
623 auto caller = CreatePeerConnectionWithAudioVideo();
624 auto callee = CreatePeerConnectionWithAudioVideo();
625
626 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
627
628 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
629 callee->AddIceCandidate(&candidate);
630 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
631 ASSERT_EQ(1u, candidates.size());
632 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
633 candidates[0]->candidate());
634}
635
Steve Anton46d926a2018-01-23 10:23:06 -0800636TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700637 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
638 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
639
640 auto caller = CreatePeerConnectionWithAudioVideo();
641 auto callee = CreatePeerConnectionWithAudioVideo();
642
643 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
644 ASSERT_TRUE(
645 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
646
647 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
648 caller->AddIceCandidate(&candidate1);
649
650 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
651 caller->AddIceCandidate(&candidate2);
652
653 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
654 ASSERT_EQ(2u, candidates.size());
655 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
656 candidates[0]->candidate());
657 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
658 candidates[1]->candidate());
659}
660
Steve Anton46d926a2018-01-23 10:23:06 -0800661TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700662 const SocketAddress kLocalAddress("1.1.1.1", 0);
663
664 RTCConfiguration config;
665 config.continual_gathering_policy =
666 PeerConnectionInterface::GATHER_CONTINUALLY;
667 auto caller = CreatePeerConnectionWithAudioVideo(config);
668 caller->network()->AddInterface(kLocalAddress);
669
670 // Start ICE candidate gathering by setting the local offer.
671 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
672
673 // Since we're using continual gathering, we won't get "gathering done".
674 EXPECT_TRUE_WAIT(
675 caller->pc()->local_description()->candidates(0)->count() > 0,
676 kIceCandidatesTimeout);
677}
678
679// Test that when continual gathering is enabled, and a network interface goes
680// down, the candidate is signaled as removed and removed from the local
681// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800682TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700683 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
684 const SocketAddress kLocalAddress("1.1.1.1", 0);
685
686 RTCConfiguration config;
687 config.continual_gathering_policy =
688 PeerConnectionInterface::GATHER_CONTINUALLY;
689 auto caller = CreatePeerConnectionWithAudioVideo(config);
690 caller->network()->AddInterface(kLocalAddress);
691
692 // Start ICE candidate gathering by setting the local offer.
693 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
694
695 EXPECT_TRUE_WAIT(
696 caller->pc()->local_description()->candidates(0)->count() > 0,
697 kIceCandidatesTimeout);
698
699 // Remove the only network interface, causing the PeerConnection to signal
700 // the removal of all candidates derived from this interface.
701 caller->network()->RemoveInterface(kLocalAddress);
702
703 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
704 kIceCandidatesTimeout);
705 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
706}
707
Steve Anton46d926a2018-01-23 10:23:06 -0800708TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700709 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
710 const SocketAddress kLocalAddress("1.1.1.1", 0);
711
712 RTCConfiguration config;
713 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
714 auto caller = CreatePeerConnectionWithAudioVideo(config);
715 caller->network()->AddInterface(kLocalAddress);
716
717 // Start ICE candidate gathering by setting the local offer.
718 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
719
720 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
721
722 caller->network()->RemoveInterface(kLocalAddress);
723
724 // Verify that the local candidates are not removed;
725 rtc::Thread::Current()->ProcessMessages(1000);
726 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
727}
728
729// The following group tests that when an offer includes a new ufrag or pwd
730// (indicating an ICE restart) the old candidates are removed and new candidates
731// added to the remote description.
732
Steve Anton46d926a2018-01-23 10:23:06 -0800733TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700734 const SocketAddress kCallerAddress("1.1.1.1", 1111);
735
736 auto caller = CreatePeerConnectionWithAudioVideo();
737 auto callee = CreatePeerConnectionWithAudioVideo();
738
739 auto offer = caller->CreateOffer();
740 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
741 AddCandidateToFirstTransport(&candidate, offer.get());
742
743 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
744
745 RTCOfferAnswerOptions options;
746 options.ice_restart = true;
747 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer(options)));
748
749 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
750}
Steve Anton46d926a2018-01-23 10:23:06 -0800751TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700752 IceRestartOfferCandidateReplacesExistingCandidate) {
753 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
754 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
755
756 auto caller = CreatePeerConnectionWithAudioVideo();
757 auto callee = CreatePeerConnectionWithAudioVideo();
758
759 auto offer = caller->CreateOffer();
760 cricket::Candidate old_candidate =
761 CreateLocalUdpCandidate(kFirstCallerAddress);
762 AddCandidateToFirstTransport(&old_candidate, offer.get());
763
764 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
765
766 RTCOfferAnswerOptions options;
767 options.ice_restart = true;
768 auto restart_offer = caller->CreateOffer(options);
769 cricket::Candidate new_candidate =
770 CreateLocalUdpCandidate(kRestartedCallerAddress);
771 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
772
773 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
774
775 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
776 ASSERT_EQ(1u, remote_candidates.size());
777 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
778 remote_candidates[0]->candidate());
779}
780
781// Test that if there is not an ICE restart (i.e., nothing changes), then the
782// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800783TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700784 auto caller = CreatePeerConnectionWithAudioVideo();
785 auto callee = CreatePeerConnectionWithAudioVideo();
786
787 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
788 ASSERT_TRUE(
789 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
790
791 // Re-offer.
792 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
793
794 auto answer = callee->CreateAnswer();
795 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
796 auto* local_transport_desc =
797 GetFirstTransportDescription(callee->pc()->local_description());
798
799 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
800 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
801}
802
803// The following parameterized test verifies that if an offer is sent with a
804// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
805// other side has initiated an ICE restart and generate a new ufrag and pwd.
806// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
807// a=ice-pwd attributes compared to the previous SDP from the peer, it
808// indicates that ICE is restarting for this media stream."
809
Steve Anton46d926a2018-01-23 10:23:06 -0800810class PeerConnectionIceUfragPwdAnswerTest
811 : public PeerConnectionIceBaseTest,
812 public ::testing::WithParamInterface<
813 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -0700814 protected:
Steve Anton46d926a2018-01-23 10:23:06 -0800815 PeerConnectionIceUfragPwdAnswerTest()
816 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
817 auto param = std::get<1>(GetParam());
818 offer_new_ufrag_ = std::get<0>(param);
819 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -0700820 }
821
822 bool offer_new_ufrag_;
823 bool offer_new_pwd_;
824};
825
Steve Anton46d926a2018-01-23 10:23:06 -0800826TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700827 auto caller = CreatePeerConnectionWithAudioVideo();
828 auto callee = CreatePeerConnectionWithAudioVideo();
829
830 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
831 ASSERT_TRUE(
832 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
833
834 auto offer = caller->CreateOffer();
835 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
836 if (offer_new_ufrag_) {
837 offer_transport_desc->ice_ufrag += "_new";
838 }
839 if (offer_new_pwd_) {
840 offer_transport_desc->ice_pwd += "_new";
841 }
842
843 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
844
845 auto answer = callee->CreateAnswer();
846 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
847 auto* local_transport_desc =
848 GetFirstTransportDescription(callee->pc()->local_description());
849
850 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
851 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
852}
853
854INSTANTIATE_TEST_CASE_P(
Steve Anton46d926a2018-01-23 10:23:06 -0800855 PeerConnectionIceTest,
856 PeerConnectionIceUfragPwdAnswerTest,
857 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
858 Values(std::make_pair(true, true), // Both changed.
859 std::make_pair(true, false), // Only ufrag changed.
860 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -0700861
862// Test that if an ICE restart is offered on one media section, then the answer
863// will only change ICE ufrag/pwd for that section and keep the other sections
864// the same.
865// Note that this only works if we have disabled BUNDLE, otherwise all media
866// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -0800867TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700868 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
869 auto caller = CreatePeerConnectionWithAudioVideo();
870 auto callee = CreatePeerConnectionWithAudioVideo();
871
872 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
873 ASSERT_TRUE(
874 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
875
876 RTCOfferAnswerOptions disable_bundle_options;
877 disable_bundle_options.use_rtp_mux = false;
878
879 auto offer = caller->CreateOffer(disable_bundle_options);
880
881 // Signal ICE restart on the first media section.
882 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
883 offer_transport_desc->ice_ufrag += "_new";
884 offer_transport_desc->ice_pwd += "_new";
885
886 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
887
888 auto answer = callee->CreateAnswer(disable_bundle_options);
889 const auto& answer_transports = answer->description()->transport_infos();
890 const auto& local_transports =
891 callee->pc()->local_description()->description()->transport_infos();
892
893 EXPECT_NE(answer_transports[0].description.ice_ufrag,
894 local_transports[0].description.ice_ufrag);
895 EXPECT_NE(answer_transports[0].description.ice_pwd,
896 local_transports[0].description.ice_pwd);
897 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
898 local_transports[1].description.ice_ufrag);
899 EXPECT_EQ(answer_transports[1].description.ice_pwd,
900 local_transports[1].description.ice_pwd);
901}
902
Qingsi Wange1692722017-11-29 13:27:20 -0800903// Test that when the initial offerer (caller) uses the lite implementation of
904// ICE and the callee uses the full implementation, the caller takes the
905// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
906// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800907TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800908 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
909 auto caller = CreatePeerConnectionWithAudioVideo();
910 auto callee = CreatePeerConnectionWithAudioVideo();
911
912 auto offer = caller->CreateOffer();
913 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
914 ASSERT_TRUE(
915 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
916 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
917
918 auto answer = callee->CreateAnswer();
919 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
920 ASSERT_TRUE(
921 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
922 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
923
924 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
925 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
926}
927
928// Test that when the caller and the callee both use the lite implementation of
929// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
930// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800931TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800932 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
933 auto caller = CreatePeerConnectionWithAudioVideo();
934 auto callee = CreatePeerConnectionWithAudioVideo();
935
936 auto offer = caller->CreateOffer();
937 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
938 ASSERT_TRUE(
939 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
940 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
941
942 auto answer = callee->CreateAnswer();
943 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
944 ASSERT_TRUE(
945 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
946 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
947
948 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
949 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
950}
951
Steve Anton46d926a2018-01-23 10:23:06 -0800952INSTANTIATE_TEST_CASE_P(PeerConnectionIceTest,
953 PeerConnectionIceTest,
954 Values(SdpSemantics::kPlanB,
955 SdpSemantics::kUnifiedPlan));
956
Qingsi Wang4ff54432018-03-01 18:25:20 -0800957class PeerConnectionIceConfigTest : public testing::Test {
958 protected:
959 void SetUp() override {
960 pc_factory_ = CreatePeerConnectionFactory(
961 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
962 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +0200963 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
964 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
965 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -0800966 }
967 void CreatePeerConnection(const RTCConfiguration& config) {
968 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
969 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
970 port_allocator_ = port_allocator.get();
971 rtc::scoped_refptr<PeerConnectionInterface> pc(
972 pc_factory_->CreatePeerConnection(
973 config, nullptr /* constraint */, std::move(port_allocator),
974 nullptr /* cert_generator */, &observer_));
975 EXPECT_TRUE(pc.get());
976 pc_ = std::move(pc.get());
977 }
978
979 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
980 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
981 cricket::FakePortAllocator* port_allocator_ = nullptr;
982
983 MockPeerConnectionObserver observer_;
984};
985
986TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
987 RTCConfiguration config;
988 config.stun_candidate_keepalive_interval = 123;
989 config.ice_candidate_pool_size = 1;
990 CreatePeerConnection(config);
991 ASSERT_NE(port_allocator_, nullptr);
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200992 absl::optional<int> actual_stun_keepalive_interval =
Qingsi Wang4ff54432018-03-01 18:25:20 -0800993 port_allocator_->stun_candidate_keepalive_interval();
994 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
995 config.stun_candidate_keepalive_interval = 321;
996 RTCError error;
997 pc_->SetConfiguration(config, &error);
998 actual_stun_keepalive_interval =
999 port_allocator_->stun_candidate_keepalive_interval();
1000 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1001}
1002
Steve Antonf1c6db12017-10-13 11:13:35 -07001003} // namespace webrtc