blob: e3168d8b99598614bbab982cc4d234144f0e7c9f [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"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000027#include "rtc_base/ref_counted_object.h"
Harald Alvestrandc85328f2019-02-28 07:51:00 +010028#include "test/gmock.h"
29#include "test/gtest.h"
30
31constexpr int kDefaultTimeout = 1000; // milliseconds
Harald Alvestrand97716c02019-05-21 10:52:59 +020032constexpr int kTestMaxSctpStreams = 1234;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010033
34using cricket::FakeDtlsTransport;
35using ::testing::ElementsAre;
36
37namespace webrtc {
38
39namespace {
40
41class FakeCricketSctpTransport : public cricket::SctpTransportInternal {
42 public:
43 void SetDtlsTransport(rtc::PacketTransportInternal* transport) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020044 bool Start(int local_port, int remote_port, int max_message_size) override {
45 return true;
46 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010047 bool OpenStream(int sid) override { return true; }
48 bool ResetStream(int sid) override { return true; }
Florent Castellid95b1492021-05-10 11:29:56 +020049 bool SendData(int sid,
50 const SendDataParams& params,
Harald Alvestrandc85328f2019-02-28 07:51:00 +010051 const rtc::CopyOnWriteBuffer& payload,
52 cricket::SendDataResult* result = nullptr) override {
53 return true;
54 }
55 bool ReadyToSendData() override { return true; }
56 void set_debug_name_for_testing(const char* debug_name) override {}
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +020057 int max_message_size() const override { return 0; }
Harald Alvestrand97716c02019-05-21 10:52:59 +020058 absl::optional<int> max_outbound_streams() const override {
59 return max_outbound_streams_;
60 }
61 absl::optional<int> max_inbound_streams() const override {
62 return max_inbound_streams_;
63 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010064 // Methods exposed for testing
65 void SendSignalReadyToSendData() { SignalReadyToSendData(); }
66
Harald Alvestrand97716c02019-05-21 10:52:59 +020067 void SendSignalAssociationChangeCommunicationUp() {
68 SignalAssociationChangeCommunicationUp();
69 }
70
Harald Alvestrandc85328f2019-02-28 07:51:00 +010071 void SendSignalClosingProcedureStartedRemotely() {
72 SignalClosingProcedureStartedRemotely(1);
73 }
74
75 void SendSignalClosingProcedureComplete() {
76 SignalClosingProcedureComplete(1);
77 }
Harald Alvestrand97716c02019-05-21 10:52:59 +020078 void set_max_outbound_streams(int streams) {
79 max_outbound_streams_ = streams;
80 }
81 void set_max_inbound_streams(int streams) { max_inbound_streams_ = streams; }
82
83 private:
84 absl::optional<int> max_outbound_streams_;
85 absl::optional<int> max_inbound_streams_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010086};
87
88} // namespace
89
90class TestSctpTransportObserver : public SctpTransportObserverInterface {
91 public:
Harald Alvestrand97716c02019-05-21 10:52:59 +020092 TestSctpTransportObserver() : info_(SctpTransportState::kNew) {}
93
Harald Alvestrandc85328f2019-02-28 07:51:00 +010094 void OnStateChange(SctpTransportInformation info) override {
Harald Alvestrand97716c02019-05-21 10:52:59 +020095 info_ = info;
Harald Alvestrandc85328f2019-02-28 07:51:00 +010096 states_.push_back(info.state());
97 }
98
99 SctpTransportState State() {
100 if (states_.size() > 0) {
101 return states_[states_.size() - 1];
102 } else {
103 return SctpTransportState::kNew;
104 }
105 }
106
107 const std::vector<SctpTransportState>& States() { return states_; }
108
Harald Alvestrand97716c02019-05-21 10:52:59 +0200109 const SctpTransportInformation LastReceivedInformation() { return info_; }
110
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100111 private:
112 std::vector<SctpTransportState> states_;
Harald Alvestrand97716c02019-05-21 10:52:59 +0200113 SctpTransportInformation info_;
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100114};
115
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200116class SctpTransportTest : public ::testing::Test {
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100117 public:
118 SctpTransport* transport() { return transport_.get(); }
119 SctpTransportObserverInterface* observer() { return &observer_; }
120
121 void CreateTransport() {
122 auto cricket_sctp_transport =
123 absl::WrapUnique(new FakeCricketSctpTransport());
Tommi87f70902021-04-27 14:43:08 +0200124 transport_ =
125 rtc::make_ref_counted<SctpTransport>(std::move(cricket_sctp_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100126 }
127
128 void AddDtlsTransport() {
129 std::unique_ptr<cricket::DtlsTransportInternal> cricket_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200130 std::make_unique<FakeDtlsTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100131 "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
132 dtls_transport_ =
Tommi87f70902021-04-27 14:43:08 +0200133 rtc::make_ref_counted<DtlsTransport>(std::move(cricket_transport));
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100134 transport_->SetDtlsTransport(dtls_transport_);
135 }
136
137 void CompleteSctpHandshake() {
138 CricketSctpTransport()->SendSignalReadyToSendData();
Harald Alvestrand97716c02019-05-21 10:52:59 +0200139 // The computed MaxChannels shall be the minimum of the outgoing
140 // and incoming # of streams.
141 CricketSctpTransport()->set_max_outbound_streams(kTestMaxSctpStreams);
142 CricketSctpTransport()->set_max_inbound_streams(kTestMaxSctpStreams + 1);
143 CricketSctpTransport()->SendSignalAssociationChangeCommunicationUp();
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100144 }
145
146 FakeCricketSctpTransport* CricketSctpTransport() {
147 return static_cast<FakeCricketSctpTransport*>(transport_->internal());
148 }
149
150 rtc::scoped_refptr<SctpTransport> transport_;
151 rtc::scoped_refptr<DtlsTransport> dtls_transport_;
152 TestSctpTransportObserver observer_;
153};
154
155TEST(SctpTransportSimpleTest, CreateClearDelete) {
156 std::unique_ptr<cricket::SctpTransportInternal> fake_cricket_sctp_transport =
157 absl::WrapUnique(new FakeCricketSctpTransport());
158 rtc::scoped_refptr<SctpTransport> sctp_transport =
Tommi87f70902021-04-27 14:43:08 +0200159 rtc::make_ref_counted<SctpTransport>(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100160 std::move(fake_cricket_sctp_transport));
161 ASSERT_TRUE(sctp_transport->internal());
162 ASSERT_EQ(SctpTransportState::kNew, sctp_transport->Information().state());
163 sctp_transport->Clear();
164 ASSERT_FALSE(sctp_transport->internal());
165 ASSERT_EQ(SctpTransportState::kClosed, sctp_transport->Information().state());
166}
167
168TEST_F(SctpTransportTest, EventsObservedWhenConnecting) {
169 CreateTransport();
170 transport()->RegisterObserver(observer());
171 AddDtlsTransport();
172 CompleteSctpHandshake();
173 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
174 kDefaultTimeout);
175 EXPECT_THAT(observer_.States(), ElementsAre(SctpTransportState::kConnecting,
176 SctpTransportState::kConnected));
177}
178
179TEST_F(SctpTransportTest, CloseWhenClearing) {
180 CreateTransport();
181 transport()->RegisterObserver(observer());
182 AddDtlsTransport();
183 CompleteSctpHandshake();
184 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
185 kDefaultTimeout);
186 transport()->Clear();
187 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
188 kDefaultTimeout);
189}
190
Harald Alvestrand97716c02019-05-21 10:52:59 +0200191TEST_F(SctpTransportTest, MaxChannelsSignalled) {
192 CreateTransport();
193 transport()->RegisterObserver(observer());
194 AddDtlsTransport();
195 EXPECT_FALSE(transport()->Information().MaxChannels());
196 EXPECT_FALSE(observer_.LastReceivedInformation().MaxChannels());
197 CompleteSctpHandshake();
198 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
199 kDefaultTimeout);
200 EXPECT_TRUE(transport()->Information().MaxChannels());
201 EXPECT_EQ(kTestMaxSctpStreams, *(transport()->Information().MaxChannels()));
202 EXPECT_TRUE(observer_.LastReceivedInformation().MaxChannels());
203 EXPECT_EQ(kTestMaxSctpStreams,
204 *(observer_.LastReceivedInformation().MaxChannels()));
205}
206
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100207TEST_F(SctpTransportTest, CloseWhenTransportCloses) {
208 CreateTransport();
209 transport()->RegisterObserver(observer());
210 AddDtlsTransport();
211 CompleteSctpHandshake();
212 ASSERT_EQ_WAIT(SctpTransportState::kConnected, observer_.State(),
213 kDefaultTimeout);
214 static_cast<cricket::FakeDtlsTransport*>(dtls_transport_->internal())
Mirko Bonadei9f6808b2021-05-21 20:46:09 +0200215 ->SetDtlsState(DtlsTransportState::kClosed);
Harald Alvestrand408cb4b2019-11-16 12:09:08 +0100216 ASSERT_EQ_WAIT(SctpTransportState::kClosed, observer_.State(),
217 kDefaultTimeout);
218}
219
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100220} // namespace webrtc