blob: 16bd000dbebd5a1c791cc95af1629e89a32f12fe [file] [log] [blame]
Steve Anton6f25b092017-10-23 09:39:20 -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
Karl Wiberg32df86e2017-11-03 10:24:27 +010011#include "api/audio_codecs/builtin_audio_decoder_factory.h"
12#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Steve Anton6f25b092017-10-23 09:39:20 -070013#include "api/peerconnectionproxy.h"
14#include "p2p/base/fakeportallocator.h"
15#include "p2p/base/teststunserver.h"
16#include "p2p/client/basicportallocator.h"
17#include "pc/mediasession.h"
18#include "pc/peerconnection.h"
19#include "pc/peerconnectionwrapper.h"
20#include "pc/sdputils.h"
21#ifdef WEBRTC_ANDROID
22#include "pc/test/androidtestinitializer.h"
23#endif
24#include "pc/test/fakeaudiocapturemodule.h"
25#include "rtc_base/fakenetwork.h"
26#include "rtc_base/gunit.h"
27#include "rtc_base/ptr_util.h"
28#include "rtc_base/virtualsocketserver.h"
29#include "test/gmock.h"
30
31namespace webrtc {
32
33using BundlePolicy = PeerConnectionInterface::BundlePolicy;
34using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
35using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
36using RtcpMuxPolicy = PeerConnectionInterface::RtcpMuxPolicy;
37using rtc::SocketAddress;
Steve Anton7464fca2018-01-19 11:10:37 -080038using ::testing::Combine;
Steve Anton6f25b092017-10-23 09:39:20 -070039using ::testing::ElementsAre;
40using ::testing::UnorderedElementsAre;
41using ::testing::Values;
42
43constexpr int kDefaultTimeout = 10000;
44
45// TODO(steveanton): These tests should be rewritten to use the standard
46// RtpSenderInterface/DtlsTransportInterface objects once they're available in
47// the API. The RtpSender can be used to determine which transport a given media
48// will use: https://www.w3.org/TR/webrtc/#dom-rtcrtpsender-transport
Steve Anton7464fca2018-01-19 11:10:37 -080049// Should also be able to remove GetTransceiversForTesting at that point.
Steve Anton6f25b092017-10-23 09:39:20 -070050
51class PeerConnectionWrapperForBundleTest : public PeerConnectionWrapper {
52 public:
53 using PeerConnectionWrapper::PeerConnectionWrapper;
54
55 bool AddIceCandidateToMedia(cricket::Candidate* candidate,
56 cricket::MediaType media_type) {
57 auto* desc = pc()->remote_description()->description();
58 for (size_t i = 0; i < desc->contents().size(); i++) {
59 const auto& content = desc->contents()[i];
Steve Antonb1c1de12017-12-21 15:14:30 -080060 if (content.media_description()->type() == media_type) {
Steve Anton6f25b092017-10-23 09:39:20 -070061 candidate->set_transport_name(content.name);
62 JsepIceCandidate jsep_candidate(content.name, i, *candidate);
63 return pc()->AddIceCandidate(&jsep_candidate);
64 }
65 }
66 RTC_NOTREACHED();
67 return false;
68 }
69
70 rtc::PacketTransportInternal* voice_rtp_transport_channel() {
71 return (voice_channel() ? voice_channel()->rtp_dtls_transport() : nullptr);
72 }
73
74 rtc::PacketTransportInternal* voice_rtcp_transport_channel() {
75 return (voice_channel() ? voice_channel()->rtcp_dtls_transport() : nullptr);
76 }
77
78 cricket::VoiceChannel* voice_channel() {
Steve Antonb8867112018-02-13 10:07:54 -080079 auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
Steve Anton7464fca2018-01-19 11:10:37 -080080 for (auto transceiver : transceivers) {
Steve Anton69470252018-02-09 11:43:08 -080081 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton7464fca2018-01-19 11:10:37 -080082 return static_cast<cricket::VoiceChannel*>(
83 transceiver->internal()->channel());
84 }
85 }
86 return nullptr;
Steve Anton6f25b092017-10-23 09:39:20 -070087 }
88
89 rtc::PacketTransportInternal* video_rtp_transport_channel() {
90 return (video_channel() ? video_channel()->rtp_dtls_transport() : nullptr);
91 }
92
93 rtc::PacketTransportInternal* video_rtcp_transport_channel() {
94 return (video_channel() ? video_channel()->rtcp_dtls_transport() : nullptr);
95 }
96
97 cricket::VideoChannel* video_channel() {
Steve Antonb8867112018-02-13 10:07:54 -080098 auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
Steve Anton7464fca2018-01-19 11:10:37 -080099 for (auto transceiver : transceivers) {
Steve Anton69470252018-02-09 11:43:08 -0800100 if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
Steve Anton7464fca2018-01-19 11:10:37 -0800101 return static_cast<cricket::VideoChannel*>(
102 transceiver->internal()->channel());
103 }
104 }
105 return nullptr;
Steve Anton6f25b092017-10-23 09:39:20 -0700106 }
107
108 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100109 auto* pci =
110 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
111 pc());
112 return static_cast<PeerConnection*>(pci->internal());
Steve Anton6f25b092017-10-23 09:39:20 -0700113 }
114
115 // Returns true if the stats indicate that an ICE connection is either in
116 // progress or established with the given remote address.
117 bool HasConnectionWithRemoteAddress(const SocketAddress& address) {
118 auto report = GetStats();
119 if (!report) {
120 return false;
121 }
122 std::string matching_candidate_id;
123 for (auto* ice_candidate_stats :
124 report->GetStatsOfType<RTCRemoteIceCandidateStats>()) {
125 if (*ice_candidate_stats->ip == address.HostAsURIString() &&
126 *ice_candidate_stats->port == address.port()) {
127 matching_candidate_id = ice_candidate_stats->id();
128 break;
129 }
130 }
131 if (matching_candidate_id.empty()) {
132 return false;
133 }
134 for (auto* pair_stats :
135 report->GetStatsOfType<RTCIceCandidatePairStats>()) {
136 if (*pair_stats->remote_candidate_id == matching_candidate_id) {
137 if (*pair_stats->state == RTCStatsIceCandidatePairState::kInProgress ||
138 *pair_stats->state == RTCStatsIceCandidatePairState::kSucceeded) {
139 return true;
140 }
141 }
142 }
143 return false;
144 }
145
146 rtc::FakeNetworkManager* network() { return network_; }
147
148 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
149
150 private:
151 rtc::FakeNetworkManager* network_;
152};
153
Steve Anton7464fca2018-01-19 11:10:37 -0800154class PeerConnectionBundleBaseTest : public ::testing::Test {
Steve Anton6f25b092017-10-23 09:39:20 -0700155 protected:
156 typedef std::unique_ptr<PeerConnectionWrapperForBundleTest> WrapperPtr;
157
Steve Anton7464fca2018-01-19 11:10:37 -0800158 explicit PeerConnectionBundleBaseTest(SdpSemantics sdp_semantics)
159 : vss_(new rtc::VirtualSocketServer()),
160 main_(vss_.get()),
161 sdp_semantics_(sdp_semantics) {
Steve Anton6f25b092017-10-23 09:39:20 -0700162#ifdef WEBRTC_ANDROID
163 InitializeAndroidObjects();
164#endif
165 pc_factory_ = CreatePeerConnectionFactory(
166 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Karl Wiberg32df86e2017-11-03 10:24:27 +0100167 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
168 CreateBuiltinAudioDecoderFactory(), nullptr, nullptr);
Steve Anton6f25b092017-10-23 09:39:20 -0700169 }
170
171 WrapperPtr CreatePeerConnection() {
172 return CreatePeerConnection(RTCConfiguration());
173 }
174
175 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
176 auto* fake_network = NewFakeNetwork();
177 auto port_allocator =
178 rtc::MakeUnique<cricket::BasicPortAllocator>(fake_network);
179 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
180 cricket::PORTALLOCATOR_DISABLE_RELAY);
181 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
182 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
Steve Anton7464fca2018-01-19 11:10:37 -0800183 RTCConfiguration modified_config = config;
184 modified_config.sdp_semantics = sdp_semantics_;
Steve Anton6f25b092017-10-23 09:39:20 -0700185 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton7464fca2018-01-19 11:10:37 -0800186 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Anton6f25b092017-10-23 09:39:20 -0700187 if (!pc) {
188 return nullptr;
189 }
190
191 auto wrapper = rtc::MakeUnique<PeerConnectionWrapperForBundleTest>(
192 pc_factory_, pc, std::move(observer));
193 wrapper->set_network(fake_network);
194 return wrapper;
195 }
196
197 // Accepts the same arguments as CreatePeerConnection and adds default audio
198 // and video tracks.
199 template <typename... Args>
200 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
201 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
202 if (!wrapper) {
203 return nullptr;
204 }
205 wrapper->AddAudioTrack("a");
206 wrapper->AddVideoTrack("v");
207 return wrapper;
208 }
209
210 cricket::Candidate CreateLocalUdpCandidate(
211 const rtc::SocketAddress& address) {
212 cricket::Candidate candidate;
213 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
214 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
215 candidate.set_address(address);
216 candidate.set_type(cricket::LOCAL_PORT_TYPE);
217 return candidate;
218 }
219
220 rtc::FakeNetworkManager* NewFakeNetwork() {
221 // The PeerConnection's port allocator is tied to the PeerConnection's
222 // lifetime and expects the underlying NetworkManager to outlive it. If
223 // PeerConnectionWrapper owned the NetworkManager, it would be destroyed
224 // before the PeerConnection (since subclass members are destroyed before
225 // base class members). Therefore, the test fixture will own all the fake
226 // networks even though tests should access the fake network through the
227 // PeerConnectionWrapper.
228 auto* fake_network = new rtc::FakeNetworkManager();
229 fake_networks_.emplace_back(fake_network);
230 return fake_network;
231 }
232
233 std::unique_ptr<rtc::VirtualSocketServer> vss_;
234 rtc::AutoSocketServerThread main_;
235 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
236 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton7464fca2018-01-19 11:10:37 -0800237 const SdpSemantics sdp_semantics_;
238};
239
240class PeerConnectionBundleTest
241 : public PeerConnectionBundleBaseTest,
242 public ::testing::WithParamInterface<SdpSemantics> {
243 protected:
244 PeerConnectionBundleTest() : PeerConnectionBundleBaseTest(GetParam()) {}
Steve Anton6f25b092017-10-23 09:39:20 -0700245};
246
247SdpContentMutator RemoveRtcpMux() {
248 return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800249 content->media_description()->set_rtcp_mux(false);
Steve Anton6f25b092017-10-23 09:39:20 -0700250 };
251}
252
253std::vector<int> GetCandidateComponents(
254 const std::vector<IceCandidateInterface*> candidates) {
255 std::vector<int> components;
256 for (auto* candidate : candidates) {
257 components.push_back(candidate->candidate().component());
258 }
259 return components;
260}
261
262// Test that there are 2 local UDP candidates (1 RTP and 1 RTCP candidate) for
263// each media section when disabling bundling and disabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800264TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700265 TwoCandidatesForEachTransportWhenNoBundleNoRtcpMux) {
266 const SocketAddress kCallerAddress("1.1.1.1", 0);
267 const SocketAddress kCalleeAddress("2.2.2.2", 0);
268
269 RTCConfiguration config;
270 config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
271 auto caller = CreatePeerConnectionWithAudioVideo(config);
272 caller->network()->AddInterface(kCallerAddress);
273 auto callee = CreatePeerConnectionWithAudioVideo(config);
274 callee->network()->AddInterface(kCalleeAddress);
275
276 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
277 RTCOfferAnswerOptions options_no_bundle;
278 options_no_bundle.use_rtp_mux = false;
279 auto answer = callee->CreateAnswer(options_no_bundle);
280 SdpContentsForEach(RemoveRtcpMux(), answer->description());
281 ASSERT_TRUE(
282 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
283 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
284
285 // Check that caller has separate RTP and RTCP candidates for each media.
286 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
287 EXPECT_THAT(
288 GetCandidateComponents(caller->observer()->GetCandidatesByMline(0)),
289 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
290 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
291 EXPECT_THAT(
292 GetCandidateComponents(caller->observer()->GetCandidatesByMline(1)),
293 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
294 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
295
296 // Check that callee has separate RTP and RTCP candidates for each media.
297 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kDefaultTimeout);
298 EXPECT_THAT(
299 GetCandidateComponents(callee->observer()->GetCandidatesByMline(0)),
300 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
301 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
302 EXPECT_THAT(
303 GetCandidateComponents(callee->observer()->GetCandidatesByMline(1)),
304 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
305 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
306}
307
308// Test that there is 1 local UDP candidate for both RTP and RTCP for each media
309// section when disabling bundle but enabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800310TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700311 OneCandidateForEachTransportWhenNoBundleButRtcpMux) {
312 const SocketAddress kCallerAddress("1.1.1.1", 0);
313
314 auto caller = CreatePeerConnectionWithAudioVideo();
315 caller->network()->AddInterface(kCallerAddress);
316 auto callee = CreatePeerConnectionWithAudioVideo();
317
318 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
319 RTCOfferAnswerOptions options_no_bundle;
320 options_no_bundle.use_rtp_mux = false;
321 ASSERT_TRUE(
322 caller->SetRemoteDescription(callee->CreateAnswer(options_no_bundle)));
323
324 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
325
326 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
327 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(1).size());
328}
329
330// Test that there is 1 local UDP candidate in only the first media section when
331// bundling and enabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800332TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700333 OneCandidateOnlyOnFirstTransportWhenBundleAndRtcpMux) {
334 const SocketAddress kCallerAddress("1.1.1.1", 0);
335
336 RTCConfiguration config;
337 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
338 auto caller = CreatePeerConnectionWithAudioVideo(config);
339 caller->network()->AddInterface(kCallerAddress);
340 auto callee = CreatePeerConnectionWithAudioVideo(config);
341
342 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
343 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
344
345 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
346
347 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
348 EXPECT_EQ(0u, caller->observer()->GetCandidatesByMline(1).size());
349}
350
351// The following parameterized test verifies that an offer/answer with varying
352// bundle policies and either bundle in the answer or not will produce the
353// expected RTP transports for audio and video. In particular, for bundling we
354// care about whether they are separate transports or the same.
355
356enum class BundleIncluded { kBundleInAnswer, kBundleNotInAnswer };
357std::ostream& operator<<(std::ostream& out, BundleIncluded value) {
358 switch (value) {
359 case BundleIncluded::kBundleInAnswer:
360 return out << "bundle in answer";
361 case BundleIncluded::kBundleNotInAnswer:
362 return out << "bundle not in answer";
363 }
364 return out << "unknown";
365}
366
367class PeerConnectionBundleMatrixTest
Steve Anton7464fca2018-01-19 11:10:37 -0800368 : public PeerConnectionBundleBaseTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700369 public ::testing::WithParamInterface<
Steve Anton7464fca2018-01-19 11:10:37 -0800370 std::tuple<SdpSemantics,
371 std::tuple<BundlePolicy, BundleIncluded, bool, bool>>> {
Steve Anton6f25b092017-10-23 09:39:20 -0700372 protected:
Steve Anton7464fca2018-01-19 11:10:37 -0800373 PeerConnectionBundleMatrixTest()
374 : PeerConnectionBundleBaseTest(std::get<0>(GetParam())) {
375 auto param = std::get<1>(GetParam());
376 bundle_policy_ = std::get<0>(param);
377 bundle_included_ = std::get<1>(param);
378 expected_same_before_ = std::get<2>(param);
379 expected_same_after_ = std::get<3>(param);
Steve Anton6f25b092017-10-23 09:39:20 -0700380 }
381
382 PeerConnectionInterface::BundlePolicy bundle_policy_;
383 BundleIncluded bundle_included_;
384 bool expected_same_before_;
385 bool expected_same_after_;
386};
387
388TEST_P(PeerConnectionBundleMatrixTest,
389 VerifyTransportsBeforeAndAfterSettingRemoteAnswer) {
390 RTCConfiguration config;
391 config.bundle_policy = bundle_policy_;
392 auto caller = CreatePeerConnectionWithAudioVideo(config);
393 auto callee = CreatePeerConnectionWithAudioVideo();
394
395 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
396 bool equal_before = (caller->voice_rtp_transport_channel() ==
397 caller->video_rtp_transport_channel());
398 EXPECT_EQ(expected_same_before_, equal_before);
399
400 RTCOfferAnswerOptions options;
401 options.use_rtp_mux = (bundle_included_ == BundleIncluded::kBundleInAnswer);
402 ASSERT_TRUE(
403 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
404 bool equal_after = (caller->voice_rtp_transport_channel() ==
405 caller->video_rtp_transport_channel());
406 EXPECT_EQ(expected_same_after_, equal_after);
407}
408
409// The max-bundle policy means we should anticipate bundling being negotiated,
410// and multiplex audio/video from the start.
411// For all other policies, bundling should only be enabled if negotiated by the
412// answer.
413INSTANTIATE_TEST_CASE_P(
414 PeerConnectionBundleTest,
415 PeerConnectionBundleMatrixTest,
Steve Anton7464fca2018-01-19 11:10:37 -0800416 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
417 Values(std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
418 BundleIncluded::kBundleInAnswer,
419 false,
420 true),
421 std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
422 BundleIncluded::kBundleNotInAnswer,
423 false,
424 false),
425 std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
426 BundleIncluded::kBundleInAnswer,
427 true,
428 true),
429 std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
430 BundleIncluded::kBundleNotInAnswer,
431 true,
432 true),
433 std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
434 BundleIncluded::kBundleInAnswer,
435 false,
436 true),
437 std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
438 BundleIncluded::kBundleNotInAnswer,
439 false,
440 false))));
Steve Anton6f25b092017-10-23 09:39:20 -0700441
442// Test that the audio/video transports on the callee side are the same before
443// and after setting a local answer when max BUNDLE is enabled and an offer with
444// BUNDLE is received.
Steve Anton7464fca2018-01-19 11:10:37 -0800445TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700446 TransportsSameForMaxBundleWithBundleInRemoteOffer) {
447 auto caller = CreatePeerConnectionWithAudioVideo();
448 RTCConfiguration config;
449 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
450 auto callee = CreatePeerConnectionWithAudioVideo(config);
451
452 RTCOfferAnswerOptions options_with_bundle;
453 options_with_bundle.use_rtp_mux = true;
454 ASSERT_TRUE(callee->SetRemoteDescription(
455 caller->CreateOfferAndSetAsLocal(options_with_bundle)));
456
457 EXPECT_EQ(callee->voice_rtp_transport_channel(),
458 callee->video_rtp_transport_channel());
459
460 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
461
462 EXPECT_EQ(callee->voice_rtp_transport_channel(),
463 callee->video_rtp_transport_channel());
464}
465
Steve Anton7464fca2018-01-19 11:10:37 -0800466TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700467 FailToSetRemoteOfferWithNoBundleWhenBundlePolicyMaxBundle) {
468 auto caller = CreatePeerConnectionWithAudioVideo();
469 RTCConfiguration config;
470 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
471 auto callee = CreatePeerConnectionWithAudioVideo(config);
472
473 RTCOfferAnswerOptions options_no_bundle;
474 options_no_bundle.use_rtp_mux = false;
475 EXPECT_FALSE(callee->SetRemoteDescription(
476 caller->CreateOfferAndSetAsLocal(options_no_bundle)));
477}
478
479// Test that if the media section which has the bundled transport is rejected,
480// then the peers still connect and the bundled transport switches to the other
481// media section.
482// Note: This is currently failing because of the following bug:
483// https://bugs.chromium.org/p/webrtc/issues/detail?id=6280
Steve Anton7464fca2018-01-19 11:10:37 -0800484TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700485 DISABLED_SuccessfullyNegotiateMaxBundleIfBundleTransportMediaRejected) {
486 RTCConfiguration config;
487 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
488 auto caller = CreatePeerConnectionWithAudioVideo(config);
489 auto callee = CreatePeerConnection();
490 callee->AddVideoTrack("v");
491
492 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
493
494 RTCOfferAnswerOptions options;
495 options.offer_to_receive_audio = 0;
496 ASSERT_TRUE(
497 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
498
499 EXPECT_FALSE(caller->voice_rtp_transport_channel());
500 EXPECT_TRUE(caller->video_rtp_transport_channel());
501}
502
503// When requiring RTCP multiplexing, the PeerConnection never makes RTCP
504// transport channels.
Steve Anton7464fca2018-01-19 11:10:37 -0800505TEST_P(PeerConnectionBundleTest, NeverCreateRtcpTransportWithRtcpMuxRequired) {
Steve Anton6f25b092017-10-23 09:39:20 -0700506 RTCConfiguration config;
507 config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyRequire;
508 auto caller = CreatePeerConnectionWithAudioVideo(config);
509 auto callee = CreatePeerConnectionWithAudioVideo();
510
511 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
512
513 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
514 EXPECT_FALSE(caller->video_rtcp_transport_channel());
515
516 ASSERT_TRUE(
517 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
518
519 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
520 EXPECT_FALSE(caller->video_rtcp_transport_channel());
521}
522
523// When negotiating RTCP multiplexing, the PeerConnection makes RTCP transport
524// channels when the offer is sent, but will destroy them once the remote answer
525// is set.
Steve Anton7464fca2018-01-19 11:10:37 -0800526TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700527 CreateRtcpTransportOnlyBeforeAnswerWithRtcpMuxNegotiate) {
528 RTCConfiguration config;
529 config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyNegotiate;
530 auto caller = CreatePeerConnectionWithAudioVideo(config);
531 auto callee = CreatePeerConnectionWithAudioVideo();
532
533 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
534
535 EXPECT_TRUE(caller->voice_rtcp_transport_channel());
536 EXPECT_TRUE(caller->video_rtcp_transport_channel());
537
538 ASSERT_TRUE(
539 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
540
541 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
542 EXPECT_FALSE(caller->video_rtcp_transport_channel());
543}
544
Steve Anton7464fca2018-01-19 11:10:37 -0800545TEST_P(PeerConnectionBundleTest, FailToSetDescriptionWithBundleAndNoRtcpMux) {
Steve Anton6f25b092017-10-23 09:39:20 -0700546 auto caller = CreatePeerConnectionWithAudioVideo();
547 auto callee = CreatePeerConnectionWithAudioVideo();
548
549 RTCOfferAnswerOptions options;
550 options.use_rtp_mux = true;
551
552 auto offer = caller->CreateOffer(options);
553 SdpContentsForEach(RemoveRtcpMux(), offer->description());
554
555 std::string error;
556 EXPECT_FALSE(caller->SetLocalDescription(CloneSessionDescription(offer.get()),
557 &error));
558 EXPECT_EQ(
559 "Failed to set local offer sdp: rtcp-mux must be enabled when BUNDLE is "
560 "enabled.",
561 error);
562
563 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
564 EXPECT_EQ(
565 "Failed to set remote offer sdp: rtcp-mux must be enabled when BUNDLE is "
566 "enabled.",
567 error);
568}
569
570// Test that candidates sent to the "video" transport do not get pushed down to
571// the "audio" transport channel when bundling.
Steve Anton7464fca2018-01-19 11:10:37 -0800572TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700573 IgnoreCandidatesForUnusedTransportWhenBundling) {
574 const SocketAddress kAudioAddress1("1.1.1.1", 1111);
575 const SocketAddress kAudioAddress2("2.2.2.2", 2222);
576 const SocketAddress kVideoAddress("3.3.3.3", 3333);
577 const SocketAddress kCallerAddress("4.4.4.4", 0);
578 const SocketAddress kCalleeAddress("5.5.5.5", 0);
579
580 auto caller = CreatePeerConnectionWithAudioVideo();
581 auto callee = CreatePeerConnectionWithAudioVideo();
582
583 caller->network()->AddInterface(kCallerAddress);
584 callee->network()->AddInterface(kCalleeAddress);
585
586 RTCOfferAnswerOptions options;
587 options.use_rtp_mux = true;
588
589 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
590 ASSERT_TRUE(
591 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
592
593 // The way the *_WAIT checks work is they only wait if the condition fails,
594 // which does not help in the case where state is not changing. This is
595 // problematic in this test since we want to verify that adding a video
596 // candidate does _not_ change state. So we interleave candidates and assume
597 // that messages are executed in the order they were posted.
598
599 cricket::Candidate audio_candidate1 = CreateLocalUdpCandidate(kAudioAddress1);
600 ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate1,
601 cricket::MEDIA_TYPE_AUDIO));
602
603 cricket::Candidate video_candidate = CreateLocalUdpCandidate(kVideoAddress);
604 ASSERT_TRUE(caller->AddIceCandidateToMedia(&video_candidate,
605 cricket::MEDIA_TYPE_VIDEO));
606
607 cricket::Candidate audio_candidate2 = CreateLocalUdpCandidate(kAudioAddress2);
608 ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate2,
609 cricket::MEDIA_TYPE_AUDIO));
610
611 EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress1),
612 kDefaultTimeout);
613 EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress2),
614 kDefaultTimeout);
615 EXPECT_FALSE(caller->HasConnectionWithRemoteAddress(kVideoAddress));
616}
617
618// Test that the transport used by both audio and video is the transport
619// associated with the first MID in the answer BUNDLE group, even if it's in a
620// different order from the offer.
Steve Anton7464fca2018-01-19 11:10:37 -0800621TEST_P(PeerConnectionBundleTest, BundleOnFirstMidInAnswer) {
Steve Anton6f25b092017-10-23 09:39:20 -0700622 auto caller = CreatePeerConnectionWithAudioVideo();
623 auto callee = CreatePeerConnectionWithAudioVideo();
624
625 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
626
627 auto* old_video_transport = caller->video_rtp_transport_channel();
628
629 auto answer = callee->CreateAnswer();
630 auto* old_bundle_group =
631 answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
Steve Anton7464fca2018-01-19 11:10:37 -0800632 std::string first_mid = old_bundle_group->content_names()[0];
633 std::string second_mid = old_bundle_group->content_names()[1];
Steve Anton6f25b092017-10-23 09:39:20 -0700634 answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
635
636 cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
Steve Anton7464fca2018-01-19 11:10:37 -0800637 new_bundle_group.AddContentName(second_mid);
638 new_bundle_group.AddContentName(first_mid);
Steve Anton6f25b092017-10-23 09:39:20 -0700639 answer->description()->AddGroup(new_bundle_group);
640
641 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
642
643 EXPECT_EQ(old_video_transport, caller->video_rtp_transport_channel());
644 EXPECT_EQ(caller->voice_rtp_transport_channel(),
645 caller->video_rtp_transport_channel());
646}
647
Steve Anton7464fca2018-01-19 11:10:37 -0800648INSTANTIATE_TEST_CASE_P(PeerConnectionBundleTest,
649 PeerConnectionBundleTest,
650 Values(SdpSemantics::kPlanB,
651 SdpSemantics::kUnifiedPlan));
652
Steve Anton6f25b092017-10-23 09:39:20 -0700653} // namespace webrtc