1 /*
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 <memory>
12
13 #include "p2p/base/fake_port_allocator.h"
14 #include "p2p/base/test_stun_server.h"
15 #include "p2p/client/basic_port_allocator.h"
16 #include "pc/media_session.h"
17 #include "pc/peer_connection.h"
18 #include "pc/peer_connection_wrapper.h"
19 #include "pc/sdp_utils.h"
20 #ifdef WEBRTC_ANDROID
21 #include "pc/test/android_test_initializer.h"
22 #endif
23 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
24 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
25 #include "api/create_peerconnection_factory.h"
26 #include "api/peer_connection_proxy.h"
27 #include "api/uma_metrics.h"
28 #include "api/video_codecs/builtin_video_decoder_factory.h"
29 #include "api/video_codecs/builtin_video_encoder_factory.h"
30 #include "pc/test/fake_audio_capture_module.h"
31 #include "pc/test/mock_peer_connection_observers.h"
32 #include "rtc_base/fake_network.h"
33 #include "rtc_base/gunit.h"
34 #include "rtc_base/strings/string_builder.h"
35 #include "rtc_base/virtual_socket_server.h"
36 #include "system_wrappers/include/metrics.h"
37 #include "test/gmock.h"
38
39 namespace webrtc {
40
41 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
42 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
43 using rtc::SocketAddress;
44 using ::testing::Combine;
45 using ::testing::ElementsAre;
46 using ::testing::Pair;
47 using ::testing::Values;
48
49 constexpr int kIceCandidatesTimeout = 10000;
50 constexpr int64_t kWaitTimeout = 10000;
51
52 class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
53 public:
54 using PeerConnectionWrapper::PeerConnectionWrapper;
55
CreateJsepCandidateForFirstTransport(cricket::Candidate * candidate)56 std::unique_ptr<IceCandidateInterface> CreateJsepCandidateForFirstTransport(
57 cricket::Candidate* candidate) {
58 RTC_DCHECK(pc()->remote_description());
59 const auto* desc = pc()->remote_description()->description();
60 RTC_DCHECK(desc->contents().size() > 0);
61 const auto& first_content = desc->contents()[0];
62 candidate->set_transport_name(first_content.name);
63 return CreateIceCandidate(first_content.name, -1, *candidate);
64 }
65
66 // Adds a new ICE candidate to the first transport.
AddIceCandidate(cricket::Candidate * candidate)67 bool AddIceCandidate(cricket::Candidate* candidate) {
68 return pc()->AddIceCandidate(
69 CreateJsepCandidateForFirstTransport(candidate).get());
70 }
71
72 // Returns ICE candidates from the remote session description.
73 std::vector<const IceCandidateInterface*>
GetIceCandidatesFromRemoteDescription()74 GetIceCandidatesFromRemoteDescription() {
75 const SessionDescriptionInterface* sdesc = pc()->remote_description();
76 RTC_DCHECK(sdesc);
77 std::vector<const IceCandidateInterface*> candidates;
78 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
79 mline_index++) {
80 const auto* candidate_collection = sdesc->candidates(mline_index);
81 for (size_t i = 0; i < candidate_collection->count(); i++) {
82 candidates.push_back(candidate_collection->at(i));
83 }
84 }
85 return candidates;
86 }
87
network()88 rtc::FakeNetworkManager* network() { return network_; }
89
set_network(rtc::FakeNetworkManager * network)90 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
91
92 // The port allocator used by this PC.
93 cricket::PortAllocator* port_allocator_;
94
95 private:
96 rtc::FakeNetworkManager* network_;
97 };
98
99 class PeerConnectionIceBaseTest : public ::testing::Test {
100 protected:
101 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
102
PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)103 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
104 : vss_(new rtc::VirtualSocketServer()),
105 main_(vss_.get()),
106 sdp_semantics_(sdp_semantics) {
107 #ifdef WEBRTC_ANDROID
108 InitializeAndroidObjects();
109 #endif
110 pc_factory_ = CreatePeerConnectionFactory(
111 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
112 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
113 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
114 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
115 nullptr /* audio_mixer */, nullptr /* audio_processing */);
116 }
117
CreatePeerConnection()118 WrapperPtr CreatePeerConnection() {
119 return CreatePeerConnection(RTCConfiguration());
120 }
121
CreatePeerConnection(const RTCConfiguration & config)122 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
123 auto* fake_network = NewFakeNetwork();
124 auto port_allocator =
125 std::make_unique<cricket::BasicPortAllocator>(fake_network);
126 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
127 cricket::PORTALLOCATOR_DISABLE_RELAY);
128 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
129 RTCConfiguration modified_config = config;
130 modified_config.sdp_semantics = sdp_semantics_;
131 auto observer = std::make_unique<MockPeerConnectionObserver>();
132 auto port_allocator_copy = port_allocator.get();
133 auto pc = pc_factory_->CreatePeerConnection(
134 modified_config, std::move(port_allocator), nullptr, observer.get());
135 if (!pc) {
136 return nullptr;
137 }
138
139 observer->SetPeerConnectionInterface(pc.get());
140 auto wrapper = std::make_unique<PeerConnectionWrapperForIceTest>(
141 pc_factory_, pc, std::move(observer));
142 wrapper->set_network(fake_network);
143 wrapper->port_allocator_ = port_allocator_copy;
144 return wrapper;
145 }
146
147 // Accepts the same arguments as CreatePeerConnection and adds default audio
148 // and video tracks.
149 template <typename... Args>
CreatePeerConnectionWithAudioVideo(Args &&...args)150 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
151 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
152 if (!wrapper) {
153 return nullptr;
154 }
155 wrapper->AddAudioTrack("a");
156 wrapper->AddVideoTrack("v");
157 return wrapper;
158 }
159
CreateLocalUdpCandidate(const rtc::SocketAddress & address)160 cricket::Candidate CreateLocalUdpCandidate(
161 const rtc::SocketAddress& address) {
162 cricket::Candidate candidate;
163 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
164 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
165 candidate.set_address(address);
166 candidate.set_type(cricket::LOCAL_PORT_TYPE);
167 return candidate;
168 }
169
170 // Remove all ICE ufrag/pwd lines from the given session description.
RemoveIceUfragPwd(SessionDescriptionInterface * sdesc)171 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
172 SetIceUfragPwd(sdesc, "", "");
173 }
174
175 // Sets all ICE ufrag/pwds on the given session description.
SetIceUfragPwd(SessionDescriptionInterface * sdesc,const std::string & ufrag,const std::string & pwd)176 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
177 const std::string& ufrag,
178 const std::string& pwd) {
179 auto* desc = sdesc->description();
180 for (const auto& content : desc->contents()) {
181 auto* transport_info = desc->GetTransportInfoByName(content.name);
182 transport_info->description.ice_ufrag = ufrag;
183 transport_info->description.ice_pwd = pwd;
184 }
185 }
186
187 // Set ICE mode on the given session description.
SetIceMode(SessionDescriptionInterface * sdesc,const cricket::IceMode ice_mode)188 void SetIceMode(SessionDescriptionInterface* sdesc,
189 const cricket::IceMode ice_mode) {
190 auto* desc = sdesc->description();
191 for (const auto& content : desc->contents()) {
192 auto* transport_info = desc->GetTransportInfoByName(content.name);
193 transport_info->description.ice_mode = ice_mode;
194 }
195 }
196
GetFirstTransportDescription(SessionDescriptionInterface * sdesc)197 cricket::TransportDescription* GetFirstTransportDescription(
198 SessionDescriptionInterface* sdesc) {
199 auto* desc = sdesc->description();
200 RTC_DCHECK(desc->contents().size() > 0);
201 auto* transport_info =
202 desc->GetTransportInfoByName(desc->contents()[0].name);
203 RTC_DCHECK(transport_info);
204 return &transport_info->description;
205 }
206
GetFirstTransportDescription(const SessionDescriptionInterface * sdesc)207 const cricket::TransportDescription* GetFirstTransportDescription(
208 const SessionDescriptionInterface* sdesc) {
209 auto* desc = sdesc->description();
210 RTC_DCHECK(desc->contents().size() > 0);
211 auto* transport_info =
212 desc->GetTransportInfoByName(desc->contents()[0].name);
213 RTC_DCHECK(transport_info);
214 return &transport_info->description;
215 }
216
217 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
218 // after it is implemented.
GetIceRole(const WrapperPtr & pc_wrapper_ptr)219 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
220 auto* pc_proxy =
221 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
222 pc_wrapper_ptr->pc());
223 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
224 for (const auto& transceiver : pc->GetTransceiversInternal()) {
225 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
226 auto dtls_transport = pc->LookupDtlsTransportByMidInternal(
227 transceiver->internal()->channel()->content_name());
228 return dtls_transport->ice_transport()->internal()->GetIceRole();
229 }
230 }
231 RTC_NOTREACHED();
232 return cricket::ICEROLE_UNKNOWN;
233 }
234
235 // Returns a list of (ufrag, pwd) pairs in the order that they appear in
236 // |description|, or the empty list if |description| is null.
GetIceCredentials(const SessionDescriptionInterface * description)237 std::vector<std::pair<std::string, std::string>> GetIceCredentials(
238 const SessionDescriptionInterface* description) {
239 std::vector<std::pair<std::string, std::string>> ice_credentials;
240 if (!description)
241 return ice_credentials;
242 const auto* desc = description->description();
243 for (const auto& content_info : desc->contents()) {
244 const auto* transport_info =
245 desc->GetTransportInfoByName(content_info.name);
246 if (transport_info) {
247 ice_credentials.push_back(
248 std::make_pair(transport_info->description.ice_ufrag,
249 transport_info->description.ice_pwd));
250 }
251 }
252 return ice_credentials;
253 }
254
AddCandidateToFirstTransport(cricket::Candidate * candidate,SessionDescriptionInterface * sdesc)255 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
256 SessionDescriptionInterface* sdesc) {
257 auto* desc = sdesc->description();
258 RTC_DCHECK(desc->contents().size() > 0);
259 const auto& first_content = desc->contents()[0];
260 candidate->set_transport_name(first_content.name);
261 std::unique_ptr<IceCandidateInterface> jsep_candidate =
262 CreateIceCandidate(first_content.name, 0, *candidate);
263 return sdesc->AddCandidate(jsep_candidate.get());
264 }
265
NewFakeNetwork()266 rtc::FakeNetworkManager* NewFakeNetwork() {
267 // The PeerConnection's port allocator is tied to the PeerConnection's
268 // lifetime and expects the underlying NetworkManager to outlive it. That
269 // prevents us from having the PeerConnectionWrapper own the fake network.
270 // Therefore, the test fixture will own all the fake networks even though
271 // tests should access the fake network through the PeerConnectionWrapper.
272 auto* fake_network = new rtc::FakeNetworkManager();
273 fake_networks_.emplace_back(fake_network);
274 return fake_network;
275 }
276
277 std::unique_ptr<rtc::VirtualSocketServer> vss_;
278 rtc::AutoSocketServerThread main_;
279 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
280 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
281 const SdpSemantics sdp_semantics_;
282 };
283
284 class PeerConnectionIceTest
285 : public PeerConnectionIceBaseTest,
286 public ::testing::WithParamInterface<SdpSemantics> {
287 protected:
PeerConnectionIceTest()288 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
289 webrtc::metrics::Reset();
290 }
291 };
292
AssertCandidatesEqual(const char * a_expr,const char * b_expr,const cricket::Candidate & a,const cricket::Candidate & b)293 ::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
294 const char* b_expr,
295 const cricket::Candidate& a,
296 const cricket::Candidate& b) {
297 rtc::StringBuilder failure_info;
298 if (a.component() != b.component()) {
299 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
300 }
301 if (a.protocol() != b.protocol()) {
302 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
303 }
304 if (a.address() != b.address()) {
305 failure_info << "\naddress: " << a.address().ToString()
306 << " != " << b.address().ToString();
307 }
308 if (a.type() != b.type()) {
309 failure_info << "\ntype: " << a.type() << " != " << b.type();
310 }
311 std::string failure_info_str = failure_info.str();
312 if (failure_info_str.empty()) {
313 return ::testing::AssertionSuccess();
314 } else {
315 return ::testing::AssertionFailure()
316 << a_expr << " and " << b_expr << " are not equal"
317 << failure_info_str;
318 }
319 }
320
TEST_P(PeerConnectionIceTest,OfferContainsGatheredCandidates)321 TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
322 const SocketAddress kLocalAddress("1.1.1.1", 0);
323
324 auto caller = CreatePeerConnectionWithAudioVideo();
325 caller->network()->AddInterface(kLocalAddress);
326
327 // Start ICE candidate gathering by setting the local offer.
328 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
329
330 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
331
332 auto offer = caller->CreateOffer();
333 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
334 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
335 offer->candidates(0)->count());
336 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
337 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
338 offer->candidates(1)->count());
339 }
340
TEST_P(PeerConnectionIceTest,AnswerContainsGatheredCandidates)341 TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
342 const SocketAddress kCallerAddress("1.1.1.1", 0);
343
344 auto caller = CreatePeerConnectionWithAudioVideo();
345 auto callee = CreatePeerConnectionWithAudioVideo();
346 caller->network()->AddInterface(kCallerAddress);
347
348 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
349 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
350
351 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
352
353 auto* answer = callee->pc()->local_description();
354 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
355 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
356 answer->candidates(0)->count());
357 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
358 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
359 answer->candidates(1)->count());
360 }
361
TEST_P(PeerConnectionIceTest,CanSetRemoteSessionDescriptionWithRemoteCandidates)362 TEST_P(PeerConnectionIceTest,
363 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
364 const SocketAddress kCallerAddress("1.1.1.1", 1111);
365
366 auto caller = CreatePeerConnectionWithAudioVideo();
367 auto callee = CreatePeerConnectionWithAudioVideo();
368
369 auto offer = caller->CreateOfferAndSetAsLocal();
370 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
371 AddCandidateToFirstTransport(&candidate, offer.get());
372
373 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
374 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
375 ASSERT_EQ(1u, remote_candidates.size());
376 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
377 remote_candidates[0]->candidate());
378 }
379
TEST_P(PeerConnectionIceTest,SetLocalDescriptionFailsIfNoIceCredentials)380 TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
381 auto caller = CreatePeerConnectionWithAudioVideo();
382
383 auto offer = caller->CreateOffer();
384 RemoveIceUfragPwd(offer.get());
385
386 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
387 }
388
TEST_P(PeerConnectionIceTest,SetRemoteDescriptionFailsIfNoIceCredentials)389 TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
390 auto caller = CreatePeerConnectionWithAudioVideo();
391 auto callee = CreatePeerConnectionWithAudioVideo();
392
393 auto offer = caller->CreateOfferAndSetAsLocal();
394 RemoveIceUfragPwd(offer.get());
395
396 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
397 }
398
399 // Test that doing an offer/answer exchange with no transport (i.e., no data
400 // channel or media) results in the ICE connection state staying at New.
TEST_P(PeerConnectionIceTest,OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState)401 TEST_P(PeerConnectionIceTest,
402 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
403 auto caller = CreatePeerConnection();
404 auto callee = CreatePeerConnection();
405
406 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
407
408 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
409 caller->pc()->ice_connection_state());
410 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
411 callee->pc()->ice_connection_state());
412 }
413
414 // The following group tests that ICE candidates are not generated before
415 // SetLocalDescription is called on a PeerConnection.
416
TEST_P(PeerConnectionIceTest,NoIceCandidatesBeforeSetLocalDescription)417 TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
418 const SocketAddress kLocalAddress("1.1.1.1", 0);
419
420 auto caller = CreatePeerConnectionWithAudioVideo();
421 caller->network()->AddInterface(kLocalAddress);
422
423 // Pump for 1 second and verify that no candidates are generated.
424 rtc::Thread::Current()->ProcessMessages(1000);
425
426 EXPECT_EQ(0u, caller->observer()->candidates_.size());
427 }
TEST_P(PeerConnectionIceTest,NoIceCandidatesBeforeAnswerSetAsLocalDescription)428 TEST_P(PeerConnectionIceTest,
429 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
430 const SocketAddress kCallerAddress("1.1.1.1", 1111);
431
432 auto caller = CreatePeerConnectionWithAudioVideo();
433 auto callee = CreatePeerConnectionWithAudioVideo();
434 caller->network()->AddInterface(kCallerAddress);
435
436 auto offer = caller->CreateOfferAndSetAsLocal();
437 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
438 AddCandidateToFirstTransport(&candidate, offer.get());
439 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
440
441 // Pump for 1 second and verify that no candidates are generated.
442 rtc::Thread::Current()->ProcessMessages(1000);
443
444 EXPECT_EQ(0u, callee->observer()->candidates_.size());
445 }
446
TEST_P(PeerConnectionIceTest,CannotAddCandidateWhenRemoteDescriptionNotSet)447 TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
448 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
449
450 auto caller = CreatePeerConnectionWithAudioVideo();
451 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
452 std::unique_ptr<IceCandidateInterface> jsep_candidate =
453 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
454
455 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
456
457 caller->CreateOfferAndSetAsLocal();
458
459 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
460 EXPECT_METRIC_THAT(
461 webrtc::metrics::Samples("WebRTC.PeerConnection.AddIceCandidate"),
462 ElementsAre(Pair(kAddIceCandidateFailNoRemoteDescription, 2)));
463 }
464
TEST_P(PeerConnectionIceTest,CannotAddCandidateWhenPeerConnectionClosed)465 TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
466 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
467
468 auto caller = CreatePeerConnectionWithAudioVideo();
469 auto callee = CreatePeerConnectionWithAudioVideo();
470
471 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
472
473 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
474 auto* audio_content = cricket::GetFirstAudioContent(
475 caller->pc()->local_description()->description());
476 std::unique_ptr<IceCandidateInterface> jsep_candidate =
477 CreateIceCandidate(audio_content->name, 0, candidate);
478
479 caller->pc()->Close();
480
481 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
482 }
483
TEST_P(PeerConnectionIceTest,DuplicateIceCandidateIgnoredWhenAdded)484 TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
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 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
495 caller->AddIceCandidate(&candidate);
496 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
497 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
498 }
499
TEST_P(PeerConnectionIceTest,CannotRemoveIceCandidatesWhenPeerConnectionClosed)500 TEST_P(PeerConnectionIceTest,
501 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
502 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
503
504 auto caller = CreatePeerConnectionWithAudioVideo();
505 auto callee = CreatePeerConnectionWithAudioVideo();
506
507 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
508
509 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
510 auto* audio_content = cricket::GetFirstAudioContent(
511 caller->pc()->local_description()->description());
512 std::unique_ptr<IceCandidateInterface> ice_candidate =
513 CreateIceCandidate(audio_content->name, 0, candidate);
514
515 ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
516
517 caller->pc()->Close();
518
519 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
520 }
521
TEST_P(PeerConnectionIceTest,AddRemoveCandidateWithEmptyTransportDoesNotCrash)522 TEST_P(PeerConnectionIceTest,
523 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
524 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
525
526 auto caller = CreatePeerConnectionWithAudioVideo();
527 auto callee = CreatePeerConnectionWithAudioVideo();
528
529 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
530 ASSERT_TRUE(
531 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
532
533 // |candidate.transport_name()| is empty.
534 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
535 auto* audio_content = cricket::GetFirstAudioContent(
536 caller->pc()->local_description()->description());
537 std::unique_ptr<IceCandidateInterface> ice_candidate =
538 CreateIceCandidate(audio_content->name, 0, candidate);
539 EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
540 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
541 }
542
TEST_P(PeerConnectionIceTest,RemoveCandidateRemovesFromRemoteDescription)543 TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
544 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
545
546 auto caller = CreatePeerConnectionWithAudioVideo();
547 auto callee = CreatePeerConnectionWithAudioVideo();
548
549 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
550 ASSERT_TRUE(
551 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
552
553 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
554 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
555 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
556 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
557 }
558
559 // Test that if a candidate is added via AddIceCandidate and via an updated
560 // remote description, then both candidates appear in the stored remote
561 // description.
TEST_P(PeerConnectionIceTest,CandidateInSubsequentOfferIsAddedToRemoteDescription)562 TEST_P(PeerConnectionIceTest,
563 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
564 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
565 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
566
567 auto caller = CreatePeerConnectionWithAudioVideo();
568 auto callee = CreatePeerConnectionWithAudioVideo();
569
570 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
571 ASSERT_TRUE(
572 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
573
574 // Add one candidate via |AddIceCandidate|.
575 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
576 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
577
578 // Add the second candidate via a reoffer.
579 auto offer = caller->CreateOffer();
580 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
581 AddCandidateToFirstTransport(&candidate2, offer.get());
582
583 // Expect both candidates to appear in the callee's remote description.
584 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
585 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
586 }
587
588 // The follow test verifies that SetLocal/RemoteDescription fails when an offer
589 // has either ICE ufrag/pwd too short or too long and succeeds otherwise.
590 // The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
591 // pwd must be 22-256 characters and ufrag must be 4-256 characters.
TEST_P(PeerConnectionIceTest,VerifyUfragPwdLength)592 TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
593 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
594 int pwd_len) {
595 auto pc = CreatePeerConnectionWithAudioVideo();
596 auto offer = pc->CreateOffer();
597 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
598 std::string(pwd_len, 'x'));
599 return pc->SetLocalDescription(std::move(offer));
600 };
601
602 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
603 int pwd_len) {
604 auto pc = CreatePeerConnectionWithAudioVideo();
605 auto offer = pc->CreateOffer();
606 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
607 std::string(pwd_len, 'x'));
608 return pc->SetRemoteDescription(std::move(offer));
609 };
610
611 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
612 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
613 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
614 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
615 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
616 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
617 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
618 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
619 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
620 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
621 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
622 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
623 }
624
AssertIpInCandidates(const char * address_expr,const char * candidates_expr,const SocketAddress & address,const std::vector<IceCandidateInterface * > candidates)625 ::testing::AssertionResult AssertIpInCandidates(
626 const char* address_expr,
627 const char* candidates_expr,
628 const SocketAddress& address,
629 const std::vector<IceCandidateInterface*> candidates) {
630 rtc::StringBuilder candidate_hosts;
631 for (const auto* candidate : candidates) {
632 const auto& candidate_ip = candidate->candidate().address().ipaddr();
633 if (candidate_ip == address.ipaddr()) {
634 return ::testing::AssertionSuccess();
635 }
636 candidate_hosts << "\n" << candidate_ip.ToString();
637 }
638 return ::testing::AssertionFailure()
639 << address_expr << " (host " << address.HostAsURIString()
640 << ") not in " << candidates_expr
641 << " which have the following address hosts:" << candidate_hosts.str();
642 }
643
TEST_P(PeerConnectionIceTest,CandidatesGeneratedForEachLocalInterface)644 TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
645 const SocketAddress kLocalAddress1("1.1.1.1", 0);
646 const SocketAddress kLocalAddress2("2.2.2.2", 0);
647
648 auto caller = CreatePeerConnectionWithAudioVideo();
649 caller->network()->AddInterface(kLocalAddress1);
650 caller->network()->AddInterface(kLocalAddress2);
651
652 caller->CreateOfferAndSetAsLocal();
653 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
654
655 auto candidates = caller->observer()->GetCandidatesByMline(0);
656 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
657 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
658 }
659
TEST_P(PeerConnectionIceTest,TrickledSingleCandidateAddedToRemoteDescription)660 TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
661 const SocketAddress kCallerAddress("1.1.1.1", 1111);
662
663 auto caller = CreatePeerConnectionWithAudioVideo();
664 auto callee = CreatePeerConnectionWithAudioVideo();
665
666 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
667
668 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
669 callee->AddIceCandidate(&candidate);
670 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
671 ASSERT_EQ(1u, candidates.size());
672 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
673 candidates[0]->candidate());
674 }
675
TEST_P(PeerConnectionIceTest,TwoTrickledCandidatesAddedToRemoteDescription)676 TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
677 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
678 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
679
680 auto caller = CreatePeerConnectionWithAudioVideo();
681 auto callee = CreatePeerConnectionWithAudioVideo();
682
683 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
684 ASSERT_TRUE(
685 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
686
687 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
688 caller->AddIceCandidate(&candidate1);
689
690 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
691 caller->AddIceCandidate(&candidate2);
692
693 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
694 ASSERT_EQ(2u, candidates.size());
695 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
696 candidates[0]->candidate());
697 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
698 candidates[1]->candidate());
699 }
700
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateIsAddedToRemoteDescription)701 TEST_P(PeerConnectionIceTest, AsyncAddIceCandidateIsAddedToRemoteDescription) {
702 auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
703
704 auto caller = CreatePeerConnectionWithAudioVideo();
705 auto callee = CreatePeerConnectionWithAudioVideo();
706
707 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
708
709 auto jsep_candidate =
710 callee->CreateJsepCandidateForFirstTransport(&candidate);
711 bool operation_completed = false;
712 callee->pc()->AddIceCandidate(std::move(jsep_candidate),
713 [&operation_completed](RTCError result) {
714 EXPECT_TRUE(result.ok());
715 operation_completed = true;
716 });
717 EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
718
719 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
720 ASSERT_EQ(1u, candidates.size());
721 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
722 candidates[0]->candidate());
723 }
724
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateCompletesImmediatelyIfNoPendingOperation)725 TEST_P(PeerConnectionIceTest,
726 AsyncAddIceCandidateCompletesImmediatelyIfNoPendingOperation) {
727 auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
728
729 auto caller = CreatePeerConnectionWithAudioVideo();
730 auto callee = CreatePeerConnectionWithAudioVideo();
731
732 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
733
734 auto jsep_candidate =
735 callee->CreateJsepCandidateForFirstTransport(&candidate);
736 bool operation_completed = false;
737 callee->pc()->AddIceCandidate(
738 std::move(jsep_candidate),
739 [&operation_completed](RTCError result) { operation_completed = true; });
740 EXPECT_TRUE(operation_completed);
741 }
742
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateCompletesWhenPendingOperationCompletes)743 TEST_P(PeerConnectionIceTest,
744 AsyncAddIceCandidateCompletesWhenPendingOperationCompletes) {
745 auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
746
747 auto caller = CreatePeerConnectionWithAudioVideo();
748 auto callee = CreatePeerConnectionWithAudioVideo();
749
750 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
751
752 // Chain an operation that will block AddIceCandidate() from executing.
753 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> answer_observer(
754 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
755 callee->pc()->CreateAnswer(answer_observer, RTCOfferAnswerOptions());
756
757 auto jsep_candidate =
758 callee->CreateJsepCandidateForFirstTransport(&candidate);
759 bool operation_completed = false;
760 callee->pc()->AddIceCandidate(
761 std::move(jsep_candidate),
762 [&operation_completed](RTCError result) { operation_completed = true; });
763 // The operation will not be able to complete until we EXPECT_TRUE_WAIT()
764 // allowing CreateAnswer() to complete.
765 EXPECT_FALSE(operation_completed);
766 EXPECT_TRUE_WAIT(answer_observer->called(), kWaitTimeout);
767 // As soon as it does, AddIceCandidate() will execute without delay, so it
768 // must also have completed.
769 EXPECT_TRUE(operation_completed);
770 }
771
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateFailsBeforeSetRemoteDescription)772 TEST_P(PeerConnectionIceTest,
773 AsyncAddIceCandidateFailsBeforeSetRemoteDescription) {
774 auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
775
776 auto caller = CreatePeerConnectionWithAudioVideo();
777 std::unique_ptr<IceCandidateInterface> jsep_candidate =
778 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
779
780 bool operation_completed = false;
781 caller->pc()->AddIceCandidate(
782 std::move(jsep_candidate), [&operation_completed](RTCError result) {
783 EXPECT_FALSE(result.ok());
784 EXPECT_EQ(result.message(),
785 std::string("Error processing ICE candidate"));
786 operation_completed = true;
787 });
788 EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
789 }
790
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateFailsIfPeerConnectionDestroyed)791 TEST_P(PeerConnectionIceTest,
792 AsyncAddIceCandidateFailsIfPeerConnectionDestroyed) {
793 auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
794
795 auto caller = CreatePeerConnectionWithAudioVideo();
796 auto callee = CreatePeerConnectionWithAudioVideo();
797
798 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
799
800 // Chain an operation that will block AddIceCandidate() from executing.
801 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> answer_observer(
802 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
803 callee->pc()->CreateAnswer(answer_observer, RTCOfferAnswerOptions());
804
805 auto jsep_candidate =
806 callee->CreateJsepCandidateForFirstTransport(&candidate);
807 bool operation_completed = false;
808 callee->pc()->AddIceCandidate(
809 std::move(jsep_candidate), [&operation_completed](RTCError result) {
810 EXPECT_FALSE(result.ok());
811 EXPECT_EQ(
812 result.message(),
813 std::string(
814 "AddIceCandidate failed because the session was shut down"));
815 operation_completed = true;
816 });
817 // The operation will not be able to run until EXPECT_TRUE_WAIT(), giving us
818 // time to remove all references to the PeerConnection.
819 EXPECT_FALSE(operation_completed);
820 // This should delete the callee PC.
821 callee = nullptr;
822 EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
823 }
824
TEST_P(PeerConnectionIceTest,LocalDescriptionUpdatedWhenContinualGathering)825 TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
826 const SocketAddress kLocalAddress("1.1.1.1", 0);
827
828 RTCConfiguration config;
829 config.continual_gathering_policy =
830 PeerConnectionInterface::GATHER_CONTINUALLY;
831 auto caller = CreatePeerConnectionWithAudioVideo(config);
832 caller->network()->AddInterface(kLocalAddress);
833
834 // Start ICE candidate gathering by setting the local offer.
835 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
836
837 // Since we're using continual gathering, we won't get "gathering done".
838 EXPECT_TRUE_WAIT(
839 caller->pc()->local_description()->candidates(0)->count() > 0,
840 kIceCandidatesTimeout);
841 }
842
843 // Test that when continual gathering is enabled, and a network interface goes
844 // down, the candidate is signaled as removed and removed from the local
845 // description.
TEST_P(PeerConnectionIceTest,LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually)846 TEST_P(PeerConnectionIceTest,
847 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
848 const SocketAddress kLocalAddress("1.1.1.1", 0);
849
850 RTCConfiguration config;
851 config.continual_gathering_policy =
852 PeerConnectionInterface::GATHER_CONTINUALLY;
853 auto caller = CreatePeerConnectionWithAudioVideo(config);
854 caller->network()->AddInterface(kLocalAddress);
855
856 // Start ICE candidate gathering by setting the local offer.
857 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
858
859 EXPECT_TRUE_WAIT(
860 caller->pc()->local_description()->candidates(0)->count() > 0,
861 kIceCandidatesTimeout);
862
863 // Remove the only network interface, causing the PeerConnection to signal
864 // the removal of all candidates derived from this interface.
865 caller->network()->RemoveInterface(kLocalAddress);
866
867 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
868 kIceCandidatesTimeout);
869 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
870 }
871
TEST_P(PeerConnectionIceTest,LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce)872 TEST_P(PeerConnectionIceTest,
873 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
874 const SocketAddress kLocalAddress("1.1.1.1", 0);
875
876 RTCConfiguration config;
877 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
878 auto caller = CreatePeerConnectionWithAudioVideo(config);
879 caller->network()->AddInterface(kLocalAddress);
880
881 // Start ICE candidate gathering by setting the local offer.
882 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
883
884 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
885
886 caller->network()->RemoveInterface(kLocalAddress);
887
888 // Verify that the local candidates are not removed;
889 rtc::Thread::Current()->ProcessMessages(1000);
890 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
891 }
892
893 // The following group tests that when an offer includes a new ufrag or pwd
894 // (indicating an ICE restart) the old candidates are removed and new candidates
895 // added to the remote description.
896
TEST_P(PeerConnectionIceTest,IceRestartOfferClearsExistingCandidate)897 TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
898 const SocketAddress kCallerAddress("1.1.1.1", 1111);
899
900 auto caller = CreatePeerConnectionWithAudioVideo();
901 auto callee = CreatePeerConnectionWithAudioVideo();
902
903 auto offer = caller->CreateOfferAndSetAsLocal();
904 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
905 AddCandidateToFirstTransport(&candidate, offer.get());
906
907 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
908
909 RTCOfferAnswerOptions options;
910 options.ice_restart = true;
911 ASSERT_TRUE(
912 callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
913
914 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
915 }
TEST_P(PeerConnectionIceTest,IceRestartOfferCandidateReplacesExistingCandidate)916 TEST_P(PeerConnectionIceTest,
917 IceRestartOfferCandidateReplacesExistingCandidate) {
918 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
919 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
920
921 auto caller = CreatePeerConnectionWithAudioVideo();
922 auto callee = CreatePeerConnectionWithAudioVideo();
923
924 auto offer = caller->CreateOfferAndSetAsLocal();
925 cricket::Candidate old_candidate =
926 CreateLocalUdpCandidate(kFirstCallerAddress);
927 AddCandidateToFirstTransport(&old_candidate, offer.get());
928
929 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
930
931 RTCOfferAnswerOptions options;
932 options.ice_restart = true;
933 auto restart_offer = caller->CreateOfferAndSetAsLocal(options);
934 cricket::Candidate new_candidate =
935 CreateLocalUdpCandidate(kRestartedCallerAddress);
936 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
937
938 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
939
940 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
941 ASSERT_EQ(1u, remote_candidates.size());
942 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
943 remote_candidates[0]->candidate());
944 }
945
946 // Test that if there is not an ICE restart (i.e., nothing changes), then the
947 // answer to a later offer should have the same ufrag/pwd as the first answer.
TEST_P(PeerConnectionIceTest,LaterAnswerHasSameIceCredentialsIfNoIceRestart)948 TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
949 auto caller = CreatePeerConnectionWithAudioVideo();
950 auto callee = CreatePeerConnectionWithAudioVideo();
951
952 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
953 ASSERT_TRUE(
954 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
955
956 // Re-offer.
957 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
958
959 auto answer = callee->CreateAnswer();
960 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
961 auto* local_transport_desc =
962 GetFirstTransportDescription(callee->pc()->local_description());
963
964 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
965 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
966 }
967
TEST_P(PeerConnectionIceTest,RestartIceGeneratesNewCredentials)968 TEST_P(PeerConnectionIceTest, RestartIceGeneratesNewCredentials) {
969 auto caller = CreatePeerConnectionWithAudioVideo();
970 auto callee = CreatePeerConnectionWithAudioVideo();
971
972 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
973 auto initial_ice_credentials =
974 GetIceCredentials(caller->pc()->local_description());
975 caller->pc()->RestartIce();
976 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
977 auto restarted_ice_credentials =
978 GetIceCredentials(caller->pc()->local_description());
979 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
980 }
981
TEST_P(PeerConnectionIceTest,RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer)982 TEST_P(PeerConnectionIceTest,
983 RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer) {
984 auto caller = CreatePeerConnectionWithAudioVideo();
985 auto callee = CreatePeerConnectionWithAudioVideo();
986
987 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
988 auto initial_ice_credentials =
989 GetIceCredentials(caller->pc()->local_description());
990 // ICE restart becomes needed while an O/A is pending and |caller| is the
991 // offerer.
992 caller->pc()->RestartIce();
993 ASSERT_TRUE(
994 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
995 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
996 auto restarted_ice_credentials =
997 GetIceCredentials(caller->pc()->local_description());
998 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
999 }
1000
TEST_P(PeerConnectionIceTest,RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer)1001 TEST_P(PeerConnectionIceTest,
1002 RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer) {
1003 auto caller = CreatePeerConnectionWithAudioVideo();
1004 auto callee = CreatePeerConnectionWithAudioVideo();
1005
1006 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1007 auto initial_ice_credentials =
1008 GetIceCredentials(caller->pc()->local_description());
1009 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
1010 // ICE restart becomes needed while an O/A is pending and |caller| is the
1011 // answerer.
1012 caller->pc()->RestartIce();
1013 ASSERT_TRUE(
1014 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
1015 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
1016 auto restarted_ice_credentials =
1017 GetIceCredentials(caller->pc()->local_description());
1018 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1019 }
1020
TEST_P(PeerConnectionIceTest,RestartIceTriggeredByRemoteSide)1021 TEST_P(PeerConnectionIceTest, RestartIceTriggeredByRemoteSide) {
1022 auto caller = CreatePeerConnectionWithAudioVideo();
1023 auto callee = CreatePeerConnectionWithAudioVideo();
1024
1025 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1026 auto initial_ice_credentials =
1027 GetIceCredentials(caller->pc()->local_description());
1028
1029 // Remote restart and O/A exchange with |caller| as the answerer should
1030 // restart ICE locally as well.
1031 callee->pc()->RestartIce();
1032 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1033
1034 auto restarted_ice_credentials =
1035 GetIceCredentials(caller->pc()->local_description());
1036 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1037 }
1038
TEST_P(PeerConnectionIceTest,RestartIceCausesNegotiationNeeded)1039 TEST_P(PeerConnectionIceTest, RestartIceCausesNegotiationNeeded) {
1040 auto caller = CreatePeerConnectionWithAudioVideo();
1041 auto callee = CreatePeerConnectionWithAudioVideo();
1042
1043 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1044 caller->observer()->clear_negotiation_needed();
1045 caller->pc()->RestartIce();
1046 EXPECT_TRUE(caller->observer()->negotiation_needed());
1047 }
1048
1049 // In Unified Plan, "onnegotiationneeded" is spec-compliant, including not
1050 // firing multipe times in a row, or firing when returning to the stable
1051 // signaling state if negotiation is still needed. In Plan B it fires any time
1052 // something changes. As such, some tests are SdpSemantics-specific.
1053 class PeerConnectionIceTestUnifiedPlan : public PeerConnectionIceBaseTest {
1054 protected:
PeerConnectionIceTestUnifiedPlan()1055 PeerConnectionIceTestUnifiedPlan()
1056 : PeerConnectionIceBaseTest(SdpSemantics::kUnifiedPlan) {}
1057 };
1058
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable)1059 TEST_F(PeerConnectionIceTestUnifiedPlan,
1060 RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable) {
1061 auto caller = CreatePeerConnectionWithAudioVideo();
1062 auto callee = CreatePeerConnectionWithAudioVideo();
1063
1064 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1065 // ICE restart becomes needed while an O/A is pending and |caller| is the
1066 // offerer.
1067 caller->observer()->clear_negotiation_needed();
1068 caller->pc()->RestartIce();
1069 // In Unified Plan, the event should not fire until we are back in the stable
1070 // signaling state.
1071 EXPECT_FALSE(caller->observer()->negotiation_needed());
1072 ASSERT_TRUE(
1073 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1074 EXPECT_TRUE(caller->observer()->negotiation_needed());
1075 }
1076
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable)1077 TEST_F(PeerConnectionIceTestUnifiedPlan,
1078 RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable) {
1079 auto caller = CreatePeerConnectionWithAudioVideo();
1080 auto callee = CreatePeerConnectionWithAudioVideo();
1081
1082 // Establish initial credentials as the caller.
1083 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1084 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
1085 // ICE restart becomes needed while an O/A is pending and |caller| is the
1086 // answerer.
1087 caller->observer()->clear_negotiation_needed();
1088 caller->pc()->RestartIce();
1089 // In Unified Plan, the event should not fire until we are back in the stable
1090 // signaling state.
1091 EXPECT_FALSE(caller->observer()->negotiation_needed());
1092 ASSERT_TRUE(
1093 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
1094 EXPECT_TRUE(caller->observer()->negotiation_needed());
1095 }
1096
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded)1097 TEST_F(PeerConnectionIceTestUnifiedPlan,
1098 RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded) {
1099 auto caller = CreatePeerConnectionWithAudioVideo();
1100 auto callee = CreatePeerConnectionWithAudioVideo();
1101
1102 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1103 // Local restart.
1104 caller->pc()->RestartIce();
1105 caller->observer()->clear_negotiation_needed();
1106 // Remote restart and O/A exchange with |caller| as the answerer should
1107 // restart ICE locally as well.
1108 callee->pc()->RestartIce();
1109 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1110 // Having restarted ICE by the remote offer, we do not need to renegotiate ICE
1111 // credentials when back in the stable signaling state.
1112 EXPECT_FALSE(caller->observer()->negotiation_needed());
1113 }
1114
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceTwiceDoesNotFireNegotiationNeededTwice)1115 TEST_F(PeerConnectionIceTestUnifiedPlan,
1116 RestartIceTwiceDoesNotFireNegotiationNeededTwice) {
1117 auto caller = CreatePeerConnectionWithAudioVideo();
1118 auto callee = CreatePeerConnectionWithAudioVideo();
1119
1120 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1121 caller->pc()->RestartIce();
1122 EXPECT_TRUE(caller->observer()->negotiation_needed());
1123 caller->observer()->clear_negotiation_needed();
1124 caller->pc()->RestartIce();
1125 EXPECT_FALSE(caller->observer()->negotiation_needed());
1126 }
1127
1128 // In Plan B, "onnegotiationneeded" is not spec-compliant, firing based on if
1129 // something changed rather than if negotiation is needed. In Unified Plan it
1130 // fires according to spec. As such, some tests are SdpSemantics-specific.
1131 class PeerConnectionIceTestPlanB : public PeerConnectionIceBaseTest {
1132 protected:
PeerConnectionIceTestPlanB()1133 PeerConnectionIceTestPlanB()
1134 : PeerConnectionIceBaseTest(SdpSemantics::kPlanB) {}
1135 };
1136
TEST_F(PeerConnectionIceTestPlanB,RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately)1137 TEST_F(PeerConnectionIceTestPlanB,
1138 RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately) {
1139 auto caller = CreatePeerConnectionWithAudioVideo();
1140 auto callee = CreatePeerConnectionWithAudioVideo();
1141
1142 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1143 caller->observer()->clear_negotiation_needed();
1144 caller->pc()->RestartIce();
1145 EXPECT_TRUE(caller->observer()->negotiation_needed());
1146 caller->observer()->clear_negotiation_needed();
1147 ASSERT_TRUE(
1148 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1149 // In Plan B, the event fired early so we don't expect it to fire now. This is
1150 // not spec-compliant but follows the pattern of existing Plan B behavior.
1151 EXPECT_FALSE(caller->observer()->negotiation_needed());
1152 }
1153
TEST_F(PeerConnectionIceTestPlanB,RestartIceTwiceDoesFireNegotiationNeededTwice)1154 TEST_F(PeerConnectionIceTestPlanB,
1155 RestartIceTwiceDoesFireNegotiationNeededTwice) {
1156 auto caller = CreatePeerConnectionWithAudioVideo();
1157 auto callee = CreatePeerConnectionWithAudioVideo();
1158
1159 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1160 caller->observer()->clear_negotiation_needed();
1161 caller->pc()->RestartIce();
1162 EXPECT_TRUE(caller->observer()->negotiation_needed());
1163 caller->observer()->clear_negotiation_needed();
1164 caller->pc()->RestartIce();
1165 // In Plan B, the event fires every time something changed, even if we have
1166 // already fired the event. This is not spec-compliant but follows the same
1167 // pattern of existing Plan B behavior.
1168 EXPECT_TRUE(caller->observer()->negotiation_needed());
1169 }
1170
1171 // The following parameterized test verifies that if an offer is sent with a
1172 // modified ICE ufrag and/or ICE pwd, then the answer should identify that the
1173 // other side has initiated an ICE restart and generate a new ufrag and pwd.
1174 // RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
1175 // a=ice-pwd attributes compared to the previous SDP from the peer, it
1176 // indicates that ICE is restarting for this media stream."
1177
1178 class PeerConnectionIceUfragPwdAnswerTest
1179 : public PeerConnectionIceBaseTest,
1180 public ::testing::WithParamInterface<
1181 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
1182 protected:
PeerConnectionIceUfragPwdAnswerTest()1183 PeerConnectionIceUfragPwdAnswerTest()
1184 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
1185 auto param = std::get<1>(GetParam());
1186 offer_new_ufrag_ = std::get<0>(param);
1187 offer_new_pwd_ = std::get<1>(param);
1188 }
1189
1190 bool offer_new_ufrag_;
1191 bool offer_new_pwd_;
1192 };
1193
TEST_P(PeerConnectionIceUfragPwdAnswerTest,TestIncludedInAnswer)1194 TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
1195 auto caller = CreatePeerConnectionWithAudioVideo();
1196 auto callee = CreatePeerConnectionWithAudioVideo();
1197
1198 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1199 ASSERT_TRUE(
1200 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1201
1202 auto offer = caller->CreateOffer();
1203 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1204 if (offer_new_ufrag_) {
1205 offer_transport_desc->ice_ufrag += "+new";
1206 }
1207 if (offer_new_pwd_) {
1208 offer_transport_desc->ice_pwd += "+new";
1209 }
1210
1211 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1212
1213 auto answer = callee->CreateAnswer();
1214 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
1215 auto* local_transport_desc =
1216 GetFirstTransportDescription(callee->pc()->local_description());
1217
1218 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
1219 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
1220 }
1221
1222 INSTANTIATE_TEST_SUITE_P(
1223 PeerConnectionIceTest,
1224 PeerConnectionIceUfragPwdAnswerTest,
1225 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
1226 Values(std::make_pair(true, true), // Both changed.
1227 std::make_pair(true, false), // Only ufrag changed.
1228 std::make_pair(false, true)))); // Only pwd changed.
1229
1230 // Test that if an ICE restart is offered on one media section, then the answer
1231 // will only change ICE ufrag/pwd for that section and keep the other sections
1232 // the same.
1233 // Note that this only works if we have disabled BUNDLE, otherwise all media
1234 // sections will share the same transport.
TEST_P(PeerConnectionIceTest,CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted)1235 TEST_P(PeerConnectionIceTest,
1236 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
1237 auto caller = CreatePeerConnectionWithAudioVideo();
1238 auto callee = CreatePeerConnectionWithAudioVideo();
1239
1240 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1241 ASSERT_TRUE(
1242 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1243
1244 RTCOfferAnswerOptions disable_bundle_options;
1245 disable_bundle_options.use_rtp_mux = false;
1246
1247 auto offer = caller->CreateOffer(disable_bundle_options);
1248
1249 // Signal ICE restart on the first media section.
1250 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1251 offer_transport_desc->ice_ufrag += "+new";
1252 offer_transport_desc->ice_pwd += "+new";
1253
1254 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1255
1256 auto answer = callee->CreateAnswer(disable_bundle_options);
1257 const auto& answer_transports = answer->description()->transport_infos();
1258 const auto& local_transports =
1259 callee->pc()->local_description()->description()->transport_infos();
1260
1261 EXPECT_NE(answer_transports[0].description.ice_ufrag,
1262 local_transports[0].description.ice_ufrag);
1263 EXPECT_NE(answer_transports[0].description.ice_pwd,
1264 local_transports[0].description.ice_pwd);
1265 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
1266 local_transports[1].description.ice_ufrag);
1267 EXPECT_EQ(answer_transports[1].description.ice_pwd,
1268 local_transports[1].description.ice_pwd);
1269 }
1270
1271 // Test that when the initial offerer (caller) uses the lite implementation of
1272 // ICE and the callee uses the full implementation, the caller takes the
1273 // CONTROLLED role and the callee takes the CONTROLLING role. This is specified
1274 // in RFC5245 Section 5.1.1.
TEST_P(PeerConnectionIceTest,OfferFromLiteIceControlledAndAnswerFromFullIceControlling)1275 TEST_P(PeerConnectionIceTest,
1276 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
1277 auto caller = CreatePeerConnectionWithAudioVideo();
1278 auto callee = CreatePeerConnectionWithAudioVideo();
1279
1280 auto offer = caller->CreateOffer();
1281 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1282 ASSERT_TRUE(
1283 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1284 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1285
1286 auto answer = callee->CreateAnswer();
1287 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
1288 ASSERT_TRUE(
1289 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1290 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1291
1292 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
1293 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
1294 }
1295
1296 // Test that when the caller and the callee both use the lite implementation of
1297 // ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
1298 // takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
TEST_P(PeerConnectionIceTest,OfferFromLiteIceControllingAndAnswerFromLiteIceControlled)1299 TEST_P(PeerConnectionIceTest,
1300 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
1301 auto caller = CreatePeerConnectionWithAudioVideo();
1302 auto callee = CreatePeerConnectionWithAudioVideo();
1303
1304 auto offer = caller->CreateOffer();
1305 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1306 ASSERT_TRUE(
1307 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1308 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1309
1310 auto answer = callee->CreateAnswer();
1311 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
1312 ASSERT_TRUE(
1313 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1314 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1315
1316 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
1317 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
1318 }
1319
1320 INSTANTIATE_TEST_SUITE_P(PeerConnectionIceTest,
1321 PeerConnectionIceTest,
1322 Values(SdpSemantics::kPlanB,
1323 SdpSemantics::kUnifiedPlan));
1324
1325 class PeerConnectionIceConfigTest : public ::testing::Test {
1326 protected:
SetUp()1327 void SetUp() override {
1328 pc_factory_ = CreatePeerConnectionFactory(
1329 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
1330 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
1331 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
1332 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
1333 nullptr /* audio_processing */);
1334 }
CreatePeerConnection(const RTCConfiguration & config)1335 void CreatePeerConnection(const RTCConfiguration& config) {
1336 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
1337 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
1338 port_allocator_ = port_allocator.get();
1339 rtc::scoped_refptr<PeerConnectionInterface> pc(
1340 pc_factory_->CreatePeerConnection(config, std::move(port_allocator),
1341 nullptr /* cert_generator */,
1342 &observer_));
1343 EXPECT_TRUE(pc.get());
1344 pc_ = std::move(pc);
1345 }
1346
1347 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
1348 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
1349 cricket::FakePortAllocator* port_allocator_ = nullptr;
1350
1351 MockPeerConnectionObserver observer_;
1352 };
1353
TEST_F(PeerConnectionIceConfigTest,SetStunCandidateKeepaliveInterval)1354 TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
1355 RTCConfiguration config;
1356 config.stun_candidate_keepalive_interval = 123;
1357 config.ice_candidate_pool_size = 1;
1358 CreatePeerConnection(config);
1359 ASSERT_NE(port_allocator_, nullptr);
1360 absl::optional<int> actual_stun_keepalive_interval =
1361 port_allocator_->stun_candidate_keepalive_interval();
1362 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1363 config.stun_candidate_keepalive_interval = 321;
1364 ASSERT_TRUE(pc_->SetConfiguration(config).ok());
1365 actual_stun_keepalive_interval =
1366 port_allocator_->stun_candidate_keepalive_interval();
1367 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1368 }
1369
TEST_P(PeerConnectionIceTest,IceCredentialsCreateOffer)1370 TEST_P(PeerConnectionIceTest, IceCredentialsCreateOffer) {
1371 RTCConfiguration config;
1372 config.ice_candidate_pool_size = 1;
1373 auto pc = CreatePeerConnectionWithAudioVideo(config);
1374 ASSERT_NE(pc->port_allocator_, nullptr);
1375 auto offer = pc->CreateOffer();
1376 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1377 ASSERT_EQ(1u, credentials.size());
1378
1379 auto* desc = offer->description();
1380 for (const auto& content : desc->contents()) {
1381 auto* transport_info = desc->GetTransportInfoByName(content.name);
1382 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1383 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1384 }
1385 }
1386
TEST_P(PeerConnectionIceTest,IceCredentialsCreateAnswer)1387 TEST_P(PeerConnectionIceTest, IceCredentialsCreateAnswer) {
1388 RTCConfiguration config;
1389 config.ice_candidate_pool_size = 1;
1390 auto pc = CreatePeerConnectionWithAudioVideo(config);
1391 ASSERT_NE(pc->port_allocator_, nullptr);
1392 auto offer = pc->CreateOffer();
1393 ASSERT_TRUE(pc->SetRemoteDescription(std::move(offer)));
1394 auto answer = pc->CreateAnswer();
1395
1396 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1397 ASSERT_EQ(1u, credentials.size());
1398
1399 auto* desc = answer->description();
1400 for (const auto& content : desc->contents()) {
1401 auto* transport_info = desc->GetTransportInfoByName(content.name);
1402 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1403 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1404 }
1405 }
1406
1407 // Regression test for https://bugs.chromium.org/p/webrtc/issues/detail?id=4728
TEST_P(PeerConnectionIceTest,CloseDoesNotTransitionGatheringStateToComplete)1408 TEST_P(PeerConnectionIceTest, CloseDoesNotTransitionGatheringStateToComplete) {
1409 auto pc = CreatePeerConnectionWithAudioVideo();
1410 pc->pc()->Close();
1411 EXPECT_FALSE(pc->IsIceGatheringDone());
1412 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1413 pc->pc()->ice_gathering_state());
1414 }
1415
1416 } // namespace webrtc
1417