Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / media / sctp / sctpdataengine_unittest.cc
1 /*
2  * libjingle SCTP
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/base/bind.h"
35 #include "talk/base/buffer.h"
36 #include "talk/base/criticalsection.h"
37 #include "talk/base/gunit.h"
38 #include "talk/base/helpers.h"
39 #include "talk/base/messagehandler.h"
40 #include "talk/base/messagequeue.h"
41 #include "talk/base/scoped_ptr.h"
42 #include "talk/base/ssladapter.h"
43 #include "talk/base/thread.h"
44 #include "talk/media/base/constants.h"
45 #include "talk/media/base/mediachannel.h"
46 #include "talk/media/sctp/sctpdataengine.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 talk_base::MessageHandler {
56  public:
57   explicit SctpFakeNetworkInterface(talk_base::Thread* thread)
58     : thread_(thread),
59       dest_(NULL) {
60   }
61
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).
66   virtual bool SendPacket(talk_base::Buffer* packet,
67                           talk_base::DiffServCodePoint dscp) {
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     talk_base::Buffer* buffer = new talk_base::Buffer(packet->data(),
73                                                       packet->length());
74     thread_->Post(this, MSG_PACKET, talk_base::WrapMessageData(buffer));
75     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::SendPacket, Posted message.";
76     return true;
77   }
78
79   // Called when a raw packet has been recieved. This passes the data to the
80   // code that will interpret the packet. e.g. to get the content payload from
81   // an SCTP packet.
82   virtual void OnMessage(talk_base::Message* msg) {
83     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::OnMessage";
84     talk_base::Buffer* buffer =
85         static_cast<talk_base::TypedMessageData<talk_base::Buffer*>*>(
86             msg->pdata)->data();
87     if (dest_) {
88       dest_->OnPacketReceived(buffer, talk_base::PacketTime());
89     }
90     delete buffer;
91   }
92
93   // Unsupported functions required to exist by NetworkInterface.
94   // TODO(ldixon): Refactor parent NetworkInterface class so these are not
95   // required. They are RTC specific and should be in an appropriate subclass.
96   virtual bool SendRtcp(talk_base::Buffer* packet,
97                         talk_base::DiffServCodePoint dscp) {
98     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SendRtcp.";
99     return false;
100   }
101   virtual int SetOption(SocketType type, talk_base::Socket::Option opt,
102                         int option) {
103     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SetOption.";
104     return 0;
105   }
106   virtual void SetDefaultDSCPCode(talk_base::DiffServCodePoint dscp) {
107     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SetOption.";
108   }
109
110  private:
111   // Not owned by this class.
112   talk_base::Thread* thread_;
113   cricket::DataMediaChannel* dest_;
114 };
115
116 // This is essentially a buffer to hold recieved data. It stores only the last
117 // received data. Calling OnDataReceived twice overwrites old data with the
118 // newer one.
119 // TODO(ldixon): Implement constraints, and allow new data to be added to old
120 // instead of replacing it.
121 class SctpFakeDataReceiver : public sigslot::has_slots<> {
122  public:
123   SctpFakeDataReceiver() : received_(false) {}
124
125   void Clear() {
126     received_ = false;
127     last_data_ = "";
128     last_params_ = cricket::ReceiveDataParams();
129   }
130
131   virtual void OnDataReceived(const cricket::ReceiveDataParams& params,
132                               const char* data, size_t length) {
133     received_ = true;
134     last_data_ = std::string(data, length);
135     last_params_ = params;
136   }
137
138   bool received() const { return received_; }
139   std::string last_data() const { return last_data_; }
140   cricket::ReceiveDataParams last_params() const { return last_params_; }
141
142  private:
143   bool received_;
144   std::string last_data_;
145   cricket::ReceiveDataParams last_params_;
146 };
147
148 class SignalReadyToSendObserver : public sigslot::has_slots<> {
149  public:
150   SignalReadyToSendObserver() : signaled_(false), writable_(false) {}
151
152   void OnSignaled(bool writable) {
153     signaled_ = true;
154     writable_ = writable;
155   }
156
157   bool IsSignaled(bool writable) {
158     return signaled_ && (writable_ == writable);
159   }
160
161  private:
162   bool signaled_;
163   bool writable_;
164 };
165
166 class SignalChannelClosedObserver : public sigslot::has_slots<> {
167  public:
168   SignalChannelClosedObserver() {}
169   void BindSelf(cricket::SctpDataMediaChannel* channel) {
170     channel->SignalStreamClosed.connect(
171         this, &SignalChannelClosedObserver::OnStreamClosed);
172   }
173   void OnStreamClosed(int stream) {
174     streams_.push_back(stream);
175   }
176
177   int StreamCloseCount(int stream) {
178     return std::count(streams_.begin(), streams_.end(), stream);
179   }
180
181   bool WasStreamClosed(int stream) {
182     return std::find(streams_.begin(), streams_.end(), stream)
183         != streams_.end();
184   }
185
186  private:
187   std::vector<int> streams_;
188 };
189
190 class SignalChannelClosedReopener : public sigslot::has_slots<> {
191  public:
192   SignalChannelClosedReopener(cricket::SctpDataMediaChannel* channel,
193                               cricket::SctpDataMediaChannel* peer)
194       : channel_(channel), peer_(peer) {}
195
196   void OnStreamClosed(int stream) {
197     cricket::StreamParams p(cricket::StreamParams::CreateLegacy(stream));
198     channel_->AddSendStream(p);
199     channel_->AddRecvStream(p);
200     peer_->AddSendStream(p);
201     peer_->AddRecvStream(p);
202     streams_.push_back(stream);
203   }
204
205   int StreamCloseCount(int stream) {
206     return std::count(streams_.begin(), streams_.end(), stream);
207   }
208
209  private:
210   cricket::SctpDataMediaChannel* channel_;
211   cricket::SctpDataMediaChannel* peer_;
212   std::vector<int> streams_;
213 };
214
215 // SCTP Data Engine testing framework.
216 class SctpDataMediaChannelTest : public testing::Test,
217                                  public sigslot::has_slots<> {
218  protected:
219   // usrsctp uses the NSS random number generator on non-Android platforms,
220   // so we need to initialize SSL.
221   static void SetUpTestCase() {
222     talk_base::InitializeSSL();
223   }
224
225   static void TearDownTestCase() {
226     talk_base::CleanupSSL();
227   }
228
229   virtual void SetUp() {
230     engine_.reset(new cricket::SctpDataEngine());
231   }
232
233   void SetupConnectedChannels() {
234     net1_.reset(new SctpFakeNetworkInterface(talk_base::Thread::Current()));
235     net2_.reset(new SctpFakeNetworkInterface(talk_base::Thread::Current()));
236     recv1_.reset(new SctpFakeDataReceiver());
237     recv2_.reset(new SctpFakeDataReceiver());
238     chan1_.reset(CreateChannel(net1_.get(), recv1_.get()));
239     chan1_->set_debug_name("chan1/connector");
240     chan2_.reset(CreateChannel(net2_.get(), recv2_.get()));
241     chan2_->set_debug_name("chan2/listener");
242     // Setup two connected channels ready to send and receive.
243     net1_->SetDestination(chan2_.get());
244     net2_->SetDestination(chan1_.get());
245
246     LOG(LS_VERBOSE) << "Channel setup ----------------------------- ";
247     AddStream(1);
248     AddStream(2);
249
250     LOG(LS_VERBOSE) << "Connect the channels -----------------------------";
251     // chan1 wants to setup a data connection.
252     chan1_->SetReceive(true);
253     // chan1 will have sent chan2 a request to setup a data connection. After
254     // chan2 accepts the offer, chan2 connects to chan1 with the following.
255     chan2_->SetReceive(true);
256     chan2_->SetSend(true);
257     // Makes sure that network packets are delivered and simulates a
258     // deterministic and realistic small timing delay between the SetSend calls.
259     ProcessMessagesUntilIdle();
260
261     // chan1 and chan2 are now connected so chan1 enables sending to complete
262     // the creation of the connection.
263     chan1_->SetSend(true);
264   }
265
266   virtual void TearDown() {
267     channel1()->SetSend(false);
268     channel2()->SetSend(false);
269   }
270
271   void AddStream(int ssrc) {
272     cricket::StreamParams p(cricket::StreamParams::CreateLegacy(ssrc));
273     chan1_->AddSendStream(p);
274     chan1_->AddRecvStream(p);
275     chan2_->AddSendStream(p);
276     chan2_->AddRecvStream(p);
277   }
278
279   cricket::SctpDataMediaChannel* CreateChannel(
280       SctpFakeNetworkInterface* net, SctpFakeDataReceiver* recv) {
281     cricket::SctpDataMediaChannel* channel =
282         static_cast<cricket::SctpDataMediaChannel*>(engine_->CreateChannel(
283             cricket::DCT_SCTP));
284     channel->SetInterface(net);
285     // When data is received, pass it to the SctpFakeDataReceiver.
286     channel->SignalDataReceived.connect(
287         recv, &SctpFakeDataReceiver::OnDataReceived);
288     return channel;
289   }
290
291   bool SendData(cricket::SctpDataMediaChannel* chan, uint32 ssrc,
292                 const std::string& msg,
293                 cricket::SendDataResult* result) {
294     cricket::SendDataParams params;
295     params.ssrc = ssrc;
296
297     return chan->SendData(params, talk_base::Buffer(
298         msg.data(), msg.length()), result);
299   }
300
301   bool ReceivedData(const SctpFakeDataReceiver* recv, uint32 ssrc,
302                     const std::string& msg ) {
303     return (recv->received() &&
304             recv->last_params().ssrc == ssrc &&
305             recv->last_data() == msg);
306   }
307
308   bool ProcessMessagesUntilIdle() {
309     talk_base::Thread* thread = talk_base::Thread::Current();
310     while (!thread->empty()) {
311       talk_base::Message msg;
312       if (thread->Get(&msg, talk_base::kForever)) {
313         thread->Dispatch(&msg);
314       }
315     }
316     return !thread->IsQuitting();
317   }
318
319   cricket::SctpDataMediaChannel* channel1() { return chan1_.get(); }
320   cricket::SctpDataMediaChannel* channel2() { return chan2_.get(); }
321   SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
322   SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
323
324  private:
325   talk_base::scoped_ptr<cricket::SctpDataEngine> engine_;
326   talk_base::scoped_ptr<SctpFakeNetworkInterface> net1_;
327   talk_base::scoped_ptr<SctpFakeNetworkInterface> net2_;
328   talk_base::scoped_ptr<SctpFakeDataReceiver> recv1_;
329   talk_base::scoped_ptr<SctpFakeDataReceiver> recv2_;
330   talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan1_;
331   talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan2_;
332 };
333
334 // Verifies that SignalReadyToSend is fired.
335 TEST_F(SctpDataMediaChannelTest, SignalReadyToSend) {
336   SetupConnectedChannels();
337
338   SignalReadyToSendObserver signal_observer_1;
339   SignalReadyToSendObserver signal_observer_2;
340
341   channel1()->SignalReadyToSend.connect(&signal_observer_1,
342                                         &SignalReadyToSendObserver::OnSignaled);
343   channel2()->SignalReadyToSend.connect(&signal_observer_2,
344                                         &SignalReadyToSendObserver::OnSignaled);
345
346   cricket::SendDataResult result;
347   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
348   EXPECT_EQ(cricket::SDR_SUCCESS, result);
349   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
350   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
351   EXPECT_EQ(cricket::SDR_SUCCESS, result);
352   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
353
354   EXPECT_TRUE_WAIT(signal_observer_1.IsSignaled(true), 1000);
355   EXPECT_TRUE_WAIT(signal_observer_2.IsSignaled(true), 1000);
356 }
357
358 TEST_F(SctpDataMediaChannelTest, SendData) {
359   SetupConnectedChannels();
360
361   cricket::SendDataResult result;
362   LOG(LS_VERBOSE) << "chan1 sending: 'hello?' -----------------------------";
363   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
364   EXPECT_EQ(cricket::SDR_SUCCESS, result);
365   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
366   LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
367                   << "recv2.last_params.ssrc="
368                   << receiver2()->last_params().ssrc
369                   << "recv2.last_params.timestamp="
370                   << receiver2()->last_params().ssrc
371                   << "recv2.last_params.seq_num="
372                   << receiver2()->last_params().seq_num
373                   << "recv2.last_data=" << receiver2()->last_data();
374
375   LOG(LS_VERBOSE) << "chan2 sending: 'hi chan1' -----------------------------";
376   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
377   EXPECT_EQ(cricket::SDR_SUCCESS, result);
378   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
379   LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
380                   << "recv1.last_params.ssrc="
381                   << receiver1()->last_params().ssrc
382                   << "recv1.last_params.timestamp="
383                   << receiver1()->last_params().ssrc
384                   << "recv1.last_params.seq_num="
385                   << receiver1()->last_params().seq_num
386                   << "recv1.last_data=" << receiver1()->last_data();
387 }
388
389 // Sends a lot of large messages at once and verifies SDR_BLOCK is returned.
390 TEST_F(SctpDataMediaChannelTest, SendDataBlocked) {
391   SetupConnectedChannels();
392
393   cricket::SendDataResult result;
394   cricket::SendDataParams params;
395   params.ssrc = 1;
396
397   std::vector<char> buffer(1024 * 64, 0);
398
399   for (size_t i = 0; i < 100; ++i) {
400     channel1()->SendData(
401         params, talk_base::Buffer(buffer.data(), buffer.size()), &result);
402     if (result == cricket::SDR_BLOCK)
403       break;
404   }
405
406   EXPECT_EQ(cricket::SDR_BLOCK, result);
407 }
408
409 TEST_F(SctpDataMediaChannelTest, ClosesRemoteStream) {
410   SetupConnectedChannels();
411   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
412   chan_1_sig_receiver.BindSelf(channel1());
413   chan_2_sig_receiver.BindSelf(channel2());
414
415   cricket::SendDataResult result;
416   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
417   EXPECT_EQ(cricket::SDR_SUCCESS, result);
418   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
419   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
420   EXPECT_EQ(cricket::SDR_SUCCESS, result);
421   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
422
423   // Close channel 1.  Channel 2 should notify us.
424   channel1()->RemoveSendStream(1);
425   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
426 }
427
428 TEST_F(SctpDataMediaChannelTest, ClosesTwoRemoteStreams) {
429   SetupConnectedChannels();
430   AddStream(3);
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 two streams on one side.
444   channel2()->RemoveSendStream(2);
445   channel2()->RemoveSendStream(3);
446   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(2), 1000);
447   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(3), 1000);
448 }
449
450 TEST_F(SctpDataMediaChannelTest, ClosesStreamsOnBothSides) {
451   SetupConnectedChannels();
452   AddStream(3);
453   AddStream(4);
454   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
455   chan_1_sig_receiver.BindSelf(channel1());
456   chan_2_sig_receiver.BindSelf(channel2());
457
458   cricket::SendDataResult result;
459   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
460   EXPECT_EQ(cricket::SDR_SUCCESS, result);
461   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
462   ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
463   EXPECT_EQ(cricket::SDR_SUCCESS, result);
464   EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
465
466   // Close one stream on channel1(), while closing three streams on
467   // channel2().  They will conflict (only one side can close anything at a
468   // time, apparently).  Test the resolution of the conflict.
469   channel1()->RemoveSendStream(1);
470
471   channel2()->RemoveSendStream(2);
472   channel2()->RemoveSendStream(3);
473   channel2()->RemoveSendStream(4);
474   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
475   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(2), 1000);
476   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(3), 1000);
477   EXPECT_TRUE_WAIT(chan_1_sig_receiver.WasStreamClosed(4), 1000);
478 }
479
480 TEST_F(SctpDataMediaChannelTest, ReusesAStream) {
481   // Shut down channel 1, then open it up again for reuse.
482   SetupConnectedChannels();
483   cricket::SendDataResult result;
484   SignalChannelClosedObserver chan_2_sig_receiver;
485   chan_2_sig_receiver.BindSelf(channel2());
486
487   ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
488   EXPECT_EQ(cricket::SDR_SUCCESS, result);
489   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
490
491   channel1()->RemoveSendStream(1);
492   EXPECT_TRUE_WAIT(chan_2_sig_receiver.WasStreamClosed(1), 1000);
493   // Channel 1 is gone now.
494
495   // Create a new channel 1.
496   AddStream(1);
497   ASSERT_TRUE(SendData(channel1(), 1, "hi?", &result));
498   EXPECT_EQ(cricket::SDR_SUCCESS, result);
499   EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), 1000);
500   channel1()->RemoveSendStream(1);
501   EXPECT_TRUE_WAIT(chan_2_sig_receiver.StreamCloseCount(1) == 2, 1000);
502 }