blob: 679b481f4cc95d5cdbaef223e2ae379a32fc5752 [file] [log] [blame]
Harald Alvestrandc85328f2019-02-28 07:51:00 +01001/*
2 * Copyright 2019 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 "pc/sctp_transport.h"
12
13#include <utility>
14#include <vector>
15
16#include "absl/memory/memory.h"
Mirko Bonadei9f6808b2021-05-21 20:46:09 +020017#include "api/dtls_transport_interface.h"
Harald Alvestrandc85328f2019-02-28 07:51:00 +010018#include "p2p/base/fake_dtls_transport.h"
19#include "pc/dtls_transport.h"
20#include "rtc_base/gunit.h"
21#include "test/gmock.h"
22#include "test/gtest.h"
23
24constexpr int kDefaultTimeout = 1000; // milliseconds
Harald Alvestrand97716c02019-05-21 10:52:59 +020025constexpr int kTestMaxSctpStreams = 1234;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010026
27using cricket::FakeDtlsTransport;
28using ::testing::ElementsAre;
29
30namespace webrtc {
31
32namespace {
33
34class FakeCricketSctpTransport : public cricket::SctpTransportInternal {
35 public:
36 void SetDtlsTransport(rtc::PacketTransportInternal* transport) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020037 bool Start(int local_port, int remote_port, int max_message_size) override {
38 return true;
39 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010040 bool OpenStream(int sid) override { return true; }
41 bool ResetStream(int sid) override { return true; }
Florent Castellid95b1492021-05-10 11:29:56 +020042 bool SendData(int sid,
43 const SendDataParams& params,
Harald Alvestrandc85328f2019-02-28 07:51:00 +010044 const rtc::CopyOnWriteBuffer& payload,
45 cricket::SendDataResult* result = nullptr) override {
46 return true;
47 }
48 bool ReadyToSendData() override { return true; }
49 void set_debug_name_for_testing(const char* debug_name) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020050 int max_message_size() const override { return 0; }
Harald Alvestrand97716c02019-05-21 10:52:59 +020051 absl::optional<int> max_outbound_streams() const override {
52 return max_outbound_streams_;
53 }
54 absl::optional<int> max_inbound_streams() const override {
55 return max_inbound_streams_;
56 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010057 // Methods exposed for testing
58 void SendSignalReadyToSendData() { SignalReadyToSendData(); }
59
Harald Alvestrand97716c02019-05-21 10:52:59 +020060 void SendSignalAssociationChangeCommunicationUp() {
61 SignalAssociationChangeCommunicationUp();
62 }
63
Harald Alvestrandc85328f2019-02-28 07:51:00 +010064 void SendSignalClosingProcedureStartedRemotely() {
65 SignalClosingProcedureStartedRemotely(1);
66 }
67
68 void SendSignalClosingProcedureComplete() {
69 SignalClosingProcedureComplete(1);
70 }
Harald Alvestrand97716c02019-05-21 10:52:59 +020071 void set_max_outbound_streams(int streams) {
72 max_outbound_streams_ = streams;
73 }
74 void set_max_inbound_streams(int streams) { max_inbound_streams_ = streams; }
75
76 private:
77 absl::optional<int> max_outbound_streams_;
78 absl::optional<int> max_inbound_streams_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010079};
80
81} // namespace
82
83class TestSctpTransportObserver : public SctpTransportObserverInterface {
84 public:
Harald Alvestrand97716c02019-05-21 10:52:59 +020085 TestSctpTransportObserver() : info_(SctpTransportState::kNew) {}
86
Harald Alvestrandc85328f2019-02-28 07:51:00 +010087 void OnStateChange(SctpTransportInformation info) override {
Harald Alvestrand97716c02019-05-21 10:52:59 +020088 info_ = info;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010089 states_.push_back(info.state());
90 }
91
92 SctpTransportState State() {
93 if (states_.size() > 0) {
94 return states_[states_.size() - 1];
95 } else {
96 return SctpTransportState::kNew;
97 }
98 }
99
100 const std::vector<SctpTransportState>& States() { return states_; }
101
Harald Alvestrand97716c02019-05-21 10:52:59 +0200102 const SctpTransportInformation LastReceivedInformation() { return info_; }
103
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100104 private:
105 std::vector<SctpTransportState> states_;
Harald Alvestrand97716c02019-05-21 10:52:59 +0200106 SctpTransportInformation info_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100107};
108
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200109class SctpTransportTest : public ::testing::Test {
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100110 public:
111 SctpTransport* transport() { return transport_.get(); }
112 SctpTransportObserverInterface* observer() { return &observer_; }
113
114 void CreateTransport() {
115 auto cricket_sctp_transport =
116 absl::WrapUnique(new FakeCricketSctpTransport());
Tommi87f70902021-04-27 14:43:08 +0200117 transport_ =
118 rtc::make_ref_counted<SctpTransport>(std::move(cricket_sctp_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100119 }
120
121 void AddDtlsTransport() {
122 std::unique_ptr<cricket::DtlsTransportInternal> cricket_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200123 std::make_unique<FakeDtlsTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100124 "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
125 dtls_transport_ =
Tommi87f70902021-04-27 14:43:08 +0200126 rtc::make_ref_counted<DtlsTransport>(std::move(cricket_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100127 transport_->SetDtlsTransport(dtls_transport_);
128 }
129
130 void CompleteSctpHandshake() {
131 CricketSctpTransport()->SendSignalReadyToSendData();
Harald Alvestrand97716c02019-05-21 10:52:59 +0200132 // The computed MaxChannels shall be the minimum of the outgoing
133 // and incoming # of streams.
134 CricketSctpTransport()->set_max_outbound_streams(kTestMaxSctpStreams);
135 CricketSctpTransport()->set_max_inbound_streams(kTestMaxSctpStreams + 1);
136 CricketSctpTransport()->SendSignalAssociationChangeCommunicationUp();
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100137 }
138
139 FakeCricketSctpTransport* CricketSctpTransport() {
140 return static_cast<FakeCricketSctpTransport*>(transport_->internal());
141 }
142
143 rtc::scoped_refptr<SctpTransport> transport_;
144 rtc::scoped_refptr<DtlsTransport> dtls_transport_;
145 TestSctpTransportObserver observer_;
146};
147
148TEST(SctpTransportSimpleTest, CreateClearDelete) {
149 std::unique_ptr<cricket::SctpTransportInternal> fake_cricket_sctp_transport =
150 absl::WrapUnique(new FakeCricketSctpTransport());
151 rtc::scoped_refptr<SctpTransport> sctp_transport =
Tommi87f70902021-04-27 14:43:08 +0200152 rtc::make_ref_counted<SctpTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100153 std::move(fake_cricket_sctp_transport));
154 ASSERT_TRUE(sctp_transport->internal());
155 ASSERT_EQ(SctpTransportState::kNew, sctp_transport->Information().state());
156 sctp_transport->Clear();
157 ASSERT_FALSE(sctp_transport->internal());
158 ASSERT_EQ(SctpTransportState::kClosed, sctp_transport->Information().state());
159}
160
161TEST_F(SctpTransportTest, EventsObservedWhenConnecting) {
162 CreateTransport();
163 transport()->RegisterObserver(observer());
164 AddDtlsTransport();
165 CompleteSctpHandshake();
166 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
167 kDefaultTimeout);
168 EXPECT_THAT(observer_.States(), ElementsAre(SctpTransportState::kConnecting,
169 SctpTransportState::kConnected));
170}
171
172TEST_F(SctpTransportTest, CloseWhenClearing) {
173 CreateTransport();
174 transport()->RegisterObserver(observer());
175 AddDtlsTransport();
176 CompleteSctpHandshake();
177 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
178 kDefaultTimeout);
179 transport()->Clear();
180 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
181 kDefaultTimeout);
182}
183
Harald Alvestrand97716c02019-05-21 10:52:59 +0200184TEST_F(SctpTransportTest, MaxChannelsSignalled) {
185 CreateTransport();
186 transport()->RegisterObserver(observer());
187 AddDtlsTransport();
188 EXPECT_FALSE(transport()->Information().MaxChannels());
189 EXPECT_FALSE(observer_.LastReceivedInformation().MaxChannels());
190 CompleteSctpHandshake();
191 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
192 kDefaultTimeout);
193 EXPECT_TRUE(transport()->Information().MaxChannels());
194 EXPECT_EQ(kTestMaxSctpStreams, *(transport()->Information().MaxChannels()));
195 EXPECT_TRUE(observer_.LastReceivedInformation().MaxChannels());
196 EXPECT_EQ(kTestMaxSctpStreams,
197 *(observer_.LastReceivedInformation().MaxChannels()));
198}
199
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100200TEST_F(SctpTransportTest, CloseWhenTransportCloses) {
201 CreateTransport();
202 transport()->RegisterObserver(observer());
203 AddDtlsTransport();
204 CompleteSctpHandshake();
205 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
206 kDefaultTimeout);
207 static_cast<cricket::FakeDtlsTransport*>(dtls_transport_->internal())
Mirko Bonadei9f6808b2021-05-21 20:46:09 +0200208 ->SetDtlsState(DtlsTransportState::kClosed);
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100209 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
210 kDefaultTimeout);
211}
212
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100213} // namespace webrtc