blob: 1f8213ec29696faecee208fa6fe9042814bcfddd [file] [log] [blame]
Steve Antonf1c6db12017-10-13 11:13:35 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "p2p/base/fakeportallocator.h"
12#include "p2p/base/teststunserver.h"
13#include "p2p/client/basicportallocator.h"
14#include "pc/mediasession.h"
Qingsi Wange1692722017-11-29 13:27:20 -080015#include "pc/peerconnection.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070016#include "pc/peerconnectionwrapper.h"
17#include "pc/sdputils.h"
18#ifdef WEBRTC_ANDROID
19#include "pc/test/androidtestinitializer.h"
20#endif
Karl Wiberg1b0eae32017-10-17 14:48:54 +020021#include "api/audio_codecs/builtin_audio_decoder_factory.h"
22#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Qingsi Wange1692722017-11-29 13:27:20 -080023#include "api/peerconnectionproxy.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070024#include "pc/test/fakeaudiocapturemodule.h"
25#include "rtc_base/fakenetwork.h"
26#include "rtc_base/gunit.h"
27#include "rtc_base/ptr_util.h"
28#include "rtc_base/virtualsocketserver.h"
29
30namespace webrtc {
31
32using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
33using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
34using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080035using ::testing::Combine;
Steve Antonf1c6db12017-10-13 11:13:35 -070036using ::testing::Values;
37
38constexpr int kIceCandidatesTimeout = 10000;
39
Steve Anton46d926a2018-01-23 10:23:06 -080040class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070041 public:
42 using PeerConnectionWrapper::PeerConnectionWrapper;
43
44 // Adds a new ICE candidate to the first transport.
45 bool AddIceCandidate(cricket::Candidate* candidate) {
46 RTC_DCHECK(pc()->remote_description());
47 const auto* desc = pc()->remote_description()->description();
48 RTC_DCHECK(desc->contents().size() > 0);
49 const auto& first_content = desc->contents()[0];
50 candidate->set_transport_name(first_content.name);
51 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
52 return pc()->AddIceCandidate(&jsep_candidate);
53 }
54
55 // Returns ICE candidates from the remote session description.
56 std::vector<const IceCandidateInterface*>
57 GetIceCandidatesFromRemoteDescription() {
58 const SessionDescriptionInterface* sdesc = pc()->remote_description();
59 RTC_DCHECK(sdesc);
60 std::vector<const IceCandidateInterface*> candidates;
61 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
62 mline_index++) {
63 const auto* candidate_collection = sdesc->candidates(mline_index);
64 for (size_t i = 0; i < candidate_collection->count(); i++) {
65 candidates.push_back(candidate_collection->at(i));
66 }
67 }
68 return candidates;
69 }
70
71 rtc::FakeNetworkManager* network() { return network_; }
72
73 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
74
75 private:
76 rtc::FakeNetworkManager* network_;
77};
78
Steve Anton46d926a2018-01-23 10:23:06 -080079class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070080 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080081 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070082
Steve Anton46d926a2018-01-23 10:23:06 -080083 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
84 : vss_(new rtc::VirtualSocketServer()),
85 main_(vss_.get()),
86 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -070087#ifdef WEBRTC_ANDROID
88 InitializeAndroidObjects();
89#endif
90 pc_factory_ = CreatePeerConnectionFactory(
91 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Karl Wiberg1b0eae32017-10-17 14:48:54 +020092 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
93 CreateBuiltinAudioDecoderFactory(), nullptr, nullptr);
Steve Antonf1c6db12017-10-13 11:13:35 -070094 }
95
96 WrapperPtr CreatePeerConnection() {
97 return CreatePeerConnection(RTCConfiguration());
98 }
99
100 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
101 auto* fake_network = NewFakeNetwork();
102 auto port_allocator =
103 rtc::MakeUnique<cricket::BasicPortAllocator>(fake_network);
104 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
105 cricket::PORTALLOCATOR_DISABLE_RELAY);
106 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800107 RTCConfiguration modified_config = config;
108 modified_config.sdp_semantics = sdp_semantics_;
Steve Antonf1c6db12017-10-13 11:13:35 -0700109 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
110 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800111 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700112 if (!pc) {
113 return nullptr;
114 }
115
Steve Anton46d926a2018-01-23 10:23:06 -0800116 auto wrapper = rtc::MakeUnique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700117 pc_factory_, pc, std::move(observer));
118 wrapper->set_network(fake_network);
119 return wrapper;
120 }
121
122 // Accepts the same arguments as CreatePeerConnection and adds default audio
123 // and video tracks.
124 template <typename... Args>
125 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
126 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
127 if (!wrapper) {
128 return nullptr;
129 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700130 wrapper->AddAudioTrack("a");
131 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700132 return wrapper;
133 }
134
135 cricket::Candidate CreateLocalUdpCandidate(
136 const rtc::SocketAddress& address) {
137 cricket::Candidate candidate;
138 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
139 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
140 candidate.set_address(address);
141 candidate.set_type(cricket::LOCAL_PORT_TYPE);
142 return candidate;
143 }
144
145 // Remove all ICE ufrag/pwd lines from the given session description.
146 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
147 SetIceUfragPwd(sdesc, "", "");
148 }
149
150 // Sets all ICE ufrag/pwds on the given session description.
151 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
152 const std::string& ufrag,
153 const std::string& pwd) {
154 auto* desc = sdesc->description();
155 for (const auto& content : desc->contents()) {
156 auto* transport_info = desc->GetTransportInfoByName(content.name);
157 transport_info->description.ice_ufrag = ufrag;
158 transport_info->description.ice_pwd = pwd;
159 }
160 }
161
Qingsi Wange1692722017-11-29 13:27:20 -0800162 // Set ICE mode on the given session description.
163 void SetIceMode(SessionDescriptionInterface* sdesc,
164 const cricket::IceMode ice_mode) {
165 auto* desc = sdesc->description();
166 for (const auto& content : desc->contents()) {
167 auto* transport_info = desc->GetTransportInfoByName(content.name);
168 transport_info->description.ice_mode = ice_mode;
169 }
170 }
171
Steve Antonf1c6db12017-10-13 11:13:35 -0700172 cricket::TransportDescription* GetFirstTransportDescription(
173 SessionDescriptionInterface* sdesc) {
174 auto* desc = sdesc->description();
175 RTC_DCHECK(desc->contents().size() > 0);
176 auto* transport_info =
177 desc->GetTransportInfoByName(desc->contents()[0].name);
178 RTC_DCHECK(transport_info);
179 return &transport_info->description;
180 }
181
182 const cricket::TransportDescription* GetFirstTransportDescription(
183 const SessionDescriptionInterface* sdesc) {
184 auto* desc = sdesc->description();
185 RTC_DCHECK(desc->contents().size() > 0);
186 auto* transport_info =
187 desc->GetTransportInfoByName(desc->contents()[0].name);
188 RTC_DCHECK(transport_info);
189 return &transport_info->description;
190 }
191
Qingsi Wange1692722017-11-29 13:27:20 -0800192 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
193 // after it is implemented.
194 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100195 auto* pc_proxy =
196 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
197 pc_wrapper_ptr->pc());
198 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Steve Antonb8867112018-02-13 10:07:54 -0800199 for (auto transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800200 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton46d926a2018-01-23 10:23:06 -0800201 cricket::BaseChannel* channel = transceiver->internal()->channel();
202 if (channel) {
Zhi Huange830e682018-03-30 10:48:35 -0700203 auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
204 channel->rtp_packet_transport());
205 return dtls_transport->ice_transport()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800206 }
207 }
208 }
209 RTC_NOTREACHED();
210 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800211 }
212
Steve Antonf1c6db12017-10-13 11:13:35 -0700213 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
214 SessionDescriptionInterface* sdesc) {
215 auto* desc = sdesc->description();
216 RTC_DCHECK(desc->contents().size() > 0);
217 const auto& first_content = desc->contents()[0];
218 candidate->set_transport_name(first_content.name);
219 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
220 return sdesc->AddCandidate(&jsep_candidate);
221 }
222
223 rtc::FakeNetworkManager* NewFakeNetwork() {
224 // The PeerConnection's port allocator is tied to the PeerConnection's
225 // lifetime and expects the underlying NetworkManager to outlive it. That
226 // prevents us from having the PeerConnectionWrapper own the fake network.
227 // Therefore, the test fixture will own all the fake networks even though
228 // tests should access the fake network through the PeerConnectionWrapper.
229 auto* fake_network = new rtc::FakeNetworkManager();
230 fake_networks_.emplace_back(fake_network);
231 return fake_network;
232 }
233
234 std::unique_ptr<rtc::VirtualSocketServer> vss_;
235 rtc::AutoSocketServerThread main_;
236 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
237 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800238 const SdpSemantics sdp_semantics_;
239};
240
241class PeerConnectionIceTest
242 : public PeerConnectionIceBaseTest,
243 public ::testing::WithParamInterface<SdpSemantics> {
244 protected:
245 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {}
Steve Antonf1c6db12017-10-13 11:13:35 -0700246};
247
248::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
249 const char* b_expr,
250 const cricket::Candidate& a,
251 const cricket::Candidate& b) {
252 std::stringstream failure_info;
253 if (a.component() != b.component()) {
254 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
255 }
256 if (a.protocol() != b.protocol()) {
257 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
258 }
259 if (a.address() != b.address()) {
260 failure_info << "\naddress: " << a.address().ToString()
261 << " != " << b.address().ToString();
262 }
263 if (a.type() != b.type()) {
264 failure_info << "\ntype: " << a.type() << " != " << b.type();
265 }
266 std::string failure_info_str = failure_info.str();
267 if (failure_info_str.empty()) {
268 return ::testing::AssertionSuccess();
269 } else {
270 return ::testing::AssertionFailure()
271 << a_expr << " and " << b_expr << " are not equal"
272 << failure_info_str;
273 }
274}
275
Steve Anton46d926a2018-01-23 10:23:06 -0800276TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700277 const SocketAddress kLocalAddress("1.1.1.1", 0);
278
279 auto caller = CreatePeerConnectionWithAudioVideo();
280 caller->network()->AddInterface(kLocalAddress);
281
282 // Start ICE candidate gathering by setting the local offer.
283 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
284
285 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
286
287 auto offer = caller->CreateOffer();
288 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
289 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
290 offer->candidates(0)->count());
291 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
292 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
293 offer->candidates(1)->count());
294}
295
Steve Anton46d926a2018-01-23 10:23:06 -0800296TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700297 const SocketAddress kCallerAddress("1.1.1.1", 0);
298
299 auto caller = CreatePeerConnectionWithAudioVideo();
300 auto callee = CreatePeerConnectionWithAudioVideo();
301 caller->network()->AddInterface(kCallerAddress);
302
303 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
304 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
305
306 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
307
Steve Antondffead82018-02-06 10:31:29 -0800308 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700309 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
310 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
311 answer->candidates(0)->count());
312 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
313 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
314 answer->candidates(1)->count());
315}
316
Steve Anton46d926a2018-01-23 10:23:06 -0800317TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700318 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
319 const SocketAddress kCallerAddress("1.1.1.1", 1111);
320
321 auto caller = CreatePeerConnectionWithAudioVideo();
322 auto callee = CreatePeerConnectionWithAudioVideo();
323
324 auto offer = caller->CreateOfferAndSetAsLocal();
325 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
326 AddCandidateToFirstTransport(&candidate, offer.get());
327
328 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
329 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
330 ASSERT_EQ(1u, remote_candidates.size());
331 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
332 remote_candidates[0]->candidate());
333}
334
Steve Anton46d926a2018-01-23 10:23:06 -0800335TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700336 auto caller = CreatePeerConnectionWithAudioVideo();
337
338 auto offer = caller->CreateOffer();
339 RemoveIceUfragPwd(offer.get());
340
341 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
342}
343
Steve Anton46d926a2018-01-23 10:23:06 -0800344TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700345 auto caller = CreatePeerConnectionWithAudioVideo();
346 auto callee = CreatePeerConnectionWithAudioVideo();
347
348 auto offer = caller->CreateOfferAndSetAsLocal();
349 RemoveIceUfragPwd(offer.get());
350
351 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
352}
353
Steve Antonf764cf42018-05-01 14:32:17 -0700354// Test that doing an offer/answer exchange with no transport (i.e., no data
355// channel or media) results in the ICE connection state staying at New.
356TEST_P(PeerConnectionIceTest,
357 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
358 auto caller = CreatePeerConnection();
359 auto callee = CreatePeerConnection();
360
361 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
362
363 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
364 caller->pc()->ice_connection_state());
365 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
366 callee->pc()->ice_connection_state());
367}
368
Steve Antonf1c6db12017-10-13 11:13:35 -0700369// The following group tests that ICE candidates are not generated before
370// SetLocalDescription is called on a PeerConnection.
371
Steve Anton46d926a2018-01-23 10:23:06 -0800372TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700373 const SocketAddress kLocalAddress("1.1.1.1", 0);
374
375 auto caller = CreatePeerConnectionWithAudioVideo();
376 caller->network()->AddInterface(kLocalAddress);
377
378 // Pump for 1 second and verify that no candidates are generated.
379 rtc::Thread::Current()->ProcessMessages(1000);
380
381 EXPECT_EQ(0u, caller->observer()->candidates_.size());
382}
Steve Anton46d926a2018-01-23 10:23:06 -0800383TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700384 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
385 const SocketAddress kCallerAddress("1.1.1.1", 1111);
386
387 auto caller = CreatePeerConnectionWithAudioVideo();
388 auto callee = CreatePeerConnectionWithAudioVideo();
389 caller->network()->AddInterface(kCallerAddress);
390
391 auto offer = caller->CreateOfferAndSetAsLocal();
392 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
393 AddCandidateToFirstTransport(&candidate, offer.get());
394 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
395
396 // Pump for 1 second and verify that no candidates are generated.
397 rtc::Thread::Current()->ProcessMessages(1000);
398
399 EXPECT_EQ(0u, callee->observer()->candidates_.size());
400}
401
Steve Anton46d926a2018-01-23 10:23:06 -0800402TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700403 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
404
405 auto caller = CreatePeerConnectionWithAudioVideo();
406 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
407 JsepIceCandidate jsep_candidate(cricket::CN_AUDIO, 0, candidate);
408
409 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
410
411 caller->CreateOfferAndSetAsLocal();
412
413 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
414}
415
Steve Antonc79268f2018-04-24 09:54:10 -0700416TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
417 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
418
419 auto caller = CreatePeerConnectionWithAudioVideo();
420 auto callee = CreatePeerConnectionWithAudioVideo();
421
422 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
423
424 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
425 auto* audio_content = cricket::GetFirstAudioContent(
426 caller->pc()->local_description()->description());
427 JsepIceCandidate jsep_candidate(audio_content->name, 0, candidate);
428
429 caller->pc()->Close();
430
431 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
432}
433
Steve Anton46d926a2018-01-23 10:23:06 -0800434TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700435 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
436
437 auto caller = CreatePeerConnectionWithAudioVideo();
438 auto callee = CreatePeerConnectionWithAudioVideo();
439
440 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
441 ASSERT_TRUE(
442 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
443
444 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
445 caller->AddIceCandidate(&candidate);
446 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
447 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
448}
449
Steve Anton46d926a2018-01-23 10:23:06 -0800450TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700451 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
452 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
453
454 auto caller = CreatePeerConnectionWithAudioVideo();
455 auto callee = CreatePeerConnectionWithAudioVideo();
456
457 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
458
459 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
460 auto* audio_content = cricket::GetFirstAudioContent(
461 caller->pc()->local_description()->description());
462 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
463
464 ASSERT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
465
466 caller->pc()->Close();
467
468 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
469}
470
471TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700472 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
473 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
474
475 auto caller = CreatePeerConnectionWithAudioVideo();
476 auto callee = CreatePeerConnectionWithAudioVideo();
477
478 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
479 ASSERT_TRUE(
480 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
481
482 // |candidate.transport_name()| is empty.
483 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800484 auto* audio_content = cricket::GetFirstAudioContent(
485 caller->pc()->local_description()->description());
486 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700487 EXPECT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
488 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
489}
490
Steve Anton46d926a2018-01-23 10:23:06 -0800491TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700492 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
493
494 auto caller = CreatePeerConnectionWithAudioVideo();
495 auto callee = CreatePeerConnectionWithAudioVideo();
496
497 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
498 ASSERT_TRUE(
499 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
500
501 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
502 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
503 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
504 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
505}
506
507// Test that if a candidate is added via AddIceCandidate and via an updated
508// remote description, then both candidates appear in the stored remote
509// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800510TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700511 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
512 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
513 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
514
515 auto caller = CreatePeerConnectionWithAudioVideo();
516 auto callee = CreatePeerConnectionWithAudioVideo();
517
518 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
519 ASSERT_TRUE(
520 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
521
522 // Add one candidate via |AddIceCandidate|.
523 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
524 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
525
526 // Add the second candidate via a reoffer.
527 auto offer = caller->CreateOffer();
528 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
529 AddCandidateToFirstTransport(&candidate2, offer.get());
530
531 // Expect both candidates to appear in the callee's remote description.
532 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
533 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
534}
535
536// The follow test verifies that SetLocal/RemoteDescription fails when an offer
537// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
538// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
539// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800540TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700541 auto set_local_description_with_ufrag_pwd_length =
Steve Anton80dd7b52018-02-16 17:08:42 -0800542 [this](int ufrag_len, int pwd_len) {
543 auto pc = CreatePeerConnectionWithAudioVideo();
544 auto offer = pc->CreateOffer();
Steve Antonf1c6db12017-10-13 11:13:35 -0700545 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
546 std::string(pwd_len, 'x'));
Steve Anton80dd7b52018-02-16 17:08:42 -0800547 return pc->SetLocalDescription(std::move(offer));
Steve Antonf1c6db12017-10-13 11:13:35 -0700548 };
549
550 auto set_remote_description_with_ufrag_pwd_length =
Steve Anton80dd7b52018-02-16 17:08:42 -0800551 [this](int ufrag_len, int pwd_len) {
552 auto pc = CreatePeerConnectionWithAudioVideo();
553 auto offer = pc->CreateOffer();
Steve Antonf1c6db12017-10-13 11:13:35 -0700554 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
555 std::string(pwd_len, 'x'));
Steve Anton80dd7b52018-02-16 17:08:42 -0800556 return pc->SetRemoteDescription(std::move(offer));
Steve Antonf1c6db12017-10-13 11:13:35 -0700557 };
558
559 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
560 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
561 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
562 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
563 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
564 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
565 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
566 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
567 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
568 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
569 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
570 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
571}
572
573::testing::AssertionResult AssertIpInCandidates(
574 const char* address_expr,
575 const char* candidates_expr,
576 const SocketAddress& address,
577 const std::vector<IceCandidateInterface*> candidates) {
578 std::stringstream candidate_hosts;
579 for (const auto* candidate : candidates) {
580 const auto& candidate_ip = candidate->candidate().address().ipaddr();
581 if (candidate_ip == address.ipaddr()) {
582 return ::testing::AssertionSuccess();
583 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200584 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700585 }
586 return ::testing::AssertionFailure()
587 << address_expr << " (host " << address.HostAsURIString()
588 << ") not in " << candidates_expr
589 << " which have the following address hosts:" << candidate_hosts.str();
590}
591
Steve Anton46d926a2018-01-23 10:23:06 -0800592TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700593 const SocketAddress kLocalAddress1("1.1.1.1", 0);
594 const SocketAddress kLocalAddress2("2.2.2.2", 0);
595
596 auto caller = CreatePeerConnectionWithAudioVideo();
597 caller->network()->AddInterface(kLocalAddress1);
598 caller->network()->AddInterface(kLocalAddress2);
599
600 caller->CreateOfferAndSetAsLocal();
601 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
602
603 auto candidates = caller->observer()->GetCandidatesByMline(0);
604 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
605 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
606}
607
Steve Anton46d926a2018-01-23 10:23:06 -0800608TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700609 const SocketAddress kCallerAddress("1.1.1.1", 1111);
610
611 auto caller = CreatePeerConnectionWithAudioVideo();
612 auto callee = CreatePeerConnectionWithAudioVideo();
613
614 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
615
616 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
617 callee->AddIceCandidate(&candidate);
618 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
619 ASSERT_EQ(1u, candidates.size());
620 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
621 candidates[0]->candidate());
622}
623
Steve Anton46d926a2018-01-23 10:23:06 -0800624TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700625 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
626 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
627
628 auto caller = CreatePeerConnectionWithAudioVideo();
629 auto callee = CreatePeerConnectionWithAudioVideo();
630
631 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
632 ASSERT_TRUE(
633 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
634
635 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
636 caller->AddIceCandidate(&candidate1);
637
638 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
639 caller->AddIceCandidate(&candidate2);
640
641 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
642 ASSERT_EQ(2u, candidates.size());
643 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
644 candidates[0]->candidate());
645 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
646 candidates[1]->candidate());
647}
648
Steve Anton46d926a2018-01-23 10:23:06 -0800649TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700650 const SocketAddress kLocalAddress("1.1.1.1", 0);
651
652 RTCConfiguration config;
653 config.continual_gathering_policy =
654 PeerConnectionInterface::GATHER_CONTINUALLY;
655 auto caller = CreatePeerConnectionWithAudioVideo(config);
656 caller->network()->AddInterface(kLocalAddress);
657
658 // Start ICE candidate gathering by setting the local offer.
659 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
660
661 // Since we're using continual gathering, we won't get "gathering done".
662 EXPECT_TRUE_WAIT(
663 caller->pc()->local_description()->candidates(0)->count() > 0,
664 kIceCandidatesTimeout);
665}
666
667// Test that when continual gathering is enabled, and a network interface goes
668// down, the candidate is signaled as removed and removed from the local
669// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800670TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700671 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
672 const SocketAddress kLocalAddress("1.1.1.1", 0);
673
674 RTCConfiguration config;
675 config.continual_gathering_policy =
676 PeerConnectionInterface::GATHER_CONTINUALLY;
677 auto caller = CreatePeerConnectionWithAudioVideo(config);
678 caller->network()->AddInterface(kLocalAddress);
679
680 // Start ICE candidate gathering by setting the local offer.
681 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
682
683 EXPECT_TRUE_WAIT(
684 caller->pc()->local_description()->candidates(0)->count() > 0,
685 kIceCandidatesTimeout);
686
687 // Remove the only network interface, causing the PeerConnection to signal
688 // the removal of all candidates derived from this interface.
689 caller->network()->RemoveInterface(kLocalAddress);
690
691 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
692 kIceCandidatesTimeout);
693 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
694}
695
Steve Anton46d926a2018-01-23 10:23:06 -0800696TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700697 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
698 const SocketAddress kLocalAddress("1.1.1.1", 0);
699
700 RTCConfiguration config;
701 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
702 auto caller = CreatePeerConnectionWithAudioVideo(config);
703 caller->network()->AddInterface(kLocalAddress);
704
705 // Start ICE candidate gathering by setting the local offer.
706 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
707
708 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
709
710 caller->network()->RemoveInterface(kLocalAddress);
711
712 // Verify that the local candidates are not removed;
713 rtc::Thread::Current()->ProcessMessages(1000);
714 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
715}
716
717// The following group tests that when an offer includes a new ufrag or pwd
718// (indicating an ICE restart) the old candidates are removed and new candidates
719// added to the remote description.
720
Steve Anton46d926a2018-01-23 10:23:06 -0800721TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700722 const SocketAddress kCallerAddress("1.1.1.1", 1111);
723
724 auto caller = CreatePeerConnectionWithAudioVideo();
725 auto callee = CreatePeerConnectionWithAudioVideo();
726
727 auto offer = caller->CreateOffer();
728 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
729 AddCandidateToFirstTransport(&candidate, offer.get());
730
731 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
732
733 RTCOfferAnswerOptions options;
734 options.ice_restart = true;
735 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer(options)));
736
737 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
738}
Steve Anton46d926a2018-01-23 10:23:06 -0800739TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700740 IceRestartOfferCandidateReplacesExistingCandidate) {
741 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
742 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
743
744 auto caller = CreatePeerConnectionWithAudioVideo();
745 auto callee = CreatePeerConnectionWithAudioVideo();
746
747 auto offer = caller->CreateOffer();
748 cricket::Candidate old_candidate =
749 CreateLocalUdpCandidate(kFirstCallerAddress);
750 AddCandidateToFirstTransport(&old_candidate, offer.get());
751
752 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
753
754 RTCOfferAnswerOptions options;
755 options.ice_restart = true;
756 auto restart_offer = caller->CreateOffer(options);
757 cricket::Candidate new_candidate =
758 CreateLocalUdpCandidate(kRestartedCallerAddress);
759 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
760
761 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
762
763 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
764 ASSERT_EQ(1u, remote_candidates.size());
765 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
766 remote_candidates[0]->candidate());
767}
768
769// Test that if there is not an ICE restart (i.e., nothing changes), then the
770// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800771TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700772 auto caller = CreatePeerConnectionWithAudioVideo();
773 auto callee = CreatePeerConnectionWithAudioVideo();
774
775 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
776 ASSERT_TRUE(
777 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
778
779 // Re-offer.
780 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
781
782 auto answer = callee->CreateAnswer();
783 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
784 auto* local_transport_desc =
785 GetFirstTransportDescription(callee->pc()->local_description());
786
787 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
788 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
789}
790
791// The following parameterized test verifies that if an offer is sent with a
792// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
793// other side has initiated an ICE restart and generate a new ufrag and pwd.
794// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
795// a=ice-pwd attributes compared to the previous SDP from the peer, it
796// indicates that ICE is restarting for this media stream."
797
Steve Anton46d926a2018-01-23 10:23:06 -0800798class PeerConnectionIceUfragPwdAnswerTest
799 : public PeerConnectionIceBaseTest,
800 public ::testing::WithParamInterface<
801 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -0700802 protected:
Steve Anton46d926a2018-01-23 10:23:06 -0800803 PeerConnectionIceUfragPwdAnswerTest()
804 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
805 auto param = std::get<1>(GetParam());
806 offer_new_ufrag_ = std::get<0>(param);
807 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -0700808 }
809
810 bool offer_new_ufrag_;
811 bool offer_new_pwd_;
812};
813
Steve Anton46d926a2018-01-23 10:23:06 -0800814TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700815 auto caller = CreatePeerConnectionWithAudioVideo();
816 auto callee = CreatePeerConnectionWithAudioVideo();
817
818 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
819 ASSERT_TRUE(
820 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
821
822 auto offer = caller->CreateOffer();
823 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
824 if (offer_new_ufrag_) {
825 offer_transport_desc->ice_ufrag += "_new";
826 }
827 if (offer_new_pwd_) {
828 offer_transport_desc->ice_pwd += "_new";
829 }
830
831 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
832
833 auto answer = callee->CreateAnswer();
834 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
835 auto* local_transport_desc =
836 GetFirstTransportDescription(callee->pc()->local_description());
837
838 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
839 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
840}
841
842INSTANTIATE_TEST_CASE_P(
Steve Anton46d926a2018-01-23 10:23:06 -0800843 PeerConnectionIceTest,
844 PeerConnectionIceUfragPwdAnswerTest,
845 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
846 Values(std::make_pair(true, true), // Both changed.
847 std::make_pair(true, false), // Only ufrag changed.
848 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -0700849
850// Test that if an ICE restart is offered on one media section, then the answer
851// will only change ICE ufrag/pwd for that section and keep the other sections
852// the same.
853// Note that this only works if we have disabled BUNDLE, otherwise all media
854// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -0800855TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700856 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
857 auto caller = CreatePeerConnectionWithAudioVideo();
858 auto callee = CreatePeerConnectionWithAudioVideo();
859
860 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
861 ASSERT_TRUE(
862 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
863
864 RTCOfferAnswerOptions disable_bundle_options;
865 disable_bundle_options.use_rtp_mux = false;
866
867 auto offer = caller->CreateOffer(disable_bundle_options);
868
869 // Signal ICE restart on the first media section.
870 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
871 offer_transport_desc->ice_ufrag += "_new";
872 offer_transport_desc->ice_pwd += "_new";
873
874 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
875
876 auto answer = callee->CreateAnswer(disable_bundle_options);
877 const auto& answer_transports = answer->description()->transport_infos();
878 const auto& local_transports =
879 callee->pc()->local_description()->description()->transport_infos();
880
881 EXPECT_NE(answer_transports[0].description.ice_ufrag,
882 local_transports[0].description.ice_ufrag);
883 EXPECT_NE(answer_transports[0].description.ice_pwd,
884 local_transports[0].description.ice_pwd);
885 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
886 local_transports[1].description.ice_ufrag);
887 EXPECT_EQ(answer_transports[1].description.ice_pwd,
888 local_transports[1].description.ice_pwd);
889}
890
Qingsi Wange1692722017-11-29 13:27:20 -0800891// Test that when the initial offerer (caller) uses the lite implementation of
892// ICE and the callee uses the full implementation, the caller takes the
893// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
894// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800895TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800896 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
897 auto caller = CreatePeerConnectionWithAudioVideo();
898 auto callee = CreatePeerConnectionWithAudioVideo();
899
900 auto offer = caller->CreateOffer();
901 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
902 ASSERT_TRUE(
903 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
904 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
905
906 auto answer = callee->CreateAnswer();
907 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
908 ASSERT_TRUE(
909 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
910 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
911
912 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
913 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
914}
915
916// Test that when the caller and the callee both use the lite implementation of
917// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
918// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800919TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800920 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
921 auto caller = CreatePeerConnectionWithAudioVideo();
922 auto callee = CreatePeerConnectionWithAudioVideo();
923
924 auto offer = caller->CreateOffer();
925 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
926 ASSERT_TRUE(
927 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
928 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
929
930 auto answer = callee->CreateAnswer();
931 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
932 ASSERT_TRUE(
933 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
934 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
935
936 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
937 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
938}
939
Steve Anton46d926a2018-01-23 10:23:06 -0800940INSTANTIATE_TEST_CASE_P(PeerConnectionIceTest,
941 PeerConnectionIceTest,
942 Values(SdpSemantics::kPlanB,
943 SdpSemantics::kUnifiedPlan));
944
Qingsi Wang4ff54432018-03-01 18:25:20 -0800945class PeerConnectionIceConfigTest : public testing::Test {
946 protected:
947 void SetUp() override {
948 pc_factory_ = CreatePeerConnectionFactory(
949 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
950 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
951 CreateBuiltinAudioDecoderFactory(), nullptr, nullptr);
952 }
953 void CreatePeerConnection(const RTCConfiguration& config) {
954 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
955 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
956 port_allocator_ = port_allocator.get();
957 rtc::scoped_refptr<PeerConnectionInterface> pc(
958 pc_factory_->CreatePeerConnection(
959 config, nullptr /* constraint */, std::move(port_allocator),
960 nullptr /* cert_generator */, &observer_));
961 EXPECT_TRUE(pc.get());
962 pc_ = std::move(pc.get());
963 }
964
965 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
966 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
967 cricket::FakePortAllocator* port_allocator_ = nullptr;
968
969 MockPeerConnectionObserver observer_;
970};
971
972TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
973 RTCConfiguration config;
974 config.stun_candidate_keepalive_interval = 123;
975 config.ice_candidate_pool_size = 1;
976 CreatePeerConnection(config);
977 ASSERT_NE(port_allocator_, nullptr);
978 rtc::Optional<int> actual_stun_keepalive_interval =
979 port_allocator_->stun_candidate_keepalive_interval();
980 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
981 config.stun_candidate_keepalive_interval = 321;
982 RTCError error;
983 pc_->SetConfiguration(config, &error);
984 actual_stun_keepalive_interval =
985 port_allocator_->stun_candidate_keepalive_interval();
986 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
987}
988
Steve Antonf1c6db12017-10-13 11:13:35 -0700989} // namespace webrtc