3 * Copyright 2013, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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"
37 #define MAYBE_SKIP_TEST(feature) \
39 LOG(LS_INFO) << "Feature disabled... skipping"; \
43 using webrtc::DataChannelInterface;
44 using webrtc::FakeConstraints;
45 using webrtc::MediaConstraintsInterface;
46 using webrtc::MediaStreamInterface;
47 using webrtc::PeerConnectionInterface;
51 const char kExternalGiceUfrag[] = "1234567890123456";
52 const char kExternalGicePwd[] = "123456789012345678901234";
53 const size_t kMaxWait = 10000;
55 void RemoveLinesFromSdp(const std::string& line_start,
57 const char kSdpLineEnd[] = "\r\n";
59 while ((ssrc_pos = sdp->find(line_start, ssrc_pos)) !=
61 size_t end_ssrc = sdp->find(kSdpLineEnd, ssrc_pos);
62 sdp->erase(ssrc_pos, end_ssrc - ssrc_pos + strlen(kSdpLineEnd));
66 // Add |newlines| to the |message| after |line|.
67 void 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);
75 void 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);
82 void 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);
101 void UseGice(std::string* sdp) {
102 InjectAfter("t=0 0\r\n", "a=ice-options:google-ice\r\n", sdp);
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;
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);
119 void RemoveBundle(std::string* sdp) {
120 RemoveLinesFromSdp("a=group:BUNDLE", sdp);
125 class PeerConnectionEndToEndTest
126 : public sigslot::has_slots<>,
127 public testing::Test {
129 typedef std::vector<rtc::scoped_refptr<DataChannelInterface> >
132 PeerConnectionEndToEndTest()
133 : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
135 callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>(
137 rtc::InitializeSSL(NULL);
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());
149 caller_->SignalOnDataChannel.connect(
150 this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel);
151 callee_->SignalOnDataChannel.connect(
152 this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel);
155 void GetAndAddUserMedia() {
156 FakeConstraints audio_constraints;
157 FakeConstraints video_constraints;
158 GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
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);
170 caller_->CreateOffer(NULL);
173 void WaitForCallEstablished() {
174 caller_->WaitForCallEstablished();
175 callee_->WaitForCallEstablished();
178 void WaitForConnection() {
179 caller_->WaitForConnection();
180 callee_->WaitForConnection();
183 void SetupLegacySdpConverter() {
184 caller_->SignalOnSdpCreated.connect(
185 this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
186 callee_->SignalOnSdpCreated.connect(
187 this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
190 void ConvertToLegacySdp(std::string* sdp) {
191 UseExternalSdes(sdp);
194 LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
197 void SetupGiceConverter() {
198 caller_->SignalOnIceCandidateCreated.connect(
199 this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
200 callee_->SignalOnIceCandidateCreated.connect(
201 this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
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;
214 void OnCallerAddedDataChanel(DataChannelInterface* dc) {
215 caller_signaled_data_channels_.push_back(dc);
218 void OnCalleeAddedDataChannel(DataChannelInterface* dc) {
219 callee_signaled_data_channels_.push_back(dc);
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));
228 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer(
229 new webrtc::MockDataChannelObserver(dc2));
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);
236 EXPECT_TRUE(dc2->Send(buffer));
237 EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait);
239 EXPECT_EQ(1U, dc1_observer->received_message_count());
240 EXPECT_EQ(1U, dc2_observer->received_message_count());
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);
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(),
252 EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id());
255 void CloseDataChannels(DataChannelInterface* local_dc,
256 const DataChannelList& remote_dc_list,
257 size_t remote_dc_index) {
259 EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait);
260 EXPECT_EQ_WAIT(DataChannelInterface::kClosed,
261 remote_dc_list[remote_dc_index]->state(),
265 ~PeerConnectionEndToEndTest() {
270 rtc::scoped_refptr<PeerConnectionTestWrapper> caller_;
271 rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
272 DataChannelList caller_signaled_data_channels_;
273 DataChannelList callee_signaled_data_channels_;
276 // Disable for TSan v2, see
277 // https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
278 #if !defined(THREAD_SANITIZER)
280 TEST_F(PeerConnectionEndToEndTest, Call) {
282 GetAndAddUserMedia();
284 WaitForCallEstablished();
287 // Disabled per b/14899892
288 TEST_F(PeerConnectionEndToEndTest, DISABLED_CallWithLegacySdp) {
289 FakeConstraints pc_constraints;
290 pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
292 CreatePcs(&pc_constraints);
293 SetupLegacySdpConverter();
294 SetupGiceConverter();
295 GetAndAddUserMedia();
297 WaitForCallEstablished();
300 // Verifies that a DataChannel created before the negotiation can transition to
301 // "OPEN" and transfer data.
302 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) {
303 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
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));
316 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
317 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
319 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]);
320 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
322 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
323 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
326 // Verifies that a DataChannel created after the negotiation can transition to
327 // "OPEN" and transfer data.
328 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelAfterNegotiate) {
329 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
333 webrtc::DataChannelInit init;
335 // This DataChannel is for creating the data content in the negotiation.
336 rtc::scoped_refptr<DataChannelInterface> dummy(
337 caller_->CreateDataChannel("data", init));
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));
347 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
348 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0);
350 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
351 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]);
353 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
354 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0);
357 // Verifies that DataChannel IDs are even/odd based on the DTLS roles.
358 TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) {
359 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
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));
372 EXPECT_EQ(1U, caller_dc_1->id() % 2);
373 EXPECT_EQ(0U, callee_dc_1->id() % 2);
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));
380 EXPECT_EQ(1U, caller_dc_2->id() % 2);
381 EXPECT_EQ(0U, callee_dc_2->id() % 2);
384 // Verifies that the message is received by the right remote DataChannel when
385 // there are multiple DataChannels.
386 TEST_F(PeerConnectionEndToEndTest,
387 MessageTransferBetweenTwoPairsOfDataChannels) {
388 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
392 webrtc::DataChannelInit init;
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));
401 WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0);
402 WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1);
404 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
405 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0]));
407 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
408 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1]));
410 const std::string message_1 = "hello 1";
411 const std::string message_2 = "hello 2";
413 caller_dc_1->Send(webrtc::DataBuffer(message_1));
414 EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
416 caller_dc_2->Send(webrtc::DataBuffer(message_2));
417 EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
419 EXPECT_EQ(1U, dc_1_observer->received_message_count());
420 EXPECT_EQ(1U, dc_2_observer->received_message_count());
422 #endif // if !defined(THREAD_SANITIZER)