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