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 "talk/app/webrtc/test/peerconnectiontestwrapper.h"
29#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
30#ifdef WEBRTC_ANDROID
31#include "talk/app/webrtc/test/androidtestinitializer.h"
32#endif
33#include "webrtc/base/gunit.h"
34#include "webrtc/base/logging.h"
35#include "webrtc/base/ssladapter.h"
36#include "webrtc/base/sslstreamadapter.h"
37#include "webrtc/base/stringencode.h"
38#include "webrtc/base/stringutils.h"
39
40#define MAYBE_SKIP_TEST(feature)                    \
41  if (!(feature())) {                               \
42    LOG(LS_INFO) << "Feature disabled... skipping"; \
43    return;                                         \
44  }
45
46using webrtc::DataChannelInterface;
47using webrtc::FakeConstraints;
48using webrtc::MediaConstraintsInterface;
49using webrtc::MediaStreamInterface;
50using webrtc::PeerConnectionInterface;
51
52namespace {
53
54const size_t kMaxWait = 10000;
55
56}  // namespace
57
58class PeerConnectionEndToEndTest
59    : public sigslot::has_slots<>,
60      public testing::Test {
61 public:
62  typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
63      DataChannelList;
64
65  PeerConnectionEndToEndTest()
66      : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
67                    "caller")),
68        callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
69                    "callee")) {
70#ifdef WEBRTC_ANDROID
71    webrtc::InitializeAndroidObjects();
72#endif
73  }
74
75  void CreatePcs() {
76    CreatePcs(NULL);
77  }
78
79  void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
80    EXPECT_TRUE(caller_->CreatePc(pc_constraints));
81    EXPECT_TRUE(callee_->CreatePc(pc_constraints));
82    PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
83
84    caller_->SignalOnDataChannel.connect(
85        this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
86    callee_->SignalOnDataChannel.connect(
87        this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
88  }
89
90  void GetAndAddUserMedia() {
91    FakeConstraints audio_constraints;
92    FakeConstraints video_constraints;
93    GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
94  }
95
96  void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
97                          bool video, FakeConstraints video_constraints) {
98    caller_->GetAndAddUserMedia(audio, audio_constraints,
99                                video, video_constraints);
100    callee_->GetAndAddUserMedia(audio, audio_constraints,
101                                video, video_constraints);
102  }
103
104  void Negotiate() {
105    caller_->CreateOffer(NULL);
106  }
107
108  void WaitForCallEstablished() {
109    caller_->WaitForCallEstablished();
110    callee_->WaitForCallEstablished();
111  }
112
113  void WaitForConnection() {
114    caller_->WaitForConnection();
115    callee_->WaitForConnection();
116  }
117
118  void OnCallerAddedDataChanel(DataChannelInterface* dc) {
119    caller_signaled_data_channels_.push_back(dc);
120  }
121
122  void OnCalleeAddedDataChannel(DataChannelInterface* dc) {
123    callee_signaled_data_channels_.push_back(dc);
124  }
125
126  // Tests that |dc1| and |dc2| can send to and receive from each other.
127  void TestDataChannelSendAndReceive(
128      DataChannelInterface* dc1, DataChannelInterface* dc2) {
129    rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer(
130        new webrtc::MockDataChannelObserver(dc1));
131
132    rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
133        new webrtc::MockDataChannelObserver(dc2));
134
135    static const std::string kDummyData = "abcdefg";
136    webrtc::DataBuffer buffer(kDummyData);
137    EXPECT_TRUE(dc1->Send(buffer));
138    EXPECT_EQ_WAIT(kDummyData, dc2_observer->last_message(), kMaxWait);
139
140    EXPECT_TRUE(dc2->Send(buffer));
141    EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait);
142
143    EXPECT_EQ(1U, dc1_observer->received_message_count());
144    EXPECT_EQ(1U, dc2_observer->received_message_count());
145  }
146
147  void WaitForDataChannelsToOpen(DataChannelInterface* local_dc,
148                                 const DataChannelList& remote_dc_list,
149                                 size_t remote_dc_index) {
150    EXPECT_EQ_WAIT(DataChannelInterface::kOpen, local_dc->state(), kMaxWait);
151
152    EXPECT_TRUE_WAIT(remote_dc_list.size() > remote_dc_index, kMaxWait);
153    EXPECT_EQ_WAIT(DataChannelInterface::kOpen,
154                   remote_dc_list[remote_dc_index]->state(),
155                   kMaxWait);
156    EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id());
157  }
158
159  void CloseDataChannels(DataChannelInterface* local_dc,
160                         const DataChannelList& remote_dc_list,
161                         size_t remote_dc_index) {
162    local_dc->Close();
163    EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait);
164    EXPECT_EQ_WAIT(DataChannelInterface::kClosed,
165                   remote_dc_list[remote_dc_index]->state(),
166                   kMaxWait);
167  }
168
169 protected:
170  rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
171  rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
172  DataChannelList caller_signaled_data_channels_;
173  DataChannelList callee_signaled_data_channels_;
174};
175
176// Disabled for TSan v2, see
177// https://bugs.chromium.org/p/webrtc/issues/detail?id=4719 for details.
178// Disabled for Mac, see
179// https://bugs.chromium.org/p/webrtc/issues/detail?id=5231 for details.
180#if !defined(THREAD_SANITIZER) && !defined(WEBRTC_MAC)
181TEST_F(PeerConnectionEndToEndTest, Call) {
182  CreatePcs();
183  GetAndAddUserMedia();
184  Negotiate();
185  WaitForCallEstablished();
186}
187#endif // if !defined(THREAD_SANITIZER) && !defined(WEBRTC_MAC)
188
189TEST_F(PeerConnectionEndToEndTest, CallWithLegacySdp) {
190  FakeConstraints pc_constraints;
191  pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
192                              false);
193  CreatePcs(&pc_constraints);
194  GetAndAddUserMedia();
195  Negotiate();
196  WaitForCallEstablished();
197}
198
199// Verifies that a DataChannel created before the negotiation can transition to
200// "OPEN" and transfer data.
201TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
202  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
203
204  CreatePcs();
205
206  webrtc::DataChannelInit init;
207  rtc::scoped_refptr<DataChannelInterface> caller_dc(
208      caller_->CreateDataChannel("data", init));
209  rtc::scoped_refptr<DataChannelInterface> callee_dc(
210      callee_->CreateDataChannel("data", init));
211
212  Negotiate();
213  WaitForConnection();
214
215  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
216  WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
217
218  TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
219  TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
220
221  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
222  CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
223}
224
225// Verifies that a DataChannel created after the negotiation can transition to
226// "OPEN" and transfer data.
227#if defined(MEMORY_SANITIZER)
228// Fails under MemorySanitizer:
229// See https://code.google.com/p/webrtc/issues/detail?id=3980.
230#define MAYBE_CreateDataChannelAfterNegotiate DISABLED_CreateDataChannelAfterNegotiate
231#else
232#define MAYBE_CreateDataChannelAfterNegotiate CreateDataChannelAfterNegotiate
233#endif
234TEST_F(PeerConnectionEndToEndTest, MAYBE_CreateDataChannelAfterNegotiate) {
235  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
236
237  CreatePcs();
238
239  webrtc::DataChannelInit init;
240
241  // This DataChannel is for creating the data content in the negotiation.
242  rtc::scoped_refptr<DataChannelInterface> dummy(
243      caller_->CreateDataChannel("data", init));
244  Negotiate();
245  WaitForConnection();
246
247  // Creates new DataChannels after the negotiation and verifies their states.
248  rtc::scoped_refptr<DataChannelInterface> caller_dc(
249      caller_->CreateDataChannel("hello", init));
250  rtc::scoped_refptr<DataChannelInterface> callee_dc(
251      callee_->CreateDataChannel("hello", init));
252
253  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
254  WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
255
256  TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
257  TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
258
259  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
260  CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
261}
262
263// Verifies that DataChannel IDs are even/odd based on the DTLS roles.
264TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
265  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
266
267  CreatePcs();
268
269  webrtc::DataChannelInit init;
270  rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
271      caller_->CreateDataChannel("data", init));
272  rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
273      callee_->CreateDataChannel("data", init));
274
275  Negotiate();
276  WaitForConnection();
277
278  EXPECT_EQ(1U, caller_dc_1->id() % 2);
279  EXPECT_EQ(0U, callee_dc_1->id() % 2);
280
281  rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
282      caller_->CreateDataChannel("data", init));
283  rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
284      callee_->CreateDataChannel("data", init));
285
286  EXPECT_EQ(1U, caller_dc_2->id() % 2);
287  EXPECT_EQ(0U, callee_dc_2->id() % 2);
288}
289
290// Verifies that the message is received by the right remote DataChannel when
291// there are multiple DataChannels.
292TEST_F(PeerConnectionEndToEndTest,
293       MessageTransferBetweenTwoPairsOfDataChannels) {
294  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
295
296  CreatePcs();
297
298  webrtc::DataChannelInit init;
299
300  rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
301      caller_->CreateDataChannel("data", init));
302  rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
303      caller_->CreateDataChannel("data", init));
304
305  Negotiate();
306  WaitForConnection();
307  WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
308  WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
309
310  rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
311      new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
312
313  rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
314      new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
315
316  const std::string message_1 = "hello 1";
317  const std::string message_2 = "hello 2";
318
319  caller_dc_1->Send(webrtc::DataBuffer(message_1));
320  EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
321
322  caller_dc_2->Send(webrtc::DataBuffer(message_2));
323  EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
324
325  EXPECT_EQ(1U, dc_1_observer->received_message_count());
326  EXPECT_EQ(1U, dc_2_observer->received_message_count());
327}
328
329// Verifies that a DataChannel added from an OPEN message functions after
330// a channel has been previously closed (webrtc issue 3778).
331// This previously failed because the new channel re-uses the ID of the closed
332// channel, and the closed channel was incorrectly still assigned to the id.
333// TODO(deadbeef): This is disabled because there's currently a race condition
334// caused by the fact that a data channel signals that it's closed before it
335// really is. Re-enable this test once that's fixed.
336TEST_F(PeerConnectionEndToEndTest,
337       DISABLED_DataChannelFromOpenWorksAfterClose) {
338  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
339
340  CreatePcs();
341
342  webrtc::DataChannelInit init;
343  rtc::scoped_refptr<DataChannelInterface> caller_dc(
344      caller_->CreateDataChannel("data", init));
345
346  Negotiate();
347  WaitForConnection();
348
349  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
350  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
351
352  // Create a new channel and ensure it works after closing the previous one.
353  caller_dc = caller_->CreateDataChannel("data2", init);
354
355  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
356  TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
357
358  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
359}
360
361// This tests that if a data channel is closed remotely while not referenced
362// by the application (meaning only the PeerConnection contributes to its
363// reference count), no memory access violation will occur.
364// See: https://code.google.com/p/chromium/issues/detail?id=565048
365TEST_F(PeerConnectionEndToEndTest, CloseDataChannelRemotelyWhileNotReferenced) {
366  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
367
368  CreatePcs();
369
370  webrtc::DataChannelInit init;
371  rtc::scoped_refptr<DataChannelInterface> caller_dc(
372      caller_->CreateDataChannel("data", init));
373
374  Negotiate();
375  WaitForConnection();
376
377  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
378  // This removes the reference to the remote data channel that we hold.
379  callee_signaled_data_channels_.clear();
380  caller_dc->Close();
381  EXPECT_EQ_WAIT(DataChannelInterface::kClosed, caller_dc->state(), kMaxWait);
382
383  // Wait for a bit longer so the remote data channel will receive the
384  // close message and be destroyed.
385  rtc::Thread::Current()->ProcessMessages(100);
386}
387