blob: b4618edbffae7cd3f4fa8a02020a25ac4dd321f1 [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"
17#include "p2p/base/fake_dtls_transport.h"
18#include "pc/dtls_transport.h"
19#include "rtc_base/gunit.h"
20#include "test/gmock.h"
21#include "test/gtest.h"
22
23constexpr int kDefaultTimeout = 1000; // milliseconds
Harald Alvestrand97716c02019-05-21 10:52:59 +020024constexpr int kTestMaxSctpStreams = 1234;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010025
26using cricket::FakeDtlsTransport;
27using ::testing::ElementsAre;
28
29namespace webrtc {
30
31namespace {
32
33class FakeCricketSctpTransport : public cricket::SctpTransportInternal {
34 public:
35 void SetDtlsTransport(rtc::PacketTransportInternal* transport) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020036 bool Start(int local_port, int remote_port, int max_message_size) override {
37 return true;
38 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010039 bool OpenStream(int sid) override { return true; }
40 bool ResetStream(int sid) override { return true; }
Florent Castellid95b1492021-05-10 11:29:56 +020041 bool SendData(int sid,
42 const SendDataParams& params,
Harald Alvestrandc85328f2019-02-28 07:51:00 +010043 const rtc::CopyOnWriteBuffer& payload,
44 cricket::SendDataResult* result = nullptr) override {
45 return true;
46 }
47 bool ReadyToSendData() override { return true; }
48 void set_debug_name_for_testing(const char* debug_name) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020049 int max_message_size() const override { return 0; }
Harald Alvestrand97716c02019-05-21 10:52:59 +020050 absl::optional<int> max_outbound_streams() const override {
51 return max_outbound_streams_;
52 }
53 absl::optional<int> max_inbound_streams() const override {
54 return max_inbound_streams_;
55 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010056 // Methods exposed for testing
57 void SendSignalReadyToSendData() { SignalReadyToSendData(); }
58
Harald Alvestrand97716c02019-05-21 10:52:59 +020059 void SendSignalAssociationChangeCommunicationUp() {
60 SignalAssociationChangeCommunicationUp();
61 }
62
Harald Alvestrandc85328f2019-02-28 07:51:00 +010063 void SendSignalClosingProcedureStartedRemotely() {
64 SignalClosingProcedureStartedRemotely(1);
65 }
66
67 void SendSignalClosingProcedureComplete() {
68 SignalClosingProcedureComplete(1);
69 }
Harald Alvestrand97716c02019-05-21 10:52:59 +020070 void set_max_outbound_streams(int streams) {
71 max_outbound_streams_ = streams;
72 }
73 void set_max_inbound_streams(int streams) { max_inbound_streams_ = streams; }
74
75 private:
76 absl::optional<int> max_outbound_streams_;
77 absl::optional<int> max_inbound_streams_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010078};
79
80} // namespace
81
82class TestSctpTransportObserver : public SctpTransportObserverInterface {
83 public:
Harald Alvestrand97716c02019-05-21 10:52:59 +020084 TestSctpTransportObserver() : info_(SctpTransportState::kNew) {}
85
Harald Alvestrandc85328f2019-02-28 07:51:00 +010086 void OnStateChange(SctpTransportInformation info) override {
Harald Alvestrand97716c02019-05-21 10:52:59 +020087 info_ = info;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010088 states_.push_back(info.state());
89 }
90
91 SctpTransportState State() {
92 if (states_.size() > 0) {
93 return states_[states_.size() - 1];
94 } else {
95 return SctpTransportState::kNew;
96 }
97 }
98
99 const std::vector<SctpTransportState>& States() { return states_; }
100
Harald Alvestrand97716c02019-05-21 10:52:59 +0200101 const SctpTransportInformation LastReceivedInformation() { return info_; }
102
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100103 private:
104 std::vector<SctpTransportState> states_;
Harald Alvestrand97716c02019-05-21 10:52:59 +0200105 SctpTransportInformation info_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100106};
107
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200108class SctpTransportTest : public ::testing::Test {
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100109 public:
110 SctpTransport* transport() { return transport_.get(); }
111 SctpTransportObserverInterface* observer() { return &observer_; }
112
113 void CreateTransport() {
114 auto cricket_sctp_transport =
115 absl::WrapUnique(new FakeCricketSctpTransport());
Tommi87f70902021-04-27 14:43:08 +0200116 transport_ =
117 rtc::make_ref_counted<SctpTransport>(std::move(cricket_sctp_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100118 }
119
120 void AddDtlsTransport() {
121 std::unique_ptr<cricket::DtlsTransportInternal> cricket_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200122 std::make_unique<FakeDtlsTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100123 "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
124 dtls_transport_ =
Tommi87f70902021-04-27 14:43:08 +0200125 rtc::make_ref_counted<DtlsTransport>(std::move(cricket_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100126 transport_->SetDtlsTransport(dtls_transport_);
127 }
128
129 void CompleteSctpHandshake() {
130 CricketSctpTransport()->SendSignalReadyToSendData();
Harald Alvestrand97716c02019-05-21 10:52:59 +0200131 // The computed MaxChannels shall be the minimum of the outgoing
132 // and incoming # of streams.
133 CricketSctpTransport()->set_max_outbound_streams(kTestMaxSctpStreams);
134 CricketSctpTransport()->set_max_inbound_streams(kTestMaxSctpStreams + 1);
135 CricketSctpTransport()->SendSignalAssociationChangeCommunicationUp();
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100136 }
137
138 FakeCricketSctpTransport* CricketSctpTransport() {
139 return static_cast<FakeCricketSctpTransport*>(transport_->internal());
140 }
141
142 rtc::scoped_refptr<SctpTransport> transport_;
143 rtc::scoped_refptr<DtlsTransport> dtls_transport_;
144 TestSctpTransportObserver observer_;
145};
146
147TEST(SctpTransportSimpleTest, CreateClearDelete) {
148 std::unique_ptr<cricket::SctpTransportInternal> fake_cricket_sctp_transport =
149 absl::WrapUnique(new FakeCricketSctpTransport());
150 rtc::scoped_refptr<SctpTransport> sctp_transport =
Tommi87f70902021-04-27 14:43:08 +0200151 rtc::make_ref_counted<SctpTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100152 std::move(fake_cricket_sctp_transport));
153 ASSERT_TRUE(sctp_transport->internal());
154 ASSERT_EQ(SctpTransportState::kNew, sctp_transport->Information().state());
155 sctp_transport->Clear();
156 ASSERT_FALSE(sctp_transport->internal());
157 ASSERT_EQ(SctpTransportState::kClosed, sctp_transport->Information().state());
158}
159
160TEST_F(SctpTransportTest, EventsObservedWhenConnecting) {
161 CreateTransport();
162 transport()->RegisterObserver(observer());
163 AddDtlsTransport();
164 CompleteSctpHandshake();
165 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
166 kDefaultTimeout);
167 EXPECT_THAT(observer_.States(), ElementsAre(SctpTransportState::kConnecting,
168 SctpTransportState::kConnected));
169}
170
171TEST_F(SctpTransportTest, CloseWhenClearing) {
172 CreateTransport();
173 transport()->RegisterObserver(observer());
174 AddDtlsTransport();
175 CompleteSctpHandshake();
176 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
177 kDefaultTimeout);
178 transport()->Clear();
179 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
180 kDefaultTimeout);
181}
182
Harald Alvestrand97716c02019-05-21 10:52:59 +0200183TEST_F(SctpTransportTest, MaxChannelsSignalled) {
184 CreateTransport();
185 transport()->RegisterObserver(observer());
186 AddDtlsTransport();
187 EXPECT_FALSE(transport()->Information().MaxChannels());
188 EXPECT_FALSE(observer_.LastReceivedInformation().MaxChannels());
189 CompleteSctpHandshake();
190 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
191 kDefaultTimeout);
192 EXPECT_TRUE(transport()->Information().MaxChannels());
193 EXPECT_EQ(kTestMaxSctpStreams, *(transport()->Information().MaxChannels()));
194 EXPECT_TRUE(observer_.LastReceivedInformation().MaxChannels());
195 EXPECT_EQ(kTestMaxSctpStreams,
196 *(observer_.LastReceivedInformation().MaxChannels()));
197}
198
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100199TEST_F(SctpTransportTest, CloseWhenTransportCloses) {
200 CreateTransport();
201 transport()->RegisterObserver(observer());
202 AddDtlsTransport();
203 CompleteSctpHandshake();
204 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
205 kDefaultTimeout);
206 static_cast<cricket::FakeDtlsTransport*>(dtls_transport_->internal())
207 ->SetDtlsState(cricket::DTLS_TRANSPORT_CLOSED);
208 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
209 kDefaultTimeout);
210}
211
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100212} // namespace webrtc