1 /*
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
11 #include "media/sctp/sctp_transport.h"
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <usrsctp.h>
16
17 #include <memory>
18 #include <string>
19 #include <vector>
20
21 #include "absl/algorithm/container.h"
22 #include "media/sctp/sctp_transport_internal.h"
23 #include "p2p/base/fake_dtls_transport.h"
24 #include "rtc_base/copy_on_write_buffer.h"
25 #include "rtc_base/gunit.h"
26 #include "rtc_base/logging.h"
27 #include "rtc_base/thread.h"
28 #include "test/gtest.h"
29
30 namespace {
31 static const int kDefaultTimeout = 10000; // 10 seconds.
32 // Use ports other than the default 5000 for testing.
33 static const int kTransport1Port = 5001;
34 static const int kTransport2Port = 5002;
35 } // namespace
36
37 namespace 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.
44 class SctpFakeDataReceiver : public sigslot::has_slots<> {
45 public:
SctpFakeDataReceiver()46 SctpFakeDataReceiver() : received_(false) {}
47
Clear()48 void Clear() {
49 received_ = false;
50 last_data_ = "";
51 last_params_ = ReceiveDataParams();
52 num_messages_received_ = 0;
53 }
54
OnDataReceived(const ReceiveDataParams & params,const rtc::CopyOnWriteBuffer & data)55 void OnDataReceived(const ReceiveDataParams& params,
56 const rtc::CopyOnWriteBuffer& data) {
57 num_messages_received_++;
58 received_ = true;
59 last_data_ = std::string(data.data<char>(), data.size());
60 last_params_ = params;
61 }
62
received() const63 bool received() const { return received_; }
last_data() const64 std::string last_data() const { return last_data_; }
last_params() const65 ReceiveDataParams last_params() const { return last_params_; }
num_messages_received() const66 size_t num_messages_received() const { return num_messages_received_; }
67
68 private:
69 bool received_;
70 std::string last_data_;
71 size_t num_messages_received_ = 0;
72 ReceiveDataParams last_params_;
73 };
74
75 class SctpTransportObserver : public sigslot::has_slots<> {
76 public:
SctpTransportObserver(SctpTransport * transport)77 explicit SctpTransportObserver(SctpTransport* transport) {
78 transport->SignalClosingProcedureComplete.connect(
79 this, &SctpTransportObserver::OnClosingProcedureComplete);
80 transport->SignalReadyToSendData.connect(
81 this, &SctpTransportObserver::OnReadyToSend);
82 }
83
StreamCloseCount(int stream)84 int StreamCloseCount(int stream) {
85 return absl::c_count(closed_streams_, stream);
86 }
87
WasStreamClosed(int stream)88 bool WasStreamClosed(int stream) {
89 return absl::c_linear_search(closed_streams_, stream);
90 }
91
ReadyToSend()92 bool ReadyToSend() { return ready_to_send_; }
93
94 private:
OnClosingProcedureComplete(int stream)95 void OnClosingProcedureComplete(int stream) {
96 closed_streams_.push_back(stream);
97 }
OnReadyToSend()98 void OnReadyToSend() { ready_to_send_ = true; }
99
100 std::vector<int> closed_streams_;
101 bool ready_to_send_ = false;
102 };
103
104 // Helper class used to immediately attempt to reopen a stream as soon as it's
105 // been closed.
106 class SignalTransportClosedReopener : public sigslot::has_slots<> {
107 public:
SignalTransportClosedReopener(SctpTransport * transport,SctpTransport * peer)108 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
109 : transport_(transport), peer_(peer) {}
110
StreamCloseCount(int stream)111 int StreamCloseCount(int stream) { return absl::c_count(streams_, stream); }
112
113 private:
OnStreamClosed(int stream)114 void OnStreamClosed(int stream) {
115 transport_->OpenStream(stream);
116 peer_->OpenStream(stream);
117 streams_.push_back(stream);
118 }
119
120 SctpTransport* transport_;
121 SctpTransport* peer_;
122 std::vector<int> streams_;
123 };
124
125 // SCTP Data Engine testing framework.
126 class SctpTransportTest : public ::testing::Test, public sigslot::has_slots<> {
127 protected:
128 // usrsctp uses the NSS random number generator on non-Android platforms,
129 // so we need to initialize SSL.
SetUpTestSuite()130 static void SetUpTestSuite() {}
131
SetupConnectedTransportsWithTwoStreams()132 void SetupConnectedTransportsWithTwoStreams() {
133 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
134 }
135
SetupConnectedTransportsWithTwoStreams(int port1,int port2)136 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
137 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
138 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
139 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
153 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
154 AddStream(1);
155 AddStream(2);
156
157 RTC_LOG(LS_VERBOSE)
158 << "Connect the transports -----------------------------";
159 // Both transports need to have started (with matching ports) for an
160 // association to be formed.
161 transport1_->Start(port1, port2, kSctpSendBufferSize);
162 transport2_->Start(port2, port1, kSctpSendBufferSize);
163 }
164
AddStream(int sid)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
CreateTransport(FakeDtlsTransport * fake_dtls,SctpFakeDataReceiver * recv)172 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
173 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
SendData(SctpTransport * chan,int sid,const std::string & msg,SendDataResult * result,bool ordered=false)182 bool SendData(SctpTransport* chan,
183 int sid,
184 const std::string& msg,
185 SendDataResult* result,
186 bool ordered = false) {
187 SendDataParams params;
188 params.sid = sid;
189 params.ordered = ordered;
190
191 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
192 result);
193 }
194
ReceivedData(const SctpFakeDataReceiver * recv,int sid,const std::string & msg)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
ProcessMessagesUntilIdle()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
transport1()213 SctpTransport* transport1() { return transport1_.get(); }
transport2()214 SctpTransport* transport2() { return transport2_.get(); }
receiver1()215 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
receiver2()216 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
fake_dtls1()217 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
fake_dtls2()218 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
219
transport1_ready_to_send_count()220 int transport1_ready_to_send_count() {
221 return transport1_ready_to_send_count_;
222 }
transport2_ready_to_send_count()223 int transport2_ready_to_send_count() {
224 return transport2_ready_to_send_count_;
225 }
226
227 private:
228 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
229 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
230 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
OnChan1ReadyToSend()238 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
OnChan2ReadyToSend()239 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
240 };
241
TEST_F(SctpTransportTest,MessageInterleavedWithNotification)242 TEST_F(SctpTransportTest, MessageInterleavedWithNotification) {
243 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
244 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
245 SctpFakeDataReceiver recv1;
246 SctpFakeDataReceiver recv2;
247 std::unique_ptr<SctpTransport> transport1(
248 CreateTransport(&fake_dtls1, &recv1));
249 std::unique_ptr<SctpTransport> transport2(
250 CreateTransport(&fake_dtls2, &recv2));
251
252 // Add a stream.
253 transport1->OpenStream(1);
254 transport2->OpenStream(1);
255
256 // Start SCTP transports.
257 transport1->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
258 transport2->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
259
260 // Connect the two fake DTLS transports.
261 fake_dtls1.SetDestination(&fake_dtls2, false);
262
263 // Ensure the SCTP association has been established
264 // Note: I'd rather watch for an assoc established state here but couldn't
265 // find any exposed...
266 SendDataResult result;
267 ASSERT_TRUE(SendData(transport2.get(), 1, "meow", &result));
268 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "meow"), kDefaultTimeout);
269
270 // Detach the DTLS transport to ensure only we will inject packets from here
271 // on.
272 transport1->SetDtlsTransport(nullptr);
273
274 // Prepare chunk buffer and metadata
275 auto chunk = rtc::CopyOnWriteBuffer(32);
276 struct sctp_rcvinfo meta = {0};
277 meta.rcv_sid = 1;
278 meta.rcv_ssn = 1337;
279 meta.rcv_ppid = rtc::HostToNetwork32(51); // text (complete)
280
281 // Inject chunk 1/2.
282 meta.rcv_tsn = 42;
283 meta.rcv_cumtsn = 42;
284 chunk.SetData("meow?", 5);
285 EXPECT_EQ(1, transport1->InjectDataOrNotificationFromSctpForTesting(
286 chunk.data(), chunk.size(), meta, 0));
287
288 // Inject a notification in between chunks.
289 union sctp_notification notification;
290 memset(¬ification, 0, sizeof(notification));
291 // Type chosen since it's not handled apart from being logged
292 notification.sn_header.sn_type = SCTP_PEER_ADDR_CHANGE;
293 notification.sn_header.sn_flags = 0;
294 notification.sn_header.sn_length = sizeof(notification);
295 EXPECT_EQ(1, transport1->InjectDataOrNotificationFromSctpForTesting(
296 ¬ification, sizeof(notification), {0}, MSG_NOTIFICATION));
297
298 // Inject chunk 2/2
299 meta.rcv_tsn = 42;
300 meta.rcv_cumtsn = 43;
301 chunk.SetData(" rawr!", 6);
302 EXPECT_EQ(1, transport1->InjectDataOrNotificationFromSctpForTesting(
303 chunk.data(), chunk.size(), meta, MSG_EOR));
304
305 // Expect the message to contain both chunks.
306 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "meow? rawr!"), kDefaultTimeout);
307 }
308
309 // Test that data can be sent end-to-end when an SCTP transport starts with one
310 // transport (which is unwritable), and then switches to another transport. A
311 // common scenario due to how BUNDLE works.
TEST_F(SctpTransportTest,SwitchDtlsTransport)312 TEST_F(SctpTransportTest, SwitchDtlsTransport) {
313 FakeDtlsTransport black_hole("black hole", 0);
314 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
315 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
316 SctpFakeDataReceiver recv1;
317 SctpFakeDataReceiver recv2;
318
319 // Construct transport1 with the "black hole" transport.
320 std::unique_ptr<SctpTransport> transport1(
321 CreateTransport(&black_hole, &recv1));
322 std::unique_ptr<SctpTransport> transport2(
323 CreateTransport(&fake_dtls2, &recv2));
324
325 // Add a stream.
326 transport1->OpenStream(1);
327 transport2->OpenStream(1);
328
329 // Tell them both to start (though transport1_ is connected to black_hole).
330 transport1->Start(kTransport1Port, kTransport2Port, kSctpSendBufferSize);
331 transport2->Start(kTransport2Port, kTransport1Port, kSctpSendBufferSize);
332
333 // Switch transport1_ to the normal fake_dtls1_ transport.
334 transport1->SetDtlsTransport(&fake_dtls1);
335
336 // Connect the two fake DTLS transports.
337 bool asymmetric = false;
338 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
339
340 // Make sure we end up able to send data.
341 SendDataResult result;
342 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
343 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
344 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
345 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
346
347 // Setting a null DtlsTransport should work. This could happen when an SCTP
348 // data section is rejected.
349 transport1->SetDtlsTransport(nullptr);
350 }
351
352 // Calling Start twice shouldn't do anything bad, if with the same parameters.
TEST_F(SctpTransportTest,DuplicateStartCallsIgnored)353 TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
354 SetupConnectedTransportsWithTwoStreams();
355 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port,
356 kSctpSendBufferSize));
357
358 // Make sure we can still send/recv data.
359 SendDataResult result;
360 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
361 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
362 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
363 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
364 }
365
366 // Calling Start a second time with a different port should fail.
TEST_F(SctpTransportTest,CallingStartWithDifferentPortFails)367 TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
368 SetupConnectedTransportsWithTwoStreams();
369 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234, kSctpSendBufferSize));
370 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port, kSctpSendBufferSize));
371 }
372
373 // A value of -1 for the local/remote port should be treated as the default
374 // (5000).
TEST_F(SctpTransportTest,NegativeOnePortTreatedAsDefault)375 TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
376 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
377 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
378 SctpFakeDataReceiver recv1;
379 SctpFakeDataReceiver recv2;
380 std::unique_ptr<SctpTransport> transport1(
381 CreateTransport(&fake_dtls1, &recv1));
382 std::unique_ptr<SctpTransport> transport2(
383 CreateTransport(&fake_dtls2, &recv2));
384
385 // Add a stream.
386 transport1->OpenStream(1);
387 transport2->OpenStream(1);
388
389 // Tell them both to start, giving one transport the default port and the
390 // other transport -1.
391 transport1->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
392 transport2->Start(-1, -1, kSctpSendBufferSize);
393
394 // Connect the two fake DTLS transports.
395 bool asymmetric = false;
396 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
397
398 // Make sure we end up able to send data.
399 SendDataResult result;
400 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
401 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
402 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
403 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
404 }
405
TEST_F(SctpTransportTest,OpenStreamWithAlreadyOpenedStreamFails)406 TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
407 FakeDtlsTransport fake_dtls("fake dtls", 0);
408 SctpFakeDataReceiver recv;
409 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
410 EXPECT_TRUE(transport->OpenStream(1));
411 EXPECT_FALSE(transport->OpenStream(1));
412 }
413
TEST_F(SctpTransportTest,ResetStreamWithAlreadyResetStreamFails)414 TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
415 FakeDtlsTransport fake_dtls("fake dtls", 0);
416 SctpFakeDataReceiver recv;
417 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
418 EXPECT_TRUE(transport->OpenStream(1));
419 EXPECT_TRUE(transport->ResetStream(1));
420 EXPECT_FALSE(transport->ResetStream(1));
421 }
422
423 // Test that SignalReadyToSendData is fired after Start has been called and the
424 // DTLS transport is writable.
TEST_F(SctpTransportTest,SignalReadyToSendDataAfterDtlsWritable)425 TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
426 FakeDtlsTransport fake_dtls("fake dtls", 0);
427 SctpFakeDataReceiver recv;
428 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
429 SctpTransportObserver observer(transport.get());
430
431 transport->Start(kSctpDefaultPort, kSctpDefaultPort, kSctpSendBufferSize);
432 fake_dtls.SetWritable(true);
433 EXPECT_TRUE_WAIT(observer.ReadyToSend(), kDefaultTimeout);
434 }
435
436 // Run the below tests using both ordered and unordered mode.
437 class SctpTransportTestWithOrdered
438 : public SctpTransportTest,
439 public ::testing::WithParamInterface<bool> {};
440
441 // Tests that a small message gets buffered and later sent by the SctpTransport
442 // when the sctp library only accepts the message partially.
TEST_P(SctpTransportTestWithOrdered,SendSmallBufferedOutgoingMessage)443 TEST_P(SctpTransportTestWithOrdered, SendSmallBufferedOutgoingMessage) {
444 bool ordered = GetParam();
445 SetupConnectedTransportsWithTwoStreams();
446 // Wait for initial SCTP association to be formed.
447 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
448 // Make the fake transport unwritable so that messages pile up for the SCTP
449 // socket.
450 fake_dtls1()->SetWritable(false);
451 SendDataResult result;
452
453 // Fill almost all of sctp library's send buffer.
454 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
455 std::string(kSctpSendBufferSize - 1, 'a'), &result,
456 ordered));
457
458 std::string buffered_message("hello hello");
459 // SctpTransport accepts this message by buffering part of it.
460 ASSERT_TRUE(
461 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
462 ASSERT_TRUE(transport1()->ReadyToSendData());
463
464 // Sending anything else should block now.
465 ASSERT_FALSE(
466 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
467 ASSERT_EQ(SDR_BLOCK, result);
468 ASSERT_FALSE(transport1()->ReadyToSendData());
469
470 // Make sure the ready-to-send count hasn't changed.
471 EXPECT_EQ(1, transport1_ready_to_send_count());
472 // Make the transport writable again and expect a "SignalReadyToSendData" at
473 // some point after sending the buffered message.
474 fake_dtls1()->SetWritable(true);
475 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
476 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
477 kDefaultTimeout);
478 EXPECT_EQ(2u, receiver2()->num_messages_received());
479 }
480
481 // Tests that a large message gets buffered and later sent by the SctpTransport
482 // when the sctp library only accepts the message partially.
TEST_P(SctpTransportTestWithOrdered,SendLargeBufferedOutgoingMessage)483 TEST_P(SctpTransportTestWithOrdered, SendLargeBufferedOutgoingMessage) {
484 bool ordered = GetParam();
485 SetupConnectedTransportsWithTwoStreams();
486 // Wait for initial SCTP association to be formed.
487 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
488 // Make the fake transport unwritable so that messages pile up for the SCTP
489 // socket.
490 fake_dtls1()->SetWritable(false);
491 SendDataResult result;
492
493 // Fill almost all of sctp library's send buffer.
494 ASSERT_TRUE(SendData(transport1(), /*sid=*/1,
495 std::string(kSctpSendBufferSize / 2, 'a'), &result,
496 ordered));
497
498 std::string buffered_message(kSctpSendBufferSize, 'b');
499 // SctpTransport accepts this message by buffering the second half.
500 ASSERT_TRUE(
501 SendData(transport1(), /*sid=*/1, buffered_message, &result, ordered));
502 ASSERT_TRUE(transport1()->ReadyToSendData());
503
504 // Sending anything else should block now.
505 ASSERT_FALSE(
506 SendData(transport1(), /*sid=*/1, "hello again", &result, ordered));
507 ASSERT_EQ(SDR_BLOCK, result);
508 ASSERT_FALSE(transport1()->ReadyToSendData());
509
510 // Make sure the ready-to-send count hasn't changed.
511 EXPECT_EQ(1, transport1_ready_to_send_count());
512 // Make the transport writable again and expect a "SignalReadyToSendData" at
513 // some point.
514 fake_dtls1()->SetWritable(true);
515 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
516 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
517 kDefaultTimeout);
518 EXPECT_EQ(2u, receiver2()->num_messages_received());
519 }
520
TEST_P(SctpTransportTestWithOrdered,SendData)521 TEST_P(SctpTransportTestWithOrdered, SendData) {
522 bool ordered = GetParam();
523 SetupConnectedTransportsWithTwoStreams();
524
525 SendDataResult result;
526 RTC_LOG(LS_VERBOSE)
527 << "transport1 sending: 'hello?' -----------------------------";
528 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result, ordered));
529 EXPECT_EQ(SDR_SUCCESS, result);
530 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
531 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
532 << ", recv2.last_params.sid="
533 << receiver2()->last_params().sid
534 << ", recv2.last_params.timestamp="
535 << receiver2()->last_params().timestamp
536 << ", recv2.last_params.seq_num="
537 << receiver2()->last_params().seq_num
538 << ", recv2.last_data=" << receiver2()->last_data();
539
540 RTC_LOG(LS_VERBOSE)
541 << "transport2 sending: 'hi transport1' -----------------------------";
542 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result, ordered));
543 EXPECT_EQ(SDR_SUCCESS, result);
544 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
545 kDefaultTimeout);
546 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
547 << ", recv1.last_params.sid="
548 << receiver1()->last_params().sid
549 << ", recv1.last_params.timestamp="
550 << receiver1()->last_params().timestamp
551 << ", recv1.last_params.seq_num="
552 << receiver1()->last_params().seq_num
553 << ", recv1.last_data=" << receiver1()->last_data();
554 }
555
556 // Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
TEST_P(SctpTransportTestWithOrdered,SendDataBlocked)557 TEST_P(SctpTransportTestWithOrdered, SendDataBlocked) {
558 SetupConnectedTransportsWithTwoStreams();
559
560 SendDataResult result;
561 SendDataParams params;
562 params.sid = 1;
563 params.ordered = GetParam();
564
565 std::vector<char> buffer(1024 * 64, 0);
566
567 for (size_t i = 0; i < 100; ++i) {
568 transport1()->SendData(
569 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
570 if (result == SDR_BLOCK)
571 break;
572 }
573
574 EXPECT_EQ(SDR_BLOCK, result);
575 }
576
577 // Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
578 // is fired after it begins to be drained.
TEST_P(SctpTransportTestWithOrdered,SignalReadyToSendDataAfterBlocked)579 TEST_P(SctpTransportTestWithOrdered, SignalReadyToSendDataAfterBlocked) {
580 SetupConnectedTransportsWithTwoStreams();
581 // Wait for initial SCTP association to be formed.
582 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
583 // Make the fake transport unwritable so that messages pile up for the SCTP
584 // socket.
585 fake_dtls1()->SetWritable(false);
586 // Send messages until we get EWOULDBLOCK.
587 static const size_t kMaxMessages = 1024;
588 SendDataParams params;
589 params.sid = 1;
590 params.ordered = GetParam();
591 rtc::CopyOnWriteBuffer buf(1024);
592 memset(buf.data<uint8_t>(), 0, 1024);
593 SendDataResult result;
594 size_t message_count = 0;
595 for (; message_count < kMaxMessages; ++message_count) {
596 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
597 break;
598 }
599 }
600 ASSERT_NE(kMaxMessages, message_count)
601 << "Sent max number of messages without getting SDR_BLOCK?";
602 // Make sure the ready-to-send count hasn't changed.
603 EXPECT_EQ(1, transport1_ready_to_send_count());
604 // Make the transport writable again and expect a "SignalReadyToSendData" at
605 // some point.
606 fake_dtls1()->SetWritable(true);
607 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
608 EXPECT_EQ_WAIT(message_count, receiver2()->num_messages_received(),
609 kDefaultTimeout);
610 }
611
612 INSTANTIATE_TEST_SUITE_P(SctpTransportTest,
613 SctpTransportTestWithOrdered,
614 ::testing::Bool());
615
616 // This is a regression test that fails with earlier versions of SCTP in
617 // unordered mode. See bugs.webrtc.org/10939.
TEST_F(SctpTransportTest,SendsLargeDataBufferedBySctpLib)618 TEST_F(SctpTransportTest, SendsLargeDataBufferedBySctpLib) {
619 SetupConnectedTransportsWithTwoStreams();
620 // Wait for initial SCTP association to be formed.
621 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
622 // Make the fake transport unwritable so that messages pile up for the SCTP
623 // socket.
624 fake_dtls1()->SetWritable(false);
625
626 SendDataResult result;
627 std::string buffered_message(kSctpSendBufferSize - 1, 'a');
628 ASSERT_TRUE(SendData(transport1(), 1, buffered_message, &result, false));
629
630 fake_dtls1()->SetWritable(true);
631 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
632 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, buffered_message),
633 kDefaultTimeout);
634 }
635
636 // Trying to send data for a nonexistent stream should fail.
TEST_F(SctpTransportTest,SendDataWithNonexistentStreamFails)637 TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
638 SetupConnectedTransportsWithTwoStreams();
639 SendDataResult result;
640 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
641 EXPECT_EQ(SDR_ERROR, result);
642 }
643
TEST_F(SctpTransportTest,SendDataHighPorts)644 TEST_F(SctpTransportTest, SendDataHighPorts) {
645 SetupConnectedTransportsWithTwoStreams(32768, 32769);
646
647 SendDataResult result;
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 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
653 EXPECT_EQ(SDR_SUCCESS, result);
654 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
655 kDefaultTimeout);
656 }
657
TEST_F(SctpTransportTest,ClosesRemoteStream)658 TEST_F(SctpTransportTest, ClosesRemoteStream) {
659 SetupConnectedTransportsWithTwoStreams();
660 SctpTransportObserver transport1_observer(transport1());
661 SctpTransportObserver transport2_observer(transport2());
662
663 SendDataResult result;
664 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
665 EXPECT_EQ(SDR_SUCCESS, result);
666 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
667 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
668 EXPECT_EQ(SDR_SUCCESS, result);
669 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
670 kDefaultTimeout);
671
672 // Close stream 1 on transport 1. Transport 2 should notify us.
673 transport1()->ResetStream(1);
674 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
675 }
TEST_F(SctpTransportTest,ClosesRemoteStreamWithNoData)676 TEST_F(SctpTransportTest, ClosesRemoteStreamWithNoData) {
677 SetupConnectedTransportsWithTwoStreams();
678 SctpTransportObserver transport1_observer(transport1());
679 SctpTransportObserver transport2_observer(transport2());
680
681 // Close stream 1 on transport 1. Transport 2 should notify us.
682 transport1()->ResetStream(1);
683 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
684 }
685
TEST_F(SctpTransportTest,ClosesTwoRemoteStreams)686 TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
687 SetupConnectedTransportsWithTwoStreams();
688 AddStream(3);
689 SctpTransportObserver transport1_observer(transport1());
690 SctpTransportObserver transport2_observer(transport2());
691
692 SendDataResult result;
693 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
694 EXPECT_EQ(SDR_SUCCESS, result);
695 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
696 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
697 EXPECT_EQ(SDR_SUCCESS, result);
698 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
699 kDefaultTimeout);
700
701 // Close two streams on one side.
702 transport2()->ResetStream(2);
703 transport2()->ResetStream(3);
704 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(2), kDefaultTimeout);
705 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(3), kDefaultTimeout);
706 }
707
TEST_F(SctpTransportTest,ClosesStreamsOnBothSides)708 TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
709 SetupConnectedTransportsWithTwoStreams();
710 AddStream(3);
711 AddStream(4);
712 SctpTransportObserver transport1_observer(transport1());
713 SctpTransportObserver transport2_observer(transport2());
714
715 SendDataResult result;
716 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
717 EXPECT_EQ(SDR_SUCCESS, result);
718 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
719 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
720 EXPECT_EQ(SDR_SUCCESS, result);
721 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
722 kDefaultTimeout);
723
724 // Close one stream on transport1(), while closing three streams on
725 // transport2(). They will conflict (only one side can close anything at a
726 // time, apparently). Test the resolution of the conflict.
727 transport1()->ResetStream(1);
728
729 transport2()->ResetStream(2);
730 transport2()->ResetStream(3);
731 transport2()->ResetStream(4);
732 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
733 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(2), kDefaultTimeout);
734 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(3), kDefaultTimeout);
735 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(4), kDefaultTimeout);
736 }
737
TEST_F(SctpTransportTest,RefusesHighNumberedTransports)738 TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
739 SetupConnectedTransportsWithTwoStreams();
740 EXPECT_TRUE(AddStream(kMaxSctpSid));
741 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
742 }
743
TEST_F(SctpTransportTest,ReusesAStream)744 TEST_F(SctpTransportTest, ReusesAStream) {
745 // Shut down transport 1, then open it up again for reuse.
746 SetupConnectedTransportsWithTwoStreams();
747 SendDataResult result;
748 SctpTransportObserver transport2_observer(transport2());
749
750 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
751 EXPECT_EQ(SDR_SUCCESS, result);
752 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
753
754 transport1()->ResetStream(1);
755 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
756 // Transport 1 is gone now.
757
758 // Create a new transport 1.
759 AddStream(1);
760 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
761 EXPECT_EQ(SDR_SUCCESS, result);
762 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
763 transport1()->ResetStream(1);
764 EXPECT_EQ_WAIT(2, transport2_observer.StreamCloseCount(1), kDefaultTimeout);
765 }
766
TEST_F(SctpTransportTest,RejectsTooLargeMessageSize)767 TEST_F(SctpTransportTest, RejectsTooLargeMessageSize) {
768 FakeDtlsTransport fake_dtls("fake dtls", 0);
769 SctpFakeDataReceiver recv;
770 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
771
772 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort,
773 kSctpSendBufferSize + 1));
774 }
775
TEST_F(SctpTransportTest,RejectsTooSmallMessageSize)776 TEST_F(SctpTransportTest, RejectsTooSmallMessageSize) {
777 FakeDtlsTransport fake_dtls("fake dtls", 0);
778 SctpFakeDataReceiver recv;
779 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
780
781 EXPECT_FALSE(transport->Start(kSctpDefaultPort, kSctpDefaultPort, 0));
782 }
783
TEST_F(SctpTransportTest,RejectsSendTooLargeMessages)784 TEST_F(SctpTransportTest, RejectsSendTooLargeMessages) {
785 SetupConnectedTransportsWithTwoStreams();
786 // Use "Start" to reduce the max message size
787 transport1()->Start(kTransport1Port, kTransport2Port, 10);
788 EXPECT_EQ(10, transport1()->max_message_size());
789 const char eleven_characters[] = "12345678901";
790 SendDataResult result;
791 EXPECT_FALSE(SendData(transport1(), 1, eleven_characters, &result));
792 }
793
794 } // namespace cricket
795