• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
46 using webrtc::DataChannelInterface;
47 using webrtc::FakeConstraints;
48 using webrtc::MediaConstraintsInterface;
49 using webrtc::MediaStreamInterface;
50 using webrtc::PeerConnectionInterface;
51 
52 namespace {
53 
54 const size_t kMaxWait = 10000;
55 
56 }  // namespace
57 
58 class PeerConnectionEndToEndTest
59     : public sigslot::has_slots<>,
60       public testing::Test {
61  public:
62   typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
63       DataChannelList;
64 
PeerConnectionEndToEndTest()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 
CreatePcs()75   void CreatePcs() {
76     CreatePcs(NULL);
77   }
78 
CreatePcs(const MediaConstraintsInterface * pc_constraints)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 
GetAndAddUserMedia()90   void GetAndAddUserMedia() {
91     FakeConstraints audio_constraints;
92     FakeConstraints video_constraints;
93     GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
94   }
95 
GetAndAddUserMedia(bool audio,FakeConstraints audio_constraints,bool video,FakeConstraints video_constraints)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 
Negotiate()104   void Negotiate() {
105     caller_->CreateOffer(NULL);
106   }
107 
WaitForCallEstablished()108   void WaitForCallEstablished() {
109     caller_->WaitForCallEstablished();
110     callee_->WaitForCallEstablished();
111   }
112 
WaitForConnection()113   void WaitForConnection() {
114     caller_->WaitForConnection();
115     callee_->WaitForConnection();
116   }
117 
OnCallerAddedDataChanel(DataChannelInterface * dc)118   void OnCallerAddedDataChanel(DataChannelInterface* dc) {
119     caller_signaled_data_channels_.push_back(dc);
120   }
121 
OnCalleeAddedDataChannel(DataChannelInterface * dc)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.
TestDataChannelSendAndReceive(DataChannelInterface * dc1,DataChannelInterface * dc2)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 
WaitForDataChannelsToOpen(DataChannelInterface * local_dc,const DataChannelList & remote_dc_list,size_t remote_dc_index)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 
CloseDataChannels(DataChannelInterface * local_dc,const DataChannelList & remote_dc_list,size_t remote_dc_index)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)
TEST_F(PeerConnectionEndToEndTest,Call)181 TEST_F(PeerConnectionEndToEndTest, Call) {
182   CreatePcs();
183   GetAndAddUserMedia();
184   Negotiate();
185   WaitForCallEstablished();
186 }
187 #endif // if !defined(THREAD_SANITIZER) && !defined(WEBRTC_MAC)
188 
TEST_F(PeerConnectionEndToEndTest,CallWithLegacySdp)189 TEST_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.
TEST_F(PeerConnectionEndToEndTest,CreateDataChannelBeforeNegotiate)201 TEST_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
TEST_F(PeerConnectionEndToEndTest,MAYBE_CreateDataChannelAfterNegotiate)234 TEST_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.
TEST_F(PeerConnectionEndToEndTest,DataChannelIdAssignment)264 TEST_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.
TEST_F(PeerConnectionEndToEndTest,MessageTransferBetweenTwoPairsOfDataChannels)292 TEST_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.
TEST_F(PeerConnectionEndToEndTest,DISABLED_DataChannelFromOpenWorksAfterClose)336 TEST_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
TEST_F(PeerConnectionEndToEndTest,CloseDataChannelRemotelyWhileNotReferenced)365 TEST_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