blob: 8682cfa9fb4de116471071a8ca47f115b5b07856 [file] [log] [blame]
Steve Antonda6c0952017-10-23 18:41:541/*
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 15:47:4911#include <memory>
12#include <string>
13#include <type_traits>
14#include <utility>
15#include <vector>
Steve Antonda6c0952017-10-23 18:41:5416
Yves Gerey3e707812018-11-28 15:47:4917#include "absl/types/optional.h"
Yves Gerey3e707812018-11-28 15:47:4918#include "api/jsep.h"
Steve Anton10542f22019-01-11 17:11:0019#include "api/media_types.h"
20#include "api/peer_connection_interface.h"
Mirko Bonadeid9708072019-01-25 19:26:4821#include "api/scoped_refptr.h"
Harald Alvestrandc24a2182022-02-23 13:44:5922#include "api/sctp_transport_interface.h"
Danil Chapovalov53d45ba2019-07-03 12:56:3323#include "api/task_queue/default_task_queue_factory.h"
Harald Alvestrandc24a2182022-02-23 13:44:5924#include "api/task_queue/task_queue_factory.h"
25#include "api/transport/sctp_transport_factory_interface.h"
Steve Anton10542f22019-01-11 17:11:0026#include "p2p/base/p2p_constants.h"
27#include "p2p/base/port_allocator.h"
28#include "pc/media_session.h"
29#include "pc/peer_connection.h"
Markus Handella1b82012021-05-26 16:56:3030#include "pc/peer_connection_proxy.h"
Steve Anton10542f22019-01-11 17:11:0031#include "pc/peer_connection_wrapper.h"
Harald Alvestrandc24a2182022-02-23 13:44:5932#include "pc/sctp_transport.h"
Steve Anton10542f22019-01-11 17:11:0033#include "pc/sdp_utils.h"
34#include "pc/session_description.h"
Danil Chapovalovc63120a2023-11-03 10:32:2435#include "pc/test/enable_fake_media.h"
Steve Anton10542f22019-01-11 17:11:0036#include "pc/test/mock_peer_connection_observers.h"
Yves Gerey3e707812018-11-28 15:47:4937#include "rtc_base/checks.h"
Harald Alvestrandc24a2182022-02-23 13:44:5938#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 17:11:0039#include "rtc_base/rtc_certificate_generator.h"
Yves Gerey3e707812018-11-28 15:47:4940#include "rtc_base/thread.h"
Harald Alvestrand4aa11922019-05-14 20:00:0141#include "test/gmock.h"
Yves Gerey3e707812018-11-28 15:47:4942#include "test/gtest.h"
Steve Antonda6c0952017-10-23 18:41:5443#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 17:11:0044#include "pc/test/android_test_initializer.h"
Steve Antonda6c0952017-10-23 18:41:5445#endif
Steve Anton10542f22019-01-11 17:11:0046#include "rtc_base/virtual_socket_server.h"
Per Kjellander2bca0082020-08-28 07:15:1547#include "test/pc/sctp/fake_sctp_transport.h"
Steve Antonda6c0952017-10-23 18:41:5448
49namespace webrtc {
50
51using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
52using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
Harald Alvestrand4aa11922019-05-14 20:00:0153using ::testing::HasSubstr;
54using ::testing::Not;
Steve Antonda6c0952017-10-23 18:41:5455using ::testing::Values;
56
Bjorn Mellem175aa2e2018-11-08 19:23:2257namespace {
58
Per Kjellander2bca0082020-08-28 07:15:1559PeerConnectionFactoryDependencies CreatePeerConnectionFactoryDependencies() {
Bjorn Mellem175aa2e2018-11-08 19:23:2260 PeerConnectionFactoryDependencies deps;
Per Kjellander2bca0082020-08-28 07:15:1561 deps.network_thread = rtc::Thread::Current();
62 deps.worker_thread = rtc::Thread::Current();
63 deps.signaling_thread = rtc::Thread::Current();
Danil Chapovalov53d45ba2019-07-03 12:56:3364 deps.task_queue_factory = CreateDefaultTaskQueueFactory();
Danil Chapovalovc63120a2023-11-03 10:32:2465 EnableFakeMedia(deps);
Per Kjellander2bca0082020-08-28 07:15:1566 deps.sctp_factory = std::make_unique<FakeSctpTransportFactory>();
Bjorn Mellem175aa2e2018-11-08 19:23:2267 return deps;
68}
69
70} // namespace
71
Steve Antonda6c0952017-10-23 18:41:5472class PeerConnectionWrapperForDataChannelTest : public PeerConnectionWrapper {
73 public:
74 using PeerConnectionWrapper::PeerConnectionWrapper;
75
76 FakeSctpTransportFactory* sctp_transport_factory() {
77 return sctp_transport_factory_;
78 }
79
80 void set_sctp_transport_factory(
81 FakeSctpTransportFactory* sctp_transport_factory) {
82 sctp_transport_factory_ = sctp_transport_factory;
83 }
84
Harald Alvestrand1cb929f2020-02-05 11:07:3385 absl::optional<std::string> sctp_mid() {
86 return GetInternalPeerConnection()->sctp_mid();
Steve Antonda6c0952017-10-23 18:41:5487 }
88
Danil Chapovalov66cadcc2018-06-19 14:47:4389 absl::optional<std::string> sctp_transport_name() {
Steve Antonda6c0952017-10-23 18:41:5490 return GetInternalPeerConnection()->sctp_transport_name();
91 }
92
93 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 10:29:3494 auto* pci =
95 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
96 pc());
97 return static_cast<PeerConnection*>(pci->internal());
Steve Antonda6c0952017-10-23 18:41:5498 }
99
100 private:
101 FakeSctpTransportFactory* sctp_transport_factory_ = nullptr;
102};
103
Steve Antondbf9d032018-01-19 23:23:40104class PeerConnectionDataChannelBaseTest : public ::testing::Test {
Steve Antonda6c0952017-10-23 18:41:54105 protected:
106 typedef std::unique_ptr<PeerConnectionWrapperForDataChannelTest> WrapperPtr;
107
Steve Antondbf9d032018-01-19 23:23:40108 explicit PeerConnectionDataChannelBaseTest(SdpSemantics sdp_semantics)
109 : vss_(new rtc::VirtualSocketServer()),
110 main_(vss_.get()),
111 sdp_semantics_(sdp_semantics) {
Steve Antonda6c0952017-10-23 18:41:54112#ifdef WEBRTC_ANDROID
113 InitializeAndroidObjects();
114#endif
115 }
116
117 WrapperPtr CreatePeerConnection() {
118 return CreatePeerConnection(RTCConfiguration());
119 }
120
121 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
122 return CreatePeerConnection(config,
123 PeerConnectionFactoryInterface::Options());
124 }
125
126 WrapperPtr CreatePeerConnection(
127 const RTCConfiguration& config,
128 const PeerConnectionFactoryInterface::Options factory_options) {
Per Kjellander2bca0082020-08-28 07:15:15129 auto factory_deps = CreatePeerConnectionFactoryDependencies();
130 FakeSctpTransportFactory* fake_sctp_transport_factory =
131 static_cast<FakeSctpTransportFactory*>(factory_deps.sctp_factory.get());
132 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory =
133 CreateModularPeerConnectionFactory(std::move(factory_deps));
Steve Antonda6c0952017-10-23 18:41:54134 pc_factory->SetOptions(factory_options);
Mirko Bonadei317a1f02019-09-17 15:06:18135 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Antondbf9d032018-01-19 23:23:40136 RTCConfiguration modified_config = config;
137 modified_config.sdp_semantics = sdp_semantics_;
Florent Castelli72424402022-04-06 01:45:10138 auto result = pc_factory->CreatePeerConnectionOrError(
139 modified_config, PeerConnectionDependencies(observer.get()));
140 if (!result.ok()) {
Steve Antonda6c0952017-10-23 18:41:54141 return nullptr;
142 }
143
Niels Möllerafb246b2022-04-20 12:26:50144 observer->SetPeerConnectionInterface(result.value().get());
Mirko Bonadei317a1f02019-09-17 15:06:18145 auto wrapper = std::make_unique<PeerConnectionWrapperForDataChannelTest>(
Florent Castelli72424402022-04-06 01:45:10146 pc_factory, result.MoveValue(), std::move(observer));
Per Kjellander2bca0082020-08-28 07:15:15147 wrapper->set_sctp_transport_factory(fake_sctp_transport_factory);
Steve Antonda6c0952017-10-23 18:41:54148 return wrapper;
149 }
150
151 // Accepts the same arguments as CreatePeerConnection and adds a default data
152 // channel.
153 template <typename... Args>
154 WrapperPtr CreatePeerConnectionWithDataChannel(Args&&... args) {
155 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
156 if (!wrapper) {
157 return nullptr;
158 }
Florent Castelli72424402022-04-06 01:45:10159 EXPECT_TRUE(wrapper->pc()->CreateDataChannelOrError("dc", nullptr).ok());
Steve Antonda6c0952017-10-23 18:41:54160 return wrapper;
161 }
162
163 // Changes the SCTP data channel port on the given session description.
164 void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
165 int port) {
Steve Antonda6c0952017-10-23 18:41:54166 auto* data_content = cricket::GetFirstDataContent(desc);
167 RTC_DCHECK(data_content);
Harald Alvestrand5fc28b12019-05-13 11:36:16168 auto* data_desc = data_content->media_description()->as_sctp();
169 RTC_DCHECK(data_desc);
170 data_desc->set_port(port);
Steve Antonda6c0952017-10-23 18:41:54171 }
172
173 std::unique_ptr<rtc::VirtualSocketServer> vss_;
174 rtc::AutoSocketServerThread main_;
Steve Antondbf9d032018-01-19 23:23:40175 const SdpSemantics sdp_semantics_;
Steve Antonda6c0952017-10-23 18:41:54176};
177
Steve Antondbf9d032018-01-19 23:23:40178class PeerConnectionDataChannelTest
179 : public PeerConnectionDataChannelBaseTest,
180 public ::testing::WithParamInterface<SdpSemantics> {
181 protected:
182 PeerConnectionDataChannelTest()
183 : PeerConnectionDataChannelBaseTest(GetParam()) {}
184};
185
Steve Antonc8ff1602020-02-05 21:53:38186class PeerConnectionDataChannelUnifiedPlanTest
187 : public PeerConnectionDataChannelBaseTest {
188 protected:
189 PeerConnectionDataChannelUnifiedPlanTest()
190 : PeerConnectionDataChannelBaseTest(SdpSemantics::kUnifiedPlan) {}
191};
192
Bjorn A Mellembc3eebc2019-09-23 21:53:54193TEST_P(PeerConnectionDataChannelTest, InternalSctpTransportDeletedOnTeardown) {
194 auto caller = CreatePeerConnectionWithDataChannel();
195
196 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
197 EXPECT_TRUE(caller->sctp_transport_factory()->last_fake_sctp_transport());
198
199 rtc::scoped_refptr<SctpTransportInterface> sctp_transport =
200 caller->GetInternalPeerConnection()->GetSctpTransport();
201
202 caller.reset();
203 EXPECT_EQ(static_cast<SctpTransport*>(sctp_transport.get())->internal(),
204 nullptr);
205}
206
Harald Alvestrand1cb929f2020-02-05 11:07:33207// Test that sctp_mid/sctp_transport_name (used for stats) are correct
Steve Antonda6c0952017-10-23 18:41:54208// before and after BUNDLE is negotiated.
Steve Antondbf9d032018-01-19 23:23:40209TEST_P(PeerConnectionDataChannelTest, SctpContentAndTransportNameSetCorrectly) {
Steve Antonda6c0952017-10-23 18:41:54210 auto caller = CreatePeerConnection();
211 auto callee = CreatePeerConnection();
212
213 // Initially these fields should be empty.
Harald Alvestrand1cb929f2020-02-05 11:07:33214 EXPECT_FALSE(caller->sctp_mid());
Steve Antonda6c0952017-10-23 18:41:54215 EXPECT_FALSE(caller->sctp_transport_name());
216
217 // Create offer with audio/video/data.
218 // Default bundle policy is "balanced", so data should be using its own
219 // transport.
220 caller->AddAudioTrack("a");
221 caller->AddVideoTrack("v");
Florent Castelli72424402022-04-06 01:45:10222 caller->pc()->CreateDataChannelOrError("dc", nullptr);
Steve Antondbf9d032018-01-19 23:23:40223
224 auto offer = caller->CreateOffer();
225 const auto& offer_contents = offer->description()->contents();
226 ASSERT_EQ(cricket::MEDIA_TYPE_AUDIO,
227 offer_contents[0].media_description()->type());
228 std::string audio_mid = offer_contents[0].name;
229 ASSERT_EQ(cricket::MEDIA_TYPE_DATA,
230 offer_contents[2].media_description()->type());
231 std::string data_mid = offer_contents[2].name;
232
233 ASSERT_TRUE(
234 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
235 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Steve Antonda6c0952017-10-23 18:41:54236
Harald Alvestrand1cb929f2020-02-05 11:07:33237 ASSERT_TRUE(caller->sctp_mid());
238 EXPECT_EQ(data_mid, *caller->sctp_mid());
Steve Antonda6c0952017-10-23 18:41:54239 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 23:23:40240 EXPECT_EQ(data_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 18:41:54241
242 // Create answer that finishes BUNDLE negotiation, which means everything
243 // should be bundled on the first transport (audio).
244 RTCOfferAnswerOptions options;
245 options.use_rtp_mux = true;
246 ASSERT_TRUE(
247 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
248
Harald Alvestrand1cb929f2020-02-05 11:07:33249 ASSERT_TRUE(caller->sctp_mid());
250 EXPECT_EQ(data_mid, *caller->sctp_mid());
Steve Antonda6c0952017-10-23 18:41:54251 ASSERT_TRUE(caller->sctp_transport_name());
Steve Antondbf9d032018-01-19 23:23:40252 EXPECT_EQ(audio_mid, *caller->sctp_transport_name());
Steve Antonda6c0952017-10-23 18:41:54253}
254
Steve Antondbf9d032018-01-19 23:23:40255TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 18:41:54256 CreateOfferWithNoDataChannelsGivesNoDataSection) {
257 auto caller = CreatePeerConnection();
258 auto offer = caller->CreateOffer();
259
260 EXPECT_FALSE(offer->description()->GetContentByName(cricket::CN_DATA));
261 EXPECT_FALSE(offer->description()->GetTransportInfoByName(cricket::CN_DATA));
262}
263
Steve Antondbf9d032018-01-19 23:23:40264TEST_P(PeerConnectionDataChannelTest,
Steve Antonda6c0952017-10-23 18:41:54265 CreateAnswerWithRemoteSctpDataChannelIncludesDataSection) {
266 auto caller = CreatePeerConnectionWithDataChannel();
267 auto callee = CreatePeerConnection();
268
269 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
270
271 auto answer = callee->CreateAnswer();
272 ASSERT_TRUE(answer);
Steve Antondbf9d032018-01-19 23:23:40273 auto* data_content = cricket::GetFirstDataContent(answer->description());
Steve Antonda6c0952017-10-23 18:41:54274 ASSERT_TRUE(data_content);
275 EXPECT_FALSE(data_content->rejected);
Steve Antondbf9d032018-01-19 23:23:40276 EXPECT_TRUE(
277 answer->description()->GetTransportInfoByName(data_content->name));
Steve Antonda6c0952017-10-23 18:41:54278}
279
Steve Antondbf9d032018-01-19 23:23:40280TEST_P(PeerConnectionDataChannelTest, SctpPortPropagatedFromSdpToTransport) {
Steve Antonda6c0952017-10-23 18:41:54281 constexpr int kNewSendPort = 9998;
282 constexpr int kNewRecvPort = 7775;
283
284 auto caller = CreatePeerConnectionWithDataChannel();
285 auto callee = CreatePeerConnectionWithDataChannel();
286
287 auto offer = caller->CreateOffer();
288 ChangeSctpPortOnDescription(offer->description(), kNewSendPort);
289 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
290
291 auto answer = callee->CreateAnswer();
292 ChangeSctpPortOnDescription(answer->description(), kNewRecvPort);
Harald Alvestrand7af57c62021-04-16 11:12:14293 std::string sdp;
294 answer->ToString(&sdp);
Steve Antonda6c0952017-10-23 18:41:54295 ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
Steve Antonda6c0952017-10-23 18:41:54296 auto* callee_transport =
297 callee->sctp_transport_factory()->last_fake_sctp_transport();
298 ASSERT_TRUE(callee_transport);
299 EXPECT_EQ(kNewSendPort, callee_transport->remote_port());
300 EXPECT_EQ(kNewRecvPort, callee_transport->local_port());
301}
302
Guido Urdanetacecf87f2019-05-31 10:17:38303TEST_P(PeerConnectionDataChannelTest, ModernSdpSyntaxByDefault) {
Harald Alvestrand4aa11922019-05-14 20:00:01304 PeerConnectionInterface::RTCOfferAnswerOptions options;
305 auto caller = CreatePeerConnectionWithDataChannel();
306 auto offer = caller->CreateOffer(options);
307 EXPECT_FALSE(cricket::GetFirstSctpDataContentDescription(offer->description())
308 ->use_sctpmap());
309 std::string sdp;
310 offer->ToString(&sdp);
311 RTC_LOG(LS_ERROR) << sdp;
312 EXPECT_THAT(sdp, HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel"));
313 EXPECT_THAT(sdp, Not(HasSubstr("a=sctpmap:")));
314}
315
316TEST_P(PeerConnectionDataChannelTest, ObsoleteSdpSyntaxIfSet) {
317 PeerConnectionInterface::RTCOfferAnswerOptions options;
318 options.use_obsolete_sctp_sdp = true;
319 auto caller = CreatePeerConnectionWithDataChannel();
320 auto offer = caller->CreateOffer(options);
321 EXPECT_TRUE(cricket::GetFirstSctpDataContentDescription(offer->description())
322 ->use_sctpmap());
323 std::string sdp;
324 offer->ToString(&sdp);
325 EXPECT_THAT(sdp, Not(HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel")));
326 EXPECT_THAT(sdp, HasSubstr("a=sctpmap:"));
327}
328
Mirko Bonadeic84f6612019-01-31 11:20:57329INSTANTIATE_TEST_SUITE_P(PeerConnectionDataChannelTest,
330 PeerConnectionDataChannelTest,
Florent Castelli15a38de2022-04-05 22:38:21331 Values(SdpSemantics::kPlanB_DEPRECATED,
Mirko Bonadeic84f6612019-01-31 11:20:57332 SdpSemantics::kUnifiedPlan));
Steve Antondbf9d032018-01-19 23:23:40333
Steve Antonda6c0952017-10-23 18:41:54334} // namespace webrtc