blob: 4c776ed2b377db7cdc6c58218e529d2cf8177307 [file] [log] [blame]
deadbeef953c2ce2017-01-09 14:53:41 -08001/*
2 * Copyright (c) 2013 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "media/sctp/sctp_transport.h"
12
deadbeef953c2ce2017-01-09 14:53:41 -080013#include <stdio.h>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
deadbeef953c2ce2017-01-09 14:53:41 -080016#include <memory>
17#include <string>
18#include <vector>
19
Steve Anton2c9ebef2019-01-28 17:27:58 -080020#include "absl/algorithm/container.h"
Seth Hampson66d6c3b2019-08-30 09:02:46 -070021#include "media/sctp/sctp_transport_internal.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "p2p/base/fake_dtls_transport.h"
23#include "rtc_base/copy_on_write_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/gunit.h"
Yves Gerey3e707812018-11-28 16:47:49 +010025#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/message_queue.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "rtc_base/thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010028#include "test/gtest.h"
deadbeef953c2ce2017-01-09 14:53:41 -080029
30namespace {
31static const int kDefaultTimeout = 10000; // 10 seconds.
32// Use ports other than the default 5000 for testing.
33static const int kTransport1Port = 5001;
34static const int kTransport2Port = 5002;
Yves Gerey665174f2018-06-19 15:03:05 +020035} // namespace
deadbeef953c2ce2017-01-09 14:53:41 -080036
37namespace cricket {
38
39// This is essentially a buffer to hold recieved data. It stores only the last
40// received data. Calling OnDataReceived twice overwrites old data with the
41// newer one.
42// TODO(ldixon): Implement constraints, and allow new data to be added to old
43// instead of replacing it.
44class SctpFakeDataReceiver : public sigslot::has_slots<> {
45 public:
46 SctpFakeDataReceiver() : received_(false) {}
47
48 void Clear() {
49 received_ = false;
50 last_data_ = "";
51 last_params_ = ReceiveDataParams();
Seth Hampson66d6c3b2019-08-30 09:02:46 -070052 num_messages_received_ = 0;
deadbeef953c2ce2017-01-09 14:53:41 -080053 }
54
deadbeef8d517c42017-02-19 14:12:24 -080055 void OnDataReceived(const ReceiveDataParams& params,
56 const rtc::CopyOnWriteBuffer& data) {
Seth Hampson66d6c3b2019-08-30 09:02:46 -070057 num_messages_received_++;
deadbeef953c2ce2017-01-09 14:53:41 -080058 received_ = true;
59 last_data_ = std::string(data.data<char>(), data.size());
60 last_params_ = params;
61 }
62
63 bool received() const { return received_; }
64 std::string last_data() const { return last_data_; }
65 ReceiveDataParams last_params() const { return last_params_; }
Seth Hampson66d6c3b2019-08-30 09:02:46 -070066 size_t num_messages_received() const { return num_messages_received_; }
deadbeef953c2ce2017-01-09 14:53:41 -080067
68 private:
69 bool received_;
70 std::string last_data_;
Seth Hampson66d6c3b2019-08-30 09:02:46 -070071 size_t num_messages_received_ = 0;
deadbeef953c2ce2017-01-09 14:53:41 -080072 ReceiveDataParams last_params_;
73};
74
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070075class SctpTransportObserver : public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -080076 public:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070077 explicit SctpTransportObserver(SctpTransport* transport) {
78 transport->SignalClosingProcedureComplete.connect(
79 this, &SctpTransportObserver::OnClosingProcedureComplete);
80 transport->SignalReadyToSendData.connect(
81 this, &SctpTransportObserver::OnReadyToSend);
deadbeef953c2ce2017-01-09 14:53:41 -080082 }
deadbeef953c2ce2017-01-09 14:53:41 -080083
84 int StreamCloseCount(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080085 return absl::c_count(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080086 }
87
88 bool WasStreamClosed(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080089 return absl::c_linear_search(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080090 }
91
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070092 bool ReadyToSend() { return ready_to_send_; }
93
deadbeef953c2ce2017-01-09 14:53:41 -080094 private:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070095 void OnClosingProcedureComplete(int stream) {
96 closed_streams_.push_back(stream);
97 }
98 void OnReadyToSend() { ready_to_send_ = true; }
99
100 std::vector<int> closed_streams_;
101 bool ready_to_send_ = false;
deadbeef953c2ce2017-01-09 14:53:41 -0800102};
103
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700104// Helper class used to immediately attempt to reopen a stream as soon as it's
105// been closed.
deadbeef953c2ce2017-01-09 14:53:41 -0800106class SignalTransportClosedReopener : public sigslot::has_slots<> {
107 public:
108 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
109 : transport_(transport), peer_(peer) {}
110
Steve Anton2c9ebef2019-01-28 17:27:58 -0800111 int StreamCloseCount(int stream) { return absl::c_count(streams_, stream); }
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700112
113 private:
deadbeef953c2ce2017-01-09 14:53:41 -0800114 void OnStreamClosed(int stream) {
115 transport_->OpenStream(stream);
116 peer_->OpenStream(stream);
117 streams_.push_back(stream);
118 }
119
deadbeef953c2ce2017-01-09 14:53:41 -0800120 SctpTransport* transport_;
121 SctpTransport* peer_;
122 std::vector<int> streams_;
123};
124
125// SCTP Data Engine testing framework.
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200126class SctpTransportTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -0800127 protected:
128 // usrsctp uses the NSS random number generator on non-Android platforms,
129 // so we need to initialize SSL.
Mirko Bonadei71061bc2019-06-04 09:01:51 +0200130 static void SetUpTestSuite() {}
deadbeef953c2ce2017-01-09 14:53:41 -0800131
132 void SetupConnectedTransportsWithTwoStreams() {
jbauch46d24572017-03-10 16:20:04 -0800133 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
134 }
135
136 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
zhihuangb2cdd932017-01-19 16:54:25 -0800137 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
138 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
deadbeef953c2ce2017-01-09 14:53:41 -0800139 recv1_.reset(new SctpFakeDataReceiver());
140 recv2_.reset(new SctpFakeDataReceiver());
141 transport1_.reset(CreateTransport(fake_dtls1_.get(), recv1_.get()));
142 transport1_->set_debug_name_for_testing("transport1");
143 transport1_->SignalReadyToSendData.connect(
144 this, &SctpTransportTest::OnChan1ReadyToSend);
145 transport2_.reset(CreateTransport(fake_dtls2_.get(), recv2_.get()));
146 transport2_->set_debug_name_for_testing("transport2");
147 transport2_->SignalReadyToSendData.connect(
148 this, &SctpTransportTest::OnChan2ReadyToSend);
149 // Setup two connected transports ready to send and receive.
150 bool asymmetric = false;
151 fake_dtls1_->SetDestination(fake_dtls2_.get(), asymmetric);
152
Mirko Bonadei675513b2017-11-09 11:09:25 +0100153 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
deadbeef953c2ce2017-01-09 14:53:41 -0800154 AddStream(1);
155 AddStream(2);
156
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_VERBOSE)
158 << "Connect the transports -----------------------------";
deadbeef953c2ce2017-01-09 14:53:41 -0800159 // Both transports need to have started (with matching ports) for an
160 // association to be formed.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200161 transport1_->Start(port1, port2, kSctpSendBufferSize);
162 transport2_->Start(port2, port1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800163 }
164
165 bool AddStream(int sid) {
166 bool ret = true;
167 ret = ret && transport1_->OpenStream(sid);
168 ret = ret && transport2_->OpenStream(sid);
169 return ret;
170 }
171
zhihuangb2cdd932017-01-19 16:54:25 -0800172 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
deadbeef953c2ce2017-01-09 14:53:41 -0800173 SctpFakeDataReceiver* recv) {
174 SctpTransport* transport =
175 new SctpTransport(rtc::Thread::Current(), fake_dtls);
176 // When data is received, pass it to the SctpFakeDataReceiver.
177 transport->SignalDataReceived.connect(
178 recv, &SctpFakeDataReceiver::OnDataReceived);
179 return transport;
180 }
181
182 bool SendData(SctpTransport* chan,
183 int sid,
184 const std::string& msg,
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700185 SendDataResult* result,
186 bool ordered = false) {
deadbeef953c2ce2017-01-09 14:53:41 -0800187 SendDataParams params;
188 params.sid = sid;
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700189 params.ordered = ordered;
deadbeef953c2ce2017-01-09 14:53:41 -0800190
191 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
192 result);
193 }
194
195 bool ReceivedData(const SctpFakeDataReceiver* recv,
196 int sid,
197 const std::string& msg) {
198 return (recv->received() && recv->last_params().sid == sid &&
199 recv->last_data() == msg);
200 }
201
202 bool ProcessMessagesUntilIdle() {
203 rtc::Thread* thread = rtc::Thread::Current();
204 while (!thread->empty()) {
205 rtc::Message msg;
206 if (thread->Get(&msg, rtc::Thread::kForever)) {
207 thread->Dispatch(&msg);
208 }
209 }
210 return !thread->IsQuitting();
211 }
212
213 SctpTransport* transport1() { return transport1_.get(); }
214 SctpTransport* transport2() { return transport2_.get(); }
215 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
216 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
zhihuangb2cdd932017-01-19 16:54:25 -0800217 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
218 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
deadbeef953c2ce2017-01-09 14:53:41 -0800219
220 int transport1_ready_to_send_count() {
221 return transport1_ready_to_send_count_;
222 }
223 int transport2_ready_to_send_count() {
224 return transport2_ready_to_send_count_;
225 }
226
227 private:
zhihuangb2cdd932017-01-19 16:54:25 -0800228 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
229 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
deadbeef953c2ce2017-01-09 14:53:41 -0800230 std::unique_ptr<SctpFakeDataReceiver> recv1_;
231 std::unique_ptr<SctpFakeDataReceiver> recv2_;
232 std::unique_ptr<SctpTransport> transport1_;
233 std::unique_ptr<SctpTransport> transport2_;
234
235 int transport1_ready_to_send_count_ = 0;
236 int transport2_ready_to_send_count_ = 0;
237
238 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
239 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
240};
241
242// Test that data can be sent end-to-end when an SCTP transport starts with one
Zhi Huang644fde42018-04-02 19:16:26 -0700243// transport (which is unwritable), and then switches to another transport. A
244// common scenario due to how BUNDLE works.
245TEST_F(SctpTransportTest, SwitchDtlsTransport) {
zhihuangb2cdd932017-01-19 16:54:25 -0800246 FakeDtlsTransport black_hole("black hole", 0);
247 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
248 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800249 SctpFakeDataReceiver recv1;
250 SctpFakeDataReceiver recv2;
251
Zhi Huang644fde42018-04-02 19:16:26 -0700252 // Construct transport1 with the "black hole" transport.
deadbeef953c2ce2017-01-09 14:53:41 -0800253 std::unique_ptr<SctpTransport> transport1(
254 CreateTransport(&black_hole, &recv1));
255 std::unique_ptr<SctpTransport> transport2(
256 CreateTransport(&fake_dtls2, &recv2));
257
258 // Add a stream.
259 transport1->OpenStream(1);
260 transport2->OpenStream(1);
261
262 // Tell them both to start (though transport1_ is connected to black_hole).
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200263 transport1->Start(kTransport1Port, kTransport2Port, kSctpSendBufferSize);
264 transport2->Start(kTransport2Port, kTransport1Port, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800265
Zhi Huang644fde42018-04-02 19:16:26 -0700266 // Switch transport1_ to the normal fake_dtls1_ transport.
267 transport1->SetDtlsTransport(&fake_dtls1);
deadbeef953c2ce2017-01-09 14:53:41 -0800268
Zhi Huang644fde42018-04-02 19:16:26 -0700269 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800270 bool asymmetric = false;
271 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
272
273 // Make sure we end up able to send data.
274 SendDataResult result;
275 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
276 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
277 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
278 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
Zhi Huang644fde42018-04-02 19:16:26 -0700279
280 // Setting a null DtlsTransport should work. This could happen when an SCTP
281 // data section is rejected.
282 transport1->SetDtlsTransport(nullptr);
deadbeef953c2ce2017-01-09 14:53:41 -0800283}
284
285// Calling Start twice shouldn't do anything bad, if with the same parameters.
286TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
287 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200288 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port,
289 kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800290
291 // Make sure we can still send/recv data.
292 SendDataResult result;
293 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
294 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
295 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
296 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
297}
298
299// Calling Start a second time with a different port should fail.
300TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
301 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200302 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234, kSctpSendBufferSize));
303 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port, kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800304}
305
306// A value of -1 for the local/remote port should be treated as the default
307// (5000).
308TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
zhihuangb2cdd932017-01-19 16:54:25 -0800309 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
310 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800311 SctpFakeDataReceiver recv1;
312 SctpFakeDataReceiver recv2;
313 std::unique_ptr<SctpTransport> transport1(
314 CreateTransport(&fake_dtls1, &recv1));
315 std::unique_ptr<SctpTransport> transport2(
316 CreateTransport(&fake_dtls2, &recv2));
317
318 // Add a stream.
319 transport1->OpenStream(1);
320 transport2->OpenStream(1);
321
322 // Tell them both to start, giving one transport the default port and the
323 // other transport -1.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200324 transport1->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
325 transport2->Start(-1, -1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800326
Zhi Huang644fde42018-04-02 19:16:26 -0700327 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800328 bool asymmetric = false;
329 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
330
331 // Make sure we end up able to send data.
332 SendDataResult result;
333 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
334 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
335 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
336 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
337}
338
339TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800340 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800341 SctpFakeDataReceiver recv;
342 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
343 EXPECT_TRUE(transport->OpenStream(1));
344 EXPECT_FALSE(transport->OpenStream(1));
345}
346
347TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800348 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800349 SctpFakeDataReceiver recv;
350 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
351 EXPECT_TRUE(transport->OpenStream(1));
352 EXPECT_TRUE(transport->ResetStream(1));
353 EXPECT_FALSE(transport->ResetStream(1));
354}
355
356// Test that SignalReadyToSendData is fired after Start has been called and the
Zhi Huang644fde42018-04-02 19:16:26 -0700357// DTLS transport is writable.
deadbeef953c2ce2017-01-09 14:53:41 -0800358TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
zhihuangb2cdd932017-01-19 16:54:25 -0800359 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800360 SctpFakeDataReceiver recv;
361 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700362 SctpTransportObserver observer(transport.get());
deadbeef953c2ce2017-01-09 14:53:41 -0800363
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200364 transport->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800365 fake_dtls.SetWritable(true);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700366 EXPECT_TRUE_WAIT(observer.ReadyToSend(), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800367}
368
369// Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
370// is fired after it begins to be drained.
371TEST_F(SctpTransportTest, SignalReadyToSendDataAfterBlocked) {
372 SetupConnectedTransportsWithTwoStreams();
373 // Wait for initial SCTP association to be formed.
374 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
375 // Make the fake transport unwritable so that messages pile up for the SCTP
376 // socket.
377 fake_dtls1()->SetWritable(false);
378 // Send messages until we get EWOULDBLOCK.
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700379 static const size_t kMaxMessages = 1024;
deadbeef953c2ce2017-01-09 14:53:41 -0800380 SendDataParams params;
381 params.sid = 1;
382 rtc::CopyOnWriteBuffer buf(1024);
383 memset(buf.data<uint8_t>(), 0, 1024);
384 SendDataResult result;
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700385 size_t message_count = 0;
386 for (; message_count < kMaxMessages; ++message_count) {
deadbeef953c2ce2017-01-09 14:53:41 -0800387 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
388 break;
389 }
390 }
391 ASSERT_NE(kMaxMessages, message_count)
392 << "Sent max number of messages without getting SDR_BLOCK?";
393 // Make sure the ready-to-send count hasn't changed.
394 EXPECT_EQ(1, transport1_ready_to_send_count());
395 // Make the transport writable again and expect a "SignalReadyToSendData" at
396 // some point.
397 fake_dtls1()->SetWritable(true);
398 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700399 EXPECT_EQ_WAIT(message_count, receiver2()->num_messages_received(),
400 kDefaultTimeout);
401}
402
403// Tests that a small message gets buffered and later sent by the SctpTransport
404// when the sctp library only accepts the message partially.
405TEST_F(SctpTransportTest, SendSmallBufferedOutgoingMessage) {
406 SetupConnectedTransportsWithTwoStreams();
407 // Wait for initial SCTP association to be formed.
408 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
409 // Make the fake transport unwritable so that messages pile up for the SCTP
410 // socket.
411 fake_dtls1()->SetWritable(false);
412 SendDataResult result;
413 // TODO(bugs.webrtc.org/10939): We can't test this behavior unless we are
414 // sending in ordered mode becuase the sctp lib drops large buffered data in
415 // unordered mode.
416 bool ordered = true;
417
418 // Fill almost all of sctp library's send buffer.
419 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
420 std::string(kSctpSendBufferSize - 1, 'a'), &result,
421 ordered));
422
423 std::string buffered_message("hello hello");
424 // SctpTransport accepts this message by buffering part of it.
425 ASSERT_TRUE(
426 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
427 ASSERT_TRUE(transport1()->ReadyToSendData());
428
429 // Sending anything else should block now.
430 ASSERT_FALSE(
431 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
432 ASSERT_EQ(SDR_BLOCK, result);
433 ASSERT_FALSE(transport1()->ReadyToSendData());
434
435 // Make sure the ready-to-send count hasn't changed.
436 EXPECT_EQ(1, transport1_ready_to_send_count());
437 // Make the transport writable again and expect a "SignalReadyToSendData" at
438 // some point after sending the buffered message.
439 fake_dtls1()->SetWritable(true);
440 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
441 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
442 kDefaultTimeout);
443 EXPECT_EQ(2u, receiver2()->num_messages_received());
444}
445
446// Tests that a large message gets buffered and later sent by the SctpTransport
447// when the sctp library only accepts the message partially.
448TEST_F(SctpTransportTest, SendLargeBufferedOutgoingMessage) {
449 SetupConnectedTransportsWithTwoStreams();
450 // Wait for initial SCTP association to be formed.
451 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
452 // Make the fake transport unwritable so that messages pile up for the SCTP
453 // socket.
454 fake_dtls1()->SetWritable(false);
455 SendDataResult result;
456 // TODO(bugs.webrtc.org/10939): We can't test this behavior unless we are
457 // sending in ordered mode becuase the sctp lib drops large buffered data in
458 // unordered mode.
459 bool ordered = true;
460
461 // Fill almost all of sctp library's send buffer.
462 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
463 std::string(kSctpSendBufferSize / 2, 'a'), &result,
464 ordered));
465
466 std::string buffered_message(kSctpSendBufferSize, 'b');
467 // SctpTransport accepts this message by buffering the second half.
468 ASSERT_TRUE(
469 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
470 ASSERT_TRUE(transport1()->ReadyToSendData());
471
472 // Sending anything else should block now.
473 ASSERT_FALSE(
474 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
475 ASSERT_EQ(SDR_BLOCK, result);
476 ASSERT_FALSE(transport1()->ReadyToSendData());
477
478 // Make sure the ready-to-send count hasn't changed.
479 EXPECT_EQ(1, transport1_ready_to_send_count());
480 // Make the transport writable again and expect a "SignalReadyToSendData" at
481 // some point.
482 fake_dtls1()->SetWritable(true);
483 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
484 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
485 kDefaultTimeout);
486 EXPECT_EQ(2u, receiver2()->num_messages_received());
deadbeef953c2ce2017-01-09 14:53:41 -0800487}
488
489TEST_F(SctpTransportTest, SendData) {
490 SetupConnectedTransportsWithTwoStreams();
491
492 SendDataResult result;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100493 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800494 << "transport1 sending: 'hello?' -----------------------------";
495 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
496 EXPECT_EQ(SDR_SUCCESS, result);
497 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100498 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
499 << ", recv2.last_params.sid="
500 << receiver2()->last_params().sid
501 << ", recv2.last_params.timestamp="
502 << receiver2()->last_params().timestamp
503 << ", recv2.last_params.seq_num="
504 << receiver2()->last_params().seq_num
505 << ", recv2.last_data=" << receiver2()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800506
Mirko Bonadei675513b2017-11-09 11:09:25 +0100507 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800508 << "transport2 sending: 'hi transport1' -----------------------------";
509 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
510 EXPECT_EQ(SDR_SUCCESS, result);
511 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
512 kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100513 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
514 << ", recv1.last_params.sid="
515 << receiver1()->last_params().sid
516 << ", recv1.last_params.timestamp="
517 << receiver1()->last_params().timestamp
518 << ", recv1.last_params.seq_num="
519 << receiver1()->last_params().seq_num
520 << ", recv1.last_data=" << receiver1()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800521}
522
523// Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
524TEST_F(SctpTransportTest, SendDataBlocked) {
525 SetupConnectedTransportsWithTwoStreams();
526
527 SendDataResult result;
528 SendDataParams params;
529 params.sid = 1;
530
531 std::vector<char> buffer(1024 * 64, 0);
532
533 for (size_t i = 0; i < 100; ++i) {
534 transport1()->SendData(
535 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
536 if (result == SDR_BLOCK)
537 break;
538 }
539
540 EXPECT_EQ(SDR_BLOCK, result);
541}
542
543// Trying to send data for a nonexistent stream should fail.
544TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
545 SetupConnectedTransportsWithTwoStreams();
546 SendDataResult result;
547 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
548 EXPECT_EQ(SDR_ERROR, result);
549}
550
jbauch46d24572017-03-10 16:20:04 -0800551TEST_F(SctpTransportTest, SendDataHighPorts) {
552 SetupConnectedTransportsWithTwoStreams(32768, 32769);
553
554 SendDataResult result;
555 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
556 EXPECT_EQ(SDR_SUCCESS, result);
557 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
558
559 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
560 EXPECT_EQ(SDR_SUCCESS, result);
561 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
562 kDefaultTimeout);
563}
564
deadbeef953c2ce2017-01-09 14:53:41 -0800565TEST_F(SctpTransportTest, ClosesRemoteStream) {
566 SetupConnectedTransportsWithTwoStreams();
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700567 SctpTransportObserver transport1_observer(transport1());
568 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800569
570 SendDataResult result;
571 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
572 EXPECT_EQ(SDR_SUCCESS, result);
573 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
574 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
575 EXPECT_EQ(SDR_SUCCESS, result);
576 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
577 kDefaultTimeout);
578
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700579 // Close stream 1 on transport 1. Transport 2 should notify us.
deadbeef953c2ce2017-01-09 14:53:41 -0800580 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700581 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800582}
583
584TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
585 SetupConnectedTransportsWithTwoStreams();
586 AddStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700587 SctpTransportObserver transport1_observer(transport1());
588 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800589
590 SendDataResult result;
591 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
592 EXPECT_EQ(SDR_SUCCESS, result);
593 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
594 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
595 EXPECT_EQ(SDR_SUCCESS, result);
596 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
597 kDefaultTimeout);
598
599 // Close two streams on one side.
600 transport2()->ResetStream(2);
601 transport2()->ResetStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700602 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(2), kDefaultTimeout);
603 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(3), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800604}
605
606TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
607 SetupConnectedTransportsWithTwoStreams();
608 AddStream(3);
609 AddStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700610 SctpTransportObserver transport1_observer(transport1());
611 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800612
613 SendDataResult result;
614 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
615 EXPECT_EQ(SDR_SUCCESS, result);
616 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
617 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
618 EXPECT_EQ(SDR_SUCCESS, result);
619 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
620 kDefaultTimeout);
621
622 // Close one stream on transport1(), while closing three streams on
623 // transport2(). They will conflict (only one side can close anything at a
624 // time, apparently). Test the resolution of the conflict.
625 transport1()->ResetStream(1);
626
627 transport2()->ResetStream(2);
628 transport2()->ResetStream(3);
629 transport2()->ResetStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700630 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
631 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(2), kDefaultTimeout);
632 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(3), kDefaultTimeout);
633 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(4), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800634}
635
636TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
637 SetupConnectedTransportsWithTwoStreams();
638 EXPECT_TRUE(AddStream(kMaxSctpSid));
639 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
640}
641
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700642TEST_F(SctpTransportTest, ReusesAStream) {
deadbeef953c2ce2017-01-09 14:53:41 -0800643 // Shut down transport 1, then open it up again for reuse.
644 SetupConnectedTransportsWithTwoStreams();
645 SendDataResult result;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700646 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800647
648 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
649 EXPECT_EQ(SDR_SUCCESS, result);
650 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
651
652 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700653 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800654 // Transport 1 is gone now.
655
656 // Create a new transport 1.
657 AddStream(1);
658 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
659 EXPECT_EQ(SDR_SUCCESS, result);
660 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
661 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700662 EXPECT_EQ_WAIT(2, transport2_observer.StreamCloseCount(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800663}
664
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200665TEST_F(SctpTransportTest, RejectsTooLargeMessageSize) {
666 FakeDtlsTransport fake_dtls("fake dtls", 0);
667 SctpFakeDataReceiver recv;
668 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
669
670 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort,
671 kSctpSendBufferSize + 1));
672}
673
674TEST_F(SctpTransportTest, RejectsTooSmallMessageSize) {
675 FakeDtlsTransport fake_dtls("fake dtls", 0);
676 SctpFakeDataReceiver recv;
677 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
678
679 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort, 0));
680}
681
682TEST_F(SctpTransportTest, RejectsSendTooLargeMessages) {
683 SetupConnectedTransportsWithTwoStreams();
684 // Use "Start" to reduce the max message size
685 transport1()->Start(kTransport1Port, kTransport2Port, 10);
686 EXPECT_EQ(10, transport1()->max_message_size());
687 const char eleven_characters[] = "12345678901";
688 SendDataResult result;
689 EXPECT_FALSE(SendData(transport1(), 1, eleven_characters, &result));
690}
691
deadbeef953c2ce2017-01-09 14:53:41 -0800692} // namespace cricket