1 /*
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 <memory>
12 #include <string>
13 #include <type_traits>
14 #include <utility>
15 #include <vector>
16 
17 #include "absl/types/optional.h"
18 #include "api/call/call_factory_interface.h"
19 #include "api/jsep.h"
20 #include "api/media_types.h"
21 #include "api/peer_connection_interface.h"
22 #include "api/peer_connection_proxy.h"
23 #include "api/scoped_refptr.h"
24 #include "api/task_queue/default_task_queue_factory.h"
25 #include "media/base/codec.h"
26 #include "media/base/fake_media_engine.h"
27 #include "media/base/media_constants.h"
28 #include "media/base/media_engine.h"
29 #include "media/sctp/sctp_transport_internal.h"
30 #include "p2p/base/p2p_constants.h"
31 #include "p2p/base/port_allocator.h"
32 #include "pc/media_session.h"
33 #include "pc/peer_connection.h"
34 #include "pc/peer_connection_factory.h"
35 #include "pc/peer_connection_wrapper.h"
36 #include "pc/sdp_utils.h"
37 #include "pc/session_description.h"
38 #include "pc/test/mock_peer_connection_observers.h"
39 #include "rtc_base/checks.h"
40 #include "rtc_base/ref_counted_object.h"
41 #include "rtc_base/rtc_certificate_generator.h"
42 #include "rtc_base/thread.h"
43 #include "test/gmock.h"
44 #include "test/gtest.h"
45 #ifdef WEBRTC_ANDROID
46 #include "pc/test/android_test_initializer.h"
47 #endif
48 #include "rtc_base/virtual_socket_server.h"
49 #include "test/pc/sctp/fake_sctp_transport.h"
50 
51 namespace webrtc {
52 
53 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
54 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
55 using ::testing::HasSubstr;
56 using ::testing::Not;
57 using ::testing::Values;
58 
59 namespace {
60 
CreatePeerConnectionFactoryDependencies()61 PeerConnectionFactoryDependencies CreatePeerConnectionFactoryDependencies() {
62   PeerConnectionFactoryDependencies deps;
63   deps.network_thread = rtc::Thread::Current();
64   deps.worker_thread = rtc::Thread::Current();
65   deps.signaling_thread = rtc::Thread::Current();
66   deps.task_queue_factory = CreateDefaultTaskQueueFactory();
67   deps.media_engine = std::make_unique<cricket::FakeMediaEngine>();
68   deps.call_factory = CreateCallFactory();
69   deps.sctp_factory = std::make_unique<FakeSctpTransportFactory>();
70   return deps;
71 }
72 
73 }  // namespace
74 
75 class PeerConnectionWrapperForDataChannelTest : public PeerConnectionWrapper {
76  public:
77   using PeerConnectionWrapper::PeerConnectionWrapper;
78 
sctp_transport_factory()79   FakeSctpTransportFactory* sctp_transport_factory() {
80     return sctp_transport_factory_;
81   }
82 
set_sctp_transport_factory(FakeSctpTransportFactory * sctp_transport_factory)83   void set_sctp_transport_factory(
84       FakeSctpTransportFactory* sctp_transport_factory) {
85     sctp_transport_factory_ = sctp_transport_factory;
86   }
87 
sctp_mid()88   absl::optional<std::string> sctp_mid() {
89     return GetInternalPeerConnection()->sctp_mid();
90   }
91 
sctp_transport_name()92   absl::optional<std::string> sctp_transport_name() {
93     return GetInternalPeerConnection()->sctp_transport_name();
94   }
95 
GetInternalPeerConnection()96   PeerConnection* GetInternalPeerConnection() {
97     auto* pci =
98         static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
99             pc());
100     return static_cast<PeerConnection*>(pci->internal());
101   }
102 
103  private:
104   FakeSctpTransportFactory* sctp_transport_factory_ = nullptr;
105 };
106 
107 class PeerConnectionDataChannelBaseTest : public ::testing::Test {
108  protected:
109   typedef std::unique_ptr<PeerConnectionWrapperForDataChannelTest> WrapperPtr;
110 
PeerConnectionDataChannelBaseTest(SdpSemantics sdp_semantics)111   explicit PeerConnectionDataChannelBaseTest(SdpSemantics sdp_semantics)
112       : vss_(new rtc::VirtualSocketServer()),
113         main_(vss_.get()),
114         sdp_semantics_(sdp_semantics) {
115 #ifdef WEBRTC_ANDROID
116     InitializeAndroidObjects();
117 #endif
118   }
119 
CreatePeerConnection()120   WrapperPtr CreatePeerConnection() {
121     return CreatePeerConnection(RTCConfiguration());
122   }
123 
CreatePeerConnection(const RTCConfiguration & config)124   WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
125     return CreatePeerConnection(config,
126                                 PeerConnectionFactoryInterface::Options());
127   }
128 
CreatePeerConnection(const RTCConfiguration & config,const PeerConnectionFactoryInterface::Options factory_options)129   WrapperPtr CreatePeerConnection(
130       const RTCConfiguration& config,
131       const PeerConnectionFactoryInterface::Options factory_options) {
132     auto factory_deps = CreatePeerConnectionFactoryDependencies();
133     FakeSctpTransportFactory* fake_sctp_transport_factory =
134         static_cast<FakeSctpTransportFactory*>(factory_deps.sctp_factory.get());
135     rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory =
136         CreateModularPeerConnectionFactory(std::move(factory_deps));
137     pc_factory->SetOptions(factory_options);
138     auto observer = std::make_unique<MockPeerConnectionObserver>();
139     RTCConfiguration modified_config = config;
140     modified_config.sdp_semantics = sdp_semantics_;
141     auto pc = pc_factory->CreatePeerConnection(modified_config, nullptr,
142                                                nullptr, observer.get());
143     if (!pc) {
144       return nullptr;
145     }
146 
147     observer->SetPeerConnectionInterface(pc.get());
148     auto wrapper = std::make_unique<PeerConnectionWrapperForDataChannelTest>(
149         pc_factory, pc, std::move(observer));
150     wrapper->set_sctp_transport_factory(fake_sctp_transport_factory);
151     return wrapper;
152   }
153 
154   // Accepts the same arguments as CreatePeerConnection and adds a default data
155   // channel.
156   template <typename... Args>
CreatePeerConnectionWithDataChannel(Args &&...args)157   WrapperPtr CreatePeerConnectionWithDataChannel(Args&&... args) {
158     auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
159     if (!wrapper) {
160       return nullptr;
161     }
162     EXPECT_TRUE(wrapper->pc()->CreateDataChannel("dc", nullptr));
163     return wrapper;
164   }
165 
166   // Changes the SCTP data channel port on the given session description.
ChangeSctpPortOnDescription(cricket::SessionDescription * desc,int port)167   void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
168                                    int port) {
169     auto* data_content = cricket::GetFirstDataContent(desc);
170     RTC_DCHECK(data_content);
171     auto* data_desc = data_content->media_description()->as_sctp();
172     RTC_DCHECK(data_desc);
173     data_desc->set_port(port);
174   }
175 
176   std::unique_ptr<rtc::VirtualSocketServer> vss_;
177   rtc::AutoSocketServerThread main_;
178   const SdpSemantics sdp_semantics_;
179 };
180 
181 class PeerConnectionDataChannelTest
182     : public PeerConnectionDataChannelBaseTest,
183       public ::testing::WithParamInterface<SdpSemantics> {
184  protected:
PeerConnectionDataChannelTest()185   PeerConnectionDataChannelTest()
186       : PeerConnectionDataChannelBaseTest(GetParam()) {}
187 };
188 
189 class PeerConnectionDataChannelUnifiedPlanTest
190     : public PeerConnectionDataChannelBaseTest {
191  protected:
PeerConnectionDataChannelUnifiedPlanTest()192   PeerConnectionDataChannelUnifiedPlanTest()
193       : PeerConnectionDataChannelBaseTest(SdpSemantics::kUnifiedPlan) {}
194 };
195 
TEST_P(PeerConnectionDataChannelTest,NoSctpTransportCreatedIfRtpDataChannelEnabled)196 TEST_P(PeerConnectionDataChannelTest,
197        NoSctpTransportCreatedIfRtpDataChannelEnabled) {
198   RTCConfiguration config;
199   config.enable_rtp_data_channel = true;
200   auto caller = CreatePeerConnectionWithDataChannel(config);
201 
202   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
203   EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
204 }
205 
TEST_P(PeerConnectionDataChannelTest,RtpDataChannelCreatedEvenIfSctpAvailable)206 TEST_P(PeerConnectionDataChannelTest,
207        RtpDataChannelCreatedEvenIfSctpAvailable) {
208   RTCConfiguration config;
209   config.enable_rtp_data_channel = true;
210   PeerConnectionFactoryInterface::Options options;
211   options.disable_sctp_data_channels = false;
212   auto caller = CreatePeerConnectionWithDataChannel(config, options);
213 
214   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
215   EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
216 }
217 
TEST_P(PeerConnectionDataChannelTest,InternalSctpTransportDeletedOnTeardown)218 TEST_P(PeerConnectionDataChannelTest, InternalSctpTransportDeletedOnTeardown) {
219   auto caller = CreatePeerConnectionWithDataChannel();
220 
221   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
222   EXPECT_TRUE(caller->sctp_transport_factory()->last_fake_sctp_transport());
223 
224   rtc::scoped_refptr<SctpTransportInterface> sctp_transport =
225       caller->GetInternalPeerConnection()->GetSctpTransport();
226 
227   caller.reset();
228   EXPECT_EQ(static_cast<SctpTransport*>(sctp_transport.get())->internal(),
229             nullptr);
230 }
231 
232 // Test that sctp_mid/sctp_transport_name (used for stats) are correct
233 // before and after BUNDLE is negotiated.
TEST_P(PeerConnectionDataChannelTest,SctpContentAndTransportNameSetCorrectly)234 TEST_P(PeerConnectionDataChannelTest, SctpContentAndTransportNameSetCorrectly) {
235   auto caller = CreatePeerConnection();
236   auto callee = CreatePeerConnection();
237 
238   // Initially these fields should be empty.
239   EXPECT_FALSE(caller->sctp_mid());
240   EXPECT_FALSE(caller->sctp_transport_name());
241 
242   // Create offer with audio/video/data.
243   // Default bundle policy is "balanced", so data should be using its own
244   // transport.
245   caller->AddAudioTrack("a");
246   caller->AddVideoTrack("v");
247   caller->pc()->CreateDataChannel("dc", nullptr);
248 
249   auto offer = caller->CreateOffer();
250   const auto& offer_contents = offer->description()->contents();
251   ASSERT_EQ(cricket::MEDIA_TYPE_AUDIO,
252             offer_contents[0].media_description()->type());
253   std::string audio_mid = offer_contents[0].name;
254   ASSERT_EQ(cricket::MEDIA_TYPE_DATA,
255             offer_contents[2].media_description()->type());
256   std::string data_mid = offer_contents[2].name;
257 
258   ASSERT_TRUE(
259       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
260   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
261 
262   ASSERT_TRUE(caller->sctp_mid());
263   EXPECT_EQ(data_mid, *caller->sctp_mid());
264   ASSERT_TRUE(caller->sctp_transport_name());
265   EXPECT_EQ(data_mid, *caller->sctp_transport_name());
266 
267   // Create answer that finishes BUNDLE negotiation, which means everything
268   // should be bundled on the first transport (audio).
269   RTCOfferAnswerOptions options;
270   options.use_rtp_mux = true;
271   ASSERT_TRUE(
272       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
273 
274   ASSERT_TRUE(caller->sctp_mid());
275   EXPECT_EQ(data_mid, *caller->sctp_mid());
276   ASSERT_TRUE(caller->sctp_transport_name());
277   EXPECT_EQ(audio_mid, *caller->sctp_transport_name());
278 }
279 
TEST_P(PeerConnectionDataChannelTest,CreateOfferWithNoDataChannelsGivesNoDataSection)280 TEST_P(PeerConnectionDataChannelTest,
281        CreateOfferWithNoDataChannelsGivesNoDataSection) {
282   auto caller = CreatePeerConnection();
283   auto offer = caller->CreateOffer();
284 
285   EXPECT_FALSE(offer->description()->GetContentByName(cricket::CN_DATA));
286   EXPECT_FALSE(offer->description()->GetTransportInfoByName(cricket::CN_DATA));
287 }
288 
TEST_P(PeerConnectionDataChannelTest,CreateAnswerWithRemoteSctpDataChannelIncludesDataSection)289 TEST_P(PeerConnectionDataChannelTest,
290        CreateAnswerWithRemoteSctpDataChannelIncludesDataSection) {
291   auto caller = CreatePeerConnectionWithDataChannel();
292   auto callee = CreatePeerConnection();
293 
294   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
295 
296   auto answer = callee->CreateAnswer();
297   ASSERT_TRUE(answer);
298   auto* data_content = cricket::GetFirstDataContent(answer->description());
299   ASSERT_TRUE(data_content);
300   EXPECT_FALSE(data_content->rejected);
301   EXPECT_TRUE(
302       answer->description()->GetTransportInfoByName(data_content->name));
303 }
304 
TEST_P(PeerConnectionDataChannelTest,CreateDataChannelWithDtlsDisabledSucceeds)305 TEST_P(PeerConnectionDataChannelTest,
306        CreateDataChannelWithDtlsDisabledSucceeds) {
307   RTCConfiguration config;
308   config.enable_dtls_srtp.emplace(false);
309   auto caller = CreatePeerConnection();
310 
311   EXPECT_TRUE(caller->pc()->CreateDataChannel("dc", nullptr));
312 }
313 
TEST_P(PeerConnectionDataChannelTest,CreateDataChannelWithSctpDisabledFails)314 TEST_P(PeerConnectionDataChannelTest, CreateDataChannelWithSctpDisabledFails) {
315   PeerConnectionFactoryInterface::Options options;
316   options.disable_sctp_data_channels = true;
317   auto caller = CreatePeerConnection(RTCConfiguration(), options);
318 
319   EXPECT_FALSE(caller->pc()->CreateDataChannel("dc", nullptr));
320 }
321 
322 // Test that if a callee has SCTP disabled and receives an offer with an SCTP
323 // data channel, the data section is rejected and no SCTP transport is created
324 // on the callee.
TEST_P(PeerConnectionDataChannelTest,DataSectionRejectedIfCalleeHasSctpDisabled)325 TEST_P(PeerConnectionDataChannelTest,
326        DataSectionRejectedIfCalleeHasSctpDisabled) {
327   auto caller = CreatePeerConnectionWithDataChannel();
328   PeerConnectionFactoryInterface::Options options;
329   options.disable_sctp_data_channels = true;
330   auto callee = CreatePeerConnection(RTCConfiguration(), options);
331 
332   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
333 
334   EXPECT_FALSE(callee->sctp_transport_factory()->last_fake_sctp_transport());
335 
336   auto answer = callee->CreateAnswer();
337   auto* data_content = cricket::GetFirstDataContent(answer->description());
338   ASSERT_TRUE(data_content);
339   EXPECT_TRUE(data_content->rejected);
340 }
341 
TEST_P(PeerConnectionDataChannelTest,SctpPortPropagatedFromSdpToTransport)342 TEST_P(PeerConnectionDataChannelTest, SctpPortPropagatedFromSdpToTransport) {
343   constexpr int kNewSendPort = 9998;
344   constexpr int kNewRecvPort = 7775;
345 
346   auto caller = CreatePeerConnectionWithDataChannel();
347   auto callee = CreatePeerConnectionWithDataChannel();
348 
349   auto offer = caller->CreateOffer();
350   ChangeSctpPortOnDescription(offer->description(), kNewSendPort);
351   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
352 
353   auto answer = callee->CreateAnswer();
354   ChangeSctpPortOnDescription(answer->description(), kNewRecvPort);
355   ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
356 
357   auto* callee_transport =
358       callee->sctp_transport_factory()->last_fake_sctp_transport();
359   ASSERT_TRUE(callee_transport);
360   EXPECT_EQ(kNewSendPort, callee_transport->remote_port());
361   EXPECT_EQ(kNewRecvPort, callee_transport->local_port());
362 }
363 
TEST_P(PeerConnectionDataChannelTest,ModernSdpSyntaxByDefault)364 TEST_P(PeerConnectionDataChannelTest, ModernSdpSyntaxByDefault) {
365   PeerConnectionInterface::RTCOfferAnswerOptions options;
366   auto caller = CreatePeerConnectionWithDataChannel();
367   auto offer = caller->CreateOffer(options);
368   EXPECT_FALSE(cricket::GetFirstSctpDataContentDescription(offer->description())
369                    ->use_sctpmap());
370   std::string sdp;
371   offer->ToString(&sdp);
372   RTC_LOG(LS_ERROR) << sdp;
373   EXPECT_THAT(sdp, HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel"));
374   EXPECT_THAT(sdp, Not(HasSubstr("a=sctpmap:")));
375 }
376 
TEST_P(PeerConnectionDataChannelTest,ObsoleteSdpSyntaxIfSet)377 TEST_P(PeerConnectionDataChannelTest, ObsoleteSdpSyntaxIfSet) {
378   PeerConnectionInterface::RTCOfferAnswerOptions options;
379   options.use_obsolete_sctp_sdp = true;
380   auto caller = CreatePeerConnectionWithDataChannel();
381   auto offer = caller->CreateOffer(options);
382   EXPECT_TRUE(cricket::GetFirstSctpDataContentDescription(offer->description())
383                   ->use_sctpmap());
384   std::string sdp;
385   offer->ToString(&sdp);
386   EXPECT_THAT(sdp, Not(HasSubstr(" UDP/DTLS/SCTP webrtc-datachannel")));
387   EXPECT_THAT(sdp, HasSubstr("a=sctpmap:"));
388 }
389 
390 INSTANTIATE_TEST_SUITE_P(PeerConnectionDataChannelTest,
391                          PeerConnectionDataChannelTest,
392                          Values(SdpSemantics::kPlanB,
393                                 SdpSemantics::kUnifiedPlan));
394 
TEST_F(PeerConnectionDataChannelUnifiedPlanTest,ReOfferAfterPeerRejectsDataChannel)395 TEST_F(PeerConnectionDataChannelUnifiedPlanTest,
396        ReOfferAfterPeerRejectsDataChannel) {
397   auto caller = CreatePeerConnectionWithDataChannel();
398   PeerConnectionFactoryInterface::Options options;
399   options.disable_sctp_data_channels = true;
400   auto callee = CreatePeerConnection(RTCConfiguration(), options);
401 
402   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
403 
404   auto offer = caller->CreateOffer();
405   ASSERT_TRUE(offer);
406   const auto& contents = offer->description()->contents();
407   ASSERT_EQ(1u, contents.size());
408   EXPECT_TRUE(contents[0].rejected);
409 
410   ASSERT_TRUE(
411       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
412   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
413 
414   auto answer = callee->CreateAnswerAndSetAsLocal();
415   ASSERT_TRUE(answer);
416   EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
417 }
418 
419 }  // namespace webrtc
420