blob: 81ef22058c52db7a0b2c7ab5508ad28765f38fe0 [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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <memory>
12#include <string>
13#include <type_traits>
14#include <utility>
15#include <vector>
Steve Antonda6c0952017-10-23 11:41:54 -070016
Yves Gerey3e707812018-11-28 16:47:49 +010017#include "absl/types/optional.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "api/call/call_factory_interface.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/jsep.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "api/media_types.h"
21#include "api/peer_connection_interface.h"
22#include "api/peer_connection_proxy.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010023#include "api/scoped_refptr.h"
Danil Chapovalov53d45ba2019-07-03 14:56:33 +020024#include "api/task_queue/default_task_queue_factory.h"
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080025#include "api/test/fake_media_transport.h"
Niels Möller65f17ca2019-09-12 13:59:36 +020026#include "api/transport/media/media_transport_interface.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "media/base/codec.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "media/base/fake_media_engine.h"
29#include "media/base/media_constants.h"
30#include "media/base/media_engine.h"
31#include "media/sctp/sctp_transport_internal.h"
32#include "p2p/base/p2p_constants.h"
33#include "p2p/base/port_allocator.h"
34#include "pc/media_session.h"
35#include "pc/peer_connection.h"
36#include "pc/peer_connection_factory.h"
37#include "pc/peer_connection_wrapper.h"
38#include "pc/sdp_utils.h"
39#include "pc/session_description.h"
40#include "pc/test/mock_peer_connection_observers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010041#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080042#include "rtc_base/ref_counted_object.h"
43#include "rtc_base/rtc_certificate_generator.h"
Yves Gerey3e707812018-11-28 16:47:49 +010044#include "rtc_base/thread.h"
Harald Alvestrand4aa11922019-05-14 22:00:01 +020045#include "test/gmock.h"
Yves Gerey3e707812018-11-28 16:47:49 +010046#include "test/gtest.h"
Steve Antonda6c0952017-10-23 11:41:54 -070047#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080048#include "pc/test/android_test_initializer.h"
Steve Antonda6c0952017-10-23 11:41:54 -070049#endif
Steve Anton10542f22019-01-11 09:11:00 -080050#include "pc/test/fake_sctp_transport.h"
51#include "rtc_base/virtual_socket_server.h"
Steve Antonda6c0952017-10-23 11:41:54 -070052
53namespace webrtc {
54
55using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
56using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
Harald Alvestrand4aa11922019-05-14 22:00:01 +020057using ::testing::HasSubstr;
58using ::testing::Not;
Steve Antonda6c0952017-10-23 11:41:54 -070059using ::testing::Values;
60
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080061namespace {
62
63PeerConnectionFactoryDependencies CreatePeerConnectionFactoryDependencies(
64 rtc::Thread* network_thread,
65 rtc::Thread* worker_thread,
66 rtc::Thread* signaling_thread,
67 std::unique_ptr<cricket::MediaEngineInterface> media_engine,
68 std::unique_ptr<CallFactoryInterface> call_factory,
69 std::unique_ptr<MediaTransportFactory> media_transport_factory) {
70 PeerConnectionFactoryDependencies deps;
71 deps.network_thread = network_thread;
72 deps.worker_thread = worker_thread;
73 deps.signaling_thread = signaling_thread;
Danil Chapovalov53d45ba2019-07-03 14:56:33 +020074 deps.task_queue_factory = CreateDefaultTaskQueueFactory();
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080075 deps.media_engine = std::move(media_engine);
76 deps.call_factory = std::move(call_factory);
77 deps.media_transport_factory = std::move(media_transport_factory);
78 return deps;
79}
80
81} // namespace
82
Steve Antonda6c0952017-10-23 11:41:54 -070083class PeerConnectionFactoryForDataChannelTest
84 : public rtc::RefCountedObject<PeerConnectionFactory> {
85 public:
86 PeerConnectionFactoryForDataChannelTest()
87 : rtc::RefCountedObject<PeerConnectionFactory>(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080088 CreatePeerConnectionFactoryDependencies(
89 rtc::Thread::Current(),
90 rtc::Thread::Current(),
91 rtc::Thread::Current(),
Mirko Bonadei317a1f02019-09-17 17:06:18 +020092 std::make_unique<cricket::FakeMediaEngine>(),
Bjorn Mellem175aa2e2018-11-08 11:23:22 -080093 CreateCallFactory(),
Mirko Bonadei317a1f02019-09-17 17:06:18 +020094 std::make_unique<FakeMediaTransportFactory>())) {}
Steve Antonda6c0952017-10-23 11:41:54 -070095
96 std::unique_ptr<cricket::SctpTransportInternalFactory>
97 CreateSctpTransportInternalFactory() {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020098 auto factory = std::make_unique<FakeSctpTransportFactory>();
Steve Antonda6c0952017-10-23 11:41:54 -070099 last_fake_sctp_transport_factory_ = factory.get();
100 return factory;
101 }
102
103 FakeSctpTransportFactory* last_fake_sctp_transport_factory_ = nullptr;
104};
105
106class PeerConnectionWrapperForDataChannelTest : public PeerConnectionWrapper {
107 public:
108 using PeerConnectionWrapper::PeerConnectionWrapper;
109
110 FakeSctpTransportFactory* sctp_transport_factory() {
111 return sctp_transport_factory_;
112 }
113
114 void set_sctp_transport_factory(
115 FakeSctpTransportFactory* sctp_transport_factory) {
116 sctp_transport_factory_ = sctp_transport_factory;
117 }
118
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200119 absl::optional<std::string> sctp_content_name() {
Steve Antonda6c0952017-10-23 11:41:54 -0700120 return GetInternalPeerConnection()->sctp_content_name();
121 }
122
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200123 absl::optional<std::string> sctp_transport_name() {
Steve Antonda6c0952017-10-23 11:41:54 -0700124 return GetInternalPeerConnection()->sctp_transport_name();
125 }
126
127 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100128 auto* pci =
129 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
130 pc());
131 return static_cast<PeerConnection*>(pci->internal());
Steve Antonda6c0952017-10-23 11:41:54 -0700132 }
133
134 private:
135 FakeSctpTransportFactory* sctp_transport_factory_ = nullptr;
136};
137
Steve Antondbf9d032018-01-19 15:23:40 -0800138class PeerConnectionDataChannelBaseTest : public ::testing::Test {
Steve Antonda6c0952017-10-23 11:41:54 -0700139 protected:
140 typedef std::unique_ptr<PeerConnectionWrapperForDataChannelTest> WrapperPtr;
141
Steve Antondbf9d032018-01-19 15:23:40 -0800142 explicit PeerConnectionDataChannelBaseTest(SdpSemantics sdp_semantics)
143 : vss_(new rtc::VirtualSocketServer()),
144 main_(vss_.get()),
145 sdp_semantics_(sdp_semantics) {
Steve Antonda6c0952017-10-23 11:41:54 -0700146#ifdef WEBRTC_ANDROID
147 InitializeAndroidObjects();
148#endif
149 }
150
151 WrapperPtr CreatePeerConnection() {
152 return CreatePeerConnection(RTCConfiguration());
153 }
154
155 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
156 return CreatePeerConnection(config,
157 PeerConnectionFactoryInterface::Options());
158 }
159
160 WrapperPtr CreatePeerConnection(
161 const RTCConfiguration& config,
162 const PeerConnectionFactoryInterface::Options factory_options) {
163 rtc::scoped_refptr<PeerConnectionFactoryForDataChannelTest> pc_factory(
164 new PeerConnectionFactoryForDataChannelTest());
165 pc_factory->SetOptions(factory_options);
166 RTC_CHECK(pc_factory->Initialize());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200167 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Antondbf9d032018-01-19 15:23:40 -0800168 RTCConfiguration modified_config = config;
169 modified_config.sdp_semantics = sdp_semantics_;
170 auto pc = pc_factory->CreatePeerConnection(modified_config, nullptr,
171 nullptr, observer.get());
Steve Antonda6c0952017-10-23 11:41:54 -0700172 if (!pc) {
173 return nullptr;
174 }
175
Yves Gerey4e933292018-10-31 15:36:05 +0100176 observer->SetPeerConnectionInterface(pc.get());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200177 auto wrapper = std::make_unique<PeerConnectionWrapperForDataChannelTest>(
Steve Antonda6c0952017-10-23 11:41:54 -0700178 pc_factory, pc, std::move(observer));
179 RTC_DCHECK(pc_factory->last_fake_sctp_transport_factory_);
180 wrapper->set_sctp_transport_factory(
181 pc_factory->last_fake_sctp_transport_factory_);
182 return wrapper;
183 }
184
185 // Accepts the same arguments as CreatePeerConnection and adds a default data
186 // channel.
187 template <typename... Args>
188 WrapperPtr CreatePeerConnectionWithDataChannel(Args&&... args) {
189 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
190 if (!wrapper) {
191 return nullptr;
192 }
193 EXPECT_TRUE(wrapper->pc()->CreateDataChannel("dc", nullptr));
194 return wrapper;
195 }
196
197 // Changes the SCTP data channel port on the given session description.
198 void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
199 int port) {
Steve Antonda6c0952017-10-23 11:41:54 -0700200 auto* data_content = cricket::GetFirstDataContent(desc);
201 RTC_DCHECK(data_content);
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200202 auto* data_desc = data_content->media_description()->as_sctp();
203 RTC_DCHECK(data_desc);
204 data_desc->set_port(port);
Steve Antonda6c0952017-10-23 11:41:54 -0700205 }
206
207 std::unique_ptr<rtc::VirtualSocketServer> vss_;
208 rtc::AutoSocketServerThread main_;
Steve Antondbf9d032018-01-19 15:23:40 -0800209 const SdpSemantics sdp_semantics_;
Steve Antonda6c0952017-10-23 11:41:54 -0700210};
211
Steve Antondbf9d032018-01-19 15:23:40 -0800212class PeerConnectionDataChannelTest
213 : public PeerConnectionDataChannelBaseTest,
214 public ::testing::WithParamInterface<SdpSemantics> {
215 protected:
216 PeerConnectionDataChannelTest()
217 : PeerConnectionDataChannelBaseTest(GetParam()) {}
218};
219
220TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700221 NoSctpTransportCreatedIfRtpDataChannelEnabled) {
222 RTCConfiguration config;
223 config.enable_rtp_data_channel = true;
224 auto caller = CreatePeerConnectionWithDataChannel(config);
225
226 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
227 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
228}
229
Steve Antondbf9d032018-01-19 15:23:40 -0800230TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700231 RtpDataChannelCreatedEvenIfSctpAvailable) {
232 RTCConfiguration config;
233 config.enable_rtp_data_channel = true;
234 PeerConnectionFactoryInterface::Options options;
235 options.disable_sctp_data_channels = false;
236 auto caller = CreatePeerConnectionWithDataChannel(config, options);
237
238 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
239 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
240}
241
242// Test that sctp_content_name/sctp_transport_name (used for stats) are correct
243// before and after BUNDLE is negotiated.
Steve Antondbf9d032018-01-19 15:23:40 -0800244TEST_P(PeerConnectionDataChannelTest, SctpContentAndTransportNameSetCorrectly) {
Steve Antonda6c0952017-10-23 11:41:54 -0700245 auto caller = CreatePeerConnection();
246 auto callee = CreatePeerConnection();
247
248 // Initially these fields should be empty.
249 EXPECT_FALSE(caller->sctp_content_name());
250 EXPECT_FALSE(caller->sctp_transport_name());
251
252 // Create offer with audio/video/data.
253 // Default bundle policy is "balanced", so data should be using its own
254 // transport.
255 caller->AddAudioTrack("a");
256 caller->AddVideoTrack("v");
257 caller->pc()->CreateDataChannel("dc", nullptr);
Steve Antondbf9d032018-01-19 15:23:40 -0800258
259 auto offer = caller->CreateOffer();
260 const auto& offer_contents = offer->description()->contents();
261 ASSERT_EQ(cricket::MEDIA_TYPE_AUDIO,
262 offer_contents[0].media_description()->type());
263 std::string audio_mid = offer_contents[0].name;
264 ASSERT_EQ(cricket::MEDIA_TYPE_DATA,
265 offer_contents[2].media_description()->type());
266 std::string data_mid = offer_contents[2].name;
267
268 ASSERT_TRUE(
269 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
270 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Steve Antonda6c0952017-10-23 11:41:54 -0700271
272 ASSERT_TRUE(caller->sctp_content_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800273 EXPECT_EQ(data_mid, *caller->sctp_content_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700274 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800275 EXPECT_EQ(data_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700276
277 // Create answer that finishes BUNDLE negotiation, which means everything
278 // should be bundled on the first transport (audio).
279 RTCOfferAnswerOptions options;
280 options.use_rtp_mux = true;
281 ASSERT_TRUE(
282 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
283
284 ASSERT_TRUE(caller->sctp_content_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800285 EXPECT_EQ(data_mid, *caller->sctp_content_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700286 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 15:23:40 -0800287 EXPECT_EQ(audio_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 11:41:54 -0700288}
289
Steve Antondbf9d032018-01-19 15:23:40 -0800290TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700291 CreateOfferWithNoDataChannelsGivesNoDataSection) {
292 auto caller = CreatePeerConnection();
293 auto offer = caller->CreateOffer();
294
295 EXPECT_FALSE(offer->description()->GetContentByName(cricket::CN_DATA));
296 EXPECT_FALSE(offer->description()->GetTransportInfoByName(cricket::CN_DATA));
297}
298
Steve Antondbf9d032018-01-19 15:23:40 -0800299TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700300 CreateAnswerWithRemoteSctpDataChannelIncludesDataSection) {
301 auto caller = CreatePeerConnectionWithDataChannel();
302 auto callee = CreatePeerConnection();
303
304 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
305
306 auto answer = callee->CreateAnswer();
307 ASSERT_TRUE(answer);
Steve Antondbf9d032018-01-19 15:23:40 -0800308 auto* data_content = cricket::GetFirstDataContent(answer->description());
Steve Antonda6c0952017-10-23 11:41:54 -0700309 ASSERT_TRUE(data_content);
310 EXPECT_FALSE(data_content->rejected);
Steve Antondbf9d032018-01-19 15:23:40 -0800311 EXPECT_TRUE(
312 answer->description()->GetTransportInfoByName(data_content->name));
Steve Antonda6c0952017-10-23 11:41:54 -0700313}
314
Steve Antondbf9d032018-01-19 15:23:40 -0800315TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700316 CreateDataChannelWithDtlsDisabledSucceeds) {
317 RTCConfiguration config;
318 config.enable_dtls_srtp.emplace(false);
319 auto caller = CreatePeerConnection();
320
321 EXPECT_TRUE(caller->pc()->CreateDataChannel("dc", nullptr));
322}
323
Steve Antondbf9d032018-01-19 15:23:40 -0800324TEST_P(PeerConnectionDataChannelTest, CreateDataChannelWithSctpDisabledFails) {
Steve Antonda6c0952017-10-23 11:41:54 -0700325 PeerConnectionFactoryInterface::Options options;
326 options.disable_sctp_data_channels = true;
327 auto caller = CreatePeerConnection(RTCConfiguration(), options);
328
329 EXPECT_FALSE(caller->pc()->CreateDataChannel("dc", nullptr));
330}
331
332// Test that if a callee has SCTP disabled and receives an offer with an SCTP
333// data channel, the data section is rejected and no SCTP transport is created
334// on the callee.
Steve Antondbf9d032018-01-19 15:23:40 -0800335TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 11:41:54 -0700336 DataSectionRejectedIfCalleeHasSctpDisabled) {
337 auto caller = CreatePeerConnectionWithDataChannel();
338 PeerConnectionFactoryInterface::Options options;
339 options.disable_sctp_data_channels = true;
340 auto callee = CreatePeerConnection(RTCConfiguration(), options);
341
342 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
343
344 EXPECT_FALSE(callee->sctp_transport_factory()->last_fake_sctp_transport());
345
346 auto answer = callee->CreateAnswer();
Steve Antondbf9d032018-01-19 15:23:40 -0800347 auto* data_content = cricket::GetFirstDataContent(answer->description());
Steve Antonda6c0952017-10-23 11:41:54 -0700348 ASSERT_TRUE(data_content);
349 EXPECT_TRUE(data_content->rejected);
350}
351
Steve Antondbf9d032018-01-19 15:23:40 -0800352TEST_P(PeerConnectionDataChannelTest, SctpPortPropagatedFromSdpToTransport) {
Steve Antonda6c0952017-10-23 11:41:54 -0700353 constexpr int kNewSendPort = 9998;
354 constexpr int kNewRecvPort = 7775;
355
356 auto caller = CreatePeerConnectionWithDataChannel();
357 auto callee = CreatePeerConnectionWithDataChannel();
358
359 auto offer = caller->CreateOffer();
360 ChangeSctpPortOnDescription(offer->description(), kNewSendPort);
361 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
362
363 auto answer = callee->CreateAnswer();
364 ChangeSctpPortOnDescription(answer->description(), kNewRecvPort);
365 ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
366
367 auto* callee_transport =
368 callee->sctp_transport_factory()->last_fake_sctp_transport();
369 ASSERT_TRUE(callee_transport);
370 EXPECT_EQ(kNewSendPort, callee_transport->remote_port());
371 EXPECT_EQ(kNewRecvPort, callee_transport->local_port());
372}
373
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800374TEST_P(PeerConnectionDataChannelTest,
375 NoSctpTransportCreatedIfMediaTransportDataChannelsEnabled) {
376 RTCConfiguration config;
377 config.use_media_transport_for_data_channels = true;
378 config.enable_dtls_srtp = false; // SDES is required to use media transport.
379 auto caller = CreatePeerConnectionWithDataChannel(config);
380
381 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
382 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
383}
384
385TEST_P(PeerConnectionDataChannelTest,
386 MediaTransportDataChannelCreatedEvenIfSctpAvailable) {
387 RTCConfiguration config;
388 config.use_media_transport_for_data_channels = true;
389 config.enable_dtls_srtp = false; // SDES is required to use media transport.
390 PeerConnectionFactoryInterface::Options options;
391 options.disable_sctp_data_channels = false;
392 auto caller = CreatePeerConnectionWithDataChannel(config, options);
393
394 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
395 EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
396}
397
398TEST_P(PeerConnectionDataChannelTest,
399 CannotEnableBothMediaTransportAndRtpDataChannels) {
400 RTCConfiguration config;
401 config.enable_rtp_data_channel = true;
402 config.use_media_transport_for_data_channels = true;
403 config.enable_dtls_srtp = false; // SDES is required to use media transport.
404 EXPECT_EQ(CreatePeerConnection(config), nullptr);
405}
406
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -0800407// This test now DCHECKs, instead of failing to SetLocalDescription.
408TEST_P(PeerConnectionDataChannelTest, MediaTransportWithoutSdesFails) {
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800409 RTCConfiguration config;
410 config.use_media_transport_for_data_channels = true;
411 config.enable_dtls_srtp = true; // Disables SDES for data sections.
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -0800412
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800413 auto caller = CreatePeerConnectionWithDataChannel(config);
414
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -0800415 EXPECT_EQ(nullptr, caller);
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800416}
417
Guido Urdanetacecf87f2019-05-31 10:17:38 +0000418TEST_P(PeerConnectionDataChannelTest, ModernSdpSyntaxByDefault) {
Harald Alvestrand4aa11922019-05-14 22:00:01 +0200419 PeerConnectionInterface::RTCOfferAnswerOptions options;
420 auto caller = CreatePeerConnectionWithDataChannel();
421 auto offer = caller->CreateOffer(options);
422 EXPECT_FALSE(cricket::GetFirstSctpDataContentDescription(offer->description())
423 ->use_sctpmap());
424 std::string sdp;
425 offer->ToString(&sdp);
426 RTC_LOG(LS_ERROR) << sdp;
427 EXPECT_THAT(sdp, HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel"));
428 EXPECT_THAT(sdp, Not(HasSubstr("a=sctpmap:")));
429}
430
431TEST_P(PeerConnectionDataChannelTest, ObsoleteSdpSyntaxIfSet) {
432 PeerConnectionInterface::RTCOfferAnswerOptions options;
433 options.use_obsolete_sctp_sdp = true;
434 auto caller = CreatePeerConnectionWithDataChannel();
435 auto offer = caller->CreateOffer(options);
436 EXPECT_TRUE(cricket::GetFirstSctpDataContentDescription(offer->description())
437 ->use_sctpmap());
438 std::string sdp;
439 offer->ToString(&sdp);
440 EXPECT_THAT(sdp, Not(HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel")));
441 EXPECT_THAT(sdp, HasSubstr("a=sctpmap:"));
442}
443
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100444INSTANTIATE_TEST_SUITE_P(PeerConnectionDataChannelTest,
445 PeerConnectionDataChannelTest,
446 Values(SdpSemantics::kPlanB,
447 SdpSemantics::kUnifiedPlan));
Steve Antondbf9d032018-01-19 15:23:40 -0800448
Steve Antonda6c0952017-10-23 11:41:54 -0700449} // namespace webrtc