blob: 47ed97d291bc97b5b65992a5a5070494d9808012 [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"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000017#include "absl/types/optional.h"
Mirko Bonadei9f6808b2021-05-21 20:46:09 +020018#include "api/dtls_transport_interface.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000019#include "api/transport/data_channel_transport_interface.h"
20#include "media/base/media_channel.h"
Harald Alvestrandc85328f2019-02-28 07:51:00 +010021#include "p2p/base/fake_dtls_transport.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000022#include "p2p/base/p2p_constants.h"
23#include "p2p/base/packet_transport_internal.h"
Harald Alvestrandc85328f2019-02-28 07:51:00 +010024#include "pc/dtls_transport.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000025#include "rtc_base/copy_on_write_buffer.h"
Harald Alvestrandc85328f2019-02-28 07:51:00 +010026#include "rtc_base/gunit.h"
27#include "test/gmock.h"
28#include "test/gtest.h"
29
30constexpr int kDefaultTimeout = 1000; // milliseconds
Harald Alvestrand97716c02019-05-21 10:52:59 +020031constexpr int kTestMaxSctpStreams = 1234;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010032
33using cricket::FakeDtlsTransport;
34using ::testing::ElementsAre;
35
36namespace webrtc {
37
38namespace {
39
40class FakeCricketSctpTransport : public cricket::SctpTransportInternal {
41 public:
Fredrik Solenberg5cb3a902022-08-22 11:34:29 +020042 void SetOnConnectedCallback(std::function<void()> callback) override {
43 on_connected_callback_ = std::move(callback);
44 }
45 void SetDataChannelSink(DataChannelSink* sink) override {}
Harald Alvestrandc85328f2019-02-28 07:51:00 +010046 void SetDtlsTransport(rtc::PacketTransportInternal* transport) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020047 bool Start(int local_port, int remote_port, int max_message_size) override {
48 return true;
49 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010050 bool OpenStream(int sid) override { return true; }
51 bool ResetStream(int sid) override { return true; }
Florent Castellid95b1492021-05-10 11:29:56 +020052 bool SendData(int sid,
53 const SendDataParams& params,
Harald Alvestrandc85328f2019-02-28 07:51:00 +010054 const rtc::CopyOnWriteBuffer& payload,
55 cricket::SendDataResult* result = nullptr) override {
56 return true;
57 }
58 bool ReadyToSendData() override { return true; }
59 void set_debug_name_for_testing(const char* debug_name) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020060 int max_message_size() const override { return 0; }
Harald Alvestrand97716c02019-05-21 10:52:59 +020061 absl::optional<int> max_outbound_streams() const override {
62 return max_outbound_streams_;
63 }
64 absl::optional<int> max_inbound_streams() const override {
65 return max_inbound_streams_;
66 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010067
Harald Alvestrand97716c02019-05-21 10:52:59 +020068 void SendSignalAssociationChangeCommunicationUp() {
Fredrik Solenberg5cb3a902022-08-22 11:34:29 +020069 ASSERT_TRUE(on_connected_callback_);
70 on_connected_callback_();
Harald Alvestrand97716c02019-05-21 10:52:59 +020071 }
72
Harald Alvestrand97716c02019-05-21 10:52:59 +020073 void set_max_outbound_streams(int streams) {
74 max_outbound_streams_ = streams;
75 }
76 void set_max_inbound_streams(int streams) { max_inbound_streams_ = streams; }
77
78 private:
79 absl::optional<int> max_outbound_streams_;
80 absl::optional<int> max_inbound_streams_;
Fredrik Solenberg5cb3a902022-08-22 11:34:29 +020081 std::function<void()> on_connected_callback_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010082};
83
84} // namespace
85
86class TestSctpTransportObserver : public SctpTransportObserverInterface {
87 public:
Harald Alvestrand97716c02019-05-21 10:52:59 +020088 TestSctpTransportObserver() : info_(SctpTransportState::kNew) {}
89
Harald Alvestrandc85328f2019-02-28 07:51:00 +010090 void OnStateChange(SctpTransportInformation info) override {
Harald Alvestrand97716c02019-05-21 10:52:59 +020091 info_ = info;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010092 states_.push_back(info.state());
93 }
94
95 SctpTransportState State() {
96 if (states_.size() > 0) {
97 return states_[states_.size() - 1];
98 } else {
99 return SctpTransportState::kNew;
100 }
101 }
102
103 const std::vector<SctpTransportState>& States() { return states_; }
104
Harald Alvestrand97716c02019-05-21 10:52:59 +0200105 const SctpTransportInformation LastReceivedInformation() { return info_; }
106
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100107 private:
108 std::vector<SctpTransportState> states_;
Harald Alvestrand97716c02019-05-21 10:52:59 +0200109 SctpTransportInformation info_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100110};
111
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200112class SctpTransportTest : public ::testing::Test {
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100113 public:
114 SctpTransport* transport() { return transport_.get(); }
115 SctpTransportObserverInterface* observer() { return &observer_; }
116
117 void CreateTransport() {
118 auto cricket_sctp_transport =
119 absl::WrapUnique(new FakeCricketSctpTransport());
Tommi87f70902021-04-27 14:43:08 +0200120 transport_ =
121 rtc::make_ref_counted<SctpTransport>(std::move(cricket_sctp_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100122 }
123
124 void AddDtlsTransport() {
125 std::unique_ptr<cricket::DtlsTransportInternal> cricket_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200126 std::make_unique<FakeDtlsTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100127 "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
128 dtls_transport_ =
Tommi87f70902021-04-27 14:43:08 +0200129 rtc::make_ref_counted<DtlsTransport>(std::move(cricket_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100130 transport_->SetDtlsTransport(dtls_transport_);
131 }
132
133 void CompleteSctpHandshake() {
Harald Alvestrand97716c02019-05-21 10:52:59 +0200134 // The computed MaxChannels shall be the minimum of the outgoing
135 // and incoming # of streams.
136 CricketSctpTransport()->set_max_outbound_streams(kTestMaxSctpStreams);
137 CricketSctpTransport()->set_max_inbound_streams(kTestMaxSctpStreams + 1);
138 CricketSctpTransport()->SendSignalAssociationChangeCommunicationUp();
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100139 }
140
141 FakeCricketSctpTransport* CricketSctpTransport() {
142 return static_cast<FakeCricketSctpTransport*>(transport_->internal());
143 }
144
Niels Möller83830f32022-05-20 09:12:57 +0200145 rtc::AutoThread main_thread_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100146 rtc::scoped_refptr<SctpTransport> transport_;
147 rtc::scoped_refptr<DtlsTransport> dtls_transport_;
148 TestSctpTransportObserver observer_;
149};
150
151TEST(SctpTransportSimpleTest, CreateClearDelete) {
Niels Möller83830f32022-05-20 09:12:57 +0200152 rtc::AutoThread main_thread;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100153 std::unique_ptr<cricket::SctpTransportInternal> fake_cricket_sctp_transport =
154 absl::WrapUnique(new FakeCricketSctpTransport());
155 rtc::scoped_refptr<SctpTransport> sctp_transport =
Tommi87f70902021-04-27 14:43:08 +0200156 rtc::make_ref_counted<SctpTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100157 std::move(fake_cricket_sctp_transport));
158 ASSERT_TRUE(sctp_transport->internal());
159 ASSERT_EQ(SctpTransportState::kNew, sctp_transport->Information().state());
160 sctp_transport->Clear();
161 ASSERT_FALSE(sctp_transport->internal());
162 ASSERT_EQ(SctpTransportState::kClosed, sctp_transport->Information().state());
163}
164
165TEST_F(SctpTransportTest, EventsObservedWhenConnecting) {
166 CreateTransport();
167 transport()->RegisterObserver(observer());
168 AddDtlsTransport();
169 CompleteSctpHandshake();
170 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
171 kDefaultTimeout);
172 EXPECT_THAT(observer_.States(), ElementsAre(SctpTransportState::kConnecting,
173 SctpTransportState::kConnected));
174}
175
176TEST_F(SctpTransportTest, CloseWhenClearing) {
177 CreateTransport();
178 transport()->RegisterObserver(observer());
179 AddDtlsTransport();
180 CompleteSctpHandshake();
181 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
182 kDefaultTimeout);
183 transport()->Clear();
184 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
185 kDefaultTimeout);
186}
187
Harald Alvestrand97716c02019-05-21 10:52:59 +0200188TEST_F(SctpTransportTest, MaxChannelsSignalled) {
189 CreateTransport();
190 transport()->RegisterObserver(observer());
191 AddDtlsTransport();
192 EXPECT_FALSE(transport()->Information().MaxChannels());
193 EXPECT_FALSE(observer_.LastReceivedInformation().MaxChannels());
194 CompleteSctpHandshake();
195 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
196 kDefaultTimeout);
197 EXPECT_TRUE(transport()->Information().MaxChannels());
198 EXPECT_EQ(kTestMaxSctpStreams, *(transport()->Information().MaxChannels()));
199 EXPECT_TRUE(observer_.LastReceivedInformation().MaxChannels());
200 EXPECT_EQ(kTestMaxSctpStreams,
201 *(observer_.LastReceivedInformation().MaxChannels()));
202}
203
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100204TEST_F(SctpTransportTest, CloseWhenTransportCloses) {
205 CreateTransport();
206 transport()->RegisterObserver(observer());
207 AddDtlsTransport();
208 CompleteSctpHandshake();
209 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
210 kDefaultTimeout);
211 static_cast<cricket::FakeDtlsTransport*>(dtls_transport_->internal())
Mirko Bonadei9f6808b2021-05-21 20:46:09 +0200212 ->SetDtlsState(DtlsTransportState::kClosed);
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100213 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
214 kDefaultTimeout);
215}
216
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100217} // namespace webrtc