blob: 3c1782c8983005cae36e154b667f409039ebe4b8 [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"
Anders Carlsson67537952018-05-03 11:28:29 +020024#include "api/video_codecs/builtin_video_decoder_factory.h"
25#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070026#include "pc/test/fakeaudiocapturemodule.h"
27#include "rtc_base/fakenetwork.h"
28#include "rtc_base/gunit.h"
29#include "rtc_base/ptr_util.h"
30#include "rtc_base/virtualsocketserver.h"
31
32namespace webrtc {
33
34using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
35using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
36using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080037using ::testing::Combine;
Steve Antonf1c6db12017-10-13 11:13:35 -070038using ::testing::Values;
39
40constexpr int kIceCandidatesTimeout = 10000;
41
Steve Anton46d926a2018-01-23 10:23:06 -080042class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070043 public:
44 using PeerConnectionWrapper::PeerConnectionWrapper;
45
46 // Adds a new ICE candidate to the first transport.
47 bool AddIceCandidate(cricket::Candidate* candidate) {
48 RTC_DCHECK(pc()->remote_description());
49 const auto* desc = pc()->remote_description()->description();
50 RTC_DCHECK(desc->contents().size() > 0);
51 const auto& first_content = desc->contents()[0];
52 candidate->set_transport_name(first_content.name);
53 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
54 return pc()->AddIceCandidate(&jsep_candidate);
55 }
56
57 // Returns ICE candidates from the remote session description.
58 std::vector<const IceCandidateInterface*>
59 GetIceCandidatesFromRemoteDescription() {
60 const SessionDescriptionInterface* sdesc = pc()->remote_description();
61 RTC_DCHECK(sdesc);
62 std::vector<const IceCandidateInterface*> candidates;
63 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
64 mline_index++) {
65 const auto* candidate_collection = sdesc->candidates(mline_index);
66 for (size_t i = 0; i < candidate_collection->count(); i++) {
67 candidates.push_back(candidate_collection->at(i));
68 }
69 }
70 return candidates;
71 }
72
73 rtc::FakeNetworkManager* network() { return network_; }
74
75 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
76
77 private:
78 rtc::FakeNetworkManager* network_;
79};
80
Steve Anton46d926a2018-01-23 10:23:06 -080081class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070082 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080083 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070084
Steve Anton46d926a2018-01-23 10:23:06 -080085 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
86 : vss_(new rtc::VirtualSocketServer()),
87 main_(vss_.get()),
88 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -070089#ifdef WEBRTC_ANDROID
90 InitializeAndroidObjects();
91#endif
92 pc_factory_ = CreatePeerConnectionFactory(
93 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +020094 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
95 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
96 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
97 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -070098 }
99
100 WrapperPtr CreatePeerConnection() {
101 return CreatePeerConnection(RTCConfiguration());
102 }
103
104 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
105 auto* fake_network = NewFakeNetwork();
106 auto port_allocator =
107 rtc::MakeUnique<cricket::BasicPortAllocator>(fake_network);
108 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
109 cricket::PORTALLOCATOR_DISABLE_RELAY);
110 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800111 RTCConfiguration modified_config = config;
112 modified_config.sdp_semantics = sdp_semantics_;
Steve Antonf1c6db12017-10-13 11:13:35 -0700113 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
114 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800115 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700116 if (!pc) {
117 return nullptr;
118 }
119
Steve Anton46d926a2018-01-23 10:23:06 -0800120 auto wrapper = rtc::MakeUnique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700121 pc_factory_, pc, std::move(observer));
122 wrapper->set_network(fake_network);
123 return wrapper;
124 }
125
126 // Accepts the same arguments as CreatePeerConnection and adds default audio
127 // and video tracks.
128 template <typename... Args>
129 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
130 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
131 if (!wrapper) {
132 return nullptr;
133 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700134 wrapper->AddAudioTrack("a");
135 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700136 return wrapper;
137 }
138
139 cricket::Candidate CreateLocalUdpCandidate(
140 const rtc::SocketAddress& address) {
141 cricket::Candidate candidate;
142 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
143 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
144 candidate.set_address(address);
145 candidate.set_type(cricket::LOCAL_PORT_TYPE);
146 return candidate;
147 }
148
149 // Remove all ICE ufrag/pwd lines from the given session description.
150 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
151 SetIceUfragPwd(sdesc, "", "");
152 }
153
154 // Sets all ICE ufrag/pwds on the given session description.
155 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
156 const std::string& ufrag,
157 const std::string& pwd) {
158 auto* desc = sdesc->description();
159 for (const auto& content : desc->contents()) {
160 auto* transport_info = desc->GetTransportInfoByName(content.name);
161 transport_info->description.ice_ufrag = ufrag;
162 transport_info->description.ice_pwd = pwd;
163 }
164 }
165
Qingsi Wange1692722017-11-29 13:27:20 -0800166 // Set ICE mode on the given session description.
167 void SetIceMode(SessionDescriptionInterface* sdesc,
168 const cricket::IceMode ice_mode) {
169 auto* desc = sdesc->description();
170 for (const auto& content : desc->contents()) {
171 auto* transport_info = desc->GetTransportInfoByName(content.name);
172 transport_info->description.ice_mode = ice_mode;
173 }
174 }
175
Steve Antonf1c6db12017-10-13 11:13:35 -0700176 cricket::TransportDescription* GetFirstTransportDescription(
177 SessionDescriptionInterface* sdesc) {
178 auto* desc = sdesc->description();
179 RTC_DCHECK(desc->contents().size() > 0);
180 auto* transport_info =
181 desc->GetTransportInfoByName(desc->contents()[0].name);
182 RTC_DCHECK(transport_info);
183 return &transport_info->description;
184 }
185
186 const cricket::TransportDescription* GetFirstTransportDescription(
187 const SessionDescriptionInterface* sdesc) {
188 auto* desc = sdesc->description();
189 RTC_DCHECK(desc->contents().size() > 0);
190 auto* transport_info =
191 desc->GetTransportInfoByName(desc->contents()[0].name);
192 RTC_DCHECK(transport_info);
193 return &transport_info->description;
194 }
195
Qingsi Wange1692722017-11-29 13:27:20 -0800196 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
197 // after it is implemented.
198 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100199 auto* pc_proxy =
200 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
201 pc_wrapper_ptr->pc());
202 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Steve Antonb8867112018-02-13 10:07:54 -0800203 for (auto transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800204 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton46d926a2018-01-23 10:23:06 -0800205 cricket::BaseChannel* channel = transceiver->internal()->channel();
206 if (channel) {
Zhi Huange830e682018-03-30 10:48:35 -0700207 auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
208 channel->rtp_packet_transport());
209 return dtls_transport->ice_transport()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800210 }
211 }
212 }
213 RTC_NOTREACHED();
214 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800215 }
216
Steve Antonf1c6db12017-10-13 11:13:35 -0700217 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
218 SessionDescriptionInterface* sdesc) {
219 auto* desc = sdesc->description();
220 RTC_DCHECK(desc->contents().size() > 0);
221 const auto& first_content = desc->contents()[0];
222 candidate->set_transport_name(first_content.name);
223 JsepIceCandidate jsep_candidate(first_content.name, 0, *candidate);
224 return sdesc->AddCandidate(&jsep_candidate);
225 }
226
227 rtc::FakeNetworkManager* NewFakeNetwork() {
228 // The PeerConnection's port allocator is tied to the PeerConnection's
229 // lifetime and expects the underlying NetworkManager to outlive it. That
230 // prevents us from having the PeerConnectionWrapper own the fake network.
231 // Therefore, the test fixture will own all the fake networks even though
232 // tests should access the fake network through the PeerConnectionWrapper.
233 auto* fake_network = new rtc::FakeNetworkManager();
234 fake_networks_.emplace_back(fake_network);
235 return fake_network;
236 }
237
238 std::unique_ptr<rtc::VirtualSocketServer> vss_;
239 rtc::AutoSocketServerThread main_;
240 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
241 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800242 const SdpSemantics sdp_semantics_;
243};
244
245class PeerConnectionIceTest
246 : public PeerConnectionIceBaseTest,
247 public ::testing::WithParamInterface<SdpSemantics> {
248 protected:
249 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {}
Steve Antonf1c6db12017-10-13 11:13:35 -0700250};
251
252::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
253 const char* b_expr,
254 const cricket::Candidate& a,
255 const cricket::Candidate& b) {
256 std::stringstream failure_info;
257 if (a.component() != b.component()) {
258 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
259 }
260 if (a.protocol() != b.protocol()) {
261 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
262 }
263 if (a.address() != b.address()) {
264 failure_info << "\naddress: " << a.address().ToString()
265 << " != " << b.address().ToString();
266 }
267 if (a.type() != b.type()) {
268 failure_info << "\ntype: " << a.type() << " != " << b.type();
269 }
270 std::string failure_info_str = failure_info.str();
271 if (failure_info_str.empty()) {
272 return ::testing::AssertionSuccess();
273 } else {
274 return ::testing::AssertionFailure()
275 << a_expr << " and " << b_expr << " are not equal"
276 << failure_info_str;
277 }
278}
279
Steve Anton46d926a2018-01-23 10:23:06 -0800280TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700281 const SocketAddress kLocalAddress("1.1.1.1", 0);
282
283 auto caller = CreatePeerConnectionWithAudioVideo();
284 caller->network()->AddInterface(kLocalAddress);
285
286 // Start ICE candidate gathering by setting the local offer.
287 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
288
289 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
290
291 auto offer = caller->CreateOffer();
292 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
293 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
294 offer->candidates(0)->count());
295 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
296 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
297 offer->candidates(1)->count());
298}
299
Steve Anton46d926a2018-01-23 10:23:06 -0800300TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700301 const SocketAddress kCallerAddress("1.1.1.1", 0);
302
303 auto caller = CreatePeerConnectionWithAudioVideo();
304 auto callee = CreatePeerConnectionWithAudioVideo();
305 caller->network()->AddInterface(kCallerAddress);
306
307 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
308 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
309
310 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
311
Steve Antondffead82018-02-06 10:31:29 -0800312 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700313 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
314 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
315 answer->candidates(0)->count());
316 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
317 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
318 answer->candidates(1)->count());
319}
320
Steve Anton46d926a2018-01-23 10:23:06 -0800321TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700322 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
323 const SocketAddress kCallerAddress("1.1.1.1", 1111);
324
325 auto caller = CreatePeerConnectionWithAudioVideo();
326 auto callee = CreatePeerConnectionWithAudioVideo();
327
328 auto offer = caller->CreateOfferAndSetAsLocal();
329 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
330 AddCandidateToFirstTransport(&candidate, offer.get());
331
332 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
333 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
334 ASSERT_EQ(1u, remote_candidates.size());
335 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
336 remote_candidates[0]->candidate());
337}
338
Steve Anton46d926a2018-01-23 10:23:06 -0800339TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700340 auto caller = CreatePeerConnectionWithAudioVideo();
341
342 auto offer = caller->CreateOffer();
343 RemoveIceUfragPwd(offer.get());
344
345 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
346}
347
Steve Anton46d926a2018-01-23 10:23:06 -0800348TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700349 auto caller = CreatePeerConnectionWithAudioVideo();
350 auto callee = CreatePeerConnectionWithAudioVideo();
351
352 auto offer = caller->CreateOfferAndSetAsLocal();
353 RemoveIceUfragPwd(offer.get());
354
355 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
356}
357
Steve Antonf764cf42018-05-01 14:32:17 -0700358// Test that doing an offer/answer exchange with no transport (i.e., no data
359// channel or media) results in the ICE connection state staying at New.
360TEST_P(PeerConnectionIceTest,
361 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
362 auto caller = CreatePeerConnection();
363 auto callee = CreatePeerConnection();
364
365 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
366
367 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
368 caller->pc()->ice_connection_state());
369 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
370 callee->pc()->ice_connection_state());
371}
372
Steve Antonf1c6db12017-10-13 11:13:35 -0700373// The following group tests that ICE candidates are not generated before
374// SetLocalDescription is called on a PeerConnection.
375
Steve Anton46d926a2018-01-23 10:23:06 -0800376TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700377 const SocketAddress kLocalAddress("1.1.1.1", 0);
378
379 auto caller = CreatePeerConnectionWithAudioVideo();
380 caller->network()->AddInterface(kLocalAddress);
381
382 // Pump for 1 second and verify that no candidates are generated.
383 rtc::Thread::Current()->ProcessMessages(1000);
384
385 EXPECT_EQ(0u, caller->observer()->candidates_.size());
386}
Steve Anton46d926a2018-01-23 10:23:06 -0800387TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700388 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
389 const SocketAddress kCallerAddress("1.1.1.1", 1111);
390
391 auto caller = CreatePeerConnectionWithAudioVideo();
392 auto callee = CreatePeerConnectionWithAudioVideo();
393 caller->network()->AddInterface(kCallerAddress);
394
395 auto offer = caller->CreateOfferAndSetAsLocal();
396 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
397 AddCandidateToFirstTransport(&candidate, offer.get());
398 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
399
400 // Pump for 1 second and verify that no candidates are generated.
401 rtc::Thread::Current()->ProcessMessages(1000);
402
403 EXPECT_EQ(0u, callee->observer()->candidates_.size());
404}
405
Steve Anton46d926a2018-01-23 10:23:06 -0800406TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700407 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
408
409 auto caller = CreatePeerConnectionWithAudioVideo();
410 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
411 JsepIceCandidate jsep_candidate(cricket::CN_AUDIO, 0, candidate);
412
413 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
414
415 caller->CreateOfferAndSetAsLocal();
416
417 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
418}
419
Steve Antonc79268f2018-04-24 09:54:10 -0700420TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
421 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
422
423 auto caller = CreatePeerConnectionWithAudioVideo();
424 auto callee = CreatePeerConnectionWithAudioVideo();
425
426 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
427
428 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
429 auto* audio_content = cricket::GetFirstAudioContent(
430 caller->pc()->local_description()->description());
431 JsepIceCandidate jsep_candidate(audio_content->name, 0, candidate);
432
433 caller->pc()->Close();
434
435 EXPECT_FALSE(caller->pc()->AddIceCandidate(&jsep_candidate));
436}
437
Steve Anton46d926a2018-01-23 10:23:06 -0800438TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700439 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
440
441 auto caller = CreatePeerConnectionWithAudioVideo();
442 auto callee = CreatePeerConnectionWithAudioVideo();
443
444 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
445 ASSERT_TRUE(
446 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
447
448 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
449 caller->AddIceCandidate(&candidate);
450 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
451 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
452}
453
Steve Anton46d926a2018-01-23 10:23:06 -0800454TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700455 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
456 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
457
458 auto caller = CreatePeerConnectionWithAudioVideo();
459 auto callee = CreatePeerConnectionWithAudioVideo();
460
461 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
462
463 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
464 auto* audio_content = cricket::GetFirstAudioContent(
465 caller->pc()->local_description()->description());
466 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
467
468 ASSERT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
469
470 caller->pc()->Close();
471
472 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
473}
474
475TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700476 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
477 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
478
479 auto caller = CreatePeerConnectionWithAudioVideo();
480 auto callee = CreatePeerConnectionWithAudioVideo();
481
482 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
483 ASSERT_TRUE(
484 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
485
486 // |candidate.transport_name()| is empty.
487 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800488 auto* audio_content = cricket::GetFirstAudioContent(
489 caller->pc()->local_description()->description());
490 JsepIceCandidate ice_candidate(audio_content->name, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700491 EXPECT_TRUE(caller->pc()->AddIceCandidate(&ice_candidate));
492 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
493}
494
Steve Anton46d926a2018-01-23 10:23:06 -0800495TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700496 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
497
498 auto caller = CreatePeerConnectionWithAudioVideo();
499 auto callee = CreatePeerConnectionWithAudioVideo();
500
501 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
502 ASSERT_TRUE(
503 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
504
505 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
506 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
507 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
508 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
509}
510
511// Test that if a candidate is added via AddIceCandidate and via an updated
512// remote description, then both candidates appear in the stored remote
513// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800514TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700515 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
516 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
517 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
518
519 auto caller = CreatePeerConnectionWithAudioVideo();
520 auto callee = CreatePeerConnectionWithAudioVideo();
521
522 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
523 ASSERT_TRUE(
524 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
525
526 // Add one candidate via |AddIceCandidate|.
527 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
528 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
529
530 // Add the second candidate via a reoffer.
531 auto offer = caller->CreateOffer();
532 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
533 AddCandidateToFirstTransport(&candidate2, offer.get());
534
535 // Expect both candidates to appear in the callee's remote description.
536 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
537 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
538}
539
540// The follow test verifies that SetLocal/RemoteDescription fails when an offer
541// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
542// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
543// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800544TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700545 auto set_local_description_with_ufrag_pwd_length =
Steve Anton80dd7b52018-02-16 17:08:42 -0800546 [this](int ufrag_len, int pwd_len) {
547 auto pc = CreatePeerConnectionWithAudioVideo();
548 auto offer = pc->CreateOffer();
Steve Antonf1c6db12017-10-13 11:13:35 -0700549 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
550 std::string(pwd_len, 'x'));
Steve Anton80dd7b52018-02-16 17:08:42 -0800551 return pc->SetLocalDescription(std::move(offer));
Steve Antonf1c6db12017-10-13 11:13:35 -0700552 };
553
554 auto set_remote_description_with_ufrag_pwd_length =
Steve Anton80dd7b52018-02-16 17:08:42 -0800555 [this](int ufrag_len, int pwd_len) {
556 auto pc = CreatePeerConnectionWithAudioVideo();
557 auto offer = pc->CreateOffer();
Steve Antonf1c6db12017-10-13 11:13:35 -0700558 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
559 std::string(pwd_len, 'x'));
Steve Anton80dd7b52018-02-16 17:08:42 -0800560 return pc->SetRemoteDescription(std::move(offer));
Steve Antonf1c6db12017-10-13 11:13:35 -0700561 };
562
563 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
564 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
565 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
566 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
567 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
568 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
569 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
570 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
571 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
572 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
573 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
574 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
575}
576
577::testing::AssertionResult AssertIpInCandidates(
578 const char* address_expr,
579 const char* candidates_expr,
580 const SocketAddress& address,
581 const std::vector<IceCandidateInterface*> candidates) {
582 std::stringstream candidate_hosts;
583 for (const auto* candidate : candidates) {
584 const auto& candidate_ip = candidate->candidate().address().ipaddr();
585 if (candidate_ip == address.ipaddr()) {
586 return ::testing::AssertionSuccess();
587 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200588 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700589 }
590 return ::testing::AssertionFailure()
591 << address_expr << " (host " << address.HostAsURIString()
592 << ") not in " << candidates_expr
593 << " which have the following address hosts:" << candidate_hosts.str();
594}
595
Steve Anton46d926a2018-01-23 10:23:06 -0800596TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700597 const SocketAddress kLocalAddress1("1.1.1.1", 0);
598 const SocketAddress kLocalAddress2("2.2.2.2", 0);
599
600 auto caller = CreatePeerConnectionWithAudioVideo();
601 caller->network()->AddInterface(kLocalAddress1);
602 caller->network()->AddInterface(kLocalAddress2);
603
604 caller->CreateOfferAndSetAsLocal();
605 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
606
607 auto candidates = caller->observer()->GetCandidatesByMline(0);
608 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
609 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
610}
611
Steve Anton46d926a2018-01-23 10:23:06 -0800612TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700613 const SocketAddress kCallerAddress("1.1.1.1", 1111);
614
615 auto caller = CreatePeerConnectionWithAudioVideo();
616 auto callee = CreatePeerConnectionWithAudioVideo();
617
618 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
619
620 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
621 callee->AddIceCandidate(&candidate);
622 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
623 ASSERT_EQ(1u, candidates.size());
624 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
625 candidates[0]->candidate());
626}
627
Steve Anton46d926a2018-01-23 10:23:06 -0800628TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700629 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
630 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
631
632 auto caller = CreatePeerConnectionWithAudioVideo();
633 auto callee = CreatePeerConnectionWithAudioVideo();
634
635 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
636 ASSERT_TRUE(
637 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
638
639 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
640 caller->AddIceCandidate(&candidate1);
641
642 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
643 caller->AddIceCandidate(&candidate2);
644
645 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
646 ASSERT_EQ(2u, candidates.size());
647 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
648 candidates[0]->candidate());
649 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
650 candidates[1]->candidate());
651}
652
Steve Anton46d926a2018-01-23 10:23:06 -0800653TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700654 const SocketAddress kLocalAddress("1.1.1.1", 0);
655
656 RTCConfiguration config;
657 config.continual_gathering_policy =
658 PeerConnectionInterface::GATHER_CONTINUALLY;
659 auto caller = CreatePeerConnectionWithAudioVideo(config);
660 caller->network()->AddInterface(kLocalAddress);
661
662 // Start ICE candidate gathering by setting the local offer.
663 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
664
665 // Since we're using continual gathering, we won't get "gathering done".
666 EXPECT_TRUE_WAIT(
667 caller->pc()->local_description()->candidates(0)->count() > 0,
668 kIceCandidatesTimeout);
669}
670
671// Test that when continual gathering is enabled, and a network interface goes
672// down, the candidate is signaled as removed and removed from the local
673// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800674TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700675 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
676 const SocketAddress kLocalAddress("1.1.1.1", 0);
677
678 RTCConfiguration config;
679 config.continual_gathering_policy =
680 PeerConnectionInterface::GATHER_CONTINUALLY;
681 auto caller = CreatePeerConnectionWithAudioVideo(config);
682 caller->network()->AddInterface(kLocalAddress);
683
684 // Start ICE candidate gathering by setting the local offer.
685 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
686
687 EXPECT_TRUE_WAIT(
688 caller->pc()->local_description()->candidates(0)->count() > 0,
689 kIceCandidatesTimeout);
690
691 // Remove the only network interface, causing the PeerConnection to signal
692 // the removal of all candidates derived from this interface.
693 caller->network()->RemoveInterface(kLocalAddress);
694
695 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
696 kIceCandidatesTimeout);
697 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
698}
699
Steve Anton46d926a2018-01-23 10:23:06 -0800700TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700701 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
702 const SocketAddress kLocalAddress("1.1.1.1", 0);
703
704 RTCConfiguration config;
705 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
706 auto caller = CreatePeerConnectionWithAudioVideo(config);
707 caller->network()->AddInterface(kLocalAddress);
708
709 // Start ICE candidate gathering by setting the local offer.
710 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
711
712 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
713
714 caller->network()->RemoveInterface(kLocalAddress);
715
716 // Verify that the local candidates are not removed;
717 rtc::Thread::Current()->ProcessMessages(1000);
718 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
719}
720
721// The following group tests that when an offer includes a new ufrag or pwd
722// (indicating an ICE restart) the old candidates are removed and new candidates
723// added to the remote description.
724
Steve Anton46d926a2018-01-23 10:23:06 -0800725TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700726 const SocketAddress kCallerAddress("1.1.1.1", 1111);
727
728 auto caller = CreatePeerConnectionWithAudioVideo();
729 auto callee = CreatePeerConnectionWithAudioVideo();
730
731 auto offer = caller->CreateOffer();
732 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
733 AddCandidateToFirstTransport(&candidate, offer.get());
734
735 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
736
737 RTCOfferAnswerOptions options;
738 options.ice_restart = true;
739 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer(options)));
740
741 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
742}
Steve Anton46d926a2018-01-23 10:23:06 -0800743TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700744 IceRestartOfferCandidateReplacesExistingCandidate) {
745 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
746 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
747
748 auto caller = CreatePeerConnectionWithAudioVideo();
749 auto callee = CreatePeerConnectionWithAudioVideo();
750
751 auto offer = caller->CreateOffer();
752 cricket::Candidate old_candidate =
753 CreateLocalUdpCandidate(kFirstCallerAddress);
754 AddCandidateToFirstTransport(&old_candidate, offer.get());
755
756 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
757
758 RTCOfferAnswerOptions options;
759 options.ice_restart = true;
760 auto restart_offer = caller->CreateOffer(options);
761 cricket::Candidate new_candidate =
762 CreateLocalUdpCandidate(kRestartedCallerAddress);
763 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
764
765 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
766
767 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
768 ASSERT_EQ(1u, remote_candidates.size());
769 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
770 remote_candidates[0]->candidate());
771}
772
773// Test that if there is not an ICE restart (i.e., nothing changes), then the
774// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800775TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700776 auto caller = CreatePeerConnectionWithAudioVideo();
777 auto callee = CreatePeerConnectionWithAudioVideo();
778
779 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
780 ASSERT_TRUE(
781 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
782
783 // Re-offer.
784 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
785
786 auto answer = callee->CreateAnswer();
787 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
788 auto* local_transport_desc =
789 GetFirstTransportDescription(callee->pc()->local_description());
790
791 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
792 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
793}
794
795// The following parameterized test verifies that if an offer is sent with a
796// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
797// other side has initiated an ICE restart and generate a new ufrag and pwd.
798// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
799// a=ice-pwd attributes compared to the previous SDP from the peer, it
800// indicates that ICE is restarting for this media stream."
801
Steve Anton46d926a2018-01-23 10:23:06 -0800802class PeerConnectionIceUfragPwdAnswerTest
803 : public PeerConnectionIceBaseTest,
804 public ::testing::WithParamInterface<
805 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -0700806 protected:
Steve Anton46d926a2018-01-23 10:23:06 -0800807 PeerConnectionIceUfragPwdAnswerTest()
808 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
809 auto param = std::get<1>(GetParam());
810 offer_new_ufrag_ = std::get<0>(param);
811 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -0700812 }
813
814 bool offer_new_ufrag_;
815 bool offer_new_pwd_;
816};
817
Steve Anton46d926a2018-01-23 10:23:06 -0800818TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700819 auto caller = CreatePeerConnectionWithAudioVideo();
820 auto callee = CreatePeerConnectionWithAudioVideo();
821
822 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
823 ASSERT_TRUE(
824 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
825
826 auto offer = caller->CreateOffer();
827 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
828 if (offer_new_ufrag_) {
829 offer_transport_desc->ice_ufrag += "_new";
830 }
831 if (offer_new_pwd_) {
832 offer_transport_desc->ice_pwd += "_new";
833 }
834
835 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
836
837 auto answer = callee->CreateAnswer();
838 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
839 auto* local_transport_desc =
840 GetFirstTransportDescription(callee->pc()->local_description());
841
842 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
843 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
844}
845
846INSTANTIATE_TEST_CASE_P(
Steve Anton46d926a2018-01-23 10:23:06 -0800847 PeerConnectionIceTest,
848 PeerConnectionIceUfragPwdAnswerTest,
849 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
850 Values(std::make_pair(true, true), // Both changed.
851 std::make_pair(true, false), // Only ufrag changed.
852 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -0700853
854// Test that if an ICE restart is offered on one media section, then the answer
855// will only change ICE ufrag/pwd for that section and keep the other sections
856// the same.
857// Note that this only works if we have disabled BUNDLE, otherwise all media
858// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -0800859TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700860 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
861 auto caller = CreatePeerConnectionWithAudioVideo();
862 auto callee = CreatePeerConnectionWithAudioVideo();
863
864 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
865 ASSERT_TRUE(
866 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
867
868 RTCOfferAnswerOptions disable_bundle_options;
869 disable_bundle_options.use_rtp_mux = false;
870
871 auto offer = caller->CreateOffer(disable_bundle_options);
872
873 // Signal ICE restart on the first media section.
874 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
875 offer_transport_desc->ice_ufrag += "_new";
876 offer_transport_desc->ice_pwd += "_new";
877
878 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
879
880 auto answer = callee->CreateAnswer(disable_bundle_options);
881 const auto& answer_transports = answer->description()->transport_infos();
882 const auto& local_transports =
883 callee->pc()->local_description()->description()->transport_infos();
884
885 EXPECT_NE(answer_transports[0].description.ice_ufrag,
886 local_transports[0].description.ice_ufrag);
887 EXPECT_NE(answer_transports[0].description.ice_pwd,
888 local_transports[0].description.ice_pwd);
889 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
890 local_transports[1].description.ice_ufrag);
891 EXPECT_EQ(answer_transports[1].description.ice_pwd,
892 local_transports[1].description.ice_pwd);
893}
894
Qingsi Wange1692722017-11-29 13:27:20 -0800895// Test that when the initial offerer (caller) uses the lite implementation of
896// ICE and the callee uses the full implementation, the caller takes the
897// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
898// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800899TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800900 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
901 auto caller = CreatePeerConnectionWithAudioVideo();
902 auto callee = CreatePeerConnectionWithAudioVideo();
903
904 auto offer = caller->CreateOffer();
905 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
906 ASSERT_TRUE(
907 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
908 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
909
910 auto answer = callee->CreateAnswer();
911 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
912 ASSERT_TRUE(
913 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
914 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
915
916 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
917 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
918}
919
920// Test that when the caller and the callee both use the lite implementation of
921// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
922// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800923TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800924 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
925 auto caller = CreatePeerConnectionWithAudioVideo();
926 auto callee = CreatePeerConnectionWithAudioVideo();
927
928 auto offer = caller->CreateOffer();
929 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
930 ASSERT_TRUE(
931 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
932 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
933
934 auto answer = callee->CreateAnswer();
935 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
936 ASSERT_TRUE(
937 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
938 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
939
940 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
941 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
942}
943
Steve Anton46d926a2018-01-23 10:23:06 -0800944INSTANTIATE_TEST_CASE_P(PeerConnectionIceTest,
945 PeerConnectionIceTest,
946 Values(SdpSemantics::kPlanB,
947 SdpSemantics::kUnifiedPlan));
948
Qingsi Wang4ff54432018-03-01 18:25:20 -0800949class PeerConnectionIceConfigTest : public testing::Test {
950 protected:
951 void SetUp() override {
952 pc_factory_ = CreatePeerConnectionFactory(
953 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
954 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +0200955 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
956 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
957 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -0800958 }
959 void CreatePeerConnection(const RTCConfiguration& config) {
960 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
961 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
962 port_allocator_ = port_allocator.get();
963 rtc::scoped_refptr<PeerConnectionInterface> pc(
964 pc_factory_->CreatePeerConnection(
965 config, nullptr /* constraint */, std::move(port_allocator),
966 nullptr /* cert_generator */, &observer_));
967 EXPECT_TRUE(pc.get());
968 pc_ = std::move(pc.get());
969 }
970
971 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
972 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
973 cricket::FakePortAllocator* port_allocator_ = nullptr;
974
975 MockPeerConnectionObserver observer_;
976};
977
978TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
979 RTCConfiguration config;
980 config.stun_candidate_keepalive_interval = 123;
981 config.ice_candidate_pool_size = 1;
982 CreatePeerConnection(config);
983 ASSERT_NE(port_allocator_, nullptr);
984 rtc::Optional<int> actual_stun_keepalive_interval =
985 port_allocator_->stun_candidate_keepalive_interval();
986 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
987 config.stun_candidate_keepalive_interval = 321;
988 RTCError error;
989 pc_->SetConfiguration(config, &error);
990 actual_stun_keepalive_interval =
991 port_allocator_->stun_candidate_keepalive_interval();
992 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
993}
994
Steve Antonf1c6db12017-10-13 11:13:35 -0700995} // namespace webrtc