blob: 86f45531d82cb13bfa3a182bd7d1b11e24217c11 [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
11#include <errno.h>
12#include <stdarg.h>
13#include <stdio.h>
14
15#include <memory>
16#include <string>
17#include <vector>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "media/sctp/sctptransport.h"
20#include "p2p/base/fakedtlstransport.h"
21#include "rtc_base/bind.h"
22#include "rtc_base/copyonwritebuffer.h"
23#include "rtc_base/criticalsection.h"
24#include "rtc_base/gunit.h"
25#include "rtc_base/helpers.h"
26#include "rtc_base/ssladapter.h"
27#include "rtc_base/thread.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;
34}
35
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) {
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070080 return std::count(closed_streams_.begin(), closed_streams_.end(), stream);
deadbeef953c2ce2017-01-09 14:53:41 -080081 }
82
83 bool WasStreamClosed(int stream) {
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070084 return std::find(closed_streams_.begin(), closed_streams_.end(), stream) !=
85 closed_streams_.end();
deadbeef953c2ce2017-01-09 14:53:41 -080086 }
87
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070088 bool ReadyToSend() { return ready_to_send_; }
89
deadbeef953c2ce2017-01-09 14:53:41 -080090 private:
Taylor Brandstettercdd05f02018-05-31 13:23:32 -070091 void OnClosingProcedureComplete(int stream) {
92 closed_streams_.push_back(stream);
93 }
94 void OnReadyToSend() { ready_to_send_ = true; }
95
96 std::vector<int> closed_streams_;
97 bool ready_to_send_ = false;
deadbeef953c2ce2017-01-09 14:53:41 -080098};
99
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700100// Helper class used to immediately attempt to reopen a stream as soon as it's
101// been closed.
deadbeef953c2ce2017-01-09 14:53:41 -0800102class SignalTransportClosedReopener : public sigslot::has_slots<> {
103 public:
104 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
105 : transport_(transport), peer_(peer) {}
106
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700107 int StreamCloseCount(int stream) {
108 return std::count(streams_.begin(), streams_.end(), stream);
109 }
110
111 private:
deadbeef953c2ce2017-01-09 14:53:41 -0800112 void OnStreamClosed(int stream) {
113 transport_->OpenStream(stream);
114 peer_->OpenStream(stream);
115 streams_.push_back(stream);
116 }
117
deadbeef953c2ce2017-01-09 14:53:41 -0800118 SctpTransport* transport_;
119 SctpTransport* peer_;
120 std::vector<int> streams_;
121};
122
123// SCTP Data Engine testing framework.
124class SctpTransportTest : public testing::Test, public sigslot::has_slots<> {
125 protected:
126 // usrsctp uses the NSS random number generator on non-Android platforms,
127 // so we need to initialize SSL.
128 static void SetUpTestCase() {}
129
130 void SetupConnectedTransportsWithTwoStreams() {
jbauch46d24572017-03-10 16:20:04 -0800131 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
132 }
133
134 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
zhihuangb2cdd932017-01-19 16:54:25 -0800135 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
136 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
deadbeef953c2ce2017-01-09 14:53:41 -0800137 recv1_.reset(new SctpFakeDataReceiver());
138 recv2_.reset(new SctpFakeDataReceiver());
139 transport1_.reset(CreateTransport(fake_dtls1_.get(), recv1_.get()));
140 transport1_->set_debug_name_for_testing("transport1");
141 transport1_->SignalReadyToSendData.connect(
142 this, &SctpTransportTest::OnChan1ReadyToSend);
143 transport2_.reset(CreateTransport(fake_dtls2_.get(), recv2_.get()));
144 transport2_->set_debug_name_for_testing("transport2");
145 transport2_->SignalReadyToSendData.connect(
146 this, &SctpTransportTest::OnChan2ReadyToSend);
147 // Setup two connected transports ready to send and receive.
148 bool asymmetric = false;
149 fake_dtls1_->SetDestination(fake_dtls2_.get(), asymmetric);
150
Mirko Bonadei675513b2017-11-09 11:09:25 +0100151 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
deadbeef953c2ce2017-01-09 14:53:41 -0800152 AddStream(1);
153 AddStream(2);
154
Mirko Bonadei675513b2017-11-09 11:09:25 +0100155 RTC_LOG(LS_VERBOSE)
156 << "Connect the transports -----------------------------";
deadbeef953c2ce2017-01-09 14:53:41 -0800157 // Both transports need to have started (with matching ports) for an
158 // association to be formed.
jbauch46d24572017-03-10 16:20:04 -0800159 transport1_->Start(port1, port2);
160 transport2_->Start(port2, port1);
deadbeef953c2ce2017-01-09 14:53:41 -0800161 }
162
163 bool AddStream(int sid) {
164 bool ret = true;
165 ret = ret && transport1_->OpenStream(sid);
166 ret = ret && transport2_->OpenStream(sid);
167 return ret;
168 }
169
zhihuangb2cdd932017-01-19 16:54:25 -0800170 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
deadbeef953c2ce2017-01-09 14:53:41 -0800171 SctpFakeDataReceiver* recv) {
172 SctpTransport* transport =
173 new SctpTransport(rtc::Thread::Current(), fake_dtls);
174 // When data is received, pass it to the SctpFakeDataReceiver.
175 transport->SignalDataReceived.connect(
176 recv, &SctpFakeDataReceiver::OnDataReceived);
177 return transport;
178 }
179
180 bool SendData(SctpTransport* chan,
181 int sid,
182 const std::string& msg,
183 SendDataResult* result) {
184 SendDataParams params;
185 params.sid = sid;
186
187 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
188 result);
189 }
190
191 bool ReceivedData(const SctpFakeDataReceiver* recv,
192 int sid,
193 const std::string& msg) {
194 return (recv->received() && recv->last_params().sid == sid &&
195 recv->last_data() == msg);
196 }
197
198 bool ProcessMessagesUntilIdle() {
199 rtc::Thread* thread = rtc::Thread::Current();
200 while (!thread->empty()) {
201 rtc::Message msg;
202 if (thread->Get(&msg, rtc::Thread::kForever)) {
203 thread->Dispatch(&msg);
204 }
205 }
206 return !thread->IsQuitting();
207 }
208
209 SctpTransport* transport1() { return transport1_.get(); }
210 SctpTransport* transport2() { return transport2_.get(); }
211 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
212 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
zhihuangb2cdd932017-01-19 16:54:25 -0800213 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
214 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
deadbeef953c2ce2017-01-09 14:53:41 -0800215
216 int transport1_ready_to_send_count() {
217 return transport1_ready_to_send_count_;
218 }
219 int transport2_ready_to_send_count() {
220 return transport2_ready_to_send_count_;
221 }
222
223 private:
zhihuangb2cdd932017-01-19 16:54:25 -0800224 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
225 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
deadbeef953c2ce2017-01-09 14:53:41 -0800226 std::unique_ptr<SctpFakeDataReceiver> recv1_;
227 std::unique_ptr<SctpFakeDataReceiver> recv2_;
228 std::unique_ptr<SctpTransport> transport1_;
229 std::unique_ptr<SctpTransport> transport2_;
230
231 int transport1_ready_to_send_count_ = 0;
232 int transport2_ready_to_send_count_ = 0;
233
234 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
235 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
236};
237
238// Test that data can be sent end-to-end when an SCTP transport starts with one
Zhi Huang644fde42018-04-02 19:16:26 -0700239// transport (which is unwritable), and then switches to another transport. A
240// common scenario due to how BUNDLE works.
241TEST_F(SctpTransportTest, SwitchDtlsTransport) {
zhihuangb2cdd932017-01-19 16:54:25 -0800242 FakeDtlsTransport black_hole("black hole", 0);
243 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
244 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800245 SctpFakeDataReceiver recv1;
246 SctpFakeDataReceiver recv2;
247
Zhi Huang644fde42018-04-02 19:16:26 -0700248 // Construct transport1 with the "black hole" transport.
deadbeef953c2ce2017-01-09 14:53:41 -0800249 std::unique_ptr<SctpTransport> transport1(
250 CreateTransport(&black_hole, &recv1));
251 std::unique_ptr<SctpTransport> transport2(
252 CreateTransport(&fake_dtls2, &recv2));
253
254 // Add a stream.
255 transport1->OpenStream(1);
256 transport2->OpenStream(1);
257
258 // Tell them both to start (though transport1_ is connected to black_hole).
259 transport1->Start(kTransport1Port, kTransport2Port);
260 transport2->Start(kTransport2Port, kTransport1Port);
261
Zhi Huang644fde42018-04-02 19:16:26 -0700262 // Switch transport1_ to the normal fake_dtls1_ transport.
263 transport1->SetDtlsTransport(&fake_dtls1);
deadbeef953c2ce2017-01-09 14:53:41 -0800264
Zhi Huang644fde42018-04-02 19:16:26 -0700265 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800266 bool asymmetric = false;
267 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
268
269 // Make sure we end up able to send data.
270 SendDataResult result;
271 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
272 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
273 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
274 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
Zhi Huang644fde42018-04-02 19:16:26 -0700275
276 // Setting a null DtlsTransport should work. This could happen when an SCTP
277 // data section is rejected.
278 transport1->SetDtlsTransport(nullptr);
deadbeef953c2ce2017-01-09 14:53:41 -0800279}
280
281// Calling Start twice shouldn't do anything bad, if with the same parameters.
282TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
283 SetupConnectedTransportsWithTwoStreams();
284 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port));
285
286 // Make sure we can still send/recv data.
287 SendDataResult result;
288 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
289 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
290 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
291 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
292}
293
294// Calling Start a second time with a different port should fail.
295TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
296 SetupConnectedTransportsWithTwoStreams();
297 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234));
298 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port));
299}
300
301// A value of -1 for the local/remote port should be treated as the default
302// (5000).
303TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
zhihuangb2cdd932017-01-19 16:54:25 -0800304 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
305 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800306 SctpFakeDataReceiver recv1;
307 SctpFakeDataReceiver recv2;
308 std::unique_ptr<SctpTransport> transport1(
309 CreateTransport(&fake_dtls1, &recv1));
310 std::unique_ptr<SctpTransport> transport2(
311 CreateTransport(&fake_dtls2, &recv2));
312
313 // Add a stream.
314 transport1->OpenStream(1);
315 transport2->OpenStream(1);
316
317 // Tell them both to start, giving one transport the default port and the
318 // other transport -1.
319 transport1->Start(kSctpDefaultPort, kSctpDefaultPort);
320 transport2->Start(-1, -1);
321
Zhi Huang644fde42018-04-02 19:16:26 -0700322 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800323 bool asymmetric = false;
324 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
325
326 // Make sure we end up able to send data.
327 SendDataResult result;
328 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
329 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
330 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
331 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
332}
333
334TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800335 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800336 SctpFakeDataReceiver recv;
337 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
338 EXPECT_TRUE(transport->OpenStream(1));
339 EXPECT_FALSE(transport->OpenStream(1));
340}
341
342TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800343 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800344 SctpFakeDataReceiver recv;
345 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
346 EXPECT_TRUE(transport->OpenStream(1));
347 EXPECT_TRUE(transport->ResetStream(1));
348 EXPECT_FALSE(transport->ResetStream(1));
349}
350
351// Test that SignalReadyToSendData is fired after Start has been called and the
Zhi Huang644fde42018-04-02 19:16:26 -0700352// DTLS transport is writable.
deadbeef953c2ce2017-01-09 14:53:41 -0800353TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
zhihuangb2cdd932017-01-19 16:54:25 -0800354 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800355 SctpFakeDataReceiver recv;
356 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700357 SctpTransportObserver observer(transport.get());
deadbeef953c2ce2017-01-09 14:53:41 -0800358
359 transport->Start(kSctpDefaultPort, kSctpDefaultPort);
360 fake_dtls.SetWritable(true);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700361 EXPECT_TRUE_WAIT(observer.ReadyToSend(), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800362}
363
364// Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
365// is fired after it begins to be drained.
366TEST_F(SctpTransportTest, SignalReadyToSendDataAfterBlocked) {
367 SetupConnectedTransportsWithTwoStreams();
368 // Wait for initial SCTP association to be formed.
369 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
370 // Make the fake transport unwritable so that messages pile up for the SCTP
371 // socket.
372 fake_dtls1()->SetWritable(false);
373 // Send messages until we get EWOULDBLOCK.
374 static const int kMaxMessages = 1024;
375 SendDataParams params;
376 params.sid = 1;
377 rtc::CopyOnWriteBuffer buf(1024);
378 memset(buf.data<uint8_t>(), 0, 1024);
379 SendDataResult result;
380 int message_count;
381 for (message_count = 0; message_count < kMaxMessages; ++message_count) {
382 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
383 break;
384 }
385 }
386 ASSERT_NE(kMaxMessages, message_count)
387 << "Sent max number of messages without getting SDR_BLOCK?";
388 // Make sure the ready-to-send count hasn't changed.
389 EXPECT_EQ(1, transport1_ready_to_send_count());
390 // Make the transport writable again and expect a "SignalReadyToSendData" at
391 // some point.
392 fake_dtls1()->SetWritable(true);
393 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
394}
395
396TEST_F(SctpTransportTest, SendData) {
397 SetupConnectedTransportsWithTwoStreams();
398
399 SendDataResult result;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100400 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800401 << "transport1 sending: 'hello?' -----------------------------";
402 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
403 EXPECT_EQ(SDR_SUCCESS, result);
404 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100405 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
406 << ", recv2.last_params.sid="
407 << receiver2()->last_params().sid
408 << ", recv2.last_params.timestamp="
409 << receiver2()->last_params().timestamp
410 << ", recv2.last_params.seq_num="
411 << receiver2()->last_params().seq_num
412 << ", recv2.last_data=" << receiver2()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800413
Mirko Bonadei675513b2017-11-09 11:09:25 +0100414 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800415 << "transport2 sending: 'hi transport1' -----------------------------";
416 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
417 EXPECT_EQ(SDR_SUCCESS, result);
418 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
419 kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100420 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
421 << ", recv1.last_params.sid="
422 << receiver1()->last_params().sid
423 << ", recv1.last_params.timestamp="
424 << receiver1()->last_params().timestamp
425 << ", recv1.last_params.seq_num="
426 << receiver1()->last_params().seq_num
427 << ", recv1.last_data=" << receiver1()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800428}
429
430// Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
431TEST_F(SctpTransportTest, SendDataBlocked) {
432 SetupConnectedTransportsWithTwoStreams();
433
434 SendDataResult result;
435 SendDataParams params;
436 params.sid = 1;
437
438 std::vector<char> buffer(1024 * 64, 0);
439
440 for (size_t i = 0; i < 100; ++i) {
441 transport1()->SendData(
442 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
443 if (result == SDR_BLOCK)
444 break;
445 }
446
447 EXPECT_EQ(SDR_BLOCK, result);
448}
449
450// Trying to send data for a nonexistent stream should fail.
451TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
452 SetupConnectedTransportsWithTwoStreams();
453 SendDataResult result;
454 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
455 EXPECT_EQ(SDR_ERROR, result);
456}
457
jbauch46d24572017-03-10 16:20:04 -0800458TEST_F(SctpTransportTest, SendDataHighPorts) {
459 SetupConnectedTransportsWithTwoStreams(32768, 32769);
460
461 SendDataResult result;
462 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
463 EXPECT_EQ(SDR_SUCCESS, result);
464 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
465
466 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
467 EXPECT_EQ(SDR_SUCCESS, result);
468 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
469 kDefaultTimeout);
470}
471
deadbeef953c2ce2017-01-09 14:53:41 -0800472TEST_F(SctpTransportTest, ClosesRemoteStream) {
473 SetupConnectedTransportsWithTwoStreams();
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700474 SctpTransportObserver transport1_observer(transport1());
475 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800476
477 SendDataResult result;
478 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
479 EXPECT_EQ(SDR_SUCCESS, result);
480 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
481 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
482 EXPECT_EQ(SDR_SUCCESS, result);
483 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
484 kDefaultTimeout);
485
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700486 // Close stream 1 on transport 1. Transport 2 should notify us.
deadbeef953c2ce2017-01-09 14:53:41 -0800487 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700488 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800489}
490
491TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
492 SetupConnectedTransportsWithTwoStreams();
493 AddStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700494 SctpTransportObserver transport1_observer(transport1());
495 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800496
497 SendDataResult result;
498 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
499 EXPECT_EQ(SDR_SUCCESS, result);
500 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
501 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
502 EXPECT_EQ(SDR_SUCCESS, result);
503 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
504 kDefaultTimeout);
505
506 // Close two streams on one side.
507 transport2()->ResetStream(2);
508 transport2()->ResetStream(3);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700509 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(2), kDefaultTimeout);
510 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(3), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800511}
512
513TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
514 SetupConnectedTransportsWithTwoStreams();
515 AddStream(3);
516 AddStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700517 SctpTransportObserver transport1_observer(transport1());
518 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800519
520 SendDataResult result;
521 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
522 EXPECT_EQ(SDR_SUCCESS, result);
523 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
524 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
525 EXPECT_EQ(SDR_SUCCESS, result);
526 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
527 kDefaultTimeout);
528
529 // Close one stream on transport1(), while closing three streams on
530 // transport2(). They will conflict (only one side can close anything at a
531 // time, apparently). Test the resolution of the conflict.
532 transport1()->ResetStream(1);
533
534 transport2()->ResetStream(2);
535 transport2()->ResetStream(3);
536 transport2()->ResetStream(4);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700537 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
538 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(2), kDefaultTimeout);
539 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(3), kDefaultTimeout);
540 EXPECT_TRUE_WAIT(transport1_observer.WasStreamClosed(4), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800541}
542
543TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
544 SetupConnectedTransportsWithTwoStreams();
545 EXPECT_TRUE(AddStream(kMaxSctpSid));
546 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
547}
548
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700549TEST_F(SctpTransportTest, ReusesAStream) {
deadbeef953c2ce2017-01-09 14:53:41 -0800550 // Shut down transport 1, then open it up again for reuse.
551 SetupConnectedTransportsWithTwoStreams();
552 SendDataResult result;
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700553 SctpTransportObserver transport2_observer(transport2());
deadbeef953c2ce2017-01-09 14:53:41 -0800554
555 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
556 EXPECT_EQ(SDR_SUCCESS, result);
557 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
558
559 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700560 EXPECT_TRUE_WAIT(transport2_observer.WasStreamClosed(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800561 // Transport 1 is gone now.
562
563 // Create a new transport 1.
564 AddStream(1);
565 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
566 EXPECT_EQ(SDR_SUCCESS, result);
567 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
568 transport1()->ResetStream(1);
Taylor Brandstettercdd05f02018-05-31 13:23:32 -0700569 EXPECT_EQ_WAIT(2, transport2_observer.StreamCloseCount(1), kDefaultTimeout);
deadbeef953c2ce2017-01-09 14:53:41 -0800570}
571
572} // namespace cricket