blob: 4e25614d3c87324d65798df76c9013a75ec135e0 [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"
Yves Gerey2e00abc2018-10-05 15:39:24 +020025#include "api/umametrics.h"
Anders Carlsson67537952018-05-03 11:28:29 +020026#include "api/video_codecs/builtin_video_decoder_factory.h"
27#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070028#include "pc/test/fakeaudiocapturemodule.h"
29#include "rtc_base/fakenetwork.h"
30#include "rtc_base/gunit.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020031#include "rtc_base/strings/string_builder.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070032#include "rtc_base/virtualsocketserver.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020033#include "system_wrappers/include/metrics.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070034
35namespace webrtc {
36
37using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
38using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
39using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080040using ::testing::Combine;
Steve Antonf1c6db12017-10-13 11:13:35 -070041using ::testing::Values;
42
43constexpr int kIceCandidatesTimeout = 10000;
44
Steve Anton46d926a2018-01-23 10:23:06 -080045class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070046 public:
47 using PeerConnectionWrapper::PeerConnectionWrapper;
48
49 // Adds a new ICE candidate to the first transport.
50 bool AddIceCandidate(cricket::Candidate* candidate) {
51 RTC_DCHECK(pc()->remote_description());
52 const auto* desc = pc()->remote_description()->description();
53 RTC_DCHECK(desc->contents().size() > 0);
54 const auto& first_content = desc->contents()[0];
55 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -070056 std::unique_ptr<IceCandidateInterface> jsep_candidate =
57 CreateIceCandidate(first_content.name, 0, *candidate);
58 return pc()->AddIceCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -070059 }
60
61 // Returns ICE candidates from the remote session description.
62 std::vector<const IceCandidateInterface*>
63 GetIceCandidatesFromRemoteDescription() {
64 const SessionDescriptionInterface* sdesc = pc()->remote_description();
65 RTC_DCHECK(sdesc);
66 std::vector<const IceCandidateInterface*> candidates;
67 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
68 mline_index++) {
69 const auto* candidate_collection = sdesc->candidates(mline_index);
70 for (size_t i = 0; i < candidate_collection->count(); i++) {
71 candidates.push_back(candidate_collection->at(i));
72 }
73 }
74 return candidates;
75 }
76
77 rtc::FakeNetworkManager* network() { return network_; }
78
79 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
80
Jonas Oreland1cd39fa2018-10-11 07:47:12 +020081 // The port allocator used by this PC.
82 cricket::PortAllocator* port_allocator_;
83
Steve Antonf1c6db12017-10-13 11:13:35 -070084 private:
85 rtc::FakeNetworkManager* network_;
86};
87
Steve Anton46d926a2018-01-23 10:23:06 -080088class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070089 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080090 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070091
Steve Anton46d926a2018-01-23 10:23:06 -080092 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
93 : vss_(new rtc::VirtualSocketServer()),
94 main_(vss_.get()),
95 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -070096#ifdef WEBRTC_ANDROID
97 InitializeAndroidObjects();
98#endif
99 pc_factory_ = CreatePeerConnectionFactory(
100 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200101 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
102 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
103 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
104 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -0700105 }
106
107 WrapperPtr CreatePeerConnection() {
108 return CreatePeerConnection(RTCConfiguration());
109 }
110
111 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
112 auto* fake_network = NewFakeNetwork();
113 auto port_allocator =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200114 absl::make_unique<cricket::BasicPortAllocator>(fake_network);
Steve Antonf1c6db12017-10-13 11:13:35 -0700115 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
116 cricket::PORTALLOCATOR_DISABLE_RELAY);
117 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800118 RTCConfiguration modified_config = config;
119 modified_config.sdp_semantics = sdp_semantics_;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200120 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200121 auto port_allocator_copy = port_allocator.get();
Steve Antonf1c6db12017-10-13 11:13:35 -0700122 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800123 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700124 if (!pc) {
125 return nullptr;
126 }
127
Karl Wiberg918f50c2018-07-05 11:40:33 +0200128 auto wrapper = absl::make_unique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700129 pc_factory_, pc, std::move(observer));
130 wrapper->set_network(fake_network);
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200131 wrapper->port_allocator_ = port_allocator_copy;
Steve Antonf1c6db12017-10-13 11:13:35 -0700132 return wrapper;
133 }
134
135 // Accepts the same arguments as CreatePeerConnection and adds default audio
136 // and video tracks.
137 template <typename... Args>
138 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
139 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
140 if (!wrapper) {
141 return nullptr;
142 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700143 wrapper->AddAudioTrack("a");
144 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700145 return wrapper;
146 }
147
148 cricket::Candidate CreateLocalUdpCandidate(
149 const rtc::SocketAddress& address) {
150 cricket::Candidate candidate;
151 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
152 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
153 candidate.set_address(address);
154 candidate.set_type(cricket::LOCAL_PORT_TYPE);
155 return candidate;
156 }
157
158 // Remove all ICE ufrag/pwd lines from the given session description.
159 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
160 SetIceUfragPwd(sdesc, "", "");
161 }
162
163 // Sets all ICE ufrag/pwds on the given session description.
164 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
165 const std::string& ufrag,
166 const std::string& pwd) {
167 auto* desc = sdesc->description();
168 for (const auto& content : desc->contents()) {
169 auto* transport_info = desc->GetTransportInfoByName(content.name);
170 transport_info->description.ice_ufrag = ufrag;
171 transport_info->description.ice_pwd = pwd;
172 }
173 }
174
Qingsi Wange1692722017-11-29 13:27:20 -0800175 // Set ICE mode on the given session description.
176 void SetIceMode(SessionDescriptionInterface* sdesc,
177 const cricket::IceMode ice_mode) {
178 auto* desc = sdesc->description();
179 for (const auto& content : desc->contents()) {
180 auto* transport_info = desc->GetTransportInfoByName(content.name);
181 transport_info->description.ice_mode = ice_mode;
182 }
183 }
184
Steve Antonf1c6db12017-10-13 11:13:35 -0700185 cricket::TransportDescription* GetFirstTransportDescription(
186 SessionDescriptionInterface* sdesc) {
187 auto* desc = sdesc->description();
188 RTC_DCHECK(desc->contents().size() > 0);
189 auto* transport_info =
190 desc->GetTransportInfoByName(desc->contents()[0].name);
191 RTC_DCHECK(transport_info);
192 return &transport_info->description;
193 }
194
195 const cricket::TransportDescription* GetFirstTransportDescription(
196 const SessionDescriptionInterface* sdesc) {
197 auto* desc = sdesc->description();
198 RTC_DCHECK(desc->contents().size() > 0);
199 auto* transport_info =
200 desc->GetTransportInfoByName(desc->contents()[0].name);
201 RTC_DCHECK(transport_info);
202 return &transport_info->description;
203 }
204
Qingsi Wange1692722017-11-29 13:27:20 -0800205 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
206 // after it is implemented.
207 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100208 auto* pc_proxy =
209 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
210 pc_wrapper_ptr->pc());
211 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Steve Antonb8867112018-02-13 10:07:54 -0800212 for (auto transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800213 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton46d926a2018-01-23 10:23:06 -0800214 cricket::BaseChannel* channel = transceiver->internal()->channel();
215 if (channel) {
Zhi Huange830e682018-03-30 10:48:35 -0700216 auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
217 channel->rtp_packet_transport());
218 return dtls_transport->ice_transport()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800219 }
220 }
221 }
222 RTC_NOTREACHED();
223 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800224 }
225
Steve Antonf1c6db12017-10-13 11:13:35 -0700226 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
227 SessionDescriptionInterface* sdesc) {
228 auto* desc = sdesc->description();
229 RTC_DCHECK(desc->contents().size() > 0);
230 const auto& first_content = desc->contents()[0];
231 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -0700232 std::unique_ptr<IceCandidateInterface> jsep_candidate =
233 CreateIceCandidate(first_content.name, 0, *candidate);
234 return sdesc->AddCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700235 }
236
237 rtc::FakeNetworkManager* NewFakeNetwork() {
238 // The PeerConnection's port allocator is tied to the PeerConnection's
239 // lifetime and expects the underlying NetworkManager to outlive it. That
240 // prevents us from having the PeerConnectionWrapper own the fake network.
241 // Therefore, the test fixture will own all the fake networks even though
242 // tests should access the fake network through the PeerConnectionWrapper.
243 auto* fake_network = new rtc::FakeNetworkManager();
244 fake_networks_.emplace_back(fake_network);
245 return fake_network;
246 }
247
248 std::unique_ptr<rtc::VirtualSocketServer> vss_;
249 rtc::AutoSocketServerThread main_;
250 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
251 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800252 const SdpSemantics sdp_semantics_;
253};
254
255class PeerConnectionIceTest
256 : public PeerConnectionIceBaseTest,
257 public ::testing::WithParamInterface<SdpSemantics> {
258 protected:
Harald Alvestrand76829d72018-07-18 23:24:36 +0200259 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
260 webrtc::metrics::Reset();
261 }
Steve Antonf1c6db12017-10-13 11:13:35 -0700262};
263
264::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
265 const char* b_expr,
266 const cricket::Candidate& a,
267 const cricket::Candidate& b) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200268 rtc::StringBuilder failure_info;
Steve Antonf1c6db12017-10-13 11:13:35 -0700269 if (a.component() != b.component()) {
270 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
271 }
272 if (a.protocol() != b.protocol()) {
273 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
274 }
275 if (a.address() != b.address()) {
276 failure_info << "\naddress: " << a.address().ToString()
277 << " != " << b.address().ToString();
278 }
279 if (a.type() != b.type()) {
280 failure_info << "\ntype: " << a.type() << " != " << b.type();
281 }
282 std::string failure_info_str = failure_info.str();
283 if (failure_info_str.empty()) {
284 return ::testing::AssertionSuccess();
285 } else {
286 return ::testing::AssertionFailure()
287 << a_expr << " and " << b_expr << " are not equal"
288 << failure_info_str;
289 }
290}
291
Steve Anton46d926a2018-01-23 10:23:06 -0800292TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700293 const SocketAddress kLocalAddress("1.1.1.1", 0);
294
295 auto caller = CreatePeerConnectionWithAudioVideo();
296 caller->network()->AddInterface(kLocalAddress);
297
298 // Start ICE candidate gathering by setting the local offer.
299 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
300
301 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
302
303 auto offer = caller->CreateOffer();
304 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
305 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
306 offer->candidates(0)->count());
307 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
308 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
309 offer->candidates(1)->count());
310}
311
Steve Anton46d926a2018-01-23 10:23:06 -0800312TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700313 const SocketAddress kCallerAddress("1.1.1.1", 0);
314
315 auto caller = CreatePeerConnectionWithAudioVideo();
316 auto callee = CreatePeerConnectionWithAudioVideo();
317 caller->network()->AddInterface(kCallerAddress);
318
319 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
320 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
321
322 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
323
Steve Antondffead82018-02-06 10:31:29 -0800324 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700325 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
326 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
327 answer->candidates(0)->count());
328 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
329 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
330 answer->candidates(1)->count());
331}
332
Steve Anton46d926a2018-01-23 10:23:06 -0800333TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700334 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
335 const SocketAddress kCallerAddress("1.1.1.1", 1111);
336
337 auto caller = CreatePeerConnectionWithAudioVideo();
338 auto callee = CreatePeerConnectionWithAudioVideo();
339
340 auto offer = caller->CreateOfferAndSetAsLocal();
341 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
342 AddCandidateToFirstTransport(&candidate, offer.get());
343
344 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
345 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
346 ASSERT_EQ(1u, remote_candidates.size());
347 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
348 remote_candidates[0]->candidate());
349}
350
Steve Anton46d926a2018-01-23 10:23:06 -0800351TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700352 auto caller = CreatePeerConnectionWithAudioVideo();
353
354 auto offer = caller->CreateOffer();
355 RemoveIceUfragPwd(offer.get());
356
357 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
358}
359
Steve Anton46d926a2018-01-23 10:23:06 -0800360TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700361 auto caller = CreatePeerConnectionWithAudioVideo();
362 auto callee = CreatePeerConnectionWithAudioVideo();
363
364 auto offer = caller->CreateOfferAndSetAsLocal();
365 RemoveIceUfragPwd(offer.get());
366
367 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
368}
369
Steve Antonf764cf42018-05-01 14:32:17 -0700370// Test that doing an offer/answer exchange with no transport (i.e., no data
371// channel or media) results in the ICE connection state staying at New.
372TEST_P(PeerConnectionIceTest,
373 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
374 auto caller = CreatePeerConnection();
375 auto callee = CreatePeerConnection();
376
377 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
378
379 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
380 caller->pc()->ice_connection_state());
381 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
382 callee->pc()->ice_connection_state());
383}
384
Steve Antonf1c6db12017-10-13 11:13:35 -0700385// The following group tests that ICE candidates are not generated before
386// SetLocalDescription is called on a PeerConnection.
387
Steve Anton46d926a2018-01-23 10:23:06 -0800388TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700389 const SocketAddress kLocalAddress("1.1.1.1", 0);
390
391 auto caller = CreatePeerConnectionWithAudioVideo();
392 caller->network()->AddInterface(kLocalAddress);
393
394 // Pump for 1 second and verify that no candidates are generated.
395 rtc::Thread::Current()->ProcessMessages(1000);
396
397 EXPECT_EQ(0u, caller->observer()->candidates_.size());
398}
Steve Anton46d926a2018-01-23 10:23:06 -0800399TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700400 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
401 const SocketAddress kCallerAddress("1.1.1.1", 1111);
402
403 auto caller = CreatePeerConnectionWithAudioVideo();
404 auto callee = CreatePeerConnectionWithAudioVideo();
405 caller->network()->AddInterface(kCallerAddress);
406
407 auto offer = caller->CreateOfferAndSetAsLocal();
408 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
409 AddCandidateToFirstTransport(&candidate, offer.get());
410 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
411
412 // Pump for 1 second and verify that no candidates are generated.
413 rtc::Thread::Current()->ProcessMessages(1000);
414
415 EXPECT_EQ(0u, callee->observer()->candidates_.size());
416}
417
Steve Anton46d926a2018-01-23 10:23:06 -0800418TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700419 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
420
421 auto caller = CreatePeerConnectionWithAudioVideo();
422 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton27ab0e52018-07-23 15:11:53 -0700423 std::unique_ptr<IceCandidateInterface> jsep_candidate =
424 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700425
Steve Anton27ab0e52018-07-23 15:11:53 -0700426 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700427
428 caller->CreateOfferAndSetAsLocal();
429
Steve Anton27ab0e52018-07-23 15:11:53 -0700430 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Harald Alvestrand76829d72018-07-18 23:24:36 +0200431 EXPECT_EQ(
432 2, webrtc::metrics::NumSamples("WebRTC.PeerConnection.AddIceCandidate"));
433 EXPECT_EQ(
434 2, webrtc::metrics::NumEvents("WebRTC.PeerConnection.AddIceCandidate",
435 kAddIceCandidateFailNoRemoteDescription));
Steve Antonf1c6db12017-10-13 11:13:35 -0700436}
437
Steve Antonc79268f2018-04-24 09:54:10 -0700438TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
439 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
440
441 auto caller = CreatePeerConnectionWithAudioVideo();
442 auto callee = CreatePeerConnectionWithAudioVideo();
443
444 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
445
446 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
447 auto* audio_content = cricket::GetFirstAudioContent(
448 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700449 std::unique_ptr<IceCandidateInterface> jsep_candidate =
450 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700451
452 caller->pc()->Close();
453
Steve Anton27ab0e52018-07-23 15:11:53 -0700454 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700455}
456
Steve Anton46d926a2018-01-23 10:23:06 -0800457TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700458 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
459
460 auto caller = CreatePeerConnectionWithAudioVideo();
461 auto callee = CreatePeerConnectionWithAudioVideo();
462
463 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
464 ASSERT_TRUE(
465 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
466
467 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
468 caller->AddIceCandidate(&candidate);
469 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
470 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
471}
472
Steve Anton46d926a2018-01-23 10:23:06 -0800473TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700474 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
475 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
476
477 auto caller = CreatePeerConnectionWithAudioVideo();
478 auto callee = CreatePeerConnectionWithAudioVideo();
479
480 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
481
482 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
483 auto* audio_content = cricket::GetFirstAudioContent(
484 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700485 std::unique_ptr<IceCandidateInterface> ice_candidate =
486 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700487
Steve Anton27ab0e52018-07-23 15:11:53 -0700488 ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700489
490 caller->pc()->Close();
491
492 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
493}
494
495TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700496 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
497 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
498
499 auto caller = CreatePeerConnectionWithAudioVideo();
500 auto callee = CreatePeerConnectionWithAudioVideo();
501
502 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
503 ASSERT_TRUE(
504 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
505
506 // |candidate.transport_name()| is empty.
507 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800508 auto* audio_content = cricket::GetFirstAudioContent(
509 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700510 std::unique_ptr<IceCandidateInterface> ice_candidate =
511 CreateIceCandidate(audio_content->name, 0, candidate);
512 EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700513 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
514}
515
Steve Anton46d926a2018-01-23 10:23:06 -0800516TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700517 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
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 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
527 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
528 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
529 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
530}
531
532// Test that if a candidate is added via AddIceCandidate and via an updated
533// remote description, then both candidates appear in the stored remote
534// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800535TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700536 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
537 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
538 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
539
540 auto caller = CreatePeerConnectionWithAudioVideo();
541 auto callee = CreatePeerConnectionWithAudioVideo();
542
543 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
544 ASSERT_TRUE(
545 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
546
547 // Add one candidate via |AddIceCandidate|.
548 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
549 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
550
551 // Add the second candidate via a reoffer.
552 auto offer = caller->CreateOffer();
553 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
554 AddCandidateToFirstTransport(&candidate2, offer.get());
555
556 // Expect both candidates to appear in the callee's remote description.
557 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
558 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
559}
560
561// The follow test verifies that SetLocal/RemoteDescription fails when an offer
562// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
563// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
564// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800565TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Yves Gerey665174f2018-06-19 15:03:05 +0200566 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
567 int pwd_len) {
568 auto pc = CreatePeerConnectionWithAudioVideo();
569 auto offer = pc->CreateOffer();
570 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
571 std::string(pwd_len, 'x'));
572 return pc->SetLocalDescription(std::move(offer));
573 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700574
Yves Gerey665174f2018-06-19 15:03:05 +0200575 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
576 int pwd_len) {
577 auto pc = CreatePeerConnectionWithAudioVideo();
578 auto offer = pc->CreateOffer();
579 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
580 std::string(pwd_len, 'x'));
581 return pc->SetRemoteDescription(std::move(offer));
582 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700583
584 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
585 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
586 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
587 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
588 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
589 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
590 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
591 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
592 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
593 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
594 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
595 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
596}
597
598::testing::AssertionResult AssertIpInCandidates(
599 const char* address_expr,
600 const char* candidates_expr,
601 const SocketAddress& address,
602 const std::vector<IceCandidateInterface*> candidates) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200603 rtc::StringBuilder candidate_hosts;
Steve Antonf1c6db12017-10-13 11:13:35 -0700604 for (const auto* candidate : candidates) {
605 const auto& candidate_ip = candidate->candidate().address().ipaddr();
606 if (candidate_ip == address.ipaddr()) {
607 return ::testing::AssertionSuccess();
608 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200609 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700610 }
611 return ::testing::AssertionFailure()
612 << address_expr << " (host " << address.HostAsURIString()
613 << ") not in " << candidates_expr
614 << " which have the following address hosts:" << candidate_hosts.str();
615}
616
Steve Anton46d926a2018-01-23 10:23:06 -0800617TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700618 const SocketAddress kLocalAddress1("1.1.1.1", 0);
619 const SocketAddress kLocalAddress2("2.2.2.2", 0);
620
621 auto caller = CreatePeerConnectionWithAudioVideo();
622 caller->network()->AddInterface(kLocalAddress1);
623 caller->network()->AddInterface(kLocalAddress2);
624
625 caller->CreateOfferAndSetAsLocal();
626 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
627
628 auto candidates = caller->observer()->GetCandidatesByMline(0);
629 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
630 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
631}
632
Steve Anton46d926a2018-01-23 10:23:06 -0800633TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700634 const SocketAddress kCallerAddress("1.1.1.1", 1111);
635
636 auto caller = CreatePeerConnectionWithAudioVideo();
637 auto callee = CreatePeerConnectionWithAudioVideo();
638
639 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
640
641 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
642 callee->AddIceCandidate(&candidate);
643 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
644 ASSERT_EQ(1u, candidates.size());
645 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
646 candidates[0]->candidate());
647}
648
Steve Anton46d926a2018-01-23 10:23:06 -0800649TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700650 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
651 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
652
653 auto caller = CreatePeerConnectionWithAudioVideo();
654 auto callee = CreatePeerConnectionWithAudioVideo();
655
656 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
657 ASSERT_TRUE(
658 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
659
660 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
661 caller->AddIceCandidate(&candidate1);
662
663 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
664 caller->AddIceCandidate(&candidate2);
665
666 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
667 ASSERT_EQ(2u, candidates.size());
668 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
669 candidates[0]->candidate());
670 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
671 candidates[1]->candidate());
672}
673
Steve Anton46d926a2018-01-23 10:23:06 -0800674TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700675 const SocketAddress kLocalAddress("1.1.1.1", 0);
676
677 RTCConfiguration config;
678 config.continual_gathering_policy =
679 PeerConnectionInterface::GATHER_CONTINUALLY;
680 auto caller = CreatePeerConnectionWithAudioVideo(config);
681 caller->network()->AddInterface(kLocalAddress);
682
683 // Start ICE candidate gathering by setting the local offer.
684 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
685
686 // Since we're using continual gathering, we won't get "gathering done".
687 EXPECT_TRUE_WAIT(
688 caller->pc()->local_description()->candidates(0)->count() > 0,
689 kIceCandidatesTimeout);
690}
691
692// Test that when continual gathering is enabled, and a network interface goes
693// down, the candidate is signaled as removed and removed from the local
694// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800695TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700696 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
697 const SocketAddress kLocalAddress("1.1.1.1", 0);
698
699 RTCConfiguration config;
700 config.continual_gathering_policy =
701 PeerConnectionInterface::GATHER_CONTINUALLY;
702 auto caller = CreatePeerConnectionWithAudioVideo(config);
703 caller->network()->AddInterface(kLocalAddress);
704
705 // Start ICE candidate gathering by setting the local offer.
706 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
707
708 EXPECT_TRUE_WAIT(
709 caller->pc()->local_description()->candidates(0)->count() > 0,
710 kIceCandidatesTimeout);
711
712 // Remove the only network interface, causing the PeerConnection to signal
713 // the removal of all candidates derived from this interface.
714 caller->network()->RemoveInterface(kLocalAddress);
715
716 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
717 kIceCandidatesTimeout);
718 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
719}
720
Steve Anton46d926a2018-01-23 10:23:06 -0800721TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700722 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
723 const SocketAddress kLocalAddress("1.1.1.1", 0);
724
725 RTCConfiguration config;
726 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
727 auto caller = CreatePeerConnectionWithAudioVideo(config);
728 caller->network()->AddInterface(kLocalAddress);
729
730 // Start ICE candidate gathering by setting the local offer.
731 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
732
733 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
734
735 caller->network()->RemoveInterface(kLocalAddress);
736
737 // Verify that the local candidates are not removed;
738 rtc::Thread::Current()->ProcessMessages(1000);
739 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
740}
741
742// The following group tests that when an offer includes a new ufrag or pwd
743// (indicating an ICE restart) the old candidates are removed and new candidates
744// added to the remote description.
745
Steve Anton46d926a2018-01-23 10:23:06 -0800746TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700747 const SocketAddress kCallerAddress("1.1.1.1", 1111);
748
749 auto caller = CreatePeerConnectionWithAudioVideo();
750 auto callee = CreatePeerConnectionWithAudioVideo();
751
752 auto offer = caller->CreateOffer();
753 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
754 AddCandidateToFirstTransport(&candidate, offer.get());
755
756 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
757
758 RTCOfferAnswerOptions options;
759 options.ice_restart = true;
760 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer(options)));
761
762 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
763}
Steve Anton46d926a2018-01-23 10:23:06 -0800764TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700765 IceRestartOfferCandidateReplacesExistingCandidate) {
766 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
767 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
768
769 auto caller = CreatePeerConnectionWithAudioVideo();
770 auto callee = CreatePeerConnectionWithAudioVideo();
771
772 auto offer = caller->CreateOffer();
773 cricket::Candidate old_candidate =
774 CreateLocalUdpCandidate(kFirstCallerAddress);
775 AddCandidateToFirstTransport(&old_candidate, offer.get());
776
777 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
778
779 RTCOfferAnswerOptions options;
780 options.ice_restart = true;
781 auto restart_offer = caller->CreateOffer(options);
782 cricket::Candidate new_candidate =
783 CreateLocalUdpCandidate(kRestartedCallerAddress);
784 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
785
786 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
787
788 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
789 ASSERT_EQ(1u, remote_candidates.size());
790 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
791 remote_candidates[0]->candidate());
792}
793
794// Test that if there is not an ICE restart (i.e., nothing changes), then the
795// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800796TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700797 auto caller = CreatePeerConnectionWithAudioVideo();
798 auto callee = CreatePeerConnectionWithAudioVideo();
799
800 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
801 ASSERT_TRUE(
802 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
803
804 // Re-offer.
805 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
806
807 auto answer = callee->CreateAnswer();
808 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
809 auto* local_transport_desc =
810 GetFirstTransportDescription(callee->pc()->local_description());
811
812 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
813 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
814}
815
816// The following parameterized test verifies that if an offer is sent with a
817// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
818// other side has initiated an ICE restart and generate a new ufrag and pwd.
819// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
820// a=ice-pwd attributes compared to the previous SDP from the peer, it
821// indicates that ICE is restarting for this media stream."
822
Steve Anton46d926a2018-01-23 10:23:06 -0800823class PeerConnectionIceUfragPwdAnswerTest
824 : public PeerConnectionIceBaseTest,
825 public ::testing::WithParamInterface<
826 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -0700827 protected:
Steve Anton46d926a2018-01-23 10:23:06 -0800828 PeerConnectionIceUfragPwdAnswerTest()
829 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
830 auto param = std::get<1>(GetParam());
831 offer_new_ufrag_ = std::get<0>(param);
832 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -0700833 }
834
835 bool offer_new_ufrag_;
836 bool offer_new_pwd_;
837};
838
Steve Anton46d926a2018-01-23 10:23:06 -0800839TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700840 auto caller = CreatePeerConnectionWithAudioVideo();
841 auto callee = CreatePeerConnectionWithAudioVideo();
842
843 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
844 ASSERT_TRUE(
845 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
846
847 auto offer = caller->CreateOffer();
848 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
849 if (offer_new_ufrag_) {
850 offer_transport_desc->ice_ufrag += "_new";
851 }
852 if (offer_new_pwd_) {
853 offer_transport_desc->ice_pwd += "_new";
854 }
855
856 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
857
858 auto answer = callee->CreateAnswer();
859 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
860 auto* local_transport_desc =
861 GetFirstTransportDescription(callee->pc()->local_description());
862
863 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
864 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
865}
866
867INSTANTIATE_TEST_CASE_P(
Steve Anton46d926a2018-01-23 10:23:06 -0800868 PeerConnectionIceTest,
869 PeerConnectionIceUfragPwdAnswerTest,
870 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
871 Values(std::make_pair(true, true), // Both changed.
872 std::make_pair(true, false), // Only ufrag changed.
873 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -0700874
875// Test that if an ICE restart is offered on one media section, then the answer
876// will only change ICE ufrag/pwd for that section and keep the other sections
877// the same.
878// Note that this only works if we have disabled BUNDLE, otherwise all media
879// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -0800880TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700881 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
882 auto caller = CreatePeerConnectionWithAudioVideo();
883 auto callee = CreatePeerConnectionWithAudioVideo();
884
885 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
886 ASSERT_TRUE(
887 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
888
889 RTCOfferAnswerOptions disable_bundle_options;
890 disable_bundle_options.use_rtp_mux = false;
891
892 auto offer = caller->CreateOffer(disable_bundle_options);
893
894 // Signal ICE restart on the first media section.
895 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
896 offer_transport_desc->ice_ufrag += "_new";
897 offer_transport_desc->ice_pwd += "_new";
898
899 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
900
901 auto answer = callee->CreateAnswer(disable_bundle_options);
902 const auto& answer_transports = answer->description()->transport_infos();
903 const auto& local_transports =
904 callee->pc()->local_description()->description()->transport_infos();
905
906 EXPECT_NE(answer_transports[0].description.ice_ufrag,
907 local_transports[0].description.ice_ufrag);
908 EXPECT_NE(answer_transports[0].description.ice_pwd,
909 local_transports[0].description.ice_pwd);
910 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
911 local_transports[1].description.ice_ufrag);
912 EXPECT_EQ(answer_transports[1].description.ice_pwd,
913 local_transports[1].description.ice_pwd);
914}
915
Qingsi Wange1692722017-11-29 13:27:20 -0800916// Test that when the initial offerer (caller) uses the lite implementation of
917// ICE and the callee uses the full implementation, the caller takes the
918// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
919// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800920TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800921 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
922 auto caller = CreatePeerConnectionWithAudioVideo();
923 auto callee = CreatePeerConnectionWithAudioVideo();
924
925 auto offer = caller->CreateOffer();
926 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
927 ASSERT_TRUE(
928 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
929 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
930
931 auto answer = callee->CreateAnswer();
932 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
933 ASSERT_TRUE(
934 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
935 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
936
937 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
938 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
939}
940
941// Test that when the caller and the callee both use the lite implementation of
942// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
943// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -0800944TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -0800945 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
946 auto caller = CreatePeerConnectionWithAudioVideo();
947 auto callee = CreatePeerConnectionWithAudioVideo();
948
949 auto offer = caller->CreateOffer();
950 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
951 ASSERT_TRUE(
952 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
953 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
954
955 auto answer = callee->CreateAnswer();
956 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
957 ASSERT_TRUE(
958 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
959 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
960
961 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
962 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
963}
964
Steve Anton46d926a2018-01-23 10:23:06 -0800965INSTANTIATE_TEST_CASE_P(PeerConnectionIceTest,
966 PeerConnectionIceTest,
967 Values(SdpSemantics::kPlanB,
968 SdpSemantics::kUnifiedPlan));
969
Qingsi Wang4ff54432018-03-01 18:25:20 -0800970class PeerConnectionIceConfigTest : public testing::Test {
971 protected:
972 void SetUp() override {
973 pc_factory_ = CreatePeerConnectionFactory(
974 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
975 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +0200976 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
977 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
978 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -0800979 }
980 void CreatePeerConnection(const RTCConfiguration& config) {
981 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
982 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
983 port_allocator_ = port_allocator.get();
984 rtc::scoped_refptr<PeerConnectionInterface> pc(
Niels Möllerf06f9232018-08-07 12:32:18 +0200985 pc_factory_->CreatePeerConnection(config, std::move(port_allocator),
986 nullptr /* cert_generator */,
987 &observer_));
Qingsi Wang4ff54432018-03-01 18:25:20 -0800988 EXPECT_TRUE(pc.get());
989 pc_ = std::move(pc.get());
990 }
991
992 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
993 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
994 cricket::FakePortAllocator* port_allocator_ = nullptr;
995
996 MockPeerConnectionObserver observer_;
997};
998
999TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
1000 RTCConfiguration config;
1001 config.stun_candidate_keepalive_interval = 123;
1002 config.ice_candidate_pool_size = 1;
1003 CreatePeerConnection(config);
1004 ASSERT_NE(port_allocator_, nullptr);
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001005 absl::optional<int> actual_stun_keepalive_interval =
Qingsi Wang4ff54432018-03-01 18:25:20 -08001006 port_allocator_->stun_candidate_keepalive_interval();
1007 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1008 config.stun_candidate_keepalive_interval = 321;
1009 RTCError error;
1010 pc_->SetConfiguration(config, &error);
1011 actual_stun_keepalive_interval =
1012 port_allocator_->stun_candidate_keepalive_interval();
1013 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1014}
1015
Jonas Oreland1cd39fa2018-10-11 07:47:12 +02001016TEST_P(PeerConnectionIceTest, IceCredentialsCreateOffer) {
1017 RTCConfiguration config;
1018 config.ice_candidate_pool_size = 1;
1019 auto pc = CreatePeerConnectionWithAudioVideo(config);
1020 ASSERT_NE(pc->port_allocator_, nullptr);
1021 auto offer = pc->CreateOffer();
1022 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1023 ASSERT_EQ(1u, credentials.size());
1024
1025 auto* desc = offer->description();
1026 for (const auto& content : desc->contents()) {
1027 auto* transport_info = desc->GetTransportInfoByName(content.name);
1028 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1029 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1030 }
1031}
1032
1033TEST_P(PeerConnectionIceTest, IceCredentialsCreateAnswer) {
1034 RTCConfiguration config;
1035 config.ice_candidate_pool_size = 1;
1036 auto pc = CreatePeerConnectionWithAudioVideo(config);
1037 ASSERT_NE(pc->port_allocator_, nullptr);
1038 auto offer = pc->CreateOffer();
1039 ASSERT_TRUE(pc->SetRemoteDescription(std::move(offer)));
1040 auto answer = pc->CreateAnswer();
1041
1042 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1043 ASSERT_EQ(1u, credentials.size());
1044
1045 auto* desc = answer->description();
1046 for (const auto& content : desc->contents()) {
1047 auto* transport_info = desc->GetTransportInfoByName(content.name);
1048 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1049 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1050 }
1051}
1052
Steve Antonf1c6db12017-10-13 11:13:35 -07001053} // namespace webrtc