blob: 61034d01388291c789f9727020c8d69ce49eecd5 [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
Mirko Bonadei317a1f02019-09-17 17:06:18 +020011#include <memory>
12
Steve Anton10542f22019-01-11 09:11:00 -080013#include "p2p/base/fake_port_allocator.h"
14#include "p2p/base/test_stun_server.h"
15#include "p2p/client/basic_port_allocator.h"
16#include "pc/media_session.h"
17#include "pc/peer_connection.h"
18#include "pc/peer_connection_wrapper.h"
19#include "pc/sdp_utils.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070020#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080021#include "pc/test/android_test_initializer.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070022#endif
Karl Wiberg1b0eae32017-10-17 14:48:54 +020023#include "api/audio_codecs/builtin_audio_decoder_factory.h"
24#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010025#include "api/create_peerconnection_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "api/peer_connection_proxy.h"
27#include "api/uma_metrics.h"
Anders Carlsson67537952018-05-03 11:28:29 +020028#include "api/video_codecs/builtin_video_decoder_factory.h"
29#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080030#include "pc/test/fake_audio_capture_module.h"
31#include "rtc_base/fake_network.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070032#include "rtc_base/gunit.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020033#include "rtc_base/strings/string_builder.h"
Steve Anton10542f22019-01-11 09:11:00 -080034#include "rtc_base/virtual_socket_server.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020035#include "system_wrappers/include/metrics.h"
Steve Antonb443dfe2019-03-05 14:09:49 -080036#include "test/gmock.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070037
38namespace webrtc {
39
40using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
41using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
42using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080043using ::testing::Combine;
Steve Antonb443dfe2019-03-05 14:09:49 -080044using ::testing::ElementsAre;
45using ::testing::Pair;
Steve Antonf1c6db12017-10-13 11:13:35 -070046using ::testing::Values;
47
48constexpr int kIceCandidatesTimeout = 10000;
49
Steve Anton46d926a2018-01-23 10:23:06 -080050class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070051 public:
52 using PeerConnectionWrapper::PeerConnectionWrapper;
53
54 // Adds a new ICE candidate to the first transport.
55 bool AddIceCandidate(cricket::Candidate* candidate) {
56 RTC_DCHECK(pc()->remote_description());
57 const auto* desc = pc()->remote_description()->description();
58 RTC_DCHECK(desc->contents().size() > 0);
59 const auto& first_content = desc->contents()[0];
60 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -070061 std::unique_ptr<IceCandidateInterface> jsep_candidate =
Guido Urdaneta41633172019-05-23 20:12:29 +020062 CreateIceCandidate(first_content.name, -1, *candidate);
Steve Anton27ab0e52018-07-23 15:11:53 -070063 return pc()->AddIceCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -070064 }
65
66 // Returns ICE candidates from the remote session description.
67 std::vector<const IceCandidateInterface*>
68 GetIceCandidatesFromRemoteDescription() {
69 const SessionDescriptionInterface* sdesc = pc()->remote_description();
70 RTC_DCHECK(sdesc);
71 std::vector<const IceCandidateInterface*> candidates;
72 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
73 mline_index++) {
74 const auto* candidate_collection = sdesc->candidates(mline_index);
75 for (size_t i = 0; i < candidate_collection->count(); i++) {
76 candidates.push_back(candidate_collection->at(i));
77 }
78 }
79 return candidates;
80 }
81
82 rtc::FakeNetworkManager* network() { return network_; }
83
84 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
85
Jonas Oreland1cd39fa2018-10-11 07:47:12 +020086 // The port allocator used by this PC.
87 cricket::PortAllocator* port_allocator_;
88
Steve Antonf1c6db12017-10-13 11:13:35 -070089 private:
90 rtc::FakeNetworkManager* network_;
91};
92
Steve Anton46d926a2018-01-23 10:23:06 -080093class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070094 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080095 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070096
Steve Anton46d926a2018-01-23 10:23:06 -080097 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
98 : vss_(new rtc::VirtualSocketServer()),
99 main_(vss_.get()),
100 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700101#ifdef WEBRTC_ANDROID
102 InitializeAndroidObjects();
103#endif
104 pc_factory_ = CreatePeerConnectionFactory(
105 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200106 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
107 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
108 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
109 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -0700110 }
111
112 WrapperPtr CreatePeerConnection() {
113 return CreatePeerConnection(RTCConfiguration());
114 }
115
116 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
117 auto* fake_network = NewFakeNetwork();
118 auto port_allocator =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200119 std::make_unique<cricket::BasicPortAllocator>(fake_network);
Steve Antonf1c6db12017-10-13 11:13:35 -0700120 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
121 cricket::PORTALLOCATOR_DISABLE_RELAY);
122 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800123 RTCConfiguration modified_config = config;
124 modified_config.sdp_semantics = sdp_semantics_;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200125 auto observer = std::make_unique<MockPeerConnectionObserver>();
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200126 auto port_allocator_copy = port_allocator.get();
Steve Antonf1c6db12017-10-13 11:13:35 -0700127 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800128 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700129 if (!pc) {
130 return nullptr;
131 }
132
Yves Gerey4e933292018-10-31 15:36:05 +0100133 observer->SetPeerConnectionInterface(pc.get());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200134 auto wrapper = std::make_unique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700135 pc_factory_, pc, std::move(observer));
136 wrapper->set_network(fake_network);
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200137 wrapper->port_allocator_ = port_allocator_copy;
Steve Antonf1c6db12017-10-13 11:13:35 -0700138 return wrapper;
139 }
140
141 // Accepts the same arguments as CreatePeerConnection and adds default audio
142 // and video tracks.
143 template <typename... Args>
144 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
145 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
146 if (!wrapper) {
147 return nullptr;
148 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700149 wrapper->AddAudioTrack("a");
150 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700151 return wrapper;
152 }
153
154 cricket::Candidate CreateLocalUdpCandidate(
155 const rtc::SocketAddress& address) {
156 cricket::Candidate candidate;
157 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
158 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
159 candidate.set_address(address);
160 candidate.set_type(cricket::LOCAL_PORT_TYPE);
161 return candidate;
162 }
163
164 // Remove all ICE ufrag/pwd lines from the given session description.
165 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
166 SetIceUfragPwd(sdesc, "", "");
167 }
168
169 // Sets all ICE ufrag/pwds on the given session description.
170 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
171 const std::string& ufrag,
172 const std::string& pwd) {
173 auto* desc = sdesc->description();
174 for (const auto& content : desc->contents()) {
175 auto* transport_info = desc->GetTransportInfoByName(content.name);
176 transport_info->description.ice_ufrag = ufrag;
177 transport_info->description.ice_pwd = pwd;
178 }
179 }
180
Qingsi Wange1692722017-11-29 13:27:20 -0800181 // Set ICE mode on the given session description.
182 void SetIceMode(SessionDescriptionInterface* sdesc,
183 const cricket::IceMode ice_mode) {
184 auto* desc = sdesc->description();
185 for (const auto& content : desc->contents()) {
186 auto* transport_info = desc->GetTransportInfoByName(content.name);
187 transport_info->description.ice_mode = ice_mode;
188 }
189 }
190
Steve Antonf1c6db12017-10-13 11:13:35 -0700191 cricket::TransportDescription* GetFirstTransportDescription(
192 SessionDescriptionInterface* sdesc) {
193 auto* desc = sdesc->description();
194 RTC_DCHECK(desc->contents().size() > 0);
195 auto* transport_info =
196 desc->GetTransportInfoByName(desc->contents()[0].name);
197 RTC_DCHECK(transport_info);
198 return &transport_info->description;
199 }
200
201 const cricket::TransportDescription* GetFirstTransportDescription(
202 const SessionDescriptionInterface* sdesc) {
203 auto* desc = sdesc->description();
204 RTC_DCHECK(desc->contents().size() > 0);
205 auto* transport_info =
206 desc->GetTransportInfoByName(desc->contents()[0].name);
207 RTC_DCHECK(transport_info);
208 return &transport_info->description;
209 }
210
Qingsi Wange1692722017-11-29 13:27:20 -0800211 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
212 // after it is implemented.
213 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100214 auto* pc_proxy =
215 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
216 pc_wrapper_ptr->pc());
217 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Mirko Bonadei739baf02019-01-27 17:29:42 +0100218 for (const auto& transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800219 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Bjorn A Mellem3a1b9272019-05-24 16:13:08 -0700220 auto dtls_transport = pc->LookupDtlsTransportByMidInternal(
221 transceiver->internal()->channel()->content_name());
222 return dtls_transport->ice_transport()->internal()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800223 }
224 }
225 RTC_NOTREACHED();
226 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800227 }
228
Henrik Boström79b69802019-07-18 11:16:56 +0200229 // Returns a list of (ufrag, pwd) pairs in the order that they appear in
230 // |description|, or the empty list if |description| is null.
231 std::vector<std::pair<std::string, std::string>> GetIceCredentials(
232 const SessionDescriptionInterface* description) {
233 std::vector<std::pair<std::string, std::string>> ice_credentials;
234 if (!description)
235 return ice_credentials;
236 const auto* desc = description->description();
237 for (const auto& content_info : desc->contents()) {
238 const auto* transport_info =
239 desc->GetTransportInfoByName(content_info.name);
240 if (transport_info) {
241 ice_credentials.push_back(
242 std::make_pair(transport_info->description.ice_ufrag,
243 transport_info->description.ice_pwd));
244 }
245 }
246 return ice_credentials;
247 }
248
Steve Antonf1c6db12017-10-13 11:13:35 -0700249 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
250 SessionDescriptionInterface* sdesc) {
251 auto* desc = sdesc->description();
252 RTC_DCHECK(desc->contents().size() > 0);
253 const auto& first_content = desc->contents()[0];
254 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -0700255 std::unique_ptr<IceCandidateInterface> jsep_candidate =
256 CreateIceCandidate(first_content.name, 0, *candidate);
257 return sdesc->AddCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700258 }
259
260 rtc::FakeNetworkManager* NewFakeNetwork() {
261 // The PeerConnection's port allocator is tied to the PeerConnection's
262 // lifetime and expects the underlying NetworkManager to outlive it. That
263 // prevents us from having the PeerConnectionWrapper own the fake network.
264 // Therefore, the test fixture will own all the fake networks even though
265 // tests should access the fake network through the PeerConnectionWrapper.
266 auto* fake_network = new rtc::FakeNetworkManager();
267 fake_networks_.emplace_back(fake_network);
268 return fake_network;
269 }
270
271 std::unique_ptr<rtc::VirtualSocketServer> vss_;
272 rtc::AutoSocketServerThread main_;
273 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
274 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800275 const SdpSemantics sdp_semantics_;
276};
277
278class PeerConnectionIceTest
279 : public PeerConnectionIceBaseTest,
280 public ::testing::WithParamInterface<SdpSemantics> {
281 protected:
Harald Alvestrand76829d72018-07-18 23:24:36 +0200282 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
283 webrtc::metrics::Reset();
284 }
Steve Antonf1c6db12017-10-13 11:13:35 -0700285};
286
287::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
288 const char* b_expr,
289 const cricket::Candidate& a,
290 const cricket::Candidate& b) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200291 rtc::StringBuilder failure_info;
Steve Antonf1c6db12017-10-13 11:13:35 -0700292 if (a.component() != b.component()) {
293 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
294 }
295 if (a.protocol() != b.protocol()) {
296 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
297 }
298 if (a.address() != b.address()) {
299 failure_info << "\naddress: " << a.address().ToString()
300 << " != " << b.address().ToString();
301 }
302 if (a.type() != b.type()) {
303 failure_info << "\ntype: " << a.type() << " != " << b.type();
304 }
305 std::string failure_info_str = failure_info.str();
306 if (failure_info_str.empty()) {
307 return ::testing::AssertionSuccess();
308 } else {
309 return ::testing::AssertionFailure()
310 << a_expr << " and " << b_expr << " are not equal"
311 << failure_info_str;
312 }
313}
314
Steve Anton46d926a2018-01-23 10:23:06 -0800315TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700316 const SocketAddress kLocalAddress("1.1.1.1", 0);
317
318 auto caller = CreatePeerConnectionWithAudioVideo();
319 caller->network()->AddInterface(kLocalAddress);
320
321 // Start ICE candidate gathering by setting the local offer.
322 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
323
324 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
325
326 auto offer = caller->CreateOffer();
327 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
328 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
329 offer->candidates(0)->count());
330 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
331 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
332 offer->candidates(1)->count());
333}
334
Steve Anton46d926a2018-01-23 10:23:06 -0800335TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700336 const SocketAddress kCallerAddress("1.1.1.1", 0);
337
338 auto caller = CreatePeerConnectionWithAudioVideo();
339 auto callee = CreatePeerConnectionWithAudioVideo();
340 caller->network()->AddInterface(kCallerAddress);
341
342 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
343 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
344
345 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
346
Steve Antondffead82018-02-06 10:31:29 -0800347 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700348 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
349 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
350 answer->candidates(0)->count());
351 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
352 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
353 answer->candidates(1)->count());
354}
355
Steve Anton46d926a2018-01-23 10:23:06 -0800356TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700357 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
358 const SocketAddress kCallerAddress("1.1.1.1", 1111);
359
360 auto caller = CreatePeerConnectionWithAudioVideo();
361 auto callee = CreatePeerConnectionWithAudioVideo();
362
363 auto offer = caller->CreateOfferAndSetAsLocal();
364 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
365 AddCandidateToFirstTransport(&candidate, offer.get());
366
367 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
368 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
369 ASSERT_EQ(1u, remote_candidates.size());
370 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
371 remote_candidates[0]->candidate());
372}
373
Steve Anton46d926a2018-01-23 10:23:06 -0800374TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700375 auto caller = CreatePeerConnectionWithAudioVideo();
376
377 auto offer = caller->CreateOffer();
378 RemoveIceUfragPwd(offer.get());
379
380 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
381}
382
Steve Anton46d926a2018-01-23 10:23:06 -0800383TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700384 auto caller = CreatePeerConnectionWithAudioVideo();
385 auto callee = CreatePeerConnectionWithAudioVideo();
386
387 auto offer = caller->CreateOfferAndSetAsLocal();
388 RemoveIceUfragPwd(offer.get());
389
390 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
391}
392
Steve Antonf764cf42018-05-01 14:32:17 -0700393// Test that doing an offer/answer exchange with no transport (i.e., no data
394// channel or media) results in the ICE connection state staying at New.
395TEST_P(PeerConnectionIceTest,
396 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
397 auto caller = CreatePeerConnection();
398 auto callee = CreatePeerConnection();
399
400 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
401
402 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
403 caller->pc()->ice_connection_state());
404 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
405 callee->pc()->ice_connection_state());
406}
407
Steve Antonf1c6db12017-10-13 11:13:35 -0700408// The following group tests that ICE candidates are not generated before
409// SetLocalDescription is called on a PeerConnection.
410
Steve Anton46d926a2018-01-23 10:23:06 -0800411TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700412 const SocketAddress kLocalAddress("1.1.1.1", 0);
413
414 auto caller = CreatePeerConnectionWithAudioVideo();
415 caller->network()->AddInterface(kLocalAddress);
416
417 // Pump for 1 second and verify that no candidates are generated.
418 rtc::Thread::Current()->ProcessMessages(1000);
419
420 EXPECT_EQ(0u, caller->observer()->candidates_.size());
421}
Steve Anton46d926a2018-01-23 10:23:06 -0800422TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700423 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
424 const SocketAddress kCallerAddress("1.1.1.1", 1111);
425
426 auto caller = CreatePeerConnectionWithAudioVideo();
427 auto callee = CreatePeerConnectionWithAudioVideo();
428 caller->network()->AddInterface(kCallerAddress);
429
430 auto offer = caller->CreateOfferAndSetAsLocal();
431 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
432 AddCandidateToFirstTransport(&candidate, offer.get());
433 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
434
435 // Pump for 1 second and verify that no candidates are generated.
436 rtc::Thread::Current()->ProcessMessages(1000);
437
438 EXPECT_EQ(0u, callee->observer()->candidates_.size());
439}
440
Steve Anton46d926a2018-01-23 10:23:06 -0800441TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700442 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
443
444 auto caller = CreatePeerConnectionWithAudioVideo();
445 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton27ab0e52018-07-23 15:11:53 -0700446 std::unique_ptr<IceCandidateInterface> jsep_candidate =
447 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700448
Steve Anton27ab0e52018-07-23 15:11:53 -0700449 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700450
451 caller->CreateOfferAndSetAsLocal();
452
Steve Anton27ab0e52018-07-23 15:11:53 -0700453 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonb443dfe2019-03-05 14:09:49 -0800454 EXPECT_THAT(webrtc::metrics::Samples("WebRTC.PeerConnection.AddIceCandidate"),
455 ElementsAre(Pair(kAddIceCandidateFailNoRemoteDescription, 2)));
Steve Antonf1c6db12017-10-13 11:13:35 -0700456}
457
Steve Antonc79268f2018-04-24 09:54:10 -0700458TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
459 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
460
461 auto caller = CreatePeerConnectionWithAudioVideo();
462 auto callee = CreatePeerConnectionWithAudioVideo();
463
464 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
465
466 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
467 auto* audio_content = cricket::GetFirstAudioContent(
468 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700469 std::unique_ptr<IceCandidateInterface> jsep_candidate =
470 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700471
472 caller->pc()->Close();
473
Steve Anton27ab0e52018-07-23 15:11:53 -0700474 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700475}
476
Steve Anton46d926a2018-01-23 10:23:06 -0800477TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700478 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
479
480 auto caller = CreatePeerConnectionWithAudioVideo();
481 auto callee = CreatePeerConnectionWithAudioVideo();
482
483 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
484 ASSERT_TRUE(
485 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
486
487 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
488 caller->AddIceCandidate(&candidate);
489 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
490 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
491}
492
Steve Anton46d926a2018-01-23 10:23:06 -0800493TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700494 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
495 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
496
497 auto caller = CreatePeerConnectionWithAudioVideo();
498 auto callee = CreatePeerConnectionWithAudioVideo();
499
500 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
501
502 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
503 auto* audio_content = cricket::GetFirstAudioContent(
504 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700505 std::unique_ptr<IceCandidateInterface> ice_candidate =
506 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700507
Steve Anton27ab0e52018-07-23 15:11:53 -0700508 ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700509
510 caller->pc()->Close();
511
512 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
513}
514
515TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700516 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
517 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 // |candidate.transport_name()| is empty.
527 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800528 auto* audio_content = cricket::GetFirstAudioContent(
529 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700530 std::unique_ptr<IceCandidateInterface> ice_candidate =
531 CreateIceCandidate(audio_content->name, 0, candidate);
532 EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700533 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
534}
535
Steve Anton46d926a2018-01-23 10:23:06 -0800536TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700537 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
538
539 auto caller = CreatePeerConnectionWithAudioVideo();
540 auto callee = CreatePeerConnectionWithAudioVideo();
541
542 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
543 ASSERT_TRUE(
544 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
545
546 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
547 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
548 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
549 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
550}
551
552// Test that if a candidate is added via AddIceCandidate and via an updated
553// remote description, then both candidates appear in the stored remote
554// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800555TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700556 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
557 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
558 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
559
560 auto caller = CreatePeerConnectionWithAudioVideo();
561 auto callee = CreatePeerConnectionWithAudioVideo();
562
563 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
564 ASSERT_TRUE(
565 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
566
567 // Add one candidate via |AddIceCandidate|.
568 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
569 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
570
571 // Add the second candidate via a reoffer.
572 auto offer = caller->CreateOffer();
573 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
574 AddCandidateToFirstTransport(&candidate2, offer.get());
575
576 // Expect both candidates to appear in the callee's remote description.
577 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
578 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
579}
580
581// The follow test verifies that SetLocal/RemoteDescription fails when an offer
582// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
583// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
584// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800585TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Yves Gerey665174f2018-06-19 15:03:05 +0200586 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
587 int pwd_len) {
588 auto pc = CreatePeerConnectionWithAudioVideo();
589 auto offer = pc->CreateOffer();
590 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
591 std::string(pwd_len, 'x'));
592 return pc->SetLocalDescription(std::move(offer));
593 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700594
Yves Gerey665174f2018-06-19 15:03:05 +0200595 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
596 int pwd_len) {
597 auto pc = CreatePeerConnectionWithAudioVideo();
598 auto offer = pc->CreateOffer();
599 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
600 std::string(pwd_len, 'x'));
601 return pc->SetRemoteDescription(std::move(offer));
602 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700603
604 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
605 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
606 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
607 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
608 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
609 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
610 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
611 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
612 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
613 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
614 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
615 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
616}
617
618::testing::AssertionResult AssertIpInCandidates(
619 const char* address_expr,
620 const char* candidates_expr,
621 const SocketAddress& address,
622 const std::vector<IceCandidateInterface*> candidates) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200623 rtc::StringBuilder candidate_hosts;
Steve Antonf1c6db12017-10-13 11:13:35 -0700624 for (const auto* candidate : candidates) {
625 const auto& candidate_ip = candidate->candidate().address().ipaddr();
626 if (candidate_ip == address.ipaddr()) {
627 return ::testing::AssertionSuccess();
628 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200629 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700630 }
631 return ::testing::AssertionFailure()
632 << address_expr << " (host " << address.HostAsURIString()
633 << ") not in " << candidates_expr
634 << " which have the following address hosts:" << candidate_hosts.str();
635}
636
Steve Anton46d926a2018-01-23 10:23:06 -0800637TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700638 const SocketAddress kLocalAddress1("1.1.1.1", 0);
639 const SocketAddress kLocalAddress2("2.2.2.2", 0);
640
641 auto caller = CreatePeerConnectionWithAudioVideo();
642 caller->network()->AddInterface(kLocalAddress1);
643 caller->network()->AddInterface(kLocalAddress2);
644
645 caller->CreateOfferAndSetAsLocal();
646 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
647
648 auto candidates = caller->observer()->GetCandidatesByMline(0);
649 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
650 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
651}
652
Steve Anton46d926a2018-01-23 10:23:06 -0800653TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700654 const SocketAddress kCallerAddress("1.1.1.1", 1111);
655
656 auto caller = CreatePeerConnectionWithAudioVideo();
657 auto callee = CreatePeerConnectionWithAudioVideo();
658
659 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
660
661 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
662 callee->AddIceCandidate(&candidate);
663 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
664 ASSERT_EQ(1u, candidates.size());
665 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
666 candidates[0]->candidate());
667}
668
Steve Anton46d926a2018-01-23 10:23:06 -0800669TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700670 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
671 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
672
673 auto caller = CreatePeerConnectionWithAudioVideo();
674 auto callee = CreatePeerConnectionWithAudioVideo();
675
676 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
677 ASSERT_TRUE(
678 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
679
680 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
681 caller->AddIceCandidate(&candidate1);
682
683 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
684 caller->AddIceCandidate(&candidate2);
685
686 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
687 ASSERT_EQ(2u, candidates.size());
688 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
689 candidates[0]->candidate());
690 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
691 candidates[1]->candidate());
692}
693
Steve Anton46d926a2018-01-23 10:23:06 -0800694TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700695 const SocketAddress kLocalAddress("1.1.1.1", 0);
696
697 RTCConfiguration config;
698 config.continual_gathering_policy =
699 PeerConnectionInterface::GATHER_CONTINUALLY;
700 auto caller = CreatePeerConnectionWithAudioVideo(config);
701 caller->network()->AddInterface(kLocalAddress);
702
703 // Start ICE candidate gathering by setting the local offer.
704 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
705
706 // Since we're using continual gathering, we won't get "gathering done".
707 EXPECT_TRUE_WAIT(
708 caller->pc()->local_description()->candidates(0)->count() > 0,
709 kIceCandidatesTimeout);
710}
711
712// Test that when continual gathering is enabled, and a network interface goes
713// down, the candidate is signaled as removed and removed from the local
714// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800715TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700716 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
717 const SocketAddress kLocalAddress("1.1.1.1", 0);
718
719 RTCConfiguration config;
720 config.continual_gathering_policy =
721 PeerConnectionInterface::GATHER_CONTINUALLY;
722 auto caller = CreatePeerConnectionWithAudioVideo(config);
723 caller->network()->AddInterface(kLocalAddress);
724
725 // Start ICE candidate gathering by setting the local offer.
726 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
727
728 EXPECT_TRUE_WAIT(
729 caller->pc()->local_description()->candidates(0)->count() > 0,
730 kIceCandidatesTimeout);
731
732 // Remove the only network interface, causing the PeerConnection to signal
733 // the removal of all candidates derived from this interface.
734 caller->network()->RemoveInterface(kLocalAddress);
735
736 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
737 kIceCandidatesTimeout);
738 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
739}
740
Steve Anton46d926a2018-01-23 10:23:06 -0800741TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700742 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
743 const SocketAddress kLocalAddress("1.1.1.1", 0);
744
745 RTCConfiguration config;
746 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
747 auto caller = CreatePeerConnectionWithAudioVideo(config);
748 caller->network()->AddInterface(kLocalAddress);
749
750 // Start ICE candidate gathering by setting the local offer.
751 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
752
753 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
754
755 caller->network()->RemoveInterface(kLocalAddress);
756
757 // Verify that the local candidates are not removed;
758 rtc::Thread::Current()->ProcessMessages(1000);
759 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
760}
761
762// The following group tests that when an offer includes a new ufrag or pwd
763// (indicating an ICE restart) the old candidates are removed and new candidates
764// added to the remote description.
765
Steve Anton46d926a2018-01-23 10:23:06 -0800766TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700767 const SocketAddress kCallerAddress("1.1.1.1", 1111);
768
769 auto caller = CreatePeerConnectionWithAudioVideo();
770 auto callee = CreatePeerConnectionWithAudioVideo();
771
Amit Hilbuchae3df542019-01-07 12:13:08 -0800772 auto offer = caller->CreateOfferAndSetAsLocal();
Steve Antonf1c6db12017-10-13 11:13:35 -0700773 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
774 AddCandidateToFirstTransport(&candidate, offer.get());
775
776 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
777
778 RTCOfferAnswerOptions options;
779 options.ice_restart = true;
Amit Hilbuchae3df542019-01-07 12:13:08 -0800780 ASSERT_TRUE(
781 callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
Steve Antonf1c6db12017-10-13 11:13:35 -0700782
783 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
784}
Steve Anton46d926a2018-01-23 10:23:06 -0800785TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700786 IceRestartOfferCandidateReplacesExistingCandidate) {
787 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
788 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
789
790 auto caller = CreatePeerConnectionWithAudioVideo();
791 auto callee = CreatePeerConnectionWithAudioVideo();
792
Amit Hilbuchae3df542019-01-07 12:13:08 -0800793 auto offer = caller->CreateOfferAndSetAsLocal();
Steve Antonf1c6db12017-10-13 11:13:35 -0700794 cricket::Candidate old_candidate =
795 CreateLocalUdpCandidate(kFirstCallerAddress);
796 AddCandidateToFirstTransport(&old_candidate, offer.get());
797
798 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
799
800 RTCOfferAnswerOptions options;
801 options.ice_restart = true;
Amit Hilbuchae3df542019-01-07 12:13:08 -0800802 auto restart_offer = caller->CreateOfferAndSetAsLocal(options);
Steve Antonf1c6db12017-10-13 11:13:35 -0700803 cricket::Candidate new_candidate =
804 CreateLocalUdpCandidate(kRestartedCallerAddress);
805 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
806
807 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
808
809 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
810 ASSERT_EQ(1u, remote_candidates.size());
811 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
812 remote_candidates[0]->candidate());
813}
814
815// Test that if there is not an ICE restart (i.e., nothing changes), then the
816// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800817TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700818 auto caller = CreatePeerConnectionWithAudioVideo();
819 auto callee = CreatePeerConnectionWithAudioVideo();
820
821 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
822 ASSERT_TRUE(
823 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
824
825 // Re-offer.
826 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
827
828 auto answer = callee->CreateAnswer();
829 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
830 auto* local_transport_desc =
831 GetFirstTransportDescription(callee->pc()->local_description());
832
833 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
834 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
835}
836
Henrik Boström79b69802019-07-18 11:16:56 +0200837TEST_P(PeerConnectionIceTest, RestartIceGeneratesNewCredentials) {
838 auto caller = CreatePeerConnectionWithAudioVideo();
839 auto callee = CreatePeerConnectionWithAudioVideo();
840
841 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
842 auto initial_ice_credentials =
843 GetIceCredentials(caller->pc()->local_description());
844 caller->pc()->RestartIce();
845 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
846 auto restarted_ice_credentials =
847 GetIceCredentials(caller->pc()->local_description());
848 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
849}
850
851TEST_P(PeerConnectionIceTest,
852 RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer) {
853 auto caller = CreatePeerConnectionWithAudioVideo();
854 auto callee = CreatePeerConnectionWithAudioVideo();
855
856 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
857 auto initial_ice_credentials =
858 GetIceCredentials(caller->pc()->local_description());
859 // ICE restart becomes needed while an O/A is pending and |caller| is the
860 // offerer.
861 caller->pc()->RestartIce();
862 ASSERT_TRUE(
863 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
864 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
865 auto restarted_ice_credentials =
866 GetIceCredentials(caller->pc()->local_description());
867 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
868}
869
870TEST_P(PeerConnectionIceTest,
871 RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer) {
872 auto caller = CreatePeerConnectionWithAudioVideo();
873 auto callee = CreatePeerConnectionWithAudioVideo();
874
875 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
876 auto initial_ice_credentials =
877 GetIceCredentials(caller->pc()->local_description());
878 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
879 // ICE restart becomes needed while an O/A is pending and |caller| is the
880 // answerer.
881 caller->pc()->RestartIce();
882 ASSERT_TRUE(
883 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
884 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
885 auto restarted_ice_credentials =
886 GetIceCredentials(caller->pc()->local_description());
887 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
888}
889
890TEST_P(PeerConnectionIceTest, RestartIceTriggeredByRemoteSide) {
891 auto caller = CreatePeerConnectionWithAudioVideo();
892 auto callee = CreatePeerConnectionWithAudioVideo();
893
894 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
895 auto initial_ice_credentials =
896 GetIceCredentials(caller->pc()->local_description());
897
898 // Remote restart and O/A exchange with |caller| as the answerer should
899 // restart ICE locally as well.
900 callee->pc()->RestartIce();
901 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
902
903 auto restarted_ice_credentials =
904 GetIceCredentials(caller->pc()->local_description());
905 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
906}
907
908TEST_P(PeerConnectionIceTest, RestartIceCausesNegotiationNeeded) {
909 auto caller = CreatePeerConnectionWithAudioVideo();
910 auto callee = CreatePeerConnectionWithAudioVideo();
911
912 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
913 caller->observer()->clear_negotiation_needed();
914 caller->pc()->RestartIce();
915 EXPECT_TRUE(caller->observer()->negotiation_needed());
916}
917
918// In Unified Plan, "onnegotiationneeded" is spec-compliant, including not
919// firing multipe times in a row, or firing when returning to the stable
920// signaling state if negotiation is still needed. In Plan B it fires any time
921// something changes. As such, some tests are SdpSemantics-specific.
922class PeerConnectionIceTestUnifiedPlan : public PeerConnectionIceBaseTest {
923 protected:
924 PeerConnectionIceTestUnifiedPlan()
925 : PeerConnectionIceBaseTest(SdpSemantics::kUnifiedPlan) {}
926};
927
928TEST_F(PeerConnectionIceTestUnifiedPlan,
929 RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable) {
930 auto caller = CreatePeerConnectionWithAudioVideo();
931 auto callee = CreatePeerConnectionWithAudioVideo();
932
933 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
934 // ICE restart becomes needed while an O/A is pending and |caller| is the
935 // offerer.
936 caller->observer()->clear_negotiation_needed();
937 caller->pc()->RestartIce();
938 // In Unified Plan, the event should not fire until we are back in the stable
939 // signaling state.
940 EXPECT_FALSE(caller->observer()->negotiation_needed());
941 ASSERT_TRUE(
942 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
943 EXPECT_TRUE(caller->observer()->negotiation_needed());
944}
945
946TEST_F(PeerConnectionIceTestUnifiedPlan,
947 RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable) {
948 auto caller = CreatePeerConnectionWithAudioVideo();
949 auto callee = CreatePeerConnectionWithAudioVideo();
950
951 // Establish initial credentials as the caller.
952 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
953 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
954 // ICE restart becomes needed while an O/A is pending and |caller| is the
955 // answerer.
956 caller->observer()->clear_negotiation_needed();
957 caller->pc()->RestartIce();
958 // In Unified Plan, the event should not fire until we are back in the stable
959 // signaling state.
960 EXPECT_FALSE(caller->observer()->negotiation_needed());
961 ASSERT_TRUE(
962 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
963 EXPECT_TRUE(caller->observer()->negotiation_needed());
964}
965
966TEST_F(PeerConnectionIceTestUnifiedPlan,
967 RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded) {
968 auto caller = CreatePeerConnectionWithAudioVideo();
969 auto callee = CreatePeerConnectionWithAudioVideo();
970
971 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
972 // Local restart.
973 caller->pc()->RestartIce();
974 caller->observer()->clear_negotiation_needed();
975 // Remote restart and O/A exchange with |caller| as the answerer should
976 // restart ICE locally as well.
977 callee->pc()->RestartIce();
978 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
979 // Having restarted ICE by the remote offer, we do not need to renegotiate ICE
980 // credentials when back in the stable signaling state.
981 EXPECT_FALSE(caller->observer()->negotiation_needed());
982}
983
984TEST_F(PeerConnectionIceTestUnifiedPlan,
985 RestartIceTwiceDoesNotFireNegotiationNeededTwice) {
986 auto caller = CreatePeerConnectionWithAudioVideo();
987 auto callee = CreatePeerConnectionWithAudioVideo();
988
989 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
990 caller->pc()->RestartIce();
991 EXPECT_TRUE(caller->observer()->negotiation_needed());
992 caller->observer()->clear_negotiation_needed();
993 caller->pc()->RestartIce();
994 EXPECT_FALSE(caller->observer()->negotiation_needed());
995}
996
997// In Plan B, "onnegotiationneeded" is not spec-compliant, firing based on if
998// something changed rather than if negotiation is needed. In Unified Plan it
999// fires according to spec. As such, some tests are SdpSemantics-specific.
1000class PeerConnectionIceTestPlanB : public PeerConnectionIceBaseTest {
1001 protected:
1002 PeerConnectionIceTestPlanB()
1003 : PeerConnectionIceBaseTest(SdpSemantics::kPlanB) {}
1004};
1005
1006TEST_F(PeerConnectionIceTestPlanB,
1007 RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately) {
1008 auto caller = CreatePeerConnectionWithAudioVideo();
1009 auto callee = CreatePeerConnectionWithAudioVideo();
1010
1011 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1012 caller->observer()->clear_negotiation_needed();
1013 caller->pc()->RestartIce();
1014 EXPECT_TRUE(caller->observer()->negotiation_needed());
1015 caller->observer()->clear_negotiation_needed();
1016 ASSERT_TRUE(
1017 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1018 // In Plan B, the event fired early so we don't expect it to fire now. This is
1019 // not spec-compliant but follows the pattern of existing Plan B behavior.
1020 EXPECT_FALSE(caller->observer()->negotiation_needed());
1021}
1022
1023TEST_F(PeerConnectionIceTestPlanB,
1024 RestartIceTwiceDoesFireNegotiationNeededTwice) {
1025 auto caller = CreatePeerConnectionWithAudioVideo();
1026 auto callee = CreatePeerConnectionWithAudioVideo();
1027
1028 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1029 caller->observer()->clear_negotiation_needed();
1030 caller->pc()->RestartIce();
1031 EXPECT_TRUE(caller->observer()->negotiation_needed());
1032 caller->observer()->clear_negotiation_needed();
1033 caller->pc()->RestartIce();
1034 // In Plan B, the event fires every time something changed, even if we have
1035 // already fired the event. This is not spec-compliant but follows the same
1036 // pattern of existing Plan B behavior.
1037 EXPECT_TRUE(caller->observer()->negotiation_needed());
1038}
1039
Steve Antonf1c6db12017-10-13 11:13:35 -07001040// The following parameterized test verifies that if an offer is sent with a
1041// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
1042// other side has initiated an ICE restart and generate a new ufrag and pwd.
1043// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
1044// a=ice-pwd attributes compared to the previous SDP from the peer, it
1045// indicates that ICE is restarting for this media stream."
1046
Steve Anton46d926a2018-01-23 10:23:06 -08001047class PeerConnectionIceUfragPwdAnswerTest
1048 : public PeerConnectionIceBaseTest,
1049 public ::testing::WithParamInterface<
1050 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -07001051 protected:
Steve Anton46d926a2018-01-23 10:23:06 -08001052 PeerConnectionIceUfragPwdAnswerTest()
1053 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
1054 auto param = std::get<1>(GetParam());
1055 offer_new_ufrag_ = std::get<0>(param);
1056 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -07001057 }
1058
1059 bool offer_new_ufrag_;
1060 bool offer_new_pwd_;
1061};
1062
Steve Anton46d926a2018-01-23 10:23:06 -08001063TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -07001064 auto caller = CreatePeerConnectionWithAudioVideo();
1065 auto callee = CreatePeerConnectionWithAudioVideo();
1066
1067 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1068 ASSERT_TRUE(
1069 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1070
1071 auto offer = caller->CreateOffer();
1072 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1073 if (offer_new_ufrag_) {
1074 offer_transport_desc->ice_ufrag += "_new";
1075 }
1076 if (offer_new_pwd_) {
1077 offer_transport_desc->ice_pwd += "_new";
1078 }
1079
1080 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1081
1082 auto answer = callee->CreateAnswer();
1083 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
1084 auto* local_transport_desc =
1085 GetFirstTransportDescription(callee->pc()->local_description());
1086
1087 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
1088 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
1089}
1090
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001091INSTANTIATE_TEST_SUITE_P(
Steve Anton46d926a2018-01-23 10:23:06 -08001092 PeerConnectionIceTest,
1093 PeerConnectionIceUfragPwdAnswerTest,
1094 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
1095 Values(std::make_pair(true, true), // Both changed.
1096 std::make_pair(true, false), // Only ufrag changed.
1097 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -07001098
1099// Test that if an ICE restart is offered on one media section, then the answer
1100// will only change ICE ufrag/pwd for that section and keep the other sections
1101// the same.
1102// Note that this only works if we have disabled BUNDLE, otherwise all media
1103// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -08001104TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -07001105 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
1106 auto caller = CreatePeerConnectionWithAudioVideo();
1107 auto callee = CreatePeerConnectionWithAudioVideo();
1108
1109 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1110 ASSERT_TRUE(
1111 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1112
1113 RTCOfferAnswerOptions disable_bundle_options;
1114 disable_bundle_options.use_rtp_mux = false;
1115
1116 auto offer = caller->CreateOffer(disable_bundle_options);
1117
1118 // Signal ICE restart on the first media section.
1119 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1120 offer_transport_desc->ice_ufrag += "_new";
1121 offer_transport_desc->ice_pwd += "_new";
1122
1123 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1124
1125 auto answer = callee->CreateAnswer(disable_bundle_options);
1126 const auto& answer_transports = answer->description()->transport_infos();
1127 const auto& local_transports =
1128 callee->pc()->local_description()->description()->transport_infos();
1129
1130 EXPECT_NE(answer_transports[0].description.ice_ufrag,
1131 local_transports[0].description.ice_ufrag);
1132 EXPECT_NE(answer_transports[0].description.ice_pwd,
1133 local_transports[0].description.ice_pwd);
1134 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
1135 local_transports[1].description.ice_ufrag);
1136 EXPECT_EQ(answer_transports[1].description.ice_pwd,
1137 local_transports[1].description.ice_pwd);
1138}
1139
Qingsi Wange1692722017-11-29 13:27:20 -08001140// Test that when the initial offerer (caller) uses the lite implementation of
1141// ICE and the callee uses the full implementation, the caller takes the
1142// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
1143// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -08001144TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -08001145 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
1146 auto caller = CreatePeerConnectionWithAudioVideo();
1147 auto callee = CreatePeerConnectionWithAudioVideo();
1148
1149 auto offer = caller->CreateOffer();
1150 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1151 ASSERT_TRUE(
1152 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1153 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1154
1155 auto answer = callee->CreateAnswer();
1156 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
1157 ASSERT_TRUE(
1158 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1159 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1160
1161 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
1162 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
1163}
1164
1165// Test that when the caller and the callee both use the lite implementation of
1166// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
1167// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -08001168TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -08001169 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
1170 auto caller = CreatePeerConnectionWithAudioVideo();
1171 auto callee = CreatePeerConnectionWithAudioVideo();
1172
1173 auto offer = caller->CreateOffer();
1174 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1175 ASSERT_TRUE(
1176 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1177 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1178
1179 auto answer = callee->CreateAnswer();
1180 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
1181 ASSERT_TRUE(
1182 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1183 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1184
1185 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
1186 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
1187}
1188
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001189INSTANTIATE_TEST_SUITE_P(PeerConnectionIceTest,
1190 PeerConnectionIceTest,
1191 Values(SdpSemantics::kPlanB,
1192 SdpSemantics::kUnifiedPlan));
Steve Anton46d926a2018-01-23 10:23:06 -08001193
Mirko Bonadei6a489f22019-04-09 15:11:12 +02001194class PeerConnectionIceConfigTest : public ::testing::Test {
Qingsi Wang4ff54432018-03-01 18:25:20 -08001195 protected:
1196 void SetUp() override {
1197 pc_factory_ = CreatePeerConnectionFactory(
1198 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
1199 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +02001200 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
1201 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
1202 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -08001203 }
1204 void CreatePeerConnection(const RTCConfiguration& config) {
1205 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
1206 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
1207 port_allocator_ = port_allocator.get();
1208 rtc::scoped_refptr<PeerConnectionInterface> pc(
Niels Möllerf06f9232018-08-07 12:32:18 +02001209 pc_factory_->CreatePeerConnection(config, std::move(port_allocator),
1210 nullptr /* cert_generator */,
1211 &observer_));
Qingsi Wang4ff54432018-03-01 18:25:20 -08001212 EXPECT_TRUE(pc.get());
Mirko Bonadei1c546052019-02-04 14:50:38 +01001213 pc_ = std::move(pc);
Qingsi Wang4ff54432018-03-01 18:25:20 -08001214 }
1215
1216 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
1217 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
1218 cricket::FakePortAllocator* port_allocator_ = nullptr;
1219
1220 MockPeerConnectionObserver observer_;
1221};
1222
1223TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
1224 RTCConfiguration config;
1225 config.stun_candidate_keepalive_interval = 123;
1226 config.ice_candidate_pool_size = 1;
1227 CreatePeerConnection(config);
1228 ASSERT_NE(port_allocator_, nullptr);
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001229 absl::optional<int> actual_stun_keepalive_interval =
Qingsi Wang4ff54432018-03-01 18:25:20 -08001230 port_allocator_->stun_candidate_keepalive_interval();
1231 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1232 config.stun_candidate_keepalive_interval = 321;
Niels Möller2579f0c2019-08-19 09:58:17 +02001233 ASSERT_TRUE(pc_->SetConfiguration(config).ok());
Qingsi Wang4ff54432018-03-01 18:25:20 -08001234 actual_stun_keepalive_interval =
1235 port_allocator_->stun_candidate_keepalive_interval();
1236 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1237}
1238
Jonas Oreland1cd39fa2018-10-11 07:47:12 +02001239TEST_P(PeerConnectionIceTest, IceCredentialsCreateOffer) {
1240 RTCConfiguration config;
1241 config.ice_candidate_pool_size = 1;
1242 auto pc = CreatePeerConnectionWithAudioVideo(config);
1243 ASSERT_NE(pc->port_allocator_, nullptr);
1244 auto offer = pc->CreateOffer();
1245 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1246 ASSERT_EQ(1u, credentials.size());
1247
1248 auto* desc = offer->description();
1249 for (const auto& content : desc->contents()) {
1250 auto* transport_info = desc->GetTransportInfoByName(content.name);
1251 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1252 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1253 }
1254}
1255
1256TEST_P(PeerConnectionIceTest, IceCredentialsCreateAnswer) {
1257 RTCConfiguration config;
1258 config.ice_candidate_pool_size = 1;
1259 auto pc = CreatePeerConnectionWithAudioVideo(config);
1260 ASSERT_NE(pc->port_allocator_, nullptr);
1261 auto offer = pc->CreateOffer();
1262 ASSERT_TRUE(pc->SetRemoteDescription(std::move(offer)));
1263 auto answer = pc->CreateAnswer();
1264
1265 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1266 ASSERT_EQ(1u, credentials.size());
1267
1268 auto* desc = answer->description();
1269 for (const auto& content : desc->contents()) {
1270 auto* transport_info = desc->GetTransportInfoByName(content.name);
1271 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1272 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1273 }
1274}
1275
Steve Antonf1c6db12017-10-13 11:13:35 -07001276} // namespace webrtc