blob: 36e0a098dd47a39965d8767a40b44ed0d7ed9a29 [file] [log] [blame]
Steve Antonf1c6db12017-10-13 11:13:35 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "p2p/base/fakeportallocator.h"
12#include "p2p/base/teststunserver.h"
13#include "p2p/client/basicportallocator.h"
14#include "pc/mediasession.h"
Qingsi Wange1692722017-11-29 13:27:20 -080015#include "pc/peerconnection.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070016#include "pc/peerconnectionwrapper.h"
17#include "pc/sdputils.h"
18#ifdef WEBRTC_ANDROID
19#include "pc/test/androidtestinitializer.h"
20#endif
Karl Wiberg918f50c2018-07-05 11:40:33 +020021#include "absl/memory/memory.h"
Karl Wiberg1b0eae32017-10-17 14:48:54 +020022#include "api/audio_codecs/builtin_audio_decoder_factory.h"
23#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Qingsi Wange1692722017-11-29 13:27:20 -080024#include "api/peerconnectionproxy.h"
Anders Carlsson67537952018-05-03 11:28:29 +020025#include "api/video_codecs/builtin_video_decoder_factory.h"
26#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070027#include "pc/test/fakeaudiocapturemodule.h"
28#include "rtc_base/fakenetwork.h"
29#include "rtc_base/gunit.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070030#include "rtc_base/virtualsocketserver.h"
Harald Alvestrand76829d72018-07-18 23:24:36 +020031#include "system_wrappers/include/metrics_default.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070032
33namespace webrtc {
34
35using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
36using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
37using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080038using ::testing::Combine;
Steve Antonf1c6db12017-10-13 11:13:35 -070039using ::testing::Values;
40
41constexpr int kIceCandidatesTimeout = 10000;
42
Steve Anton46d926a2018-01-23 10:23:06 -080043class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070044 public:
45 using PeerConnectionWrapper::PeerConnectionWrapper;
46
47 // Adds a new ICE candidate to the first transport.
48 bool AddIceCandidate(cricket::Candidate* candidate) {
49 RTC_DCHECK(pc()->remote_description());
50 const auto* desc = pc()->remote_description()->description();
51 RTC_DCHECK(desc->contents().size() > 0);
52 const auto& first_content = desc->contents()[0];
53 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -070054 std::unique_ptr<IceCandidateInterface> jsep_candidate =
55 CreateIceCandidate(first_content.name, 0, *candidate);
56 return pc()->AddIceCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -070057 }
58
59 // Returns ICE candidates from the remote session description.
60 std::vector<const IceCandidateInterface*>
61 GetIceCandidatesFromRemoteDescription() {
62 const SessionDescriptionInterface* sdesc = pc()->remote_description();
63 RTC_DCHECK(sdesc);
64 std::vector<const IceCandidateInterface*> candidates;
65 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
66 mline_index++) {
67 const auto* candidate_collection = sdesc->candidates(mline_index);
68 for (size_t i = 0; i < candidate_collection->count(); i++) {
69 candidates.push_back(candidate_collection->at(i));
70 }
71 }
72 return candidates;
73 }
74
75 rtc::FakeNetworkManager* network() { return network_; }
76
77 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
78
79 private:
80 rtc::FakeNetworkManager* network_;
81};
82
Steve Anton46d926a2018-01-23 10:23:06 -080083class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070084 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080085 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070086
Steve Anton46d926a2018-01-23 10:23:06 -080087 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
88 : vss_(new rtc::VirtualSocketServer()),
89 main_(vss_.get()),
90 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -070091#ifdef WEBRTC_ANDROID
92 InitializeAndroidObjects();
93#endif
94 pc_factory_ = CreatePeerConnectionFactory(
95 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +020096 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
97 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
98 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
99 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -0700100 }
101
102 WrapperPtr CreatePeerConnection() {
103 return CreatePeerConnection(RTCConfiguration());
104 }
105
106 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
107 auto* fake_network = NewFakeNetwork();
108 auto port_allocator =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200109 absl::make_unique<cricket::BasicPortAllocator>(fake_network);
Steve Antonf1c6db12017-10-13 11:13:35 -0700110 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
111 cricket::PORTALLOCATOR_DISABLE_RELAY);
112 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800113 RTCConfiguration modified_config = config;
114 modified_config.sdp_semantics = sdp_semantics_;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200115 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Steve Antonf1c6db12017-10-13 11:13:35 -0700116 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800117 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700118 if (!pc) {
119 return nullptr;
120 }
121
Karl Wiberg918f50c2018-07-05 11:40:33 +0200122 auto wrapper = absl::make_unique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700123 pc_factory_, pc, std::move(observer));
124 wrapper->set_network(fake_network);
125 return wrapper;
126 }
127
128 // Accepts the same arguments as CreatePeerConnection and adds default audio
129 // and video tracks.
130 template <typename... Args>
131 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
132 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
133 if (!wrapper) {
134 return nullptr;
135 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700136 wrapper->AddAudioTrack("a");
137 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700138 return wrapper;
139 }
140
141 cricket::Candidate CreateLocalUdpCandidate(
142 const rtc::SocketAddress& address) {
143 cricket::Candidate candidate;
144 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
145 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
146 candidate.set_address(address);
147 candidate.set_type(cricket::LOCAL_PORT_TYPE);
148 return candidate;
149 }
150
151 // Remove all ICE ufrag/pwd lines from the given session description.
152 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
153 SetIceUfragPwd(sdesc, "", "");
154 }
155
156 // Sets all ICE ufrag/pwds on the given session description.
157 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
158 const std::string& ufrag,
159 const std::string& pwd) {
160 auto* desc = sdesc->description();
161 for (const auto& content : desc->contents()) {
162 auto* transport_info = desc->GetTransportInfoByName(content.name);
163 transport_info->description.ice_ufrag = ufrag;
164 transport_info->description.ice_pwd = pwd;
165 }
166 }
167
Qingsi Wange1692722017-11-29 13:27:20 -0800168 // Set ICE mode on the given session description.
169 void SetIceMode(SessionDescriptionInterface* sdesc,
170 const cricket::IceMode ice_mode) {
171 auto* desc = sdesc->description();
172 for (const auto& content : desc->contents()) {
173 auto* transport_info = desc->GetTransportInfoByName(content.name);
174 transport_info->description.ice_mode = ice_mode;
175 }
176 }
177
Steve Antonf1c6db12017-10-13 11:13:35 -0700178 cricket::TransportDescription* GetFirstTransportDescription(
179 SessionDescriptionInterface* sdesc) {
180 auto* desc = sdesc->description();
181 RTC_DCHECK(desc->contents().size() > 0);
182 auto* transport_info =
183 desc->GetTransportInfoByName(desc->contents()[0].name);
184 RTC_DCHECK(transport_info);
185 return &transport_info->description;
186 }
187
188 const cricket::TransportDescription* GetFirstTransportDescription(
189 const SessionDescriptionInterface* sdesc) {
190 auto* desc = sdesc->description();
191 RTC_DCHECK(desc->contents().size() > 0);
192 auto* transport_info =
193 desc->GetTransportInfoByName(desc->contents()[0].name);
194 RTC_DCHECK(transport_info);
195 return &transport_info->description;
196 }
197
Qingsi Wange1692722017-11-29 13:27:20 -0800198 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
199 // after it is implemented.
200 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100201 auto* pc_proxy =
202 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
203 pc_wrapper_ptr->pc());
204 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Steve Antonb8867112018-02-13 10:07:54 -0800205 for (auto transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800206 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton46d926a2018-01-23 10:23:06 -0800207 cricket::BaseChannel* channel = transceiver->internal()->channel();
208 if (channel) {
Zhi Huange830e682018-03-30 10:48:35 -0700209 auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
210 channel->rtp_packet_transport());
211 return dtls_transport->ice_transport()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800212 }
213 }
214 }
215 RTC_NOTREACHED();
216 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800217 }
218
Steve Antonf1c6db12017-10-13 11:13:35 -0700219 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
220 SessionDescriptionInterface* sdesc) {
221 auto* desc = sdesc->description();
222 RTC_DCHECK(desc->contents().size() > 0);
223 const auto& first_content = desc->contents()[0];
224 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -0700225 std::unique_ptr<IceCandidateInterface> jsep_candidate =
226 CreateIceCandidate(first_content.name, 0, *candidate);
227 return sdesc->AddCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700228 }
229
230 rtc::FakeNetworkManager* NewFakeNetwork() {
231 // The PeerConnection's port allocator is tied to the PeerConnection's
232 // lifetime and expects the underlying NetworkManager to outlive it. That
233 // prevents us from having the PeerConnectionWrapper own the fake network.
234 // Therefore, the test fixture will own all the fake networks even though
235 // tests should access the fake network through the PeerConnectionWrapper.
236 auto* fake_network = new rtc::FakeNetworkManager();
237 fake_networks_.emplace_back(fake_network);
238 return fake_network;
239 }
240
241 std::unique_ptr<rtc::VirtualSocketServer> vss_;
242 rtc::AutoSocketServerThread main_;
243 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
244 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800245 const SdpSemantics sdp_semantics_;
246};
247
248class PeerConnectionIceTest
249 : public PeerConnectionIceBaseTest,
250 public ::testing::WithParamInterface<SdpSemantics> {
251 protected:
Harald Alvestrand76829d72018-07-18 23:24:36 +0200252 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
253 webrtc::metrics::Reset();
254 }
Steve Antonf1c6db12017-10-13 11:13:35 -0700255};
256
257::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
258 const char* b_expr,
259 const cricket::Candidate& a,
260 const cricket::Candidate& b) {
261 std::stringstream failure_info;
262 if (a.component() != b.component()) {
263 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
264 }
265 if (a.protocol() != b.protocol()) {
266 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
267 }
268 if (a.address() != b.address()) {
269 failure_info << "\naddress: " << a.address().ToString()
270 << " != " << b.address().ToString();
271 }
272 if (a.type() != b.type()) {
273 failure_info << "\ntype: " << a.type() << " != " << b.type();
274 }
275 std::string failure_info_str = failure_info.str();
276 if (failure_info_str.empty()) {
277 return ::testing::AssertionSuccess();
278 } else {
279 return ::testing::AssertionFailure()
280 << a_expr << " and " << b_expr << " are not equal"
281 << failure_info_str;
282 }
283}
284
Steve Anton46d926a2018-01-23 10:23:06 -0800285TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700286 const SocketAddress kLocalAddress("1.1.1.1", 0);
287
288 auto caller = CreatePeerConnectionWithAudioVideo();
289 caller->network()->AddInterface(kLocalAddress);
290
291 // Start ICE candidate gathering by setting the local offer.
292 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
293
294 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
295
296 auto offer = caller->CreateOffer();
297 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
298 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
299 offer->candidates(0)->count());
300 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
301 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
302 offer->candidates(1)->count());
303}
304
Steve Anton46d926a2018-01-23 10:23:06 -0800305TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700306 const SocketAddress kCallerAddress("1.1.1.1", 0);
307
308 auto caller = CreatePeerConnectionWithAudioVideo();
309 auto callee = CreatePeerConnectionWithAudioVideo();
310 caller->network()->AddInterface(kCallerAddress);
311
312 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
313 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
314
315 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
316
Steve Antondffead82018-02-06 10:31:29 -0800317 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700318 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
319 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
320 answer->candidates(0)->count());
321 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
322 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
323 answer->candidates(1)->count());
324}
325
Steve Anton46d926a2018-01-23 10:23:06 -0800326TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700327 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
328 const SocketAddress kCallerAddress("1.1.1.1", 1111);
329
330 auto caller = CreatePeerConnectionWithAudioVideo();
331 auto callee = CreatePeerConnectionWithAudioVideo();
332
333 auto offer = caller->CreateOfferAndSetAsLocal();
334 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
335 AddCandidateToFirstTransport(&candidate, offer.get());
336
337 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
338 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
339 ASSERT_EQ(1u, remote_candidates.size());
340 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
341 remote_candidates[0]->candidate());
342}
343
Steve Anton46d926a2018-01-23 10:23:06 -0800344TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700345 auto caller = CreatePeerConnectionWithAudioVideo();
346
347 auto offer = caller->CreateOffer();
348 RemoveIceUfragPwd(offer.get());
349
350 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
351}
352
Steve Anton46d926a2018-01-23 10:23:06 -0800353TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700354 auto caller = CreatePeerConnectionWithAudioVideo();
355 auto callee = CreatePeerConnectionWithAudioVideo();
356
357 auto offer = caller->CreateOfferAndSetAsLocal();
358 RemoveIceUfragPwd(offer.get());
359
360 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
361}
362
Steve Antonf764cf42018-05-01 14:32:17 -0700363// Test that doing an offer/answer exchange with no transport (i.e., no data
364// channel or media) results in the ICE connection state staying at New.
365TEST_P(PeerConnectionIceTest,
366 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
367 auto caller = CreatePeerConnection();
368 auto callee = CreatePeerConnection();
369
370 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
371
372 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
373 caller->pc()->ice_connection_state());
374 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
375 callee->pc()->ice_connection_state());
376}
377
Steve Antonf1c6db12017-10-13 11:13:35 -0700378// The following group tests that ICE candidates are not generated before
379// SetLocalDescription is called on a PeerConnection.
380
Steve Anton46d926a2018-01-23 10:23:06 -0800381TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700382 const SocketAddress kLocalAddress("1.1.1.1", 0);
383
384 auto caller = CreatePeerConnectionWithAudioVideo();
385 caller->network()->AddInterface(kLocalAddress);
386
387 // Pump for 1 second and verify that no candidates are generated.
388 rtc::Thread::Current()->ProcessMessages(1000);
389
390 EXPECT_EQ(0u, caller->observer()->candidates_.size());
391}
Steve Anton46d926a2018-01-23 10:23:06 -0800392TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700393 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
394 const SocketAddress kCallerAddress("1.1.1.1", 1111);
395
396 auto caller = CreatePeerConnectionWithAudioVideo();
397 auto callee = CreatePeerConnectionWithAudioVideo();
398 caller->network()->AddInterface(kCallerAddress);
399
400 auto offer = caller->CreateOfferAndSetAsLocal();
401 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
402 AddCandidateToFirstTransport(&candidate, offer.get());
403 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
404
405 // Pump for 1 second and verify that no candidates are generated.
406 rtc::Thread::Current()->ProcessMessages(1000);
407
408 EXPECT_EQ(0u, callee->observer()->candidates_.size());
409}
410
Steve Anton46d926a2018-01-23 10:23:06 -0800411TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700412 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
413
414 auto caller = CreatePeerConnectionWithAudioVideo();
415 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton27ab0e52018-07-23 15:11:53 -0700416 std::unique_ptr<IceCandidateInterface> jsep_candidate =
417 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700418
Steve Anton27ab0e52018-07-23 15:11:53 -0700419 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700420
421 caller->CreateOfferAndSetAsLocal();
422
Steve Anton27ab0e52018-07-23 15:11:53 -0700423 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Harald Alvestrand76829d72018-07-18 23:24:36 +0200424 EXPECT_EQ(
425 2, webrtc::metrics::NumSamples("WebRTC.PeerConnection.AddIceCandidate"));
426 EXPECT_EQ(
427 2, webrtc::metrics::NumEvents("WebRTC.PeerConnection.AddIceCandidate",
428 kAddIceCandidateFailNoRemoteDescription));
Steve Antonf1c6db12017-10-13 11:13:35 -0700429}
430
Steve Antonc79268f2018-04-24 09:54:10 -0700431TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
432 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
433
434 auto caller = CreatePeerConnectionWithAudioVideo();
435 auto callee = CreatePeerConnectionWithAudioVideo();
436
437 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
438
439 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
440 auto* audio_content = cricket::GetFirstAudioContent(
441 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700442 std::unique_ptr<IceCandidateInterface> jsep_candidate =
443 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700444
445 caller->pc()->Close();
446
Steve Anton27ab0e52018-07-23 15:11:53 -0700447 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700448}
449
Steve Anton46d926a2018-01-23 10:23:06 -0800450TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700451 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
452
453 auto caller = CreatePeerConnectionWithAudioVideo();
454 auto callee = CreatePeerConnectionWithAudioVideo();
455
456 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
457 ASSERT_TRUE(
458 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
459
460 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
461 caller->AddIceCandidate(&candidate);
462 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
463 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
464}
465
Steve Anton46d926a2018-01-23 10:23:06 -0800466TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700467 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
468 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
469
470 auto caller = CreatePeerConnectionWithAudioVideo();
471 auto callee = CreatePeerConnectionWithAudioVideo();
472
473 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
474
475 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
476 auto* audio_content = cricket::GetFirstAudioContent(
477 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700478 std::unique_ptr<IceCandidateInterface> ice_candidate =
479 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700480
Steve Anton27ab0e52018-07-23 15:11:53 -0700481 ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700482
483 caller->pc()->Close();
484
485 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
486}
487
488TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700489 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
490 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
491
492 auto caller = CreatePeerConnectionWithAudioVideo();
493 auto callee = CreatePeerConnectionWithAudioVideo();
494
495 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
496 ASSERT_TRUE(
497 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
498
499 // |candidate.transport_name()| is empty.
500 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800501 auto* audio_content = cricket::GetFirstAudioContent(
502 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700503 std::unique_ptr<IceCandidateInterface> ice_candidate =
504 CreateIceCandidate(audio_content->name, 0, candidate);
505 EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700506 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
507}
508
Steve Anton46d926a2018-01-23 10:23:06 -0800509TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700510 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
511
512 auto caller = CreatePeerConnectionWithAudioVideo();
513 auto callee = CreatePeerConnectionWithAudioVideo();
514
515 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
516 ASSERT_TRUE(
517 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
518
519 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
520 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
521 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
522 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
523}
524
525// Test that if a candidate is added via AddIceCandidate and via an updated
526// remote description, then both candidates appear in the stored remote
527// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800528TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700529 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
530 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
531 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
532
533 auto caller = CreatePeerConnectionWithAudioVideo();
534 auto callee = CreatePeerConnectionWithAudioVideo();
535
536 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
537 ASSERT_TRUE(
538 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
539
540 // Add one candidate via |AddIceCandidate|.
541 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
542 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
543
544 // Add the second candidate via a reoffer.
545 auto offer = caller->CreateOffer();
546 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
547 AddCandidateToFirstTransport(&candidate2, offer.get());
548
549 // Expect both candidates to appear in the callee's remote description.
550 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
551 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
552}
553
554// The follow test verifies that SetLocal/RemoteDescription fails when an offer
555// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
556// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
557// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800558TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Yves Gerey665174f2018-06-19 15:03:05 +0200559 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
560 int pwd_len) {
561 auto pc = CreatePeerConnectionWithAudioVideo();
562 auto offer = pc->CreateOffer();
563 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
564 std::string(pwd_len, 'x'));
565 return pc->SetLocalDescription(std::move(offer));
566 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700567
Yves Gerey665174f2018-06-19 15:03:05 +0200568 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
569 int pwd_len) {
570 auto pc = CreatePeerConnectionWithAudioVideo();
571 auto offer = pc->CreateOffer();
572 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
573 std::string(pwd_len, 'x'));
574 return pc->SetRemoteDescription(std::move(offer));
575 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700576
577 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
578 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
579 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
580 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
581 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
582 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
583 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
584 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
585 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
586 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
587 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
588 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
589}
590
591::testing::AssertionResult AssertIpInCandidates(
592 const char* address_expr,
593 const char* candidates_expr,
594 const SocketAddress& address,
595 const std::vector<IceCandidateInterface*> candidates) {
596 std::stringstream candidate_hosts;
597 for (const auto* candidate : candidates) {
598 const auto& candidate_ip = candidate->candidate().address().ipaddr();
599 if (candidate_ip == address.ipaddr()) {
600 return ::testing::AssertionSuccess();
601 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200602 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700603 }
604 return ::testing::AssertionFailure()
605 << address_expr << " (host " << address.HostAsURIString()
606 << ") not in " << candidates_expr
607 << " which have the following address hosts:" << candidate_hosts.str();
608}
609
Steve Anton46d926a2018-01-23 10:23:06 -0800610TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700611 const SocketAddress kLocalAddress1("1.1.1.1", 0);
612 const SocketAddress kLocalAddress2("2.2.2.2", 0);
613
614 auto caller = CreatePeerConnectionWithAudioVideo();
615 caller->network()->AddInterface(kLocalAddress1);
616 caller->network()->AddInterface(kLocalAddress2);
617
618 caller->CreateOfferAndSetAsLocal();
619 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
620
621 auto candidates = caller->observer()->GetCandidatesByMline(0);
622 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
623 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
624}
625
Steve Anton46d926a2018-01-23 10:23:06 -0800626TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700627 const SocketAddress kCallerAddress("1.1.1.1", 1111);
628
629 auto caller = CreatePeerConnectionWithAudioVideo();
630 auto callee = CreatePeerConnectionWithAudioVideo();
631
632 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
633
634 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
635 callee->AddIceCandidate(&candidate);
636 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
637 ASSERT_EQ(1u, candidates.size());
638 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
639 candidates[0]->candidate());
640}
641
Steve Anton46d926a2018-01-23 10:23:06 -0800642TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700643 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
644 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
645
646 auto caller = CreatePeerConnectionWithAudioVideo();
647 auto callee = CreatePeerConnectionWithAudioVideo();
648
649 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
650 ASSERT_TRUE(
651 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
652
653 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
654 caller->AddIceCandidate(&candidate1);
655
656 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
657 caller->AddIceCandidate(&candidate2);
658
659 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
660 ASSERT_EQ(2u, candidates.size());
661 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
662 candidates[0]->candidate());
663 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
664 candidates[1]->candidate());
665}
666
Steve Anton46d926a2018-01-23 10:23:06 -0800667TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700668 const SocketAddress kLocalAddress("1.1.1.1", 0);
669
670 RTCConfiguration config;
671 config.continual_gathering_policy =
672 PeerConnectionInterface::GATHER_CONTINUALLY;
673 auto caller = CreatePeerConnectionWithAudioVideo(config);
674 caller->network()->AddInterface(kLocalAddress);
675
676 // Start ICE candidate gathering by setting the local offer.
677 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
678
679 // Since we're using continual gathering, we won't get "gathering done".
680 EXPECT_TRUE_WAIT(
681 caller->pc()->local_description()->candidates(0)->count() > 0,
682 kIceCandidatesTimeout);
683}
684
685// Test that when continual gathering is enabled, and a network interface goes
686// down, the candidate is signaled as removed and removed from the local
687// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800688TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700689 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
690 const SocketAddress kLocalAddress("1.1.1.1", 0);
691
692 RTCConfiguration config;
693 config.continual_gathering_policy =
694 PeerConnectionInterface::GATHER_CONTINUALLY;
695 auto caller = CreatePeerConnectionWithAudioVideo(config);
696 caller->network()->AddInterface(kLocalAddress);
697
698 // Start ICE candidate gathering by setting the local offer.
699 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
700
701 EXPECT_TRUE_WAIT(
702 caller->pc()->local_description()->candidates(0)->count() > 0,
703 kIceCandidatesTimeout);
704
705 // Remove the only network interface, causing the PeerConnection to signal
706 // the removal of all candidates derived from this interface.
707 caller->network()->RemoveInterface(kLocalAddress);
708
709 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
710 kIceCandidatesTimeout);
711 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
712}
713
Steve Anton46d926a2018-01-23 10:23:06 -0800714TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700715 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
716 const SocketAddress kLocalAddress("1.1.1.1", 0);
717
718 RTCConfiguration config;
719 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
720 auto caller = CreatePeerConnectionWithAudioVideo(config);
721 caller->network()->AddInterface(kLocalAddress);
722
723 // Start ICE candidate gathering by setting the local offer.
724 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
725
726 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
727
728 caller->network()->RemoveInterface(kLocalAddress);
729
730 // Verify that the local candidates are not removed;
731 rtc::Thread::Current()->ProcessMessages(1000);
732 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
733}
734
735// The following group tests that when an offer includes a new ufrag or pwd
736// (indicating an ICE restart) the old candidates are removed and new candidates
737// added to the remote description.
738
Steve Anton46d926a2018-01-23 10:23:06 -0800739TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700740 const SocketAddress kCallerAddress("1.1.1.1", 1111);
741
742 auto caller = CreatePeerConnectionWithAudioVideo();
743 auto callee = CreatePeerConnectionWithAudioVideo();
744
745 auto offer = caller->CreateOffer();
746 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
747 AddCandidateToFirstTransport(&candidate, offer.get());
748
749 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
750
751 RTCOfferAnswerOptions options;
752 options.ice_restart = true;
753 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer(options)));
754
755 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
756}
Steve Anton46d926a2018-01-23 10:23:06 -0800757TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700758 IceRestartOfferCandidateReplacesExistingCandidate) {
759 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
760 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
761
762 auto caller = CreatePeerConnectionWithAudioVideo();
763 auto callee = CreatePeerConnectionWithAudioVideo();
764
765 auto offer = caller->CreateOffer();
766 cricket::Candidate old_candidate =
767 CreateLocalUdpCandidate(kFirstCallerAddress);
768 AddCandidateToFirstTransport(&old_candidate, offer.get());
769
770 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
771
772 RTCOfferAnswerOptions options;
773 options.ice_restart = true;
774 auto restart_offer = caller->CreateOffer(options);
775 cricket::Candidate new_candidate =
776 CreateLocalUdpCandidate(kRestartedCallerAddress);
777 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
778
779 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
780
781 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
782 ASSERT_EQ(1u, remote_candidates.size());
783 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
784 remote_candidates[0]->candidate());
785}
786
787// Test that if there is not an ICE restart (i.e., nothing changes), then the
788// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800789TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700790 auto caller = CreatePeerConnectionWithAudioVideo();
791 auto callee = CreatePeerConnectionWithAudioVideo();
792
793 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
794 ASSERT_TRUE(
795 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
796
797 // Re-offer.
798 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
799
800 auto answer = callee->CreateAnswer();
801 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
802 auto* local_transport_desc =
803 GetFirstTransportDescription(callee->pc()->local_description());
804
805 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
806 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
807}
808
809// The following parameterized test verifies that if an offer is sent with a
810// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
811// other side has initiated an ICE restart and generate a new ufrag and pwd.
812// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
813// a=ice-pwd attributes compared to the previous SDP from the peer, it
814// indicates that ICE is restarting for this media stream."
815
Steve Anton46d926a2018-01-23 10:23:06 -0800816class PeerConnectionIceUfragPwdAnswerTest
817 : public PeerConnectionIceBaseTest,
818 public ::testing::WithParamInterface<
819 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -0700820 protected:
Steve Anton46d926a2018-01-23 10:23:06 -0800821 PeerConnectionIceUfragPwdAnswerTest()
822 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
823 auto param = std::get<1>(GetParam());
824 offer_new_ufrag_ = std::get<0>(param);
825 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -0700826 }
827
828 bool offer_new_ufrag_;
829 bool offer_new_pwd_;
830};
831
Steve Anton46d926a2018-01-23 10:23:06 -0800832TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700833 auto caller = CreatePeerConnectionWithAudioVideo();
834 auto callee = CreatePeerConnectionWithAudioVideo();
835
836 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
837 ASSERT_TRUE(
838 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
839
840 auto offer = caller->CreateOffer();
841 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
842 if (offer_new_ufrag_) {
843 offer_transport_desc->ice_ufrag += "_new";
844 }
845 if (offer_new_pwd_) {
846 offer_transport_desc->ice_pwd += "_new";
847 }
848
849 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
850
851 auto answer = callee->CreateAnswer();
852 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
853 auto* local_transport_desc =
854 GetFirstTransportDescription(callee->pc()->local_description());
855
856 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
857 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
858}
859
860INSTANTIATE_TEST_CASE_P(
Steve Anton46d926a2018-01-23 10:23:06 -0800861 PeerConnectionIceTest,
862 PeerConnectionIceUfragPwdAnswerTest,
863 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
864 Values(std::make_pair(true, true), // Both changed.
865 std::make_pair(true, false), // Only ufrag changed.
866 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -0700867
868// Test that if an ICE restart is offered on one media section, then the answer
869// will only change ICE ufrag/pwd for that section and keep the other sections
870// the same.
871// Note that this only works if we have disabled BUNDLE, otherwise all media
872// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -0800873TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700874 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
875 auto caller = CreatePeerConnectionWithAudioVideo();
876 auto callee = CreatePeerConnectionWithAudioVideo();
877
878 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
879 ASSERT_TRUE(
880 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
881
882 RTCOfferAnswerOptions disable_bundle_options;
883 disable_bundle_options.use_rtp_mux = false;
884
885 auto offer = caller->CreateOffer(disable_bundle_options);
886
887 // Signal ICE restart on the first media section.
888 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
889 offer_transport_desc->ice_ufrag += "_new";
890 offer_transport_desc->ice_pwd += "_new";
891
892 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
893
894 auto answer = callee->CreateAnswer(disable_bundle_options);
895 const auto& answer_transports = answer->description()->transport_infos();
896 const auto& local_transports =
897 callee->pc()->local_description()->description()->transport_infos();
898
899 EXPECT_NE(answer_transports[0].description.ice_ufrag,
900 local_transports[0].description.ice_ufrag);
901 EXPECT_NE(answer_transports[0].description.ice_pwd,
902 local_transports[0].description.ice_pwd);
903 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
904 local_transports[1].description.ice_ufrag);
905 EXPECT_EQ(answer_transports[1].description.ice_pwd,
906 local_transports[1].description.ice_pwd);
907}
908
Qingsi Wange1692722017-11-29 13:27:20 -0800909// Test that when the initial offerer (caller) uses the lite implementation of
910// ICE and the callee uses the full implementation, the caller takes the
911// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
912// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800913TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800914 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
915 auto caller = CreatePeerConnectionWithAudioVideo();
916 auto callee = CreatePeerConnectionWithAudioVideo();
917
918 auto offer = caller->CreateOffer();
919 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
920 ASSERT_TRUE(
921 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
922 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
923
924 auto answer = callee->CreateAnswer();
925 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
926 ASSERT_TRUE(
927 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
928 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
929
930 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
931 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
932}
933
934// Test that when the caller and the callee both use the lite implementation of
935// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
936// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800937TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800938 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
939 auto caller = CreatePeerConnectionWithAudioVideo();
940 auto callee = CreatePeerConnectionWithAudioVideo();
941
942 auto offer = caller->CreateOffer();
943 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
944 ASSERT_TRUE(
945 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
946 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
947
948 auto answer = callee->CreateAnswer();
949 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
950 ASSERT_TRUE(
951 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
952 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
953
954 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
955 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
956}
957
Steve Anton46d926a2018-01-23 10:23:06 -0800958INSTANTIATE_TEST_CASE_P(PeerConnectionIceTest,
959 PeerConnectionIceTest,
960 Values(SdpSemantics::kPlanB,
961 SdpSemantics::kUnifiedPlan));
962
Qingsi Wang4ff54432018-03-01 18:25:20 -0800963class PeerConnectionIceConfigTest : public testing::Test {
964 protected:
965 void SetUp() override {
966 pc_factory_ = CreatePeerConnectionFactory(
967 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
968 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +0200969 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
970 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
971 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -0800972 }
973 void CreatePeerConnection(const RTCConfiguration& config) {
974 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
975 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
976 port_allocator_ = port_allocator.get();
977 rtc::scoped_refptr<PeerConnectionInterface> pc(
978 pc_factory_->CreatePeerConnection(
979 config, nullptr /* constraint */, std::move(port_allocator),
980 nullptr /* cert_generator */, &observer_));
981 EXPECT_TRUE(pc.get());
982 pc_ = std::move(pc.get());
983 }
984
985 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
986 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
987 cricket::FakePortAllocator* port_allocator_ = nullptr;
988
989 MockPeerConnectionObserver observer_;
990};
991
992TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
993 RTCConfiguration config;
994 config.stun_candidate_keepalive_interval = 123;
995 config.ice_candidate_pool_size = 1;
996 CreatePeerConnection(config);
997 ASSERT_NE(port_allocator_, nullptr);
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200998 absl::optional<int> actual_stun_keepalive_interval =
Qingsi Wang4ff54432018-03-01 18:25:20 -0800999 port_allocator_->stun_candidate_keepalive_interval();
1000 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1001 config.stun_candidate_keepalive_interval = 321;
1002 RTCError error;
1003 pc_->SetConfiguration(config, &error);
1004 actual_stun_keepalive_interval =
1005 port_allocator_->stun_candidate_keepalive_interval();
1006 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1007}
1008
Steve Antonf1c6db12017-10-13 11:13:35 -07001009} // namespace webrtc