xref: /aosp_15_r20/external/webrtc/pc/sctp_transport_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/sctp_transport.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <utility>
14*d9f75844SAndroid Build Coastguard Worker #include <vector>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
17*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/transport/data_channel_transport_interface.h"
20*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_channel.h"
21*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/fake_dtls_transport.h"
22*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
23*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/packet_transport_internal.h"
24*d9f75844SAndroid Build Coastguard Worker #include "pc/dtls_transport.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/copy_on_write_buffer.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
27*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
28*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker constexpr int kDefaultTimeout = 1000;  // milliseconds
31*d9f75844SAndroid Build Coastguard Worker constexpr int kTestMaxSctpStreams = 1234;
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker using cricket::FakeDtlsTransport;
34*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
37*d9f75844SAndroid Build Coastguard Worker 
38*d9f75844SAndroid Build Coastguard Worker namespace {
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker class FakeCricketSctpTransport : public cricket::SctpTransportInternal {
41*d9f75844SAndroid Build Coastguard Worker  public:
SetOnConnectedCallback(std::function<void ()> callback)42*d9f75844SAndroid Build Coastguard Worker   void SetOnConnectedCallback(std::function<void()> callback) override {
43*d9f75844SAndroid Build Coastguard Worker     on_connected_callback_ = std::move(callback);
44*d9f75844SAndroid Build Coastguard Worker   }
SetDataChannelSink(DataChannelSink * sink)45*d9f75844SAndroid Build Coastguard Worker   void SetDataChannelSink(DataChannelSink* sink) override {}
SetDtlsTransport(rtc::PacketTransportInternal * transport)46*d9f75844SAndroid Build Coastguard Worker   void SetDtlsTransport(rtc::PacketTransportInternal* transport) override {}
Start(int local_port,int remote_port,int max_message_size)47*d9f75844SAndroid Build Coastguard Worker   bool Start(int local_port, int remote_port, int max_message_size) override {
48*d9f75844SAndroid Build Coastguard Worker     return true;
49*d9f75844SAndroid Build Coastguard Worker   }
OpenStream(int sid)50*d9f75844SAndroid Build Coastguard Worker   bool OpenStream(int sid) override { return true; }
ResetStream(int sid)51*d9f75844SAndroid Build Coastguard Worker   bool ResetStream(int sid) override { return true; }
SendData(int sid,const SendDataParams & params,const rtc::CopyOnWriteBuffer & payload,cricket::SendDataResult * result=nullptr)52*d9f75844SAndroid Build Coastguard Worker   bool SendData(int sid,
53*d9f75844SAndroid Build Coastguard Worker                 const SendDataParams& params,
54*d9f75844SAndroid Build Coastguard Worker                 const rtc::CopyOnWriteBuffer& payload,
55*d9f75844SAndroid Build Coastguard Worker                 cricket::SendDataResult* result = nullptr) override {
56*d9f75844SAndroid Build Coastguard Worker     return true;
57*d9f75844SAndroid Build Coastguard Worker   }
ReadyToSendData()58*d9f75844SAndroid Build Coastguard Worker   bool ReadyToSendData() override { return true; }
set_debug_name_for_testing(const char * debug_name)59*d9f75844SAndroid Build Coastguard Worker   void set_debug_name_for_testing(const char* debug_name) override {}
max_message_size() const60*d9f75844SAndroid Build Coastguard Worker   int max_message_size() const override { return 0; }
max_outbound_streams() const61*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> max_outbound_streams() const override {
62*d9f75844SAndroid Build Coastguard Worker     return max_outbound_streams_;
63*d9f75844SAndroid Build Coastguard Worker   }
max_inbound_streams() const64*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> max_inbound_streams() const override {
65*d9f75844SAndroid Build Coastguard Worker     return max_inbound_streams_;
66*d9f75844SAndroid Build Coastguard Worker   }
67*d9f75844SAndroid Build Coastguard Worker 
SendSignalAssociationChangeCommunicationUp()68*d9f75844SAndroid Build Coastguard Worker   void SendSignalAssociationChangeCommunicationUp() {
69*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(on_connected_callback_);
70*d9f75844SAndroid Build Coastguard Worker     on_connected_callback_();
71*d9f75844SAndroid Build Coastguard Worker   }
72*d9f75844SAndroid Build Coastguard Worker 
set_max_outbound_streams(int streams)73*d9f75844SAndroid Build Coastguard Worker   void set_max_outbound_streams(int streams) {
74*d9f75844SAndroid Build Coastguard Worker     max_outbound_streams_ = streams;
75*d9f75844SAndroid Build Coastguard Worker   }
set_max_inbound_streams(int streams)76*d9f75844SAndroid Build Coastguard Worker   void set_max_inbound_streams(int streams) { max_inbound_streams_ = streams; }
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker  private:
79*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> max_outbound_streams_;
80*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> max_inbound_streams_;
81*d9f75844SAndroid Build Coastguard Worker   std::function<void()> on_connected_callback_;
82*d9f75844SAndroid Build Coastguard Worker };
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker }  // namespace
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker class TestSctpTransportObserver : public SctpTransportObserverInterface {
87*d9f75844SAndroid Build Coastguard Worker  public:
TestSctpTransportObserver()88*d9f75844SAndroid Build Coastguard Worker   TestSctpTransportObserver() : info_(SctpTransportState::kNew) {}
89*d9f75844SAndroid Build Coastguard Worker 
OnStateChange(SctpTransportInformation info)90*d9f75844SAndroid Build Coastguard Worker   void OnStateChange(SctpTransportInformation info) override {
91*d9f75844SAndroid Build Coastguard Worker     info_ = info;
92*d9f75844SAndroid Build Coastguard Worker     states_.push_back(info.state());
93*d9f75844SAndroid Build Coastguard Worker   }
94*d9f75844SAndroid Build Coastguard Worker 
State()95*d9f75844SAndroid Build Coastguard Worker   SctpTransportState State() {
96*d9f75844SAndroid Build Coastguard Worker     if (states_.size() > 0) {
97*d9f75844SAndroid Build Coastguard Worker       return states_[states_.size() - 1];
98*d9f75844SAndroid Build Coastguard Worker     } else {
99*d9f75844SAndroid Build Coastguard Worker       return SctpTransportState::kNew;
100*d9f75844SAndroid Build Coastguard Worker     }
101*d9f75844SAndroid Build Coastguard Worker   }
102*d9f75844SAndroid Build Coastguard Worker 
States()103*d9f75844SAndroid Build Coastguard Worker   const std::vector<SctpTransportState>& States() { return states_; }
104*d9f75844SAndroid Build Coastguard Worker 
LastReceivedInformation()105*d9f75844SAndroid Build Coastguard Worker   const SctpTransportInformation LastReceivedInformation() { return info_; }
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker  private:
108*d9f75844SAndroid Build Coastguard Worker   std::vector<SctpTransportState> states_;
109*d9f75844SAndroid Build Coastguard Worker   SctpTransportInformation info_;
110*d9f75844SAndroid Build Coastguard Worker };
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker class SctpTransportTest : public ::testing::Test {
113*d9f75844SAndroid Build Coastguard Worker  public:
transport()114*d9f75844SAndroid Build Coastguard Worker   SctpTransport* transport() { return transport_.get(); }
observer()115*d9f75844SAndroid Build Coastguard Worker   SctpTransportObserverInterface* observer() { return &observer_; }
116*d9f75844SAndroid Build Coastguard Worker 
CreateTransport()117*d9f75844SAndroid Build Coastguard Worker   void CreateTransport() {
118*d9f75844SAndroid Build Coastguard Worker     auto cricket_sctp_transport =
119*d9f75844SAndroid Build Coastguard Worker         absl::WrapUnique(new FakeCricketSctpTransport());
120*d9f75844SAndroid Build Coastguard Worker     transport_ =
121*d9f75844SAndroid Build Coastguard Worker         rtc::make_ref_counted<SctpTransport>(std::move(cricket_sctp_transport));
122*d9f75844SAndroid Build Coastguard Worker   }
123*d9f75844SAndroid Build Coastguard Worker 
AddDtlsTransport()124*d9f75844SAndroid Build Coastguard Worker   void AddDtlsTransport() {
125*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<cricket::DtlsTransportInternal> cricket_transport =
126*d9f75844SAndroid Build Coastguard Worker         std::make_unique<FakeDtlsTransport>(
127*d9f75844SAndroid Build Coastguard Worker             "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
128*d9f75844SAndroid Build Coastguard Worker     dtls_transport_ =
129*d9f75844SAndroid Build Coastguard Worker         rtc::make_ref_counted<DtlsTransport>(std::move(cricket_transport));
130*d9f75844SAndroid Build Coastguard Worker     transport_->SetDtlsTransport(dtls_transport_);
131*d9f75844SAndroid Build Coastguard Worker   }
132*d9f75844SAndroid Build Coastguard Worker 
CompleteSctpHandshake()133*d9f75844SAndroid Build Coastguard Worker   void CompleteSctpHandshake() {
134*d9f75844SAndroid Build Coastguard Worker     // The computed MaxChannels shall be the minimum of the outgoing
135*d9f75844SAndroid Build Coastguard Worker     // and incoming # of streams.
136*d9f75844SAndroid Build Coastguard Worker     CricketSctpTransport()->set_max_outbound_streams(kTestMaxSctpStreams);
137*d9f75844SAndroid Build Coastguard Worker     CricketSctpTransport()->set_max_inbound_streams(kTestMaxSctpStreams + 1);
138*d9f75844SAndroid Build Coastguard Worker     CricketSctpTransport()->SendSignalAssociationChangeCommunicationUp();
139*d9f75844SAndroid Build Coastguard Worker   }
140*d9f75844SAndroid Build Coastguard Worker 
CricketSctpTransport()141*d9f75844SAndroid Build Coastguard Worker   FakeCricketSctpTransport* CricketSctpTransport() {
142*d9f75844SAndroid Build Coastguard Worker     return static_cast<FakeCricketSctpTransport*>(transport_->internal());
143*d9f75844SAndroid Build Coastguard Worker   }
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker   rtc::AutoThread main_thread_;
146*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<SctpTransport> transport_;
147*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<DtlsTransport> dtls_transport_;
148*d9f75844SAndroid Build Coastguard Worker   TestSctpTransportObserver observer_;
149*d9f75844SAndroid Build Coastguard Worker };
150*d9f75844SAndroid Build Coastguard Worker 
TEST(SctpTransportSimpleTest,CreateClearDelete)151*d9f75844SAndroid Build Coastguard Worker TEST(SctpTransportSimpleTest, CreateClearDelete) {
152*d9f75844SAndroid Build Coastguard Worker   rtc::AutoThread main_thread;
153*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<cricket::SctpTransportInternal> fake_cricket_sctp_transport =
154*d9f75844SAndroid Build Coastguard Worker       absl::WrapUnique(new FakeCricketSctpTransport());
155*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<SctpTransport> sctp_transport =
156*d9f75844SAndroid Build Coastguard Worker       rtc::make_ref_counted<SctpTransport>(
157*d9f75844SAndroid Build Coastguard Worker           std::move(fake_cricket_sctp_transport));
158*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(sctp_transport->internal());
159*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(SctpTransportState::kNew, sctp_transport->Information().state());
160*d9f75844SAndroid Build Coastguard Worker   sctp_transport->Clear();
161*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(sctp_transport->internal());
162*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(SctpTransportState::kClosed, sctp_transport->Information().state());
163*d9f75844SAndroid Build Coastguard Worker }
164*d9f75844SAndroid Build Coastguard Worker 
TEST_F(SctpTransportTest,EventsObservedWhenConnecting)165*d9f75844SAndroid Build Coastguard Worker TEST_F(SctpTransportTest, EventsObservedWhenConnecting) {
166*d9f75844SAndroid Build Coastguard Worker   CreateTransport();
167*d9f75844SAndroid Build Coastguard Worker   transport()->RegisterObserver(observer());
168*d9f75844SAndroid Build Coastguard Worker   AddDtlsTransport();
169*d9f75844SAndroid Build Coastguard Worker   CompleteSctpHandshake();
170*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
171*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
172*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(observer_.States(), ElementsAre(SctpTransportState::kConnecting,
173*d9f75844SAndroid Build Coastguard Worker                                               SctpTransportState::kConnected));
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker 
TEST_F(SctpTransportTest,CloseWhenClearing)176*d9f75844SAndroid Build Coastguard Worker TEST_F(SctpTransportTest, CloseWhenClearing) {
177*d9f75844SAndroid Build Coastguard Worker   CreateTransport();
178*d9f75844SAndroid Build Coastguard Worker   transport()->RegisterObserver(observer());
179*d9f75844SAndroid Build Coastguard Worker   AddDtlsTransport();
180*d9f75844SAndroid Build Coastguard Worker   CompleteSctpHandshake();
181*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
182*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
183*d9f75844SAndroid Build Coastguard Worker   transport()->Clear();
184*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
185*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker 
TEST_F(SctpTransportTest,MaxChannelsSignalled)188*d9f75844SAndroid Build Coastguard Worker TEST_F(SctpTransportTest, MaxChannelsSignalled) {
189*d9f75844SAndroid Build Coastguard Worker   CreateTransport();
190*d9f75844SAndroid Build Coastguard Worker   transport()->RegisterObserver(observer());
191*d9f75844SAndroid Build Coastguard Worker   AddDtlsTransport();
192*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(transport()->Information().MaxChannels());
193*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(observer_.LastReceivedInformation().MaxChannels());
194*d9f75844SAndroid Build Coastguard Worker   CompleteSctpHandshake();
195*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
196*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
197*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(transport()->Information().MaxChannels());
198*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kTestMaxSctpStreams, *(transport()->Information().MaxChannels()));
199*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(observer_.LastReceivedInformation().MaxChannels());
200*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kTestMaxSctpStreams,
201*d9f75844SAndroid Build Coastguard Worker             *(observer_.LastReceivedInformation().MaxChannels()));
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker 
TEST_F(SctpTransportTest,CloseWhenTransportCloses)204*d9f75844SAndroid Build Coastguard Worker TEST_F(SctpTransportTest, CloseWhenTransportCloses) {
205*d9f75844SAndroid Build Coastguard Worker   CreateTransport();
206*d9f75844SAndroid Build Coastguard Worker   transport()->RegisterObserver(observer());
207*d9f75844SAndroid Build Coastguard Worker   AddDtlsTransport();
208*d9f75844SAndroid Build Coastguard Worker   CompleteSctpHandshake();
209*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
210*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
211*d9f75844SAndroid Build Coastguard Worker   static_cast<cricket::FakeDtlsTransport*>(dtls_transport_->internal())
212*d9f75844SAndroid Build Coastguard Worker       ->SetDtlsState(DtlsTransportState::kClosed);
213*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
214*d9f75844SAndroid Build Coastguard Worker                  kDefaultTimeout);
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker 
217*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
218