• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&notification, 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                    &notification, 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