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#include "webrtc/base/gunit.h"
31#include "webrtc/base/logging.h"
32#include "webrtc/base/ssladapter.h"
33#include "webrtc/base/sslstreamadapter.h"
34#include "webrtc/base/stringencode.h"
35#include "webrtc/base/stringutils.h"
36
37#define MAYBE_SKIP_TEST(feature)                    \
38  if (!(feature())) {                               \
39    LOG(LS_INFO) << "Feature disabled... skipping"; \
40    return;                                         \
41  }
42
43using webrtc::DataChannelInterface;
44using webrtc::FakeConstraints;
45using webrtc::MediaConstraintsInterface;
46using webrtc::MediaStreamInterface;
47using webrtc::PeerConnectionInterface;
48
49namespace {
50
51const char kExternalGiceUfrag[] = "1234567890123456";
52const char kExternalGicePwd[] = "123456789012345678901234";
53const size_t kMaxWait = 10000;
54
55void RemoveLinesFromSdp(const std::string& line_start,
56                               std::string* sdp) {
57  const char kSdpLineEnd[] = "\r\n";
58  size_t ssrc_pos = 0;
59  while ((ssrc_pos = sdp->find(line_start, ssrc_pos)) !=
60      std::string::npos) {
61    size_t end_ssrc = sdp->find(kSdpLineEnd, ssrc_pos);
62    sdp->erase(ssrc_pos, end_ssrc - ssrc_pos + strlen(kSdpLineEnd));
63  }
64}
65
66// Add |newlines| to the |message| after |line|.
67void InjectAfter(const std::string& line,
68                 const std::string& newlines,
69                 std::string* message) {
70  const std::string tmp = line + newlines;
71  rtc::replace_substrs(line.c_str(), line.length(),
72                             tmp.c_str(), tmp.length(), message);
73}
74
75void Replace(const std::string& line,
76             const std::string& newlines,
77             std::string* message) {
78  rtc::replace_substrs(line.c_str(), line.length(),
79                             newlines.c_str(), newlines.length(), message);
80}
81
82void UseExternalSdes(std::string* sdp) {
83  // Remove current crypto specification.
84  RemoveLinesFromSdp("a=crypto", sdp);
85  RemoveLinesFromSdp("a=fingerprint", sdp);
86  // Add external crypto.
87  const char kAudioSdes[] =
88      "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
89      "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR\r\n";
90  const char kVideoSdes[] =
91      "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
92      "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj\r\n";
93  const char kDataSdes[] =
94      "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
95      "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj\r\n";
96  InjectAfter("a=mid:audio\r\n", kAudioSdes, sdp);
97  InjectAfter("a=mid:video\r\n", kVideoSdes, sdp);
98  InjectAfter("a=mid:data\r\n", kDataSdes, sdp);
99}
100
101void UseGice(std::string* sdp) {
102  InjectAfter("t=0 0\r\n", "a=ice-options:google-ice\r\n", sdp);
103
104  std::string ufragline = "a=ice-ufrag:";
105  std::string pwdline = "a=ice-pwd:";
106  RemoveLinesFromSdp(ufragline, sdp);
107  RemoveLinesFromSdp(pwdline, sdp);
108  ufragline.append(kExternalGiceUfrag);
109  ufragline.append("\r\n");
110  pwdline.append(kExternalGicePwd);
111  pwdline.append("\r\n");
112  const std::string ufrag_pwd = ufragline + pwdline;
113
114  InjectAfter("a=mid:audio\r\n", ufrag_pwd, sdp);
115  InjectAfter("a=mid:video\r\n", ufrag_pwd, sdp);
116  InjectAfter("a=mid:data\r\n", ufrag_pwd, sdp);
117}
118
119void RemoveBundle(std::string* sdp) {
120  RemoveLinesFromSdp("a=group:BUNDLE", sdp);
121}
122
123}  // namespace
124
125class PeerConnectionEndToEndTest
126    : public sigslot::has_slots<>,
127      public testing::Test {
128 public:
129  typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
130      DataChannelList;
131
132  PeerConnectionEndToEndTest()
133      : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
134                    "caller")),
135        callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
136                    "callee")) {
137    rtc::InitializeSSL(NULL);
138  }
139
140  void CreatePcs() {
141    CreatePcs(NULL);
142  }
143
144  void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
145    EXPECT_TRUE(caller_->CreatePc(pc_constraints));
146    EXPECT_TRUE(callee_->CreatePc(pc_constraints));
147    PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
148
149    caller_->SignalOnDataChannel.connect(
150        this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
151    callee_->SignalOnDataChannel.connect(
152        this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
153  }
154
155  void GetAndAddUserMedia() {
156    FakeConstraints audio_constraints;
157    FakeConstraints video_constraints;
158    GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
159  }
160
161  void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
162                          bool video, FakeConstraints video_constraints) {
163    caller_->GetAndAddUserMedia(audio, audio_constraints,
164                                video, video_constraints);
165    callee_->GetAndAddUserMedia(audio, audio_constraints,
166                                video, video_constraints);
167  }
168
169  void Negotiate() {
170    caller_->CreateOffer(NULL);
171  }
172
173  void WaitForCallEstablished() {
174    caller_->WaitForCallEstablished();
175    callee_->WaitForCallEstablished();
176  }
177
178  void WaitForConnection() {
179    caller_->WaitForConnection();
180    callee_->WaitForConnection();
181  }
182
183  void SetupLegacySdpConverter() {
184    caller_->SignalOnSdpCreated.connect(
185      this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
186    callee_->SignalOnSdpCreated.connect(
187      this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
188  }
189
190  void ConvertToLegacySdp(std::string* sdp) {
191    UseExternalSdes(sdp);
192    UseGice(sdp);
193    RemoveBundle(sdp);
194    LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
195  }
196
197  void SetupGiceConverter() {
198    caller_->SignalOnIceCandidateCreated.connect(
199      this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
200    callee_->SignalOnIceCandidateCreated.connect(
201      this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
202  }
203
204  void AddGiceCredsToCandidate(std::string* sdp) {
205    std::string gice_creds = " username ";
206    gice_creds.append(kExternalGiceUfrag);
207    gice_creds.append(" password ");
208    gice_creds.append(kExternalGicePwd);
209    gice_creds.append("\r\n");
210    Replace("\r\n", gice_creds, sdp);
211    LOG(LS_INFO) << "AddGiceCredsToCandidate: " << *sdp;
212  }
213
214  void OnCallerAddedDataChanel(DataChannelInterface* dc) {
215    caller_signaled_data_channels_.push_back(dc);
216  }
217
218  void OnCalleeAddedDataChannel(DataChannelInterface* dc) {
219    callee_signaled_data_channels_.push_back(dc);
220  }
221
222  // Tests that |dc1| and |dc2| can send to and receive from each other.
223  void TestDataChannelSendAndReceive(
224      DataChannelInterface* dc1, DataChannelInterface* dc2) {
225    rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer(
226        new webrtc::MockDataChannelObserver(dc1));
227
228    rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
229        new webrtc::MockDataChannelObserver(dc2));
230
231    static const std::string kDummyData = "abcdefg";
232    webrtc::DataBuffer buffer(kDummyData);
233    EXPECT_TRUE(dc1->Send(buffer));
234    EXPECT_EQ_WAIT(kDummyData, dc2_observer->last_message(), kMaxWait);
235
236    EXPECT_TRUE(dc2->Send(buffer));
237    EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait);
238
239    EXPECT_EQ(1U, dc1_observer->received_message_count());
240    EXPECT_EQ(1U, dc2_observer->received_message_count());
241  }
242
243  void WaitForDataChannelsToOpen(DataChannelInterface* local_dc,
244                                 const DataChannelList& remote_dc_list,
245                                 size_t remote_dc_index) {
246    EXPECT_EQ_WAIT(DataChannelInterface::kOpen, local_dc->state(), kMaxWait);
247
248    EXPECT_TRUE_WAIT(remote_dc_list.size() > remote_dc_index, kMaxWait);
249    EXPECT_EQ_WAIT(DataChannelInterface::kOpen,
250                   remote_dc_list[remote_dc_index]->state(),
251                   kMaxWait);
252    EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id());
253  }
254
255  void CloseDataChannels(DataChannelInterface* local_dc,
256                         const DataChannelList& remote_dc_list,
257                         size_t remote_dc_index) {
258    local_dc->Close();
259    EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait);
260    EXPECT_EQ_WAIT(DataChannelInterface::kClosed,
261                   remote_dc_list[remote_dc_index]->state(),
262                   kMaxWait);
263  }
264
265  ~PeerConnectionEndToEndTest() {
266    rtc::CleanupSSL();
267  }
268
269 protected:
270  rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
271  rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
272  DataChannelList caller_signaled_data_channels_;
273  DataChannelList callee_signaled_data_channels_;
274};
275
276// Disable for TSan v2, see
277// https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
278#if !defined(THREAD_SANITIZER)
279
280TEST_F(PeerConnectionEndToEndTest, Call) {
281  CreatePcs();
282  GetAndAddUserMedia();
283  Negotiate();
284  WaitForCallEstablished();
285}
286
287// Disabled per b/14899892
288TEST_F(PeerConnectionEndToEndTest, DISABLED_CallWithLegacySdp) {
289  FakeConstraints pc_constraints;
290  pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
291                              false);
292  CreatePcs(&pc_constraints);
293  SetupLegacySdpConverter();
294  SetupGiceConverter();
295  GetAndAddUserMedia();
296  Negotiate();
297  WaitForCallEstablished();
298}
299
300// Verifies that a DataChannel created before the negotiation can transition to
301// "OPEN" and transfer data.
302TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
303  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
304
305  CreatePcs();
306
307  webrtc::DataChannelInit init;
308  rtc::scoped_refptr<DataChannelInterface> caller_dc(
309      caller_->CreateDataChannel("data", init));
310  rtc::scoped_refptr<DataChannelInterface> callee_dc(
311      callee_->CreateDataChannel("data", init));
312
313  Negotiate();
314  WaitForConnection();
315
316  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
317  WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
318
319  TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
320  TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
321
322  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
323  CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
324}
325
326// Verifies that a DataChannel created after the negotiation can transition to
327// "OPEN" and transfer data.
328TEST_F(PeerConnectionEndToEndTest, CreateDataChannelAfterNegotiate) {
329  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
330
331  CreatePcs();
332
333  webrtc::DataChannelInit init;
334
335  // This DataChannel is for creating the data content in the negotiation.
336  rtc::scoped_refptr<DataChannelInterface> dummy(
337      caller_->CreateDataChannel("data", init));
338  Negotiate();
339  WaitForConnection();
340
341  // Creates new DataChannels after the negotiation and verifies their states.
342  rtc::scoped_refptr<DataChannelInterface> caller_dc(
343      caller_->CreateDataChannel("hello", init));
344  rtc::scoped_refptr<DataChannelInterface> callee_dc(
345      callee_->CreateDataChannel("hello", init));
346
347  WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
348  WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
349
350  TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
351  TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
352
353  CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
354  CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
355}
356
357// Verifies that DataChannel IDs are even/odd based on the DTLS roles.
358TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
359  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
360
361  CreatePcs();
362
363  webrtc::DataChannelInit init;
364  rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
365      caller_->CreateDataChannel("data", init));
366  rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
367      callee_->CreateDataChannel("data", init));
368
369  Negotiate();
370  WaitForConnection();
371
372  EXPECT_EQ(1U, caller_dc_1->id() % 2);
373  EXPECT_EQ(0U, callee_dc_1->id() % 2);
374
375  rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
376      caller_->CreateDataChannel("data", init));
377  rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
378      callee_->CreateDataChannel("data", init));
379
380  EXPECT_EQ(1U, caller_dc_2->id() % 2);
381  EXPECT_EQ(0U, callee_dc_2->id() % 2);
382}
383
384// Verifies that the message is received by the right remote DataChannel when
385// there are multiple DataChannels.
386TEST_F(PeerConnectionEndToEndTest,
387       MessageTransferBetweenTwoPairsOfDataChannels) {
388  MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
389
390  CreatePcs();
391
392  webrtc::DataChannelInit init;
393
394  rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
395      caller_->CreateDataChannel("data", init));
396  rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
397      caller_->CreateDataChannel("data", init));
398
399  Negotiate();
400  WaitForConnection();
401  WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
402  WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
403
404  rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
405      new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
406
407  rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
408      new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
409
410  const std::string message_1 = "hello 1";
411  const std::string message_2 = "hello 2";
412
413  caller_dc_1->Send(webrtc::DataBuffer(message_1));
414  EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
415
416  caller_dc_2->Send(webrtc::DataBuffer(message_2));
417  EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
418
419  EXPECT_EQ(1U, dc_1_observer->received_message_count());
420  EXPECT_EQ(1U, dc_2_observer->received_message_count());
421}
422#endif // if !defined(THREAD_SANITIZER)
423