blob: 9864d7af0f8c3805c6c3416ee30e1473d9798cf5 [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
70class SignalReadyToSendObserver : public sigslot::has_slots<> {
71 public:
72 SignalReadyToSendObserver() : signaled_(false) {}
73
74 void OnSignaled() { signaled_ = true; }
75
76 bool IsSignaled() { return signaled_; }
77
78 private:
79 bool signaled_;
80};
81
82class SignalTransportClosedObserver : public sigslot::has_slots<> {
83 public:
84 SignalTransportClosedObserver() {}
85 void BindSelf(SctpTransport* transport) {
86 transport->SignalStreamClosedRemotely.connect(
87 this, &SignalTransportClosedObserver::OnStreamClosed);
88 }
89 void OnStreamClosed(int stream) { streams_.push_back(stream); }
90
91 int StreamCloseCount(int stream) {
92 return std::count(streams_.begin(), streams_.end(), stream);
93 }
94
95 bool WasStreamClosed(int stream) {
96 return std::find(streams_.begin(), streams_.end(), stream) !=
97 streams_.end();
98 }
99
100 private:
101 std::vector<int> streams_;
102};
103
104class SignalTransportClosedReopener : public sigslot::has_slots<> {
105 public:
106 SignalTransportClosedReopener(SctpTransport* transport, SctpTransport* peer)
107 : transport_(transport), peer_(peer) {}
108
109 void OnStreamClosed(int stream) {
110 transport_->OpenStream(stream);
111 peer_->OpenStream(stream);
112 streams_.push_back(stream);
113 }
114
115 int StreamCloseCount(int stream) {
116 return std::count(streams_.begin(), streams_.end(), stream);
117 }
118
119 private:
120 SctpTransport* transport_;
121 SctpTransport* peer_;
122 std::vector<int> streams_;
123};
124
125// SCTP Data Engine testing framework.
126class 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.
130 static void SetUpTestCase() {}
131
132 void SetupConnectedTransportsWithTwoStreams() {
jbauch46d24572017-03-10 16:20:04 -0800133 SetupConnectedTransportsWithTwoStreams(kTransport1Port, kTransport2Port);
134 }
135
136 void SetupConnectedTransportsWithTwoStreams(int port1, int port2) {
zhihuangb2cdd932017-01-19 16:54:25 -0800137 fake_dtls1_.reset(new FakeDtlsTransport("fake dtls 1", 0));
138 fake_dtls2_.reset(new FakeDtlsTransport("fake dtls 2", 0));
deadbeef953c2ce2017-01-09 14:53:41 -0800139 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
Mirko Bonadei675513b2017-11-09 11:09:25 +0100153 RTC_LOG(LS_VERBOSE) << "Transport setup ----------------------------- ";
deadbeef953c2ce2017-01-09 14:53:41 -0800154 AddStream(1);
155 AddStream(2);
156
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_VERBOSE)
158 << "Connect the transports -----------------------------";
deadbeef953c2ce2017-01-09 14:53:41 -0800159 // Both transports need to have started (with matching ports) for an
160 // association to be formed.
jbauch46d24572017-03-10 16:20:04 -0800161 transport1_->Start(port1, port2);
162 transport2_->Start(port2, port1);
deadbeef953c2ce2017-01-09 14:53:41 -0800163 }
164
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
zhihuangb2cdd932017-01-19 16:54:25 -0800172 SctpTransport* CreateTransport(FakeDtlsTransport* fake_dtls,
deadbeef953c2ce2017-01-09 14:53:41 -0800173 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
182 bool SendData(SctpTransport* chan,
183 int sid,
184 const std::string& msg,
185 SendDataResult* result) {
186 SendDataParams params;
187 params.sid = sid;
188
189 return chan->SendData(params, rtc::CopyOnWriteBuffer(&msg[0], msg.length()),
190 result);
191 }
192
193 bool ReceivedData(const SctpFakeDataReceiver* recv,
194 int sid,
195 const std::string& msg) {
196 return (recv->received() && recv->last_params().sid == sid &&
197 recv->last_data() == msg);
198 }
199
200 bool ProcessMessagesUntilIdle() {
201 rtc::Thread* thread = rtc::Thread::Current();
202 while (!thread->empty()) {
203 rtc::Message msg;
204 if (thread->Get(&msg, rtc::Thread::kForever)) {
205 thread->Dispatch(&msg);
206 }
207 }
208 return !thread->IsQuitting();
209 }
210
211 SctpTransport* transport1() { return transport1_.get(); }
212 SctpTransport* transport2() { return transport2_.get(); }
213 SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
214 SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
zhihuangb2cdd932017-01-19 16:54:25 -0800215 FakeDtlsTransport* fake_dtls1() { return fake_dtls1_.get(); }
216 FakeDtlsTransport* fake_dtls2() { return fake_dtls2_.get(); }
deadbeef953c2ce2017-01-09 14:53:41 -0800217
218 int transport1_ready_to_send_count() {
219 return transport1_ready_to_send_count_;
220 }
221 int transport2_ready_to_send_count() {
222 return transport2_ready_to_send_count_;
223 }
224
225 private:
zhihuangb2cdd932017-01-19 16:54:25 -0800226 std::unique_ptr<FakeDtlsTransport> fake_dtls1_;
227 std::unique_ptr<FakeDtlsTransport> fake_dtls2_;
deadbeef953c2ce2017-01-09 14:53:41 -0800228 std::unique_ptr<SctpFakeDataReceiver> recv1_;
229 std::unique_ptr<SctpFakeDataReceiver> recv2_;
230 std::unique_ptr<SctpTransport> transport1_;
231 std::unique_ptr<SctpTransport> transport2_;
232
233 int transport1_ready_to_send_count_ = 0;
234 int transport2_ready_to_send_count_ = 0;
235
236 void OnChan1ReadyToSend() { ++transport1_ready_to_send_count_; }
237 void OnChan2ReadyToSend() { ++transport2_ready_to_send_count_; }
238};
239
240// Test that data can be sent end-to-end when an SCTP transport starts with one
Zhi Huang644fde42018-04-02 19:16:26 -0700241// transport (which is unwritable), and then switches to another transport. A
242// common scenario due to how BUNDLE works.
243TEST_F(SctpTransportTest, SwitchDtlsTransport) {
zhihuangb2cdd932017-01-19 16:54:25 -0800244 FakeDtlsTransport black_hole("black hole", 0);
245 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
246 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800247 SctpFakeDataReceiver recv1;
248 SctpFakeDataReceiver recv2;
249
Zhi Huang644fde42018-04-02 19:16:26 -0700250 // Construct transport1 with the "black hole" transport.
deadbeef953c2ce2017-01-09 14:53:41 -0800251 std::unique_ptr<SctpTransport> transport1(
252 CreateTransport(&black_hole, &recv1));
253 std::unique_ptr<SctpTransport> transport2(
254 CreateTransport(&fake_dtls2, &recv2));
255
256 // Add a stream.
257 transport1->OpenStream(1);
258 transport2->OpenStream(1);
259
260 // Tell them both to start (though transport1_ is connected to black_hole).
261 transport1->Start(kTransport1Port, kTransport2Port);
262 transport2->Start(kTransport2Port, kTransport1Port);
263
Zhi Huang644fde42018-04-02 19:16:26 -0700264 // Switch transport1_ to the normal fake_dtls1_ transport.
265 transport1->SetDtlsTransport(&fake_dtls1);
deadbeef953c2ce2017-01-09 14:53:41 -0800266
Zhi Huang644fde42018-04-02 19:16:26 -0700267 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800268 bool asymmetric = false;
269 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
270
271 // Make sure we end up able to send data.
272 SendDataResult result;
273 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
274 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
275 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
276 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
Zhi Huang644fde42018-04-02 19:16:26 -0700277
278 // Setting a null DtlsTransport should work. This could happen when an SCTP
279 // data section is rejected.
280 transport1->SetDtlsTransport(nullptr);
deadbeef953c2ce2017-01-09 14:53:41 -0800281}
282
283// Calling Start twice shouldn't do anything bad, if with the same parameters.
284TEST_F(SctpTransportTest, DuplicateStartCallsIgnored) {
285 SetupConnectedTransportsWithTwoStreams();
286 EXPECT_TRUE(transport1()->Start(kTransport1Port, kTransport2Port));
287
288 // Make sure we can still send/recv data.
289 SendDataResult result;
290 ASSERT_TRUE(SendData(transport1(), 1, "foo", &result));
291 ASSERT_TRUE(SendData(transport2(), 1, "bar", &result));
292 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "foo"), kDefaultTimeout);
293 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 1, "bar"), kDefaultTimeout);
294}
295
296// Calling Start a second time with a different port should fail.
297TEST_F(SctpTransportTest, CallingStartWithDifferentPortFails) {
298 SetupConnectedTransportsWithTwoStreams();
299 EXPECT_FALSE(transport1()->Start(kTransport1Port, 1234));
300 EXPECT_FALSE(transport1()->Start(1234, kTransport2Port));
301}
302
303// A value of -1 for the local/remote port should be treated as the default
304// (5000).
305TEST_F(SctpTransportTest, NegativeOnePortTreatedAsDefault) {
zhihuangb2cdd932017-01-19 16:54:25 -0800306 FakeDtlsTransport fake_dtls1("fake dtls 1", 0);
307 FakeDtlsTransport fake_dtls2("fake dtls 2", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800308 SctpFakeDataReceiver recv1;
309 SctpFakeDataReceiver recv2;
310 std::unique_ptr<SctpTransport> transport1(
311 CreateTransport(&fake_dtls1, &recv1));
312 std::unique_ptr<SctpTransport> transport2(
313 CreateTransport(&fake_dtls2, &recv2));
314
315 // Add a stream.
316 transport1->OpenStream(1);
317 transport2->OpenStream(1);
318
319 // Tell them both to start, giving one transport the default port and the
320 // other transport -1.
321 transport1->Start(kSctpDefaultPort, kSctpDefaultPort);
322 transport2->Start(-1, -1);
323
Zhi Huang644fde42018-04-02 19:16:26 -0700324 // Connect the two fake DTLS transports.
deadbeef953c2ce2017-01-09 14:53:41 -0800325 bool asymmetric = false;
326 fake_dtls1.SetDestination(&fake_dtls2, asymmetric);
327
328 // Make sure we end up able to send data.
329 SendDataResult result;
330 ASSERT_TRUE(SendData(transport1.get(), 1, "foo", &result));
331 ASSERT_TRUE(SendData(transport2.get(), 1, "bar", &result));
332 EXPECT_TRUE_WAIT(ReceivedData(&recv2, 1, "foo"), kDefaultTimeout);
333 EXPECT_TRUE_WAIT(ReceivedData(&recv1, 1, "bar"), kDefaultTimeout);
334}
335
336TEST_F(SctpTransportTest, OpenStreamWithAlreadyOpenedStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800337 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800338 SctpFakeDataReceiver recv;
339 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
340 EXPECT_TRUE(transport->OpenStream(1));
341 EXPECT_FALSE(transport->OpenStream(1));
342}
343
344TEST_F(SctpTransportTest, ResetStreamWithAlreadyResetStreamFails) {
zhihuangb2cdd932017-01-19 16:54:25 -0800345 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800346 SctpFakeDataReceiver recv;
347 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
348 EXPECT_TRUE(transport->OpenStream(1));
349 EXPECT_TRUE(transport->ResetStream(1));
350 EXPECT_FALSE(transport->ResetStream(1));
351}
352
353// Test that SignalReadyToSendData is fired after Start has been called and the
Zhi Huang644fde42018-04-02 19:16:26 -0700354// DTLS transport is writable.
deadbeef953c2ce2017-01-09 14:53:41 -0800355TEST_F(SctpTransportTest, SignalReadyToSendDataAfterDtlsWritable) {
zhihuangb2cdd932017-01-19 16:54:25 -0800356 FakeDtlsTransport fake_dtls("fake dtls", 0);
deadbeef953c2ce2017-01-09 14:53:41 -0800357 SctpFakeDataReceiver recv;
358 std::unique_ptr<SctpTransport> transport(CreateTransport(&fake_dtls, &recv));
359
360 SignalReadyToSendObserver signal_observer;
361 transport->SignalReadyToSendData.connect(
362 &signal_observer, &SignalReadyToSendObserver::OnSignaled);
363
364 transport->Start(kSctpDefaultPort, kSctpDefaultPort);
365 fake_dtls.SetWritable(true);
366 EXPECT_TRUE_WAIT(signal_observer.IsSignaled(), kDefaultTimeout);
367}
368
369// Test that after an SCTP socket's buffer is filled, SignalReadyToSendData
370// is fired after it begins to be drained.
371TEST_F(SctpTransportTest, SignalReadyToSendDataAfterBlocked) {
372 SetupConnectedTransportsWithTwoStreams();
373 // Wait for initial SCTP association to be formed.
374 EXPECT_EQ_WAIT(1, transport1_ready_to_send_count(), kDefaultTimeout);
375 // Make the fake transport unwritable so that messages pile up for the SCTP
376 // socket.
377 fake_dtls1()->SetWritable(false);
378 // Send messages until we get EWOULDBLOCK.
379 static const int kMaxMessages = 1024;
380 SendDataParams params;
381 params.sid = 1;
382 rtc::CopyOnWriteBuffer buf(1024);
383 memset(buf.data<uint8_t>(), 0, 1024);
384 SendDataResult result;
385 int message_count;
386 for (message_count = 0; message_count < kMaxMessages; ++message_count) {
387 if (!transport1()->SendData(params, buf, &result) && result == SDR_BLOCK) {
388 break;
389 }
390 }
391 ASSERT_NE(kMaxMessages, message_count)
392 << "Sent max number of messages without getting SDR_BLOCK?";
393 // Make sure the ready-to-send count hasn't changed.
394 EXPECT_EQ(1, transport1_ready_to_send_count());
395 // Make the transport writable again and expect a "SignalReadyToSendData" at
396 // some point.
397 fake_dtls1()->SetWritable(true);
398 EXPECT_EQ_WAIT(2, transport1_ready_to_send_count(), kDefaultTimeout);
399}
400
401TEST_F(SctpTransportTest, SendData) {
402 SetupConnectedTransportsWithTwoStreams();
403
404 SendDataResult result;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100405 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800406 << "transport1 sending: 'hello?' -----------------------------";
407 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
408 EXPECT_EQ(SDR_SUCCESS, result);
409 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100410 RTC_LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
411 << ", recv2.last_params.sid="
412 << receiver2()->last_params().sid
413 << ", recv2.last_params.timestamp="
414 << receiver2()->last_params().timestamp
415 << ", recv2.last_params.seq_num="
416 << receiver2()->last_params().seq_num
417 << ", recv2.last_data=" << receiver2()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800418
Mirko Bonadei675513b2017-11-09 11:09:25 +0100419 RTC_LOG(LS_VERBOSE)
deadbeef953c2ce2017-01-09 14:53:41 -0800420 << "transport2 sending: 'hi transport1' -----------------------------";
421 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
422 EXPECT_EQ(SDR_SUCCESS, result);
423 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
424 kDefaultTimeout);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100425 RTC_LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
426 << ", recv1.last_params.sid="
427 << receiver1()->last_params().sid
428 << ", recv1.last_params.timestamp="
429 << receiver1()->last_params().timestamp
430 << ", recv1.last_params.seq_num="
431 << receiver1()->last_params().seq_num
432 << ", recv1.last_data=" << receiver1()->last_data();
deadbeef953c2ce2017-01-09 14:53:41 -0800433}
434
435// Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
436TEST_F(SctpTransportTest, SendDataBlocked) {
437 SetupConnectedTransportsWithTwoStreams();
438
439 SendDataResult result;
440 SendDataParams params;
441 params.sid = 1;
442
443 std::vector<char> buffer(1024 * 64, 0);
444
445 for (size_t i = 0; i < 100; ++i) {
446 transport1()->SendData(
447 params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
448 if (result == SDR_BLOCK)
449 break;
450 }
451
452 EXPECT_EQ(SDR_BLOCK, result);
453}
454
455// Trying to send data for a nonexistent stream should fail.
456TEST_F(SctpTransportTest, SendDataWithNonexistentStreamFails) {
457 SetupConnectedTransportsWithTwoStreams();
458 SendDataResult result;
459 EXPECT_FALSE(SendData(transport2(), 123, "some data", &result));
460 EXPECT_EQ(SDR_ERROR, result);
461}
462
jbauch46d24572017-03-10 16:20:04 -0800463TEST_F(SctpTransportTest, SendDataHighPorts) {
464 SetupConnectedTransportsWithTwoStreams(32768, 32769);
465
466 SendDataResult result;
467 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
468 EXPECT_EQ(SDR_SUCCESS, result);
469 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
470
471 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
472 EXPECT_EQ(SDR_SUCCESS, result);
473 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
474 kDefaultTimeout);
475}
476
deadbeef953c2ce2017-01-09 14:53:41 -0800477TEST_F(SctpTransportTest, ClosesRemoteStream) {
478 SetupConnectedTransportsWithTwoStreams();
479 SignalTransportClosedObserver transport1_sig_receiver,
480 transport2_sig_receiver;
481 transport1_sig_receiver.BindSelf(transport1());
482 transport2_sig_receiver.BindSelf(transport2());
483
484 SendDataResult result;
485 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
486 EXPECT_EQ(SDR_SUCCESS, result);
487 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
488 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
489 EXPECT_EQ(SDR_SUCCESS, result);
490 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
491 kDefaultTimeout);
492
493 // Close transport 1. Transport 2 should notify us.
494 transport1()->ResetStream(1);
495 EXPECT_TRUE_WAIT(transport2_sig_receiver.WasStreamClosed(1), kDefaultTimeout);
496}
497
498TEST_F(SctpTransportTest, ClosesTwoRemoteStreams) {
499 SetupConnectedTransportsWithTwoStreams();
500 AddStream(3);
501 SignalTransportClosedObserver transport1_sig_receiver,
502 transport2_sig_receiver;
503 transport1_sig_receiver.BindSelf(transport1());
504 transport2_sig_receiver.BindSelf(transport2());
505
506 SendDataResult result;
507 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
508 EXPECT_EQ(SDR_SUCCESS, result);
509 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
510 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
511 EXPECT_EQ(SDR_SUCCESS, result);
512 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
513 kDefaultTimeout);
514
515 // Close two streams on one side.
516 transport2()->ResetStream(2);
517 transport2()->ResetStream(3);
518 EXPECT_TRUE_WAIT(transport1_sig_receiver.WasStreamClosed(2), kDefaultTimeout);
519 EXPECT_TRUE_WAIT(transport1_sig_receiver.WasStreamClosed(3), kDefaultTimeout);
520}
521
522TEST_F(SctpTransportTest, ClosesStreamsOnBothSides) {
523 SetupConnectedTransportsWithTwoStreams();
524 AddStream(3);
525 AddStream(4);
526 SignalTransportClosedObserver transport1_sig_receiver,
527 transport2_sig_receiver;
528 transport1_sig_receiver.BindSelf(transport1());
529 transport2_sig_receiver.BindSelf(transport2());
530
531 SendDataResult result;
532 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
533 EXPECT_EQ(SDR_SUCCESS, result);
534 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
535 ASSERT_TRUE(SendData(transport2(), 2, "hi transport1", &result));
536 EXPECT_EQ(SDR_SUCCESS, result);
537 EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi transport1"),
538 kDefaultTimeout);
539
540 // Close one stream on transport1(), while closing three streams on
541 // transport2(). They will conflict (only one side can close anything at a
542 // time, apparently). Test the resolution of the conflict.
543 transport1()->ResetStream(1);
544
545 transport2()->ResetStream(2);
546 transport2()->ResetStream(3);
547 transport2()->ResetStream(4);
548 EXPECT_TRUE_WAIT(transport2_sig_receiver.WasStreamClosed(1), kDefaultTimeout);
549 EXPECT_TRUE_WAIT(transport1_sig_receiver.WasStreamClosed(2), kDefaultTimeout);
550 EXPECT_TRUE_WAIT(transport1_sig_receiver.WasStreamClosed(3), kDefaultTimeout);
551 EXPECT_TRUE_WAIT(transport1_sig_receiver.WasStreamClosed(4), kDefaultTimeout);
552}
553
554TEST_F(SctpTransportTest, RefusesHighNumberedTransports) {
555 SetupConnectedTransportsWithTwoStreams();
556 EXPECT_TRUE(AddStream(kMaxSctpSid));
557 EXPECT_FALSE(AddStream(kMaxSctpSid + 1));
558}
559
560// Flaky, see webrtc:4453.
561TEST_F(SctpTransportTest, DISABLED_ReusesAStream) {
562 // Shut down transport 1, then open it up again for reuse.
563 SetupConnectedTransportsWithTwoStreams();
564 SendDataResult result;
565 SignalTransportClosedObserver transport2_sig_receiver;
566 transport2_sig_receiver.BindSelf(transport2());
567
568 ASSERT_TRUE(SendData(transport1(), 1, "hello?", &result));
569 EXPECT_EQ(SDR_SUCCESS, result);
570 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), kDefaultTimeout);
571
572 transport1()->ResetStream(1);
573 EXPECT_TRUE_WAIT(transport2_sig_receiver.WasStreamClosed(1), kDefaultTimeout);
574 // Transport 1 is gone now.
575
576 // Create a new transport 1.
577 AddStream(1);
578 ASSERT_TRUE(SendData(transport1(), 1, "hi?", &result));
579 EXPECT_EQ(SDR_SUCCESS, result);
580 EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), kDefaultTimeout);
581 transport1()->ResetStream(1);
582 EXPECT_TRUE_WAIT(transport2_sig_receiver.StreamCloseCount(1) == 2,
583 kDefaultTimeout);
584}
585
586} // namespace cricket