blob: d7f1fcce5ac29df8c6c98825a9c3020f529dddaf [file] [log] [blame]
Steve Antonda6c0952017-10-23 11:41:54 -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 <tuple>
12
13#include "api/peerconnectionproxy.h"
14#include "media/base/fakemediaengine.h"
15#include "pc/mediasession.h"
16#include "pc/peerconnection.h"
17#include "pc/peerconnectionfactory.h"
18#include "pc/peerconnectionwrapper.h"
Steve Antondbf9d032018-01-19 15:23:40 -080019#include "pc/sdputils.h"
Steve Antonda6c0952017-10-23 11:41:54 -070020#ifdef WEBRTC_ANDROID
21#include "pc/test/androidtestinitializer.h"
22#endif
Karl Wiberg918f50c2018-07-05 11:40:33 +020023#include "absl/memory/memory.h"
Steve Antonda6c0952017-10-23 11:41:54 -070024#include "pc/test/fakesctptransport.h"
25#include "rtc_base/gunit.h"
Steve Antonda6c0952017-10-23 11:41:54 -070026#include "rtc_base/virtualsocketserver.h"
27
28namespace webrtc {
29
30using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
31using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
32using ::testing::Values;
33
34class PeerConnectionFactoryForDataChannelTest
35 : public rtc::RefCountedObject<PeerConnectionFactory> {
36 public:
37 PeerConnectionFactoryForDataChannelTest()
38 : rtc::RefCountedObject<PeerConnectionFactory>(
39 rtc::Thread::Current(),
40 rtc::Thread::Current(),
41 rtc::Thread::Current(),
Karl Wiberg918f50c2018-07-05 11:40:33 +020042 absl::make_unique<cricket::FakeMediaEngine>(),
Steve Antonda6c0952017-10-23 11:41:54 -070043 CreateCallFactory(),
44 nullptr) {}
45
46 std::unique_ptr<cricket::SctpTransportInternalFactory>
47 CreateSctpTransportInternalFactory() {
Karl Wiberg918f50c2018-07-05 11:40:33 +020048 auto factory = absl::make_unique<FakeSctpTransportFactory>();
Steve Antonda6c0952017-10-23 11:41:54 -070049 last_fake_sctp_transport_factory_ = factory.get();
50 return factory;
51 }
52
53 FakeSctpTransportFactory* last_fake_sctp_transport_factory_ = nullptr;
54};
55
56class PeerConnectionWrapperForDataChannelTest : public PeerConnectionWrapper {
57 public:
58 using PeerConnectionWrapper::PeerConnectionWrapper;
59
60 FakeSctpTransportFactory* sctp_transport_factory() {
61 return sctp_transport_factory_;
62 }
63
64 void set_sctp_transport_factory(
65 FakeSctpTransportFactory* sctp_transport_factory) {
66 sctp_transport_factory_ = sctp_transport_factory;
67 }
68
Danil Chapovalov66cadcc2018-06-19 16:47:43 +020069 absl::optional<std::string> sctp_content_name() {
Steve Antonda6c0952017-10-23 11:41:54 -070070 return GetInternalPeerConnection()->sctp_content_name();
71 }
72
Danil Chapovalov66cadcc2018-06-19 16:47:43 +020073 absl::optional<std::string> sctp_transport_name() {
Steve Antonda6c0952017-10-23 11:41:54 -070074 return GetInternalPeerConnection()->sctp_transport_name();
75 }
76
77 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +010078 auto* pci =
79 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
80 pc());
81 return static_cast<PeerConnection*>(pci->internal());
Steve Antonda6c0952017-10-23 11:41:54 -070082 }
83
84 private:
85 FakeSctpTransportFactory* sctp_transport_factory_ = nullptr;
86};
87
Steve Antondbf9d032018-01-19 15:23:40 -080088class PeerConnectionDataChannelBaseTest : public ::testing::Test {
Steve Antonda6c0952017-10-23 11:41:54 -070089 protected:
90 typedef std::unique_ptr<PeerConnectionWrapperForDataChannelTest> WrapperPtr;
91
Steve Antondbf9d032018-01-19 15:23:40 -080092 explicit PeerConnectionDataChannelBaseTest(SdpSemantics sdp_semantics)
93 : vss_(new rtc::VirtualSocketServer()),
94 main_(vss_.get()),
95 sdp_semantics_(sdp_semantics) {
Steve Antonda6c0952017-10-23 11:41:54 -070096#ifdef WEBRTC_ANDROID
97 InitializeAndroidObjects();
98#endif
99 }
100
101 WrapperPtr CreatePeerConnection() {
102 return CreatePeerConnection(RTCConfiguration());
103 }
104
105 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
106 return CreatePeerConnection(config,
107 PeerConnectionFactoryInterface::Options());
108 }
109
110 WrapperPtr CreatePeerConnection(
111 const RTCConfiguration& config,
112 const PeerConnectionFactoryInterface::Options factory_options) {
113 rtc::scoped_refptr<PeerConnectionFactoryForDataChannelTest> pc_factory(
114 new PeerConnectionFactoryForDataChannelTest());
115 pc_factory->SetOptions(factory_options);
116 RTC_CHECK(pc_factory->Initialize());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200117 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Steve Antondbf9d032018-01-19 15:23:40 -0800118 RTCConfiguration modified_config = config;
119 modified_config.sdp_semantics = sdp_semantics_;
120 auto pc = pc_factory->CreatePeerConnection(modified_config, nullptr,
121 nullptr, observer.get());
Steve Antonda6c0952017-10-23 11:41:54 -0700122 if (!pc) {
123 return nullptr;
124 }
125
Yves Gerey4e933292018-10-31 15:36:05 +0100126 observer->SetPeerConnectionInterface(pc.get());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200127 auto wrapper = absl::make_unique<PeerConnectionWrapperForDataChannelTest>(
Steve Antonda6c0952017-10-23 11:41:54 -0700128 pc_factory, pc, std::move(observer));
129 RTC_DCHECK(pc_factory->last_fake_sctp_transport_factory_);
130 wrapper->set_sctp_transport_factory(
131 pc_factory->last_fake_sctp_transport_factory_);
132 return wrapper;
133 }
134
135 // Accepts the same arguments as CreatePeerConnection and adds a default data
136 // channel.
137 template <typename... Args>
138 WrapperPtr CreatePeerConnectionWithDataChannel(Args&&... args) {
139 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
140 if (!wrapper) {
141 return nullptr;
142 }
143 EXPECT_TRUE(wrapper->pc()->CreateDataChannel("dc", nullptr));
144 return wrapper;
145 }
146
147 // Changes the SCTP data channel port on the given session description.
148 void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
149 int port) {
150 cricket::DataCodec sctp_codec(cricket::kGoogleSctpDataCodecPlType,
151 cricket::kGoogleSctpDataCodecName);
152 sctp_codec.SetParam(cricket::kCodecParamPort, port);
153
154 auto* data_content = cricket::GetFirstDataContent(desc);
155 RTC_DCHECK(data_content);
Steve Antonb1c1de12017-12-21 15:14:30 -0800156 auto* data_desc = data_content->media_description()->as_data();
Steve Antonda6c0952017-10-23 11:41:54 -0700157 data_desc->set_codecs({sctp_codec});
158 }
159
160 std::unique_ptr<rtc::VirtualSocketServer> vss_;
161 rtc::AutoSocketServerThread main_;
Steve Antondbf9d032018-01-19 15:23:40 -0800162 const SdpSemantics sdp_semantics_;
Steve Antonda6c0952017-10-23 11:41:54 -0700163};
164
Steve Antondbf9d032018-01-19 15:23:40 -0800165class PeerConnectionDataChannelTest
166 : public PeerConnectionDataChannelBaseTest,
167 public ::testing::WithParamInterface<SdpSemantics> {
168 protected:
169 PeerConnectionDataChannelTest()
170 : PeerConnectionDataChannelBaseTest(GetParam()) {}
171};
172
173TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700174 NoSctpTransportCreatedIfRtpDataChannelEnabled) {
175 RTCConfiguration config;
176 config.enable_rtp_data_channel = true;
177 auto caller = CreatePeerConnectionWithDataChannel(config);
178
179 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
180 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
181}
182
Steve Antondbf9d032018-01-19 15:23:40 -0800183TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700184 RtpDataChannelCreatedEvenIfSctpAvailable) {
185 RTCConfiguration config;
186 config.enable_rtp_data_channel = true;
187 PeerConnectionFactoryInterface::Options options;
188 options.disable_sctp_data_channels = false;
189 auto caller = CreatePeerConnectionWithDataChannel(config, options);
190
191 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
192 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
193}
194
195// Test that sctp_content_name/sctp_transport_name (used for stats) are correct
196// before and after BUNDLE is negotiated.
Steve Antondbf9d032018-01-19 15:23:40 -0800197TEST_P(PeerConnectionDataChannelTest, SctpContentAndTransportNameSetCorrectly) {
Steve Antonda6c0952017-10-23 11:41:54 -0700198 auto caller = CreatePeerConnection();
199 auto callee = CreatePeerConnection();
200
201 // Initially these fields should be empty.
202 EXPECT_FALSE(caller->sctp_content_name());
203 EXPECT_FALSE(caller->sctp_transport_name());
204
205 // Create offer with audio/video/data.
206 // Default bundle policy is "balanced", so data should be using its own
207 // transport.
208 caller->AddAudioTrack("a");
209 caller->AddVideoTrack("v");
210 caller->pc()->CreateDataChannel("dc", nullptr);
Steve Antondbf9d032018-01-19 15:23:40 -0800211
212 auto offer = caller->CreateOffer();
213 const auto& offer_contents = offer->description()->contents();
214 ASSERT_EQ(cricket::MEDIA_TYPE_AUDIO,
215 offer_contents[0].media_description()->type());
216 std::string audio_mid = offer_contents[0].name;
217 ASSERT_EQ(cricket::MEDIA_TYPE_DATA,
218 offer_contents[2].media_description()->type());
219 std::string data_mid = offer_contents[2].name;
220
221 ASSERT_TRUE(
222 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
223 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Steve Antonda6c0952017-10-23 11:41:54 -0700224
225 ASSERT_TRUE(caller->sctp_content_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800226 EXPECT_EQ(data_mid, *caller->sctp_content_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700227 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800228 EXPECT_EQ(data_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700229
230 // Create answer that finishes BUNDLE negotiation, which means everything
231 // should be bundled on the first transport (audio).
232 RTCOfferAnswerOptions options;
233 options.use_rtp_mux = true;
234 ASSERT_TRUE(
235 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
236
237 ASSERT_TRUE(caller->sctp_content_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800238 EXPECT_EQ(data_mid, *caller->sctp_content_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700239 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800240 EXPECT_EQ(audio_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700241}
242
Steve Antondbf9d032018-01-19 15:23:40 -0800243TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700244 CreateOfferWithNoDataChannelsGivesNoDataSection) {
245 auto caller = CreatePeerConnection();
246 auto offer = caller->CreateOffer();
247
248 EXPECT_FALSE(offer->description()->GetContentByName(cricket::CN_DATA));
249 EXPECT_FALSE(offer->description()->GetTransportInfoByName(cricket::CN_DATA));
250}
251
Steve Antondbf9d032018-01-19 15:23:40 -0800252TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700253 CreateAnswerWithRemoteSctpDataChannelIncludesDataSection) {
254 auto caller = CreatePeerConnectionWithDataChannel();
255 auto callee = CreatePeerConnection();
256
257 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
258
259 auto answer = callee->CreateAnswer();
260 ASSERT_TRUE(answer);
Steve Antondbf9d032018-01-19 15:23:40 -0800261 auto* data_content = cricket::GetFirstDataContent(answer->description());
Steve Antonda6c0952017-10-23 11:41:54 -0700262 ASSERT_TRUE(data_content);
263 EXPECT_FALSE(data_content->rejected);
Steve Antondbf9d032018-01-19 15:23:40 -0800264 EXPECT_TRUE(
265 answer->description()->GetTransportInfoByName(data_content->name));
Steve Antonda6c0952017-10-23 11:41:54 -0700266}
267
Steve Antondbf9d032018-01-19 15:23:40 -0800268TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700269 CreateDataChannelWithDtlsDisabledSucceeds) {
270 RTCConfiguration config;
271 config.enable_dtls_srtp.emplace(false);
272 auto caller = CreatePeerConnection();
273
274 EXPECT_TRUE(caller->pc()->CreateDataChannel("dc", nullptr));
275}
276
Steve Antondbf9d032018-01-19 15:23:40 -0800277TEST_P(PeerConnectionDataChannelTest, CreateDataChannelWithSctpDisabledFails) {
Steve Antonda6c0952017-10-23 11:41:54 -0700278 PeerConnectionFactoryInterface::Options options;
279 options.disable_sctp_data_channels = true;
280 auto caller = CreatePeerConnection(RTCConfiguration(), options);
281
282 EXPECT_FALSE(caller->pc()->CreateDataChannel("dc", nullptr));
283}
284
285// Test that if a callee has SCTP disabled and receives an offer with an SCTP
286// data channel, the data section is rejected and no SCTP transport is created
287// on the callee.
Steve Antondbf9d032018-01-19 15:23:40 -0800288TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700289 DataSectionRejectedIfCalleeHasSctpDisabled) {
290 auto caller = CreatePeerConnectionWithDataChannel();
291 PeerConnectionFactoryInterface::Options options;
292 options.disable_sctp_data_channels = true;
293 auto callee = CreatePeerConnection(RTCConfiguration(), options);
294
295 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
296
297 EXPECT_FALSE(callee->sctp_transport_factory()->last_fake_sctp_transport());
298
299 auto answer = callee->CreateAnswer();
Steve Antondbf9d032018-01-19 15:23:40 -0800300 auto* data_content = cricket::GetFirstDataContent(answer->description());
Steve Antonda6c0952017-10-23 11:41:54 -0700301 ASSERT_TRUE(data_content);
302 EXPECT_TRUE(data_content->rejected);
303}
304
Steve Antondbf9d032018-01-19 15:23:40 -0800305TEST_P(PeerConnectionDataChannelTest, SctpPortPropagatedFromSdpToTransport) {
Steve Antonda6c0952017-10-23 11:41:54 -0700306 constexpr int kNewSendPort = 9998;
307 constexpr int kNewRecvPort = 7775;
308
309 auto caller = CreatePeerConnectionWithDataChannel();
310 auto callee = CreatePeerConnectionWithDataChannel();
311
312 auto offer = caller->CreateOffer();
313 ChangeSctpPortOnDescription(offer->description(), kNewSendPort);
314 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
315
316 auto answer = callee->CreateAnswer();
317 ChangeSctpPortOnDescription(answer->description(), kNewRecvPort);
318 ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
319
320 auto* callee_transport =
321 callee->sctp_transport_factory()->last_fake_sctp_transport();
322 ASSERT_TRUE(callee_transport);
323 EXPECT_EQ(kNewSendPort, callee_transport->remote_port());
324 EXPECT_EQ(kNewRecvPort, callee_transport->local_port());
325}
326
Steve Antondbf9d032018-01-19 15:23:40 -0800327INSTANTIATE_TEST_CASE_P(PeerConnectionDataChannelTest,
328 PeerConnectionDataChannelTest,
329 Values(SdpSemantics::kPlanB,
330 SdpSemantics::kUnifiedPlan));
331
Steve Antonda6c0952017-10-23 11:41:54 -0700332} // namespace webrtc