1 /*
2  * libjingle
3  * Copyright 2013 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <errno.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string>
32 #include <vector>
33 
34 #include "talk/media/base/constants.h"
35 #include "talk/media/base/mediachannel.h"
36 #include "talk/media/sctp/sctpdataengine.h"
37 #include "webrtc/base/bind.h"
38 #include "webrtc/base/buffer.h"
39 #include "webrtc/base/criticalsection.h"
40 #include "webrtc/base/gunit.h"
41 #include "webrtc/base/helpers.h"
42 #include "webrtc/base/messagehandler.h"
43 #include "webrtc/base/messagequeue.h"
44 #include "webrtc/base/scoped_ptr.h"
45 #include "webrtc/base/ssladapter.h"
46 #include "webrtc/base/thread.h"
47 
48 enum {
49   MSG_PACKET = 1,
50 };
51 
52 // Fake NetworkInterface that sends/receives sctp packets.  The one in
53 // talk/media/base/fakenetworkinterface.h only works with rtp/rtcp.
54 class SctpFakeNetworkInterface : public cricket::MediaChannel::NetworkInterface,
55                                  public rtc::MessageHandler {
56  public:
SctpFakeNetworkInterface(rtc::Thread * thread)57   explicit SctpFakeNetworkInterface(rtc::Thread* thread)
58     : thread_(thread),
59       dest_(NULL) {
60   }
61 
SetDestination(cricket::DataMediaChannel * dest)62   void SetDestination(cricket::DataMediaChannel* dest) { dest_ = dest; }
63 
64  protected:
65   // Called to send raw packet down the wire (e.g. SCTP an packet).
SendPacket(rtc::Buffer * packet,const rtc::PacketOptions & options)66   virtual bool SendPacket(rtc::Buffer* packet,
67                           const rtc::PacketOptions& options) {
68     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::SendPacket";
69 
70     // TODO(ldixon): Can/should we use Buffer.TransferTo here?
71     // Note: this assignment does a deep copy of data from packet.
72     rtc::Buffer* buffer = new rtc::Buffer(packet->data(), packet->size());
73     thread_->Post(this, MSG_PACKET, rtc::WrapMessageData(buffer));
74     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::SendPacket, Posted message.";
75     return true;
76   }
77 
78   // Called when a raw packet has been recieved. This passes the data to the
79   // code that will interpret the packet. e.g. to get the content payload from
80   // an SCTP packet.
OnMessage(rtc::Message * msg)81   virtual void OnMessage(rtc::Message* msg) {
82     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::OnMessage";
83     rtc::scoped_ptr<rtc::Buffer> buffer(
84         static_cast<rtc::TypedMessageData<rtc::Buffer*>*>(
85             msg->pdata)->data());
86     if (dest_) {
87       dest_->OnPacketReceived(buffer.get(), rtc::PacketTime());
88     }
89     delete msg->pdata;
90   }
91 
92   // Unsupported functions required to exist by NetworkInterface.
93   // TODO(ldixon): Refactor parent NetworkInterface class so these are not
94   // required. They are RTC specific and should be in an appropriate subclass.
SendRtcp(rtc::Buffer * packet,const rtc::PacketOptions & options)95   virtual bool SendRtcp(rtc::Buffer* packet,
96                         const rtc::PacketOptions& options) {
97     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SendRtcp.";
98     return false;
99   }
SetOption(SocketType type,rtc::Socket::Option opt,int option)100   virtual int SetOption(SocketType type, rtc::Socket::Option opt,
101                         int option) {
102     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SetOption.";
103     return 0;
104   }
SetDefaultDSCPCode(rtc::DiffServCodePoint dscp)105   virtual void SetDefaultDSCPCode(rtc::DiffServCodePoint dscp) {
106     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SetOption.";
107   }
108 
109  private:
110   // Not owned by this class.
111   rtc::Thread* thread_;
112   cricket::DataMediaChannel* dest_;
113 };
114 
115 // This is essentially a buffer to hold recieved data. It stores only the last
116 // received data. Calling OnDataReceived twice overwrites old data with the
117 // newer one.
118 // TODO(ldixon): Implement constraints, and allow new data to be added to old
119 // instead of replacing it.
120 class SctpFakeDataReceiver : public sigslot::has_slots<> {
121  public:
SctpFakeDataReceiver()122   SctpFakeDataReceiver() : received_(false) {}
123 
Clear()124   void Clear() {
125     received_ = false;
126     last_data_ = "";
127     last_params_ = cricket::ReceiveDataParams();
128   }
129 
OnDataReceived(const cricket::ReceiveDataParams & params,const char * data,size_t length)130   virtual void OnDataReceived(const cricket::ReceiveDataParams& params,
131                               const char* data, size_t length) {
132     received_ = true;
133     last_data_ = std::string(data, length);
134     last_params_ = params;
135   }
136 
received() const137   bool received() const { return received_; }
last_data() const138   std::string last_data() const { return last_data_; }
last_params() const139   cricket::ReceiveDataParams last_params() const { return last_params_; }
140 
141  private:
142   bool received_;
143   std::string last_data_;
144   cricket::ReceiveDataParams last_params_;
145 };
146 
147 class SignalReadyToSendObserver : public sigslot::has_slots<> {
148  public:
SignalReadyToSendObserver()149   SignalReadyToSendObserver() : signaled_(false), writable_(false) {}
150 
OnSignaled(bool writable)151   void OnSignaled(bool writable) {
152     signaled_ = true;
153     writable_ = writable;
154   }
155 
IsSignaled(bool writable)156   bool IsSignaled(bool writable) {
157     return signaled_ && (writable_ == writable);
158   }
159 
160  private:
161   bool signaled_;
162   bool writable_;
163 };
164 
165 class SignalChannelClosedObserver : public sigslot::has_slots<> {
166  public:
SignalChannelClosedObserver()167   SignalChannelClosedObserver() {}
BindSelf(cricket::SctpDataMediaChannel * channel)168   void BindSelf(cricket::SctpDataMediaChannel* channel) {
169     channel->SignalStreamClosedRemotely.connect(
170         this, &SignalChannelClosedObserver::OnStreamClosed);
171   }
OnStreamClosed(uint32_t stream)172   void OnStreamClosed(uint32_t stream) { streams_.push_back(stream); }
173 
StreamCloseCount(uint32_t stream)174   int StreamCloseCount(uint32_t stream) {
175     return std::count(streams_.begin(), streams_.end(), stream);
176   }
177 
WasStreamClosed(uint32_t stream)178   bool WasStreamClosed(uint32_t stream) {
179     return std::find(streams_.begin(), streams_.end(), stream)
180         != streams_.end();
181   }
182 
183  private:
184   std::vector<uint32_t> streams_;
185 };
186 
187 class SignalChannelClosedReopener : public sigslot::has_slots<> {
188  public:
SignalChannelClosedReopener(cricket::SctpDataMediaChannel * channel,cricket::SctpDataMediaChannel * peer)189   SignalChannelClosedReopener(cricket::SctpDataMediaChannel* channel,
190                               cricket::SctpDataMediaChannel* peer)
191       : channel_(channel), peer_(peer) {}
192 
OnStreamClosed(int stream)193   void OnStreamClosed(int stream) {
194     cricket::StreamParams p(cricket::StreamParams::CreateLegacy(stream));
195     channel_->AddSendStream(p);
196     channel_->AddRecvStream(p);
197     peer_->AddSendStream(p);
198     peer_->AddRecvStream(p);
199     streams_.push_back(stream);
200   }
201 
StreamCloseCount(int stream)202   int StreamCloseCount(int stream) {
203     return std::count(streams_.begin(), streams_.end(), stream);
204   }
205 
206  private:
207   cricket::SctpDataMediaChannel* channel_;
208   cricket::SctpDataMediaChannel* peer_;
209   std::vector<int> streams_;
210 };
211 
212 // SCTP Data Engine testing framework.
213 class SctpDataMediaChannelTest : public testing::Test,
214                                  public sigslot::has_slots<> {
215  protected:
216   // usrsctp uses the NSS random number generator on non-Android platforms,
217   // so we need to initialize SSL.
SetUpTestCase()218   static void SetUpTestCase() {
219   }
220 
SetUp()221   virtual void SetUp() {
222     engine_.reset(new cricket::SctpDataEngine());
223   }
224 
SetupConnectedChannels()225   void SetupConnectedChannels() {
226     net1_.reset(new SctpFakeNetworkInterface(rtc::Thread::Current()));
227     net2_.reset(new SctpFakeNetworkInterface(rtc::Thread::Current()));
228     recv1_.reset(new SctpFakeDataReceiver());
229     recv2_.reset(new SctpFakeDataReceiver());
230     chan1_ready_to_send_count_ = 0;
231     chan2_ready_to_send_count_ = 0;
232     chan1_.reset(CreateChannel(net1_.get(), recv1_.get()));
233     chan1_->set_debug_name("chan1/connector");
234     chan1_->SignalReadyToSend.connect(
235         this, &SctpDataMediaChannelTest::OnChan1ReadyToSend);
236     chan2_.reset(CreateChannel(net2_.get(), recv2_.get()));
237     chan2_->set_debug_name("chan2/listener");
238     chan2_->SignalReadyToSend.connect(
239         this, &SctpDataMediaChannelTest::OnChan2ReadyToSend);
240     // Setup two connected channels ready to send and receive.
241     net1_->SetDestination(chan2_.get());
242     net2_->SetDestination(chan1_.get());
243 
244     LOG(LS_VERBOSE) << "Channel setup ----------------------------- ";
245     AddStream(1);
246     AddStream(2);
247 
248     LOG(LS_VERBOSE) << "Connect the channels -----------------------------";
249     // chan1 wants to setup a data connection.
250     chan1_->SetReceive(true);
251     // chan1 will have sent chan2 a request to setup a data connection. After
252     // chan2 accepts the offer, chan2 connects to chan1 with the following.
253     chan2_->SetReceive(true);
254     chan2_->SetSend(true);
255     // Makes sure that network packets are delivered and simulates a
256     // deterministic and realistic small timing delay between the SetSend calls.
257     ProcessMessagesUntilIdle();
258 
259     // chan1 and chan2 are now connected so chan1 enables sending to complete
260     // the creation of the connection.
261     chan1_->SetSend(true);
262   }
263 
TearDown()264   virtual void TearDown() {
265     channel1()->SetSend(false);
266     channel2()->SetSend(false);
267 
268     // Process messages until idle to prevent a sent packet from being dropped
269     // and causing memory leaks (not being deleted by the receiver).
270     ProcessMessagesUntilIdle();
271   }
272 
AddStream(int ssrc)273   bool AddStream(int ssrc) {
274     bool ret = true;
275     cricket::StreamParams p(cricket::StreamParams::CreateLegacy(ssrc));
276     ret = ret && chan1_->AddSendStream(p);
277     ret = ret && chan1_->AddRecvStream(p);
278     ret = ret && chan2_->AddSendStream(p);
279     ret = ret && chan2_->AddRecvStream(p);
280     return ret;
281   }
282 
CreateChannel(SctpFakeNetworkInterface * net,SctpFakeDataReceiver * recv)283   cricket::SctpDataMediaChannel* CreateChannel(
284       SctpFakeNetworkInterface* net, SctpFakeDataReceiver* recv) {
285     cricket::SctpDataMediaChannel* channel =
286         static_cast<cricket::SctpDataMediaChannel*>(engine_->CreateChannel(
287             cricket::DCT_SCTP));
288     channel->SetInterface(net);
289     // When data is received, pass it to the SctpFakeDataReceiver.
290     channel->SignalDataReceived.connect(
291         recv, &SctpFakeDataReceiver::OnDataReceived);
292     return channel;
293   }
294 
SendData(cricket::SctpDataMediaChannel * chan,uint32_t ssrc,const std::string & msg,cricket::SendDataResult * result)295   bool SendData(cricket::SctpDataMediaChannel* chan,
296                 uint32_t ssrc,
297                 const std::string& msg,
298                 cricket::SendDataResult* result) {
299     cricket::SendDataParams params;
300     params.ssrc = ssrc;
301 
302     return chan->SendData(params, rtc::Buffer(
303         &msg[0], msg.length()), result);
304   }
305 
ReceivedData(const SctpFakeDataReceiver * recv,uint32_t ssrc,const std::string & msg)306   bool ReceivedData(const SctpFakeDataReceiver* recv,
307                     uint32_t ssrc,
308                     const std::string& msg) {
309     return (recv->received() &&
310             recv->last_params().ssrc == ssrc &&
311             recv->last_data() == msg);
312   }
313 
ProcessMessagesUntilIdle()314   bool ProcessMessagesUntilIdle() {
315     rtc::Thread* thread = rtc::Thread::Current();
316     while (!thread->empty()) {
317       rtc::Message msg;
318       if (thread->Get(&msg, rtc::Thread::kForever)) {
319         thread->Dispatch(&msg);
320       }
321     }
322     return !thread->IsQuitting();
323   }
324 
channel1()325   cricket::SctpDataMediaChannel* channel1() { return chan1_.get(); }
channel2()326   cricket::SctpDataMediaChannel* channel2() { return chan2_.get(); }
receiver1()327   SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
receiver2()328   SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
329 
channel1_ready_to_send_count()330   int channel1_ready_to_send_count() { return chan1_ready_to_send_count_; }
channel2_ready_to_send_count()331   int channel2_ready_to_send_count() { return chan2_ready_to_send_count_; }
332  private:
333   rtc::scoped_ptr<cricket::SctpDataEngine> engine_;
334   rtc::scoped_ptr<SctpFakeNetworkInterface> net1_;
335   rtc::scoped_ptr<SctpFakeNetworkInterface> net2_;
336   rtc::scoped_ptr<SctpFakeDataReceiver> recv1_;
337   rtc::scoped_ptr<SctpFakeDataReceiver> recv2_;
338   rtc::scoped_ptr<cricket::SctpDataMediaChannel> chan1_;
339   rtc::scoped_ptr<cricket::SctpDataMediaChannel> chan2_;
340 
341   int chan1_ready_to_send_count_;
342   int chan2_ready_to_send_count_;
343 
OnChan1ReadyToSend(bool send)344   void OnChan1ReadyToSend(bool send) {
345     if (send)
346       ++chan1_ready_to_send_count_;
347   }
OnChan2ReadyToSend(bool send)348   void OnChan2ReadyToSend(bool send) {
349     if (send)
350       ++chan2_ready_to_send_count_;
351   }
352 };
353 
354 // Verifies that SignalReadyToSend is fired.
TEST_F(SctpDataMediaChannelTest,SignalReadyToSend)355 TEST_F(SctpDataMediaChannelTest, SignalReadyToSend) {
356   SetupConnectedChannels();
357 
358   SignalReadyToSendObserver signal_observer_1;
359   SignalReadyToSendObserver signal_observer_2;
360 
361   channel1()->SignalReadyToSend.connect(&signal_observer_1,
362                                         &SignalReadyToSendObserver::OnSignaled);
363   channel2()->SignalReadyToSend.connect(&signal_observer_2,
364                                         &SignalReadyToSendObserver::OnSignaled);
365 
366   cricket::SendDataResult result;
367   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
368   EXPECT_EQ(cricket::SDR_SUCCESS, result);
369   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
370   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
371   EXPECT_EQ(cricket::SDR_SUCCESS, result);
372   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
373 
374   EXPECT_TRUE_WAIT(signal_observer_1.IsSignaled(true), 1000);
375   EXPECT_TRUE_WAIT(signal_observer_2.IsSignaled(true), 1000);
376 }
377 
TEST_F(SctpDataMediaChannelTest,SendData)378 TEST_F(SctpDataMediaChannelTest, SendData) {
379   SetupConnectedChannels();
380 
381   cricket::SendDataResult result;
382   LOG(LS_VERBOSE) << "chan1 sending: 'hello?' -----------------------------";
383   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
384   EXPECT_EQ(cricket::SDR_SUCCESS, result);
385   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
386   LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
387                   << ", recv2.last_params.ssrc="
388                   << receiver2()->last_params().ssrc
389                   << ", recv2.last_params.timestamp="
390                   << receiver2()->last_params().ssrc
391                   << ", recv2.last_params.seq_num="
392                   << receiver2()->last_params().seq_num
393                   << ", recv2.last_data=" << receiver2()->last_data();
394 
395   LOG(LS_VERBOSE) << "chan2 sending: 'hi chan1' -----------------------------";
396   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
397   EXPECT_EQ(cricket::SDR_SUCCESS, result);
398   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
399   LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
400                   << ", recv1.last_params.ssrc="
401                   << receiver1()->last_params().ssrc
402                   << ", recv1.last_params.timestamp="
403                   << receiver1()->last_params().ssrc
404                   << ", recv1.last_params.seq_num="
405                   << receiver1()->last_params().seq_num
406                   << ", recv1.last_data=" << receiver1()->last_data();
407 }
408 
409 // Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
TEST_F(SctpDataMediaChannelTest,SendDataBlocked)410 TEST_F(SctpDataMediaChannelTest, SendDataBlocked) {
411   SetupConnectedChannels();
412 
413   cricket::SendDataResult result;
414   cricket::SendDataParams params;
415   params.ssrc = 1;
416 
417   std::vector<char> buffer(1024 * 64, 0);
418 
419   for (size_t i = 0; i < 100; ++i) {
420     channel1()->SendData(
421         params, rtc::Buffer(&buffer[0], buffer.size()), &result);
422     if (result == cricket::SDR_BLOCK)
423       break;
424   }
425 
426   EXPECT_EQ(cricket::SDR_BLOCK, result);
427 }
428 
TEST_F(SctpDataMediaChannelTest,ClosesRemoteStream)429 TEST_F(SctpDataMediaChannelTest, ClosesRemoteStream) {
430   SetupConnectedChannels();
431   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
432   chan_1_sig_receiver.BindSelf(channel1());
433   chan_2_sig_receiver.BindSelf(channel2());
434 
435   cricket::SendDataResult result;
436   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
437   EXPECT_EQ(cricket::SDR_SUCCESS, result);
438   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
439   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
440   EXPECT_EQ(cricket::SDR_SUCCESS, result);
441   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
442 
443   // Close channel 1.  Channel 2 should notify us.
444   channel1()->RemoveSendStream(1);
445   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
446 }
447 
TEST_F(SctpDataMediaChannelTest,ClosesTwoRemoteStreams)448 TEST_F(SctpDataMediaChannelTest, ClosesTwoRemoteStreams) {
449   SetupConnectedChannels();
450   AddStream(3);
451   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
452   chan_1_sig_receiver.BindSelf(channel1());
453   chan_2_sig_receiver.BindSelf(channel2());
454 
455   cricket::SendDataResult result;
456   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
457   EXPECT_EQ(cricket::SDR_SUCCESS, result);
458   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
459   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
460   EXPECT_EQ(cricket::SDR_SUCCESS, result);
461   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
462 
463   // Close two streams on one side.
464   channel2()->RemoveSendStream(2);
465   channel2()->RemoveSendStream(3);
466   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(2), 1000);
467   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(3), 1000);
468 }
469 
TEST_F(SctpDataMediaChannelTest,ClosesStreamsOnBothSides)470 TEST_F(SctpDataMediaChannelTest, ClosesStreamsOnBothSides) {
471   SetupConnectedChannels();
472   AddStream(3);
473   AddStream(4);
474   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
475   chan_1_sig_receiver.BindSelf(channel1());
476   chan_2_sig_receiver.BindSelf(channel2());
477 
478   cricket::SendDataResult result;
479   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
480   EXPECT_EQ(cricket::SDR_SUCCESS, result);
481   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
482   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
483   EXPECT_EQ(cricket::SDR_SUCCESS, result);
484   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
485 
486   // Close one stream on channel1(), while closing three streams on
487   // channel2().  They will conflict (only one side can close anything at a
488   // time, apparently).  Test the resolution of the conflict.
489   channel1()->RemoveSendStream(1);
490 
491   channel2()->RemoveSendStream(2);
492   channel2()->RemoveSendStream(3);
493   channel2()->RemoveSendStream(4);
494   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
495   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(2), 1000);
496   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(3), 1000);
497   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(4), 1000);
498 }
499 
TEST_F(SctpDataMediaChannelTest,EngineSignalsRightChannel)500 TEST_F(SctpDataMediaChannelTest, EngineSignalsRightChannel) {
501   SetupConnectedChannels();
502   EXPECT_TRUE_WAIT(channel1()->socket() != NULL, 1000);
503   struct socket *sock = const_cast<struct socket*>(channel1()->socket());
504   int prior_count = channel1_ready_to_send_count();
505   cricket::SctpDataEngine::SendThresholdCallback(sock, 0);
506   EXPECT_GT(channel1_ready_to_send_count(), prior_count);
507 }
508 
TEST_F(SctpDataMediaChannelTest,RefusesHighNumberedChannels)509 TEST_F(SctpDataMediaChannelTest, RefusesHighNumberedChannels) {
510   SetupConnectedChannels();
511   EXPECT_TRUE(AddStream(1022));
512   EXPECT_FALSE(AddStream(1023));
513 }
514 
515 // Flaky on Linux and Windows. See webrtc:4453.
516 #if defined(WEBRTC_WIN) || defined(WEBRTC_LINUX)
517 #define MAYBE_ReusesAStream DISABLED_ReusesAStream
518 #else
519 #define MAYBE_ReusesAStream ReusesAStream
520 #endif
TEST_F(SctpDataMediaChannelTest,MAYBE_ReusesAStream)521 TEST_F(SctpDataMediaChannelTest, MAYBE_ReusesAStream) {
522   // Shut down channel 1, then open it up again for reuse.
523   SetupConnectedChannels();
524   cricket::SendDataResult result;
525   SignalChannelClosedObserver chan_2_sig_receiver;
526   chan_2_sig_receiver.BindSelf(channel2());
527 
528   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
529   EXPECT_EQ(cricket::SDR_SUCCESS, result);
530   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
531 
532   channel1()->RemoveSendStream(1);
533   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
534   // Channel 1 is gone now.
535 
536   // Create a new channel 1.
537   AddStream(1);
538   ASSERT_TRUE(SendData(channel1(), 1, "hi?", &result));
539   EXPECT_EQ(cricket::SDR_SUCCESS, result);
540   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), 1000);
541   channel1()->RemoveSendStream(1);
542   EXPECT_TRUE_WAIT(chan_2_sig_receiver.StreamCloseCount(1) == 2, 1000);
543 }
544