blob: 843fcc2130ee11ed9687614e0ece44058c21aa0a [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"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "p2p/base/fake_dtls_transport.h"
22#include "rtc_base/copy_on_write_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/gunit.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/message_queue.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();
51 }
52
deadbeef8d517c42017-02-19 14:12:24 -080053 void OnDataReceived(const ReceiveDataParams& params,
54 const rtc::CopyOnWriteBuffer& data) {
deadbeef953c2ce2017-01-09 14:53:41 -080055 received_ = true;
56 last_data_ = std::string(data.data<char>(), data.size());
57 last_params_ = params;
58 }
59
60 bool received() const { return received_; }
61 std::string last_data() const { return last_data_; }
62 ReceiveDataParams last_params() const { return last_params_; }
63
64 private:
65 bool received_;
66 std::string last_data_;
67 ReceiveDataParams last_params_;
68};
69
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070070class SctpTransportObserver : public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -080071 public:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070072 explicit SctpTransportObserver(SctpTransport* transport) {
73 transport->SignalClosingProcedureComplete.connect(
74 this, &SctpTransportObserver::OnClosingProcedureComplete);
75 transport->SignalReadyToSendData.connect(
76 this, &SctpTransportObserver::OnReadyToSend);
deadbeef953c2ce2017-01-09 14:53:41 -080077 }
deadbeef953c2ce2017-01-09 14:53:41 -080078
79 int StreamCloseCount(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080080 return absl::c_count(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080081 }
82
83 bool WasStreamClosed(int stream) {
Steve Anton2c9ebef2019-01-28 17:27:58 -080084 return absl::c_linear_search(closed_streams_, stream);
deadbeef953c2ce2017-01-09 14:53:41 -080085 }
86
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070087 bool ReadyToSend() { return ready_to_send_; }
88
deadbeef953c2ce2017-01-09 14:53:41 -080089 private:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070090 void OnClosingProcedureComplete(int stream) {
91 closed_streams_.push_back(stream);
92 }
93 void OnReadyToSend() { ready_to_send_ = true; }
94
95 std::vector<int> closed_streams_;
96 bool ready_to_send_ = false;
deadbeef953c2ce2017-01-09 14:53:41 -080097};
98
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070099// Helper class used to immediately attempt to reopen a stream as soon as it's
100// been closed.
deadbeef953c2ce2017-01-09 14:53:41 -0800101class SignalTransportClosedReopener : public sigslot::has_slots<> {
102 public:
103 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
104 : transport_(transport), peer_(peer) {}
105
Steve Anton2c9ebef2019-01-28 17:27:58 -0800106 int StreamCloseCount(int stream) { return absl::c_count(streams_, stream); }
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700107
108 private:
deadbeef953c2ce2017-01-09 14:53:41 -0800109 void OnStreamClosed(int stream) {
110 transport_->OpenStream(stream);
111 peer_->OpenStream(stream);
112 streams_.push_back(stream);
113 }
114
deadbeef953c2ce2017-01-09 14:53:41 -0800115 SctpTransport* transport_;
116 SctpTransport* peer_;
117 std::vector<int> streams_;
118};
119
120// SCTP Data Engine testing framework.
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200121class SctpTransportTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef953c2ce2017-01-09 14:53:41 -0800122 protected:
123 // usrsctp uses the NSS random number generator on non-Android platforms,
124 // so we need to initialize SSL.
Mirko Bonadei71061bc2019-06-04 09:01:51 +0200125 static void SetUpTestSuite() {}
deadbeef953c2ce2017-01-09 14:53:41 -0800126
127 void SetupConnectedTransportsWithTwoStreams() {
jbauch46d24572017-03-10 16:20:04 -0800128 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
129 }
130
131 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
zhihuangb2cdd932017-01-19 16:54:25 -0800132 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
133 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
deadbeef953c2ce2017-01-09 14:53:41 -0800134 recv1_.reset(new SctpFakeDataReceiver());
135 recv2_.reset(new SctpFakeDataReceiver());
136 transport1_.reset(CreateTransport(fake_dtls1_.get(), recv1_.get()));
137 transport1_->set_debug_name_for_testing("transport1");
138 transport1_->SignalReadyToSendData.connect(
139 this, &SctpTransportTest::OnChan1ReadyToSend);
140 transport2_.reset(CreateTransport(fake_dtls2_.get(), recv2_.get()));
141 transport2_->set_debug_name_for_testing("transport2");
142 transport2_->SignalReadyToSendData.connect(
143 this, &SctpTransportTest::OnChan2ReadyToSend);
144 // Setup two connected transports ready to send and receive.
145 bool asymmetric = false;
146 fake_dtls1_->SetDestination(fake_dtls2_.get(), asymmetric);
147
Mirko Bonadei675513b2017-11-09 11:09:25 +0100148 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
deadbeef953c2ce2017-01-09 14:53:41 -0800149 AddStream(1);
150 AddStream(2);
151
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_VERBOSE)
153 << "Connect the transports -----------------------------";
deadbeef953c2ce2017-01-09 14:53:41 -0800154 // Both transports need to have started (with matching ports) for an
155 // association to be formed.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200156 transport1_->Start(port1, port2, kSctpSendBufferSize);
157 transport2_->Start(port2, port1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800158 }
159
160 bool AddStream(int sid) {
161 bool ret = true;
162 ret = ret && transport1_->OpenStream(sid);
163 ret = ret && transport2_->OpenStream(sid);
164 return ret;
165 }
166
zhihuangb2cdd932017-01-19 16:54:25 -0800167 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
deadbeef953c2ce2017-01-09 14:53:41 -0800168 SctpFakeDataReceiver* recv) {
169 SctpTransport* transport =
170 new SctpTransport(rtc::Thread::Current(), fake_dtls);
171 // When data is received, pass it to the SctpFakeDataReceiver.
172 transport->SignalDataReceived.connect(
173 recv, &SctpFakeDataReceiver::OnDataReceived);
174 return transport;
175 }
176
177 bool SendData(SctpTransport* chan,
178 int sid,
179 const std::string& msg,
180 SendDataResult* result) {
181 SendDataParams params;
182 params.sid = sid;
183
184 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
185 result);
186 }
187
188 bool ReceivedData(const SctpFakeDataReceiver* recv,
189 int sid,
190 const std::string& msg) {
191 return (recv->received() && recv->last_params().sid == sid &&
192 recv->last_data() == msg);
193 }
194
195 bool ProcessMessagesUntilIdle() {
196 rtc::Thread* thread = rtc::Thread::Current();
197 while (!thread->empty()) {
198 rtc::Message msg;
199 if (thread->Get(&msg, rtc::Thread::kForever)) {
200 thread->Dispatch(&msg);
201 }
202 }
203 return !thread->IsQuitting();
204 }
205
206 SctpTransport* transport1() { return transport1_.get(); }
207 SctpTransport* transport2() { return transport2_.get(); }
208 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
209 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
zhihuangb2cdd932017-01-19 16:54:25 -0800210 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
211 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
deadbeef953c2ce2017-01-09 14:53:41 -0800212
213 int transport1_ready_to_send_count() {
214 return transport1_ready_to_send_count_;
215 }
216 int transport2_ready_to_send_count() {
217 return transport2_ready_to_send_count_;
218 }
219
220 private:
zhihuangb2cdd932017-01-19 16:54:25 -0800221 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
222 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
deadbeef953c2ce2017-01-09 14:53:41 -0800223 std::unique_ptr<SctpFakeDataReceiver> recv1_;
224 std::unique_ptr<SctpFakeDataReceiver> recv2_;
225 std::unique_ptr<SctpTransport> transport1_;
226 std::unique_ptr<SctpTransport> transport2_;
227
228 int transport1_ready_to_send_count_ = 0;
229 int transport2_ready_to_send_count_ = 0;
230
231 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
232 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
233};
234
235// Test that data can be sent end-to-end when an SCTP transport starts with one
Zhi Huang644fde42018-04-02 19:16:26 -0700236// transport (which is unwritable), and then switches to another transport. A
237// common scenario due to how BUNDLE works.
238TEST_F(SctpTransportTest, SwitchDtlsTransport) {
zhihuangb2cdd932017-01-19 16:54:25 -0800239 FakeDtlsTransport black_hole("black hole", 0);
240 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
241 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800242 SctpFakeDataReceiver recv1;
243 SctpFakeDataReceiver recv2;
244
Zhi Huang644fde42018-04-02 19:16:26 -0700245 // Construct transport1 with the "black hole" transport.
deadbeef953c2ce2017-01-09 14:53:41 -0800246 std::unique_ptr<SctpTransport> transport1(
247 CreateTransport(&black_hole, &recv1));
248 std::unique_ptr<SctpTransport> transport2(
249 CreateTransport(&fake_dtls2, &recv2));
250
251 // Add a stream.
252 transport1->OpenStream(1);
253 transport2->OpenStream(1);
254
255 // Tell them both to start (though transport1_ is connected to black_hole).
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200256 transport1->Start(kTransport1Port, kTransport2Port, kSctpSendBufferSize);
257 transport2->Start(kTransport2Port, kTransport1Port, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800258
Zhi Huang644fde42018-04-02 19:16:26 -0700259 // Switch transport1_ to the normal fake_dtls1_ transport.
260 transport1->SetDtlsTransport(&fake_dtls1);
deadbeef953c2ce2017-01-09 14:53:41 -0800261
Zhi Huang644fde42018-04-02 19:16:26 -0700262 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800263 bool asymmetric = false;
264 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
265
266 // Make sure we end up able to send data.
267 SendDataResult result;
268 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
269 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
270 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
271 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
Zhi Huang644fde42018-04-02 19:16:26 -0700272
273 // Setting a null DtlsTransport should work. This could happen when an SCTP
274 // data section is rejected.
275 transport1->SetDtlsTransport(nullptr);
deadbeef953c2ce2017-01-09 14:53:41 -0800276}
277
278// Calling Start twice shouldn't do anything bad, if with the same parameters.
279TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
280 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200281 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port,
282 kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800283
284 // Make sure we can still send/recv data.
285 SendDataResult result;
286 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
287 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
288 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
289 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
290}
291
292// Calling Start a second time with a different port should fail.
293TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
294 SetupConnectedTransportsWithTwoStreams();
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200295 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234, kSctpSendBufferSize));
296 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port, kSctpSendBufferSize));
deadbeef953c2ce2017-01-09 14:53:41 -0800297}
298
299// A value of -1 for the local/remote port should be treated as the default
300// (5000).
301TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
zhihuangb2cdd932017-01-19 16:54:25 -0800302 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
303 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800304 SctpFakeDataReceiver recv1;
305 SctpFakeDataReceiver recv2;
306 std::unique_ptr<SctpTransport> transport1(
307 CreateTransport(&fake_dtls1, &recv1));
308 std::unique_ptr<SctpTransport> transport2(
309 CreateTransport(&fake_dtls2, &recv2));
310
311 // Add a stream.
312 transport1->OpenStream(1);
313 transport2->OpenStream(1);
314
315 // Tell them both to start, giving one transport the default port and the
316 // other transport -1.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200317 transport1->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
318 transport2->Start(-1, -1, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800319
Zhi Huang644fde42018-04-02 19:16:26 -0700320 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800321 bool asymmetric = false;
322 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
323
324 // Make sure we end up able to send data.
325 SendDataResult result;
326 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
327 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
328 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
329 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
330}
331
332TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800333 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800334 SctpFakeDataReceiver recv;
335 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
336 EXPECT_TRUE(transport->OpenStream(1));
337 EXPECT_FALSE(transport->OpenStream(1));
338}
339
340TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800341 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800342 SctpFakeDataReceiver recv;
343 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
344 EXPECT_TRUE(transport->OpenStream(1));
345 EXPECT_TRUE(transport->ResetStream(1));
346 EXPECT_FALSE(transport->ResetStream(1));
347}
348
349// Test that SignalReadyToSendData is fired after Start has been called and the
Zhi Huang644fde42018-04-02 19:16:26 -0700350// DTLS transport is writable.
deadbeef953c2ce2017-01-09 14:53:41 -0800351TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
zhihuangb2cdd932017-01-19 16:54:25 -0800352 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800353 SctpFakeDataReceiver recv;
354 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700355 SctpTransportObserver observer(transport.get());
deadbeef953c2ce2017-01-09 14:53:41 -0800356
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200357 transport->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
deadbeef953c2ce2017-01-09 14:53:41 -0800358 fake_dtls.SetWritable(true);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700359 EXPECT_TRUE_WAIT(observer.ReadyToSend(), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800360}
361
362// Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
363// is fired after it begins to be drained.
364TEST_F(SctpTransportTest, SignalReadyToSendDataAfterBlocked) {
365 SetupConnectedTransportsWithTwoStreams();
366 // Wait for initial SCTP association to be formed.
367 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
368 // Make the fake transport unwritable so that messages pile up for the SCTP
369 // socket.
370 fake_dtls1()->SetWritable(false);
371 // Send messages until we get EWOULDBLOCK.
372 static const int kMaxMessages = 1024;
373 SendDataParams params;
374 params.sid = 1;
375 rtc::CopyOnWriteBuffer buf(1024);
376 memset(buf.data<uint8_t>(), 0, 1024);
377 SendDataResult result;
378 int message_count;
379 for (message_count = 0; message_count < kMaxMessages; ++message_count) {
380 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
381 break;
382 }
383 }
384 ASSERT_NE(kMaxMessages, message_count)
385 << "Sent max number of messages without getting SDR_BLOCK?";
386 // Make sure the ready-to-send count hasn't changed.
387 EXPECT_EQ(1, transport1_ready_to_send_count());
388 // Make the transport writable again and expect a "SignalReadyToSendData" at
389 // some point.
390 fake_dtls1()->SetWritable(true);
391 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
392}
393
394TEST_F(SctpTransportTest, SendData) {
395 SetupConnectedTransportsWithTwoStreams();
396
397 SendDataResult result;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100398 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800399 << "transport1 sending: 'hello?' -----------------------------";
400 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
401 EXPECT_EQ(SDR_SUCCESS, result);
402 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100403 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
404 << ", recv2.last_params.sid="
405 << receiver2()->last_params().sid
406 << ", recv2.last_params.timestamp="
407 << receiver2()->last_params().timestamp
408 << ", recv2.last_params.seq_num="
409 << receiver2()->last_params().seq_num
410 << ", recv2.last_data=" << receiver2()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800411
Mirko Bonadei675513b2017-11-09 11:09:25 +0100412 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800413 << "transport2 sending: 'hi transport1' -----------------------------";
414 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
415 EXPECT_EQ(SDR_SUCCESS, result);
416 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
417 kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100418 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
419 << ", recv1.last_params.sid="
420 << receiver1()->last_params().sid
421 << ", recv1.last_params.timestamp="
422 << receiver1()->last_params().timestamp
423 << ", recv1.last_params.seq_num="
424 << receiver1()->last_params().seq_num
425 << ", recv1.last_data=" << receiver1()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800426}
427
428// Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
429TEST_F(SctpTransportTest, SendDataBlocked) {
430 SetupConnectedTransportsWithTwoStreams();
431
432 SendDataResult result;
433 SendDataParams params;
434 params.sid = 1;
435
436 std::vector<char> buffer(1024 * 64, 0);
437
438 for (size_t i = 0; i < 100; ++i) {
439 transport1()->SendData(
440 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
441 if (result == SDR_BLOCK)
442 break;
443 }
444
445 EXPECT_EQ(SDR_BLOCK, result);
446}
447
448// Trying to send data for a nonexistent stream should fail.
449TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
450 SetupConnectedTransportsWithTwoStreams();
451 SendDataResult result;
452 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
453 EXPECT_EQ(SDR_ERROR, result);
454}
455
jbauch46d24572017-03-10 16:20:04 -0800456TEST_F(SctpTransportTest, SendDataHighPorts) {
457 SetupConnectedTransportsWithTwoStreams(32768, 32769);
458
459 SendDataResult result;
460 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
461 EXPECT_EQ(SDR_SUCCESS, result);
462 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
463
464 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
465 EXPECT_EQ(SDR_SUCCESS, result);
466 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
467 kDefaultTimeout);
468}
469
deadbeef953c2ce2017-01-09 14:53:41 -0800470TEST_F(SctpTransportTest, ClosesRemoteStream) {
471 SetupConnectedTransportsWithTwoStreams();
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700472 SctpTransportObserver transport1_observer(transport1());
473 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800474
475 SendDataResult result;
476 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
477 EXPECT_EQ(SDR_SUCCESS, result);
478 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
479 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
480 EXPECT_EQ(SDR_SUCCESS, result);
481 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
482 kDefaultTimeout);
483
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700484 // Close stream 1 on transport 1. Transport 2 should notify us.
deadbeef953c2ce2017-01-09 14:53:41 -0800485 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700486 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800487}
488
489TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
490 SetupConnectedTransportsWithTwoStreams();
491 AddStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700492 SctpTransportObserver transport1_observer(transport1());
493 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800494
495 SendDataResult result;
496 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
497 EXPECT_EQ(SDR_SUCCESS, result);
498 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
499 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
500 EXPECT_EQ(SDR_SUCCESS, result);
501 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
502 kDefaultTimeout);
503
504 // Close two streams on one side.
505 transport2()->ResetStream(2);
506 transport2()->ResetStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700507 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(2), kDefaultTimeout);
508 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(3), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800509}
510
511TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
512 SetupConnectedTransportsWithTwoStreams();
513 AddStream(3);
514 AddStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700515 SctpTransportObserver transport1_observer(transport1());
516 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800517
518 SendDataResult result;
519 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
520 EXPECT_EQ(SDR_SUCCESS, result);
521 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
522 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
523 EXPECT_EQ(SDR_SUCCESS, result);
524 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
525 kDefaultTimeout);
526
527 // Close one stream on transport1(), while closing three streams on
528 // transport2(). They will conflict (only one side can close anything at a
529 // time, apparently). Test the resolution of the conflict.
530 transport1()->ResetStream(1);
531
532 transport2()->ResetStream(2);
533 transport2()->ResetStream(3);
534 transport2()->ResetStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700535 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
536 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(2), kDefaultTimeout);
537 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(3), kDefaultTimeout);
538 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(4), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800539}
540
541TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
542 SetupConnectedTransportsWithTwoStreams();
543 EXPECT_TRUE(AddStream(kMaxSctpSid));
544 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
545}
546
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700547TEST_F(SctpTransportTest, ReusesAStream) {
deadbeef953c2ce2017-01-09 14:53:41 -0800548 // Shut down transport 1, then open it up again for reuse.
549 SetupConnectedTransportsWithTwoStreams();
550 SendDataResult result;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700551 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800552
553 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
554 EXPECT_EQ(SDR_SUCCESS, result);
555 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
556
557 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700558 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800559 // Transport 1 is gone now.
560
561 // Create a new transport 1.
562 AddStream(1);
563 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
564 EXPECT_EQ(SDR_SUCCESS, result);
565 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
566 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700567 EXPECT_EQ_WAIT(2, transport2_observer.StreamCloseCount(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800568}
569
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200570TEST_F(SctpTransportTest, RejectsTooLargeMessageSize) {
571 FakeDtlsTransport fake_dtls("fake dtls", 0);
572 SctpFakeDataReceiver recv;
573 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
574
575 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort,
576 kSctpSendBufferSize + 1));
577}
578
579TEST_F(SctpTransportTest, RejectsTooSmallMessageSize) {
580 FakeDtlsTransport fake_dtls("fake dtls", 0);
581 SctpFakeDataReceiver recv;
582 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
583
584 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort, 0));
585}
586
587TEST_F(SctpTransportTest, RejectsSendTooLargeMessages) {
588 SetupConnectedTransportsWithTwoStreams();
589 // Use "Start" to reduce the max message size
590 transport1()->Start(kTransport1Port, kTransport2Port, 10);
591 EXPECT_EQ(10, transport1()->max_message_size());
592 const char eleven_characters[] = "12345678901";
593 SendDataResult result;
594 EXPECT_FALSE(SendData(transport1(), 1, eleven_characters, &result));
595}
596
deadbeef953c2ce2017-01-09 14:53:41 -0800597} // namespace cricket