blob: a267d4c090733e61473b402d59e5a1815d942a26 [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "test/gtest.h"
deadbeef953c2ce2017-01-09 14:53:41 -080028
29namespace {
30static const int kDefaultTimeout = 10000; // 10 seconds.
31// Use ports other than the default 5000 for testing.
32static const int kTransport1Port = 5001;
33static const int kTransport2Port = 5002;
Yves Gerey665174f2018-06-19 15:03:05 +020034} // namespace
deadbeef953c2ce2017-01-09 14:53:41 -080035
36namespace cricket {
37
38// This is essentially a buffer to hold recieved data. It stores only the last
39// received data. Calling OnDataReceived twice overwrites old data with the
40// newer one.
41// TODO(ldixon): Implement constraints, and allow new data to be added to old
42// instead of replacing it.
43class SctpFakeDataReceiver : public sigslot::has_slots<> {
44 public:
45 SctpFakeDataReceiver() : received_(false) {}
46
47 void Clear() {
48 received_ = false;
49 last_data_ = "";
50 last_params_ = ReceiveDataParams();
Seth Hampson66d6c3b2019-08-30 09:02:46 -070051 num_messages_received_ = 0;
deadbeef953c2ce2017-01-09 14:53:41 -080052 }
53
deadbeef8d517c42017-02-19 14:12:24 -080054 void OnDataReceived(const ReceiveDataParams& params,
55 const rtc::CopyOnWriteBuffer& data) {
Seth Hampson66d6c3b2019-08-30 09:02:46 -070056 num_messages_received_++;
deadbeef953c2ce2017-01-09 14:53:41 -080057 received_ = true;
58 last_data_ = std::string(data.data<char>(), data.size());
59 last_params_ = params;
60 }
61
62 bool received() const { return received_; }
63 std::string last_data() const { return last_data_; }
64 ReceiveDataParams last_params() const { return last_params_; }
Seth Hampson66d6c3b2019-08-30 09:02:46 -070065 size_t num_messages_received() const { return num_messages_received_; }
deadbeef953c2ce2017-01-09 14:53:41 -080066
67 private:
68 bool received_;
69 std::string last_data_;
Seth Hampson66d6c3b2019-08-30 09:02:46 -070070 size_t num_messages_received_ = 0;
deadbeef953c2ce2017-01-09 14:53:41 -080071 ReceiveDataParams last_params_;
72};
73
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070074class SctpTransportObserver : public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -080075 public:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070076 explicit SctpTransportObserver(SctpTransport* transport) {
77 transport->SignalClosingProcedureComplete.connect(
78 this, &SctpTransportObserver::OnClosingProcedureComplete);
79 transport->SignalReadyToSendData.connect(
80 this, &SctpTransportObserver::OnReadyToSend);
deadbeef953c2ce2017-01-09 14:53:41 -080081 }
deadbeef953c2ce2017-01-09 14:53:41 -080082
83 int StreamCloseCount(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080084 return absl::c_count(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080085 }
86
87 bool WasStreamClosed(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080088 return absl::c_linear_search(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080089 }
90
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070091 bool ReadyToSend() { return ready_to_send_; }
92
deadbeef953c2ce2017-01-09 14:53:41 -080093 private:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070094 void OnClosingProcedureComplete(int stream) {
95 closed_streams_.push_back(stream);
96 }
97 void OnReadyToSend() { ready_to_send_ = true; }
98
99 std::vector<int> closed_streams_;
100 bool ready_to_send_ = false;
deadbeef953c2ce2017-01-09 14:53:41 -0800101};
102
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700103// Helper class used to immediately attempt to reopen a stream as soon as it's
104// been closed.
deadbeef953c2ce2017-01-09 14:53:41 -0800105class SignalTransportClosedReopener : public sigslot::has_slots<> {
106 public:
107 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
108 : transport_(transport), peer_(peer) {}
109
Steve Anton2c9ebef2019-01-28 17:27:58 -0800110 int StreamCloseCount(int stream) { return absl::c_count(streams_, stream); }
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700111
112 private:
deadbeef953c2ce2017-01-09 14:53:41 -0800113 void OnStreamClosed(int stream) {
114 transport_->OpenStream(stream);
115 peer_->OpenStream(stream);
116 streams_.push_back(stream);
117 }
118
deadbeef953c2ce2017-01-09 14:53:41 -0800119 SctpTransport* transport_;
120 SctpTransport* peer_;
121 std::vector<int> streams_;
122};
123
124// SCTP Data Engine testing framework.
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200125class SctpTransportTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -0800126 protected:
127 // usrsctp uses the NSS random number generator on non-Android platforms,
128 // so we need to initialize SSL.
Mirko Bonadei71061bc2019-06-04 09:01:51 +0200129 static void SetUpTestSuite() {}
deadbeef953c2ce2017-01-09 14:53:41 -0800130
131 void SetupConnectedTransportsWithTwoStreams() {
jbauch46d24572017-03-10 16:20:04 -0800132 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
133 }
134
135 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
zhihuangb2cdd932017-01-19 16:54:25 -0800136 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
137 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
deadbeef953c2ce2017-01-09 14:53:41 -0800138 recv1_.reset(new SctpFakeDataReceiver());
139 recv2_.reset(new SctpFakeDataReceiver());
140 transport1_.reset(CreateTransport(fake_dtls1_.get(), recv1_.get()));
141 transport1_->set_debug_name_for_testing("transport1");
142 transport1_->SignalReadyToSendData.connect(
143 this, &SctpTransportTest::OnChan1ReadyToSend);
144 transport2_.reset(CreateTransport(fake_dtls2_.get(), recv2_.get()));
145 transport2_->set_debug_name_for_testing("transport2");
146 transport2_->SignalReadyToSendData.connect(
147 this, &SctpTransportTest::OnChan2ReadyToSend);
148 // Setup two connected transports ready to send and receive.
149 bool asymmetric = false;
150 fake_dtls1_->SetDestination(fake_dtls2_.get(), asymmetric);
151
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
deadbeef953c2ce2017-01-09 14:53:41 -0800153 AddStream(1);
154 AddStream(2);
155
Mirko Bonadei675513b2017-11-09 11:09:25 +0100156 RTC_LOG(LS_VERBOSE)
157 << "Connect the transports -----------------------------";
deadbeef953c2ce2017-01-09 14:53:41 -0800158 // Both transports need to have started (with matching ports) for an
159 // association to be formed.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200160 transport1_->Start(port1, port2, kSctpSendBufferSize);
161 transport2_->Start(port2, port1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800162 }
163
164 bool AddStream(int sid) {
165 bool ret = true;
166 ret = ret && transport1_->OpenStream(sid);
167 ret = ret && transport2_->OpenStream(sid);
168 return ret;
169 }
170
zhihuangb2cdd932017-01-19 16:54:25 -0800171 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
deadbeef953c2ce2017-01-09 14:53:41 -0800172 SctpFakeDataReceiver* recv) {
173 SctpTransport* transport =
174 new SctpTransport(rtc::Thread::Current(), fake_dtls);
175 // When data is received, pass it to the SctpFakeDataReceiver.
176 transport->SignalDataReceived.connect(
177 recv, &SctpFakeDataReceiver::OnDataReceived);
178 return transport;
179 }
180
181 bool SendData(SctpTransport* chan,
182 int sid,
183 const std::string& msg,
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700184 SendDataResult* result,
185 bool ordered = false) {
deadbeef953c2ce2017-01-09 14:53:41 -0800186 SendDataParams params;
187 params.sid = sid;
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700188 params.ordered = ordered;
deadbeef953c2ce2017-01-09 14:53:41 -0800189
190 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
191 result);
192 }
193
194 bool ReceivedData(const SctpFakeDataReceiver* recv,
195 int sid,
196 const std::string& msg) {
197 return (recv->received() && recv->last_params().sid == sid &&
198 recv->last_data() == msg);
199 }
200
201 bool ProcessMessagesUntilIdle() {
202 rtc::Thread* thread = rtc::Thread::Current();
203 while (!thread->empty()) {
204 rtc::Message msg;
205 if (thread->Get(&msg, rtc::Thread::kForever)) {
206 thread->Dispatch(&msg);
207 }
208 }
209 return !thread->IsQuitting();
210 }
211
212 SctpTransport* transport1() { return transport1_.get(); }
213 SctpTransport* transport2() { return transport2_.get(); }
214 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
215 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
zhihuangb2cdd932017-01-19 16:54:25 -0800216 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
217 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
deadbeef953c2ce2017-01-09 14:53:41 -0800218
219 int transport1_ready_to_send_count() {
220 return transport1_ready_to_send_count_;
221 }
222 int transport2_ready_to_send_count() {
223 return transport2_ready_to_send_count_;
224 }
225
226 private:
zhihuangb2cdd932017-01-19 16:54:25 -0800227 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
228 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
deadbeef953c2ce2017-01-09 14:53:41 -0800229 std::unique_ptr<SctpFakeDataReceiver> recv1_;
230 std::unique_ptr<SctpFakeDataReceiver> recv2_;
231 std::unique_ptr<SctpTransport> transport1_;
232 std::unique_ptr<SctpTransport> transport2_;
233
234 int transport1_ready_to_send_count_ = 0;
235 int transport2_ready_to_send_count_ = 0;
236
237 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
238 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
239};
240
241// Test that data can be sent end-to-end when an SCTP transport starts with one
Zhi Huang644fde42018-04-02 19:16:26 -0700242// transport (which is unwritable), and then switches to another transport. A
243// common scenario due to how BUNDLE works.
244TEST_F(SctpTransportTest, SwitchDtlsTransport) {
zhihuangb2cdd932017-01-19 16:54:25 -0800245 FakeDtlsTransport black_hole("black hole", 0);
246 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
247 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800248 SctpFakeDataReceiver recv1;
249 SctpFakeDataReceiver recv2;
250
Zhi Huang644fde42018-04-02 19:16:26 -0700251 // Construct transport1 with the "black hole" transport.
deadbeef953c2ce2017-01-09 14:53:41 -0800252 std::unique_ptr<SctpTransport> transport1(
253 CreateTransport(&black_hole, &recv1));
254 std::unique_ptr<SctpTransport> transport2(
255 CreateTransport(&fake_dtls2, &recv2));
256
257 // Add a stream.
258 transport1->OpenStream(1);
259 transport2->OpenStream(1);
260
261 // Tell them both to start (though transport1_ is connected to black_hole).
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200262 transport1->Start(kTransport1Port, kTransport2Port, kSctpSendBufferSize);
263 transport2->Start(kTransport2Port, kTransport1Port, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800264
Zhi Huang644fde42018-04-02 19:16:26 -0700265 // Switch transport1_ to the normal fake_dtls1_ transport.
266 transport1->SetDtlsTransport(&fake_dtls1);
deadbeef953c2ce2017-01-09 14:53:41 -0800267
Zhi Huang644fde42018-04-02 19:16:26 -0700268 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800269 bool asymmetric = false;
270 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
271
272 // Make sure we end up able to send data.
273 SendDataResult result;
274 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
275 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
276 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
277 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
Zhi Huang644fde42018-04-02 19:16:26 -0700278
279 // Setting a null DtlsTransport should work. This could happen when an SCTP
280 // data section is rejected.
281 transport1->SetDtlsTransport(nullptr);
deadbeef953c2ce2017-01-09 14:53:41 -0800282}
283
284// Calling Start twice shouldn't do anything bad, if with the same parameters.
285TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
286 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200287 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port,
288 kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800289
290 // Make sure we can still send/recv data.
291 SendDataResult result;
292 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
293 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
294 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
295 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
296}
297
298// Calling Start a second time with a different port should fail.
299TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
300 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200301 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234, kSctpSendBufferSize));
302 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port, kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800303}
304
305// A value of -1 for the local/remote port should be treated as the default
306// (5000).
307TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
zhihuangb2cdd932017-01-19 16:54:25 -0800308 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
309 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800310 SctpFakeDataReceiver recv1;
311 SctpFakeDataReceiver recv2;
312 std::unique_ptr<SctpTransport> transport1(
313 CreateTransport(&fake_dtls1, &recv1));
314 std::unique_ptr<SctpTransport> transport2(
315 CreateTransport(&fake_dtls2, &recv2));
316
317 // Add a stream.
318 transport1->OpenStream(1);
319 transport2->OpenStream(1);
320
321 // Tell them both to start, giving one transport the default port and the
322 // other transport -1.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200323 transport1->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
324 transport2->Start(-1, -1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800325
Zhi Huang644fde42018-04-02 19:16:26 -0700326 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800327 bool asymmetric = false;
328 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
329
330 // Make sure we end up able to send data.
331 SendDataResult result;
332 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
333 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
334 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
335 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
336}
337
338TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800339 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800340 SctpFakeDataReceiver recv;
341 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
342 EXPECT_TRUE(transport->OpenStream(1));
343 EXPECT_FALSE(transport->OpenStream(1));
344}
345
346TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800347 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800348 SctpFakeDataReceiver recv;
349 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
350 EXPECT_TRUE(transport->OpenStream(1));
351 EXPECT_TRUE(transport->ResetStream(1));
352 EXPECT_FALSE(transport->ResetStream(1));
353}
354
355// Test that SignalReadyToSendData is fired after Start has been called and the
Zhi Huang644fde42018-04-02 19:16:26 -0700356// DTLS transport is writable.
deadbeef953c2ce2017-01-09 14:53:41 -0800357TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
zhihuangb2cdd932017-01-19 16:54:25 -0800358 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800359 SctpFakeDataReceiver recv;
360 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700361 SctpTransportObserver observer(transport.get());
deadbeef953c2ce2017-01-09 14:53:41 -0800362
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200363 transport->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800364 fake_dtls.SetWritable(true);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700365 EXPECT_TRUE_WAIT(observer.ReadyToSend(), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800366}
367
368// Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
369// is fired after it begins to be drained.
370TEST_F(SctpTransportTest, SignalReadyToSendDataAfterBlocked) {
371 SetupConnectedTransportsWithTwoStreams();
372 // Wait for initial SCTP association to be formed.
373 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
374 // Make the fake transport unwritable so that messages pile up for the SCTP
375 // socket.
376 fake_dtls1()->SetWritable(false);
377 // Send messages until we get EWOULDBLOCK.
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700378 static const size_t kMaxMessages = 1024;
deadbeef953c2ce2017-01-09 14:53:41 -0800379 SendDataParams params;
380 params.sid = 1;
381 rtc::CopyOnWriteBuffer buf(1024);
382 memset(buf.data<uint8_t>(), 0, 1024);
383 SendDataResult result;
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700384 size_t message_count = 0;
385 for (; message_count < kMaxMessages; ++message_count) {
deadbeef953c2ce2017-01-09 14:53:41 -0800386 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
387 break;
388 }
389 }
390 ASSERT_NE(kMaxMessages, message_count)
391 << "Sent max number of messages without getting SDR_BLOCK?";
392 // Make sure the ready-to-send count hasn't changed.
393 EXPECT_EQ(1, transport1_ready_to_send_count());
394 // Make the transport writable again and expect a "SignalReadyToSendData" at
395 // some point.
396 fake_dtls1()->SetWritable(true);
397 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
Seth Hampson66d6c3b2019-08-30 09:02:46 -0700398 EXPECT_EQ_WAIT(message_count, receiver2()->num_messages_received(),
399 kDefaultTimeout);
400}
401
402// Tests that a small message gets buffered and later sent by the SctpTransport
403// when the sctp library only accepts the message partially.
404TEST_F(SctpTransportTest, SendSmallBufferedOutgoingMessage) {
405 SetupConnectedTransportsWithTwoStreams();
406 // Wait for initial SCTP association to be formed.
407 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
408 // Make the fake transport unwritable so that messages pile up for the SCTP
409 // socket.
410 fake_dtls1()->SetWritable(false);
411 SendDataResult result;
412 // TODO(bugs.webrtc.org/10939): We can't test this behavior unless we are
413 // sending in ordered mode becuase the sctp lib drops large buffered data in
414 // unordered mode.
415 bool ordered = true;
416
417 // Fill almost all of sctp library's send buffer.
418 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
419 std::string(kSctpSendBufferSize - 1, 'a'), &result,
420 ordered));
421
422 std::string buffered_message("hello hello");
423 // SctpTransport accepts this message by buffering part of it.
424 ASSERT_TRUE(
425 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
426 ASSERT_TRUE(transport1()->ReadyToSendData());
427
428 // Sending anything else should block now.
429 ASSERT_FALSE(
430 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
431 ASSERT_EQ(SDR_BLOCK, result);
432 ASSERT_FALSE(transport1()->ReadyToSendData());
433
434 // Make sure the ready-to-send count hasn't changed.
435 EXPECT_EQ(1, transport1_ready_to_send_count());
436 // Make the transport writable again and expect a "SignalReadyToSendData" at
437 // some point after sending the buffered message.
438 fake_dtls1()->SetWritable(true);
439 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
440 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
441 kDefaultTimeout);
442 EXPECT_EQ(2u, receiver2()->num_messages_received());
443}
444
445// Tests that a large message gets buffered and later sent by the SctpTransport
446// when the sctp library only accepts the message partially.
447TEST_F(SctpTransportTest, SendLargeBufferedOutgoingMessage) {
448 SetupConnectedTransportsWithTwoStreams();
449 // Wait for initial SCTP association to be formed.
450 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
451 // Make the fake transport unwritable so that messages pile up for the SCTP
452 // socket.
453 fake_dtls1()->SetWritable(false);
454 SendDataResult result;
455 // TODO(bugs.webrtc.org/10939): We can't test this behavior unless we are
456 // sending in ordered mode becuase the sctp lib drops large buffered data in
457 // unordered mode.
458 bool ordered = true;
459
460 // Fill almost all of sctp library's send buffer.
461 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
462 std::string(kSctpSendBufferSize / 2, 'a'), &result,
463 ordered));
464
465 std::string buffered_message(kSctpSendBufferSize, 'b');
466 // SctpTransport accepts this message by buffering the second half.
467 ASSERT_TRUE(
468 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
469 ASSERT_TRUE(transport1()->ReadyToSendData());
470
471 // Sending anything else should block now.
472 ASSERT_FALSE(
473 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
474 ASSERT_EQ(SDR_BLOCK, result);
475 ASSERT_FALSE(transport1()->ReadyToSendData());
476
477 // Make sure the ready-to-send count hasn't changed.
478 EXPECT_EQ(1, transport1_ready_to_send_count());
479 // Make the transport writable again and expect a "SignalReadyToSendData" at
480 // some point.
481 fake_dtls1()->SetWritable(true);
482 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
483 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
484 kDefaultTimeout);
485 EXPECT_EQ(2u, receiver2()->num_messages_received());
deadbeef953c2ce2017-01-09 14:53:41 -0800486}
487
488TEST_F(SctpTransportTest, SendData) {
489 SetupConnectedTransportsWithTwoStreams();
490
491 SendDataResult result;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100492 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800493 << "transport1 sending: 'hello?' -----------------------------";
494 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
495 EXPECT_EQ(SDR_SUCCESS, result);
496 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100497 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
498 << ", recv2.last_params.sid="
499 << receiver2()->last_params().sid
500 << ", recv2.last_params.timestamp="
501 << receiver2()->last_params().timestamp
502 << ", recv2.last_params.seq_num="
503 << receiver2()->last_params().seq_num
504 << ", recv2.last_data=" << receiver2()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800505
Mirko Bonadei675513b2017-11-09 11:09:25 +0100506 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800507 << "transport2 sending: 'hi transport1' -----------------------------";
508 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
509 EXPECT_EQ(SDR_SUCCESS, result);
510 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
511 kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100512 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
513 << ", recv1.last_params.sid="
514 << receiver1()->last_params().sid
515 << ", recv1.last_params.timestamp="
516 << receiver1()->last_params().timestamp
517 << ", recv1.last_params.seq_num="
518 << receiver1()->last_params().seq_num
519 << ", recv1.last_data=" << receiver1()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800520}
521
522// Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
523TEST_F(SctpTransportTest, SendDataBlocked) {
524 SetupConnectedTransportsWithTwoStreams();
525
526 SendDataResult result;
527 SendDataParams params;
528 params.sid = 1;
529
530 std::vector<char> buffer(1024 * 64, 0);
531
532 for (size_t i = 0; i < 100; ++i) {
533 transport1()->SendData(
534 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
535 if (result == SDR_BLOCK)
536 break;
537 }
538
539 EXPECT_EQ(SDR_BLOCK, result);
540}
541
542// Trying to send data for a nonexistent stream should fail.
543TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
544 SetupConnectedTransportsWithTwoStreams();
545 SendDataResult result;
546 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
547 EXPECT_EQ(SDR_ERROR, result);
548}
549
jbauch46d24572017-03-10 16:20:04 -0800550TEST_F(SctpTransportTest, SendDataHighPorts) {
551 SetupConnectedTransportsWithTwoStreams(32768, 32769);
552
553 SendDataResult result;
554 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
555 EXPECT_EQ(SDR_SUCCESS, result);
556 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
557
558 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
559 EXPECT_EQ(SDR_SUCCESS, result);
560 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
561 kDefaultTimeout);
562}
563
deadbeef953c2ce2017-01-09 14:53:41 -0800564TEST_F(SctpTransportTest, ClosesRemoteStream) {
565 SetupConnectedTransportsWithTwoStreams();
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700566 SctpTransportObserver transport1_observer(transport1());
567 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800568
569 SendDataResult result;
570 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
571 EXPECT_EQ(SDR_SUCCESS, result);
572 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
573 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
574 EXPECT_EQ(SDR_SUCCESS, result);
575 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
576 kDefaultTimeout);
577
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700578 // Close stream 1 on transport 1. Transport 2 should notify us.
deadbeef953c2ce2017-01-09 14:53:41 -0800579 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700580 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800581}
582
583TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
584 SetupConnectedTransportsWithTwoStreams();
585 AddStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700586 SctpTransportObserver transport1_observer(transport1());
587 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800588
589 SendDataResult result;
590 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
591 EXPECT_EQ(SDR_SUCCESS, result);
592 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
593 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
594 EXPECT_EQ(SDR_SUCCESS, result);
595 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
596 kDefaultTimeout);
597
598 // Close two streams on one side.
599 transport2()->ResetStream(2);
600 transport2()->ResetStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700601 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(2), kDefaultTimeout);
602 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(3), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800603}
604
605TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
606 SetupConnectedTransportsWithTwoStreams();
607 AddStream(3);
608 AddStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700609 SctpTransportObserver transport1_observer(transport1());
610 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800611
612 SendDataResult result;
613 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
614 EXPECT_EQ(SDR_SUCCESS, result);
615 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
616 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
617 EXPECT_EQ(SDR_SUCCESS, result);
618 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
619 kDefaultTimeout);
620
621 // Close one stream on transport1(), while closing three streams on
622 // transport2(). They will conflict (only one side can close anything at a
623 // time, apparently). Test the resolution of the conflict.
624 transport1()->ResetStream(1);
625
626 transport2()->ResetStream(2);
627 transport2()->ResetStream(3);
628 transport2()->ResetStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700629 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
630 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(2), kDefaultTimeout);
631 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(3), kDefaultTimeout);
632 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(4), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800633}
634
635TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
636 SetupConnectedTransportsWithTwoStreams();
637 EXPECT_TRUE(AddStream(kMaxSctpSid));
638 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
639}
640
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700641TEST_F(SctpTransportTest, ReusesAStream) {
deadbeef953c2ce2017-01-09 14:53:41 -0800642 // Shut down transport 1, then open it up again for reuse.
643 SetupConnectedTransportsWithTwoStreams();
644 SendDataResult result;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700645 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800646
647 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
648 EXPECT_EQ(SDR_SUCCESS, result);
649 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
650
651 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700652 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800653 // Transport 1 is gone now.
654
655 // Create a new transport 1.
656 AddStream(1);
657 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
658 EXPECT_EQ(SDR_SUCCESS, result);
659 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
660 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700661 EXPECT_EQ_WAIT(2, transport2_observer.StreamCloseCount(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800662}
663
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200664TEST_F(SctpTransportTest, RejectsTooLargeMessageSize) {
665 FakeDtlsTransport fake_dtls("fake dtls", 0);
666 SctpFakeDataReceiver recv;
667 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
668
669 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort,
670 kSctpSendBufferSize + 1));
671}
672
673TEST_F(SctpTransportTest, RejectsTooSmallMessageSize) {
674 FakeDtlsTransport fake_dtls("fake dtls", 0);
675 SctpFakeDataReceiver recv;
676 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
677
678 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort, 0));
679}
680
681TEST_F(SctpTransportTest, RejectsSendTooLargeMessages) {
682 SetupConnectedTransportsWithTwoStreams();
683 // Use "Start" to reduce the max message size
684 transport1()->Start(kTransport1Port, kTransport2Port, 10);
685 EXPECT_EQ(10, transport1()->max_message_size());
686 const char eleven_characters[] = "12345678901";
687 SendDataResult result;
688 EXPECT_FALSE(SendData(transport1(), 1, eleven_characters, &result));
689}
690
deadbeef953c2ce2017-01-09 14:53:41 -0800691} // namespace cricket