1 /* 2 * libjingle 3 * Copyright 2012, 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/audiotrack.h" 29 #include "talk/app/webrtc/jsepicecandidate.h" 30 #include "talk/app/webrtc/jsepsessiondescription.h" 31 #include "talk/app/webrtc/mediastreamsignaling.h" 32 #include "talk/app/webrtc/streamcollection.h" 33 #include "talk/app/webrtc/videotrack.h" 34 #include "talk/app/webrtc/test/fakeconstraints.h" 35 #include "talk/app/webrtc/test/fakedtlsidentityservice.h" 36 #include "talk/app/webrtc/test/fakemediastreamsignaling.h" 37 #include "talk/app/webrtc/webrtcsession.h" 38 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" 39 #include "talk/base/fakenetwork.h" 40 #include "talk/base/firewallsocketserver.h" 41 #include "talk/base/gunit.h" 42 #include "talk/base/logging.h" 43 #include "talk/base/network.h" 44 #include "talk/base/physicalsocketserver.h" 45 #include "talk/base/sslstreamadapter.h" 46 #include "talk/base/stringutils.h" 47 #include "talk/base/thread.h" 48 #include "talk/base/virtualsocketserver.h" 49 #include "talk/media/base/fakemediaengine.h" 50 #include "talk/media/base/fakevideorenderer.h" 51 #include "talk/media/base/mediachannel.h" 52 #include "talk/media/devices/fakedevicemanager.h" 53 #include "talk/p2p/base/stunserver.h" 54 #include "talk/p2p/base/teststunserver.h" 55 #include "talk/p2p/client/basicportallocator.h" 56 #include "talk/session/media/channelmanager.h" 57 #include "talk/session/media/mediasession.h" 58 59 #define MAYBE_SKIP_TEST(feature) \ 60 if (!(feature())) { \ 61 LOG(LS_INFO) << "Feature disabled... skipping"; \ 62 return; \ 63 } 64 65 using cricket::BaseSession; 66 using cricket::DF_PLAY; 67 using cricket::DF_SEND; 68 using cricket::FakeVoiceMediaChannel; 69 using cricket::NS_GINGLE_P2P; 70 using cricket::NS_JINGLE_ICE_UDP; 71 using cricket::TransportInfo; 72 using talk_base::SocketAddress; 73 using talk_base::scoped_ptr; 74 using webrtc::CreateSessionDescription; 75 using webrtc::CreateSessionDescriptionObserver; 76 using webrtc::CreateSessionDescriptionRequest; 77 using webrtc::DTLSIdentityRequestObserver; 78 using webrtc::DTLSIdentityServiceInterface; 79 using webrtc::FakeConstraints; 80 using webrtc::IceCandidateCollection; 81 using webrtc::JsepIceCandidate; 82 using webrtc::JsepSessionDescription; 83 using webrtc::PeerConnectionInterface; 84 using webrtc::SessionDescriptionInterface; 85 using webrtc::StreamCollection; 86 using webrtc::WebRtcSession; 87 using webrtc::kMlineMismatch; 88 using webrtc::kSdpWithoutCrypto; 89 using webrtc::kSessionError; 90 using webrtc::kSetLocalSdpFailed; 91 using webrtc::kSetRemoteSdpFailed; 92 using webrtc::kPushDownAnswerTDFailed; 93 using webrtc::kPushDownPranswerTDFailed; 94 using webrtc::kBundleWithoutRtcpMux; 95 96 static const SocketAddress kClientAddr1("11.11.11.11", 0); 97 static const SocketAddress kClientAddr2("22.22.22.22", 0); 98 static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT); 99 100 static const char kSessionVersion[] = "1"; 101 102 // Media index of candidates belonging to the first media content. 103 static const int kMediaContentIndex0 = 0; 104 static const char kMediaContentName0[] = "audio"; 105 106 // Media index of candidates belonging to the second media content. 107 static const int kMediaContentIndex1 = 1; 108 static const char kMediaContentName1[] = "video"; 109 110 static const int kIceCandidatesTimeout = 10000; 111 112 static const cricket::AudioCodec 113 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0); 114 static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0); 115 static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0); 116 117 // Add some extra |newlines| to the |message| after |line|. 118 static void InjectAfter(const std::string& line, 119 const std::string& newlines, 120 std::string* message) { 121 const std::string tmp = line + newlines; 122 talk_base::replace_substrs(line.c_str(), line.length(), 123 tmp.c_str(), tmp.length(), message); 124 } 125 126 class MockIceObserver : public webrtc::IceObserver { 127 public: 128 MockIceObserver() 129 : oncandidatesready_(false), 130 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), 131 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) { 132 } 133 134 virtual void OnIceConnectionChange( 135 PeerConnectionInterface::IceConnectionState new_state) { 136 ice_connection_state_ = new_state; 137 } 138 virtual void OnIceGatheringChange( 139 PeerConnectionInterface::IceGatheringState new_state) { 140 // We can never transition back to "new". 141 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state); 142 ice_gathering_state_ = new_state; 143 144 // oncandidatesready_ really means "ICE gathering is complete". 145 // This if statement ensures that this value remains correct when we 146 // transition from kIceGatheringComplete to kIceGatheringGathering. 147 if (new_state == PeerConnectionInterface::kIceGatheringGathering) { 148 oncandidatesready_ = false; 149 } 150 } 151 152 // Found a new candidate. 153 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { 154 if (candidate->sdp_mline_index() == kMediaContentIndex0) { 155 mline_0_candidates_.push_back(candidate->candidate()); 156 } else if (candidate->sdp_mline_index() == kMediaContentIndex1) { 157 mline_1_candidates_.push_back(candidate->candidate()); 158 } 159 // The ICE gathering state should always be Gathering when a candidate is 160 // received (or possibly Completed in the case of the final candidate). 161 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_); 162 } 163 164 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange. 165 virtual void OnIceComplete() { 166 EXPECT_FALSE(oncandidatesready_); 167 oncandidatesready_ = true; 168 169 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should 170 // be called approximately simultaneously. For ease of testing, this 171 // check additionally requires that they be called in the above order. 172 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete, 173 ice_gathering_state_); 174 } 175 176 bool oncandidatesready_; 177 std::vector<cricket::Candidate> mline_0_candidates_; 178 std::vector<cricket::Candidate> mline_1_candidates_; 179 PeerConnectionInterface::IceConnectionState ice_connection_state_; 180 PeerConnectionInterface::IceGatheringState ice_gathering_state_; 181 }; 182 183 class WebRtcSessionForTest : public webrtc::WebRtcSession { 184 public: 185 WebRtcSessionForTest(cricket::ChannelManager* cmgr, 186 talk_base::Thread* signaling_thread, 187 talk_base::Thread* worker_thread, 188 cricket::PortAllocator* port_allocator, 189 webrtc::IceObserver* ice_observer, 190 webrtc::MediaStreamSignaling* mediastream_signaling) 191 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator, 192 mediastream_signaling) { 193 RegisterIceObserver(ice_observer); 194 } 195 virtual ~WebRtcSessionForTest() {} 196 197 using cricket::BaseSession::GetTransportProxy; 198 using webrtc::WebRtcSession::SetAudioPlayout; 199 using webrtc::WebRtcSession::SetAudioSend; 200 using webrtc::WebRtcSession::SetCaptureDevice; 201 using webrtc::WebRtcSession::SetVideoPlayout; 202 using webrtc::WebRtcSession::SetVideoSend; 203 }; 204 205 class WebRtcSessionCreateSDPObserverForTest 206 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> { 207 public: 208 enum State { 209 kInit, 210 kFailed, 211 kSucceeded, 212 }; 213 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {} 214 215 // CreateSessionDescriptionObserver implementation. 216 virtual void OnSuccess(SessionDescriptionInterface* desc) { 217 description_.reset(desc); 218 state_ = kSucceeded; 219 } 220 virtual void OnFailure(const std::string& error) { 221 state_ = kFailed; 222 } 223 224 SessionDescriptionInterface* description() { return description_.get(); } 225 226 SessionDescriptionInterface* ReleaseDescription() { 227 return description_.release(); 228 } 229 230 State state() const { return state_; } 231 232 protected: 233 ~WebRtcSessionCreateSDPObserverForTest() {} 234 235 private: 236 talk_base::scoped_ptr<SessionDescriptionInterface> description_; 237 State state_; 238 }; 239 240 class FakeAudioRenderer : public cricket::AudioRenderer { 241 public: 242 FakeAudioRenderer() : channel_id_(-1) {} 243 244 virtual void AddChannel(int channel_id) OVERRIDE { 245 ASSERT(channel_id_ == -1); 246 channel_id_ = channel_id; 247 } 248 virtual void RemoveChannel(int channel_id) OVERRIDE { 249 ASSERT(channel_id == channel_id_); 250 channel_id_ = -1; 251 } 252 253 int channel_id() const { return channel_id_; } 254 private: 255 int channel_id_; 256 }; 257 258 class WebRtcSessionTest : public testing::Test { 259 protected: 260 // TODO Investigate why ChannelManager crashes, if it's created 261 // after stun_server. 262 WebRtcSessionTest() 263 : media_engine_(new cricket::FakeMediaEngine()), 264 data_engine_(new cricket::FakeDataEngine()), 265 device_manager_(new cricket::FakeDeviceManager()), 266 channel_manager_(new cricket::ChannelManager( 267 media_engine_, data_engine_, device_manager_, 268 new cricket::CaptureManager(), talk_base::Thread::Current())), 269 tdesc_factory_(new cricket::TransportDescriptionFactory()), 270 desc_factory_(new cricket::MediaSessionDescriptionFactory( 271 channel_manager_.get(), tdesc_factory_.get())), 272 pss_(new talk_base::PhysicalSocketServer), 273 vss_(new talk_base::VirtualSocketServer(pss_.get())), 274 fss_(new talk_base::FirewallSocketServer(vss_.get())), 275 ss_scope_(fss_.get()), 276 stun_server_(talk_base::Thread::Current(), kStunAddr), 277 allocator_(&network_manager_, kStunAddr, 278 SocketAddress(), SocketAddress(), SocketAddress()) { 279 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID); 280 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 281 cricket::PORTALLOCATOR_DISABLE_RELAY | 282 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 283 EXPECT_TRUE(channel_manager_->Init()); 284 desc_factory_->set_add_legacy_streams(false); 285 } 286 287 void AddInterface(const SocketAddress& addr) { 288 network_manager_.AddInterface(addr); 289 } 290 291 void Init(DTLSIdentityServiceInterface* identity_service) { 292 ASSERT_TRUE(session_.get() == NULL); 293 session_.reset(new WebRtcSessionForTest( 294 channel_manager_.get(), talk_base::Thread::Current(), 295 talk_base::Thread::Current(), &allocator_, 296 &observer_, 297 &mediastream_signaling_)); 298 299 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 300 observer_.ice_connection_state_); 301 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 302 observer_.ice_gathering_state_); 303 304 EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service)); 305 } 306 307 void InitWithDtmfCodec() { 308 // Add kTelephoneEventCodec for dtmf test. 309 std::vector<cricket::AudioCodec> codecs; 310 codecs.push_back(kTelephoneEventCodec); 311 media_engine_->SetAudioCodecs(codecs); 312 desc_factory_->set_audio_codecs(codecs); 313 Init(NULL); 314 } 315 316 void InitWithDtls() { 317 constraints_.reset(new FakeConstraints()); 318 constraints_->AddOptional( 319 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true); 320 321 Init(NULL); 322 } 323 324 void InitWithAsyncDtls(bool identity_request_should_fail) { 325 constraints_.reset(new FakeConstraints()); 326 constraints_->AddOptional( 327 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true); 328 FakeIdentityService* identity_service = new FakeIdentityService(); 329 identity_service->set_should_fail(identity_request_should_fail); 330 Init(identity_service); 331 } 332 333 // Creates a local offer and applies it. Starts ice. 334 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function 335 // to decide which streams to create. 336 void InitiateCall() { 337 SessionDescriptionInterface* offer = CreateOffer(NULL); 338 SetLocalDescriptionWithoutError(offer); 339 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew != 340 observer_.ice_gathering_state_, 341 kIceCandidatesTimeout); 342 } 343 344 SessionDescriptionInterface* CreateOffer( 345 const webrtc::MediaConstraintsInterface* constraints) { 346 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 347 observer = new WebRtcSessionCreateSDPObserverForTest(); 348 session_->CreateOffer(observer, constraints); 349 EXPECT_TRUE_WAIT( 350 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 351 1000); 352 return observer->ReleaseDescription(); 353 } 354 355 SessionDescriptionInterface* CreateAnswer( 356 const webrtc::MediaConstraintsInterface* constraints) { 357 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer 358 = new WebRtcSessionCreateSDPObserverForTest(); 359 session_->CreateAnswer(observer, constraints); 360 EXPECT_TRUE_WAIT( 361 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 362 1000); 363 return observer->ReleaseDescription(); 364 } 365 366 bool ChannelsExist() { 367 return (session_->voice_channel() != NULL && 368 session_->video_channel() != NULL); 369 } 370 371 void CheckTransportChannels() { 372 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL); 373 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL); 374 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL); 375 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL); 376 } 377 378 void VerifyCryptoParams(const cricket::SessionDescription* sdp) { 379 ASSERT_TRUE(session_.get() != NULL); 380 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 381 ASSERT_TRUE(content != NULL); 382 const cricket::AudioContentDescription* audio_content = 383 static_cast<const cricket::AudioContentDescription*>( 384 content->description); 385 ASSERT_TRUE(audio_content != NULL); 386 ASSERT_EQ(1U, audio_content->cryptos().size()); 387 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size()); 388 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 389 audio_content->cryptos()[0].cipher_suite); 390 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 391 audio_content->protocol()); 392 393 content = cricket::GetFirstVideoContent(sdp); 394 ASSERT_TRUE(content != NULL); 395 const cricket::VideoContentDescription* video_content = 396 static_cast<const cricket::VideoContentDescription*>( 397 content->description); 398 ASSERT_TRUE(video_content != NULL); 399 ASSERT_EQ(1U, video_content->cryptos().size()); 400 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 401 video_content->cryptos()[0].cipher_suite); 402 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size()); 403 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 404 video_content->protocol()); 405 } 406 407 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) { 408 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 409 ASSERT_TRUE(content != NULL); 410 const cricket::AudioContentDescription* audio_content = 411 static_cast<const cricket::AudioContentDescription*>( 412 content->description); 413 ASSERT_TRUE(audio_content != NULL); 414 ASSERT_EQ(0U, audio_content->cryptos().size()); 415 416 content = cricket::GetFirstVideoContent(sdp); 417 ASSERT_TRUE(content != NULL); 418 const cricket::VideoContentDescription* video_content = 419 static_cast<const cricket::VideoContentDescription*>( 420 content->description); 421 ASSERT_TRUE(video_content != NULL); 422 ASSERT_EQ(0U, video_content->cryptos().size()); 423 424 if (dtls) { 425 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 426 audio_content->protocol()); 427 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 428 video_content->protocol()); 429 } else { 430 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 431 audio_content->protocol()); 432 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 433 video_content->protocol()); 434 } 435 } 436 437 // Set the internal fake description factories to do DTLS-SRTP. 438 void SetFactoryDtlsSrtp() { 439 desc_factory_->set_secure(cricket::SEC_ENABLED); 440 std::string identity_name = "WebRTC" + 441 talk_base::ToString(talk_base::CreateRandomId()); 442 identity_.reset(talk_base::SSLIdentity::Generate(identity_name)); 443 tdesc_factory_->set_identity(identity_.get()); 444 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256); 445 tdesc_factory_->set_secure(cricket::SEC_REQUIRED); 446 } 447 448 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp, 449 bool expected) { 450 const TransportInfo* audio = sdp->GetTransportInfoByName("audio"); 451 ASSERT_TRUE(audio != NULL); 452 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL); 453 if (expected) { 454 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description. 455 identity_fingerprint->algorithm); 456 } 457 const TransportInfo* video = sdp->GetTransportInfoByName("video"); 458 ASSERT_TRUE(video != NULL); 459 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL); 460 if (expected) { 461 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description. 462 identity_fingerprint->algorithm); 463 } 464 } 465 466 void VerifyAnswerFromNonCryptoOffer() { 467 // Create a SDP without Crypto. 468 cricket::MediaSessionOptions options; 469 options.has_video = true; 470 JsepSessionDescription* offer( 471 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 472 ASSERT_TRUE(offer != NULL); 473 VerifyNoCryptoParams(offer->description(), false); 474 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled", 475 offer); 476 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL); 477 // Answer should be NULL as no crypto params in offer. 478 ASSERT_TRUE(answer == NULL); 479 } 480 481 void VerifyAnswerFromCryptoOffer() { 482 cricket::MediaSessionOptions options; 483 options.has_video = true; 484 options.bundle_enabled = true; 485 scoped_ptr<JsepSessionDescription> offer( 486 CreateRemoteOffer(options, cricket::SEC_REQUIRED)); 487 ASSERT_TRUE(offer.get() != NULL); 488 VerifyCryptoParams(offer->description()); 489 SetRemoteDescriptionWithoutError(offer.release()); 490 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 491 ASSERT_TRUE(answer.get() != NULL); 492 VerifyCryptoParams(answer->description()); 493 } 494 495 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1, 496 const cricket::SessionDescription* desc2, 497 bool expect_equal) { 498 if (desc1->contents().size() != desc2->contents().size()) { 499 EXPECT_FALSE(expect_equal); 500 return; 501 } 502 503 const cricket::ContentInfos& contents = desc1->contents(); 504 cricket::ContentInfos::const_iterator it = contents.begin(); 505 506 for (; it != contents.end(); ++it) { 507 const cricket::TransportDescription* transport_desc1 = 508 desc1->GetTransportDescriptionByName(it->name); 509 const cricket::TransportDescription* transport_desc2 = 510 desc2->GetTransportDescriptionByName(it->name); 511 if (!transport_desc1 || !transport_desc2) { 512 EXPECT_FALSE(expect_equal); 513 return; 514 } 515 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd || 516 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) { 517 EXPECT_FALSE(expect_equal); 518 return; 519 } 520 } 521 EXPECT_TRUE(expect_equal); 522 } 523 // Creates a remote offer and and applies it as a remote description, 524 // creates a local answer and applies is as a local description. 525 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function 526 // to decide which local and remote streams to create. 527 void CreateAndSetRemoteOfferAndLocalAnswer() { 528 SessionDescriptionInterface* offer = CreateRemoteOffer(); 529 SetRemoteDescriptionWithoutError(offer); 530 SessionDescriptionInterface* answer = CreateAnswer(NULL); 531 SetLocalDescriptionWithoutError(answer); 532 } 533 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) { 534 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL)); 535 } 536 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc, 537 BaseSession::State expected_state) { 538 SetLocalDescriptionWithoutError(desc); 539 EXPECT_EQ(expected_state, session_->state()); 540 } 541 void SetLocalDescriptionExpectError(const std::string& expected_error, 542 SessionDescriptionInterface* desc) { 543 std::string error; 544 EXPECT_FALSE(session_->SetLocalDescription(desc, &error)); 545 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed)); 546 EXPECT_NE(std::string::npos, error.find(expected_error)); 547 } 548 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) { 549 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL)); 550 } 551 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc, 552 BaseSession::State expected_state) { 553 SetRemoteDescriptionWithoutError(desc); 554 EXPECT_EQ(expected_state, session_->state()); 555 } 556 void SetRemoteDescriptionExpectError(const std::string& expected_error, 557 SessionDescriptionInterface* desc) { 558 std::string error; 559 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error)); 560 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed)); 561 EXPECT_NE(std::string::npos, error.find(expected_error)); 562 } 563 564 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer, 565 SessionDescriptionInterface** nocrypto_answer) { 566 // Create a SDP without Crypto. 567 cricket::MediaSessionOptions options; 568 options.has_video = true; 569 options.bundle_enabled = true; 570 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); 571 ASSERT_TRUE(*offer != NULL); 572 VerifyCryptoParams((*offer)->description()); 573 574 *nocrypto_answer = CreateRemoteAnswer(*offer, options, 575 cricket::SEC_DISABLED); 576 EXPECT_TRUE(*nocrypto_answer != NULL); 577 } 578 579 JsepSessionDescription* CreateRemoteOfferWithVersion( 580 cricket::MediaSessionOptions options, 581 cricket::SecurePolicy secure_policy, 582 const std::string& session_version, 583 const SessionDescriptionInterface* current_desc) { 584 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64()); 585 const cricket::SessionDescription* cricket_desc = NULL; 586 if (current_desc) { 587 cricket_desc = current_desc->description(); 588 session_id = current_desc->session_id(); 589 } 590 591 desc_factory_->set_secure(secure_policy); 592 JsepSessionDescription* offer( 593 new JsepSessionDescription(JsepSessionDescription::kOffer)); 594 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc), 595 session_id, session_version)) { 596 delete offer; 597 offer = NULL; 598 } 599 return offer; 600 } 601 JsepSessionDescription* CreateRemoteOffer( 602 cricket::MediaSessionOptions options) { 603 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 604 kSessionVersion, NULL); 605 } 606 JsepSessionDescription* CreateRemoteOffer( 607 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) { 608 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL); 609 } 610 JsepSessionDescription* CreateRemoteOffer( 611 cricket::MediaSessionOptions options, 612 const SessionDescriptionInterface* current_desc) { 613 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 614 kSessionVersion, current_desc); 615 } 616 617 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX() 618 // before this function to decide which streams to create. 619 JsepSessionDescription* CreateRemoteOffer() { 620 cricket::MediaSessionOptions options; 621 mediastream_signaling_.GetOptionsForAnswer(NULL, &options); 622 return CreateRemoteOffer(options, session_->remote_description()); 623 } 624 625 JsepSessionDescription* CreateRemoteAnswer( 626 const SessionDescriptionInterface* offer, 627 cricket::MediaSessionOptions options, 628 cricket::SecurePolicy policy) { 629 desc_factory_->set_secure(policy); 630 const std::string session_id = 631 talk_base::ToString(talk_base::CreateRandomId64()); 632 JsepSessionDescription* answer( 633 new JsepSessionDescription(JsepSessionDescription::kAnswer)); 634 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(), 635 options, NULL), 636 session_id, kSessionVersion)) { 637 delete answer; 638 answer = NULL; 639 } 640 return answer; 641 } 642 643 JsepSessionDescription* CreateRemoteAnswer( 644 const SessionDescriptionInterface* offer, 645 cricket::MediaSessionOptions options) { 646 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 647 } 648 649 // Creates an answer session description with streams based on 650 // |mediastream_signaling_|. Call 651 // mediastream_signaling_.UseOptionsWithStreamX() before this function 652 // to decide which streams to create. 653 JsepSessionDescription* CreateRemoteAnswer( 654 const SessionDescriptionInterface* offer) { 655 cricket::MediaSessionOptions options; 656 mediastream_signaling_.GetOptionsForAnswer(NULL, &options); 657 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 658 } 659 660 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) { 661 AddInterface(kClientAddr1); 662 Init(NULL); 663 mediastream_signaling_.SendAudioVideoStream1(); 664 FakeConstraints constraints; 665 constraints.SetMandatoryUseRtpMux(bundle); 666 SessionDescriptionInterface* offer = CreateOffer(&constraints); 667 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 668 // and answer. 669 SetLocalDescriptionWithoutError(offer); 670 671 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 672 CreateRemoteAnswer(session_->local_description())); 673 std::string sdp; 674 EXPECT_TRUE(answer->ToString(&sdp)); 675 676 size_t expected_candidate_num = 2; 677 if (!rtcp_mux) { 678 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex 679 // for rtp and rtcp. 680 expected_candidate_num = 4; 681 // Disable rtcp-mux from the answer 682 const std::string kRtcpMux = "a=rtcp-mux"; 683 const std::string kXRtcpMux = "a=xrtcp-mux"; 684 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(), 685 kXRtcpMux.c_str(), kXRtcpMux.length(), 686 &sdp); 687 } 688 689 SessionDescriptionInterface* new_answer = CreateSessionDescription( 690 JsepSessionDescription::kAnswer, sdp, NULL); 691 692 // SetRemoteDescription to enable rtcp mux. 693 SetRemoteDescriptionWithoutError(new_answer); 694 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 695 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size()); 696 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size()); 697 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) { 698 cricket::Candidate c0 = observer_.mline_0_candidates_[i]; 699 cricket::Candidate c1 = observer_.mline_1_candidates_[i]; 700 if (bundle) { 701 EXPECT_TRUE(c0.IsEquivalent(c1)); 702 } else { 703 EXPECT_FALSE(c0.IsEquivalent(c1)); 704 } 705 } 706 } 707 // Tests that we can only send DTMF when the dtmf codec is supported. 708 void TestCanInsertDtmf(bool can) { 709 if (can) { 710 InitWithDtmfCodec(); 711 } else { 712 Init(NULL); 713 } 714 mediastream_signaling_.SendAudioVideoStream1(); 715 CreateAndSetRemoteOfferAndLocalAnswer(); 716 EXPECT_FALSE(session_->CanInsertDtmf("")); 717 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1)); 718 } 719 720 // The method sets up a call from the session to itself, in a loopback 721 // arrangement. It also uses a firewall rule to create a temporary 722 // disconnection. This code is placed as a method so that it can be invoked 723 // by multiple tests with different allocators (e.g. with and without BUNDLE). 724 // While running the call, this method also checks if the session goes through 725 // the correct sequence of ICE states when a connection is established, 726 // broken, and re-established. 727 // The Connection state should go: 728 // New -> Checking -> Connected -> Disconnected -> Connected. 729 // The Gathering state should go: New -> Gathering -> Completed. 730 void TestLoopbackCall() { 731 AddInterface(kClientAddr1); 732 Init(NULL); 733 mediastream_signaling_.SendAudioVideoStream1(); 734 SessionDescriptionInterface* offer = CreateOffer(NULL); 735 736 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 737 observer_.ice_gathering_state_); 738 SetLocalDescriptionWithoutError(offer); 739 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 740 observer_.ice_connection_state_); 741 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering, 742 observer_.ice_gathering_state_, 743 kIceCandidatesTimeout); 744 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 745 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete, 746 observer_.ice_gathering_state_, 747 kIceCandidatesTimeout); 748 749 std::string sdp; 750 offer->ToString(&sdp); 751 SessionDescriptionInterface* desc = 752 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp); 753 ASSERT_TRUE(desc != NULL); 754 SetRemoteDescriptionWithoutError(desc); 755 756 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking, 757 observer_.ice_connection_state_, 758 kIceCandidatesTimeout); 759 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected, 760 observer_.ice_connection_state_, 761 kIceCandidatesTimeout); 762 // TODO(bemasc): EXPECT(Completed) once the details are standardized. 763 764 // Adding firewall rule to block ping requests, which should cause 765 // transport channel failure. 766 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1); 767 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, 768 observer_.ice_connection_state_, 769 kIceCandidatesTimeout); 770 771 // Clearing the rules, session should move back to completed state. 772 fss_->ClearRules(); 773 // Session is automatically calling OnSignalingReady after creation of 774 // new portallocator session which will allocate new set of candidates. 775 776 // TODO(bemasc): Change this to Completed once the details are standardized. 777 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected, 778 observer_.ice_connection_state_, 779 kIceCandidatesTimeout); 780 } 781 782 void VerifyTransportType(const std::string& content_name, 783 cricket::TransportProtocol protocol) { 784 const cricket::Transport* transport = session_->GetTransport(content_name); 785 ASSERT_TRUE(transport != NULL); 786 EXPECT_EQ(protocol, transport->protocol()); 787 } 788 789 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory. 790 void AddCNCodecs() { 791 // Add kTelephoneEventCodec for dtmf test. 792 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();; 793 codecs.push_back(kCNCodec1); 794 codecs.push_back(kCNCodec2); 795 media_engine_->SetAudioCodecs(codecs); 796 desc_factory_->set_audio_codecs(codecs); 797 } 798 799 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) { 800 const cricket::ContentDescription* description = content->description; 801 ASSERT(description != NULL); 802 const cricket::AudioContentDescription* audio_content_desc = 803 static_cast<const cricket::AudioContentDescription*>(description); 804 ASSERT(audio_content_desc != NULL); 805 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) { 806 if (audio_content_desc->codecs()[i].name == "CN") 807 return false; 808 } 809 return true; 810 } 811 812 void SetLocalDescriptionWithDataChannel() { 813 webrtc::DataChannelInit dci; 814 dci.reliable = false; 815 session_->CreateDataChannel("datachannel", &dci); 816 SessionDescriptionInterface* offer = CreateOffer(NULL); 817 SetLocalDescriptionWithoutError(offer); 818 } 819 820 void VerifyMultipleAsyncCreateDescription( 821 bool success, CreateSessionDescriptionRequest::Type type) { 822 InitWithAsyncDtls(!success); 823 824 if (type == CreateSessionDescriptionRequest::kAnswer) { 825 cricket::MediaSessionOptions options; 826 scoped_ptr<JsepSessionDescription> offer( 827 CreateRemoteOffer(options, cricket::SEC_REQUIRED)); 828 ASSERT_TRUE(offer.get() != NULL); 829 SetRemoteDescriptionWithoutError(offer.release()); 830 } 831 832 const int kNumber = 3; 833 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 834 observers[kNumber]; 835 for (int i = 0; i < kNumber; ++i) { 836 observers[i] = new WebRtcSessionCreateSDPObserverForTest(); 837 if (type == CreateSessionDescriptionRequest::kOffer) { 838 session_->CreateOffer(observers[i], NULL); 839 } else { 840 session_->CreateAnswer(observers[i], NULL); 841 } 842 } 843 844 WebRtcSessionCreateSDPObserverForTest::State expected_state = 845 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded : 846 WebRtcSessionCreateSDPObserverForTest::kFailed; 847 848 for (int i = 0; i < kNumber; ++i) { 849 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000); 850 if (success) { 851 EXPECT_TRUE(observers[i]->description() != NULL); 852 } else { 853 EXPECT_TRUE(observers[i]->description() == NULL); 854 } 855 } 856 } 857 858 cricket::FakeMediaEngine* media_engine_; 859 cricket::FakeDataEngine* data_engine_; 860 cricket::FakeDeviceManager* device_manager_; 861 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_; 862 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_; 863 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_; 864 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_; 865 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_; 866 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_; 867 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_; 868 talk_base::SocketServerScope ss_scope_; 869 cricket::TestStunServer stun_server_; 870 talk_base::FakeNetworkManager network_manager_; 871 cricket::BasicPortAllocator allocator_; 872 talk_base::scoped_ptr<FakeConstraints> constraints_; 873 FakeMediaStreamSignaling mediastream_signaling_; 874 talk_base::scoped_ptr<WebRtcSessionForTest> session_; 875 MockIceObserver observer_; 876 cricket::FakeVideoMediaChannel* video_channel_; 877 cricket::FakeVoiceMediaChannel* voice_channel_; 878 }; 879 880 TEST_F(WebRtcSessionTest, TestInitialize) { 881 Init(NULL); 882 } 883 884 TEST_F(WebRtcSessionTest, TestInitializeWithDtls) { 885 InitWithDtls(); 886 } 887 888 // Verifies that WebRtcSession uses SEC_REQUIRED by default. 889 TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) { 890 Init(NULL); 891 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy()); 892 } 893 894 TEST_F(WebRtcSessionTest, TestSessionCandidates) { 895 TestSessionCandidatesWithBundleRtcpMux(false, false); 896 } 897 898 // Below test cases (TestSessionCandidatesWith*) verify the candidates gathered 899 // with rtcp-mux and/or bundle. 900 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) { 901 TestSessionCandidatesWithBundleRtcpMux(false, true); 902 } 903 904 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) { 905 TestSessionCandidatesWithBundleRtcpMux(true, true); 906 } 907 908 TEST_F(WebRtcSessionTest, TestMultihomeCandidates) { 909 AddInterface(kClientAddr1); 910 AddInterface(kClientAddr2); 911 Init(NULL); 912 mediastream_signaling_.SendAudioVideoStream1(); 913 InitiateCall(); 914 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 915 EXPECT_EQ(8u, observer_.mline_0_candidates_.size()); 916 EXPECT_EQ(8u, observer_.mline_1_candidates_.size()); 917 } 918 919 TEST_F(WebRtcSessionTest, TestStunError) { 920 AddInterface(kClientAddr1); 921 AddInterface(kClientAddr2); 922 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1); 923 Init(NULL); 924 mediastream_signaling_.SendAudioVideoStream1(); 925 InitiateCall(); 926 // Since kClientAddr1 is blocked, not expecting stun candidates for it. 927 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 928 EXPECT_EQ(6u, observer_.mline_0_candidates_.size()); 929 EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); 930 } 931 932 // Test creating offers and receive answers and make sure the 933 // media engine creates the expected send and receive streams. 934 TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) { 935 Init(NULL); 936 mediastream_signaling_.SendAudioVideoStream1(); 937 SessionDescriptionInterface* offer = CreateOffer(NULL); 938 const std::string session_id_orig = offer->session_id(); 939 const std::string session_version_orig = offer->session_version(); 940 SetLocalDescriptionWithoutError(offer); 941 942 mediastream_signaling_.SendAudioVideoStream2(); 943 SessionDescriptionInterface* answer = 944 CreateRemoteAnswer(session_->local_description()); 945 SetRemoteDescriptionWithoutError(answer); 946 947 video_channel_ = media_engine_->GetVideoChannel(0); 948 voice_channel_ = media_engine_->GetVoiceChannel(0); 949 950 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 951 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 952 953 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 954 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 955 956 ASSERT_EQ(1u, video_channel_->send_streams().size()); 957 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 958 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 959 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 960 961 // Create new offer without send streams. 962 mediastream_signaling_.SendNothing(); 963 offer = CreateOffer(NULL); 964 965 // Verify the session id is the same and the session version is 966 // increased. 967 EXPECT_EQ(session_id_orig, offer->session_id()); 968 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig), 969 talk_base::FromString<uint64>(offer->session_version())); 970 971 SetLocalDescriptionWithoutError(offer); 972 973 mediastream_signaling_.SendAudioVideoStream2(); 974 answer = CreateRemoteAnswer(session_->local_description()); 975 SetRemoteDescriptionWithoutError(answer); 976 977 EXPECT_EQ(0u, video_channel_->send_streams().size()); 978 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 979 980 // Make sure the receive streams have not changed. 981 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 982 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 983 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 984 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 985 } 986 987 // Test receiving offers and creating answers and make sure the 988 // media engine creates the expected send and receive streams. 989 TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) { 990 Init(NULL); 991 mediastream_signaling_.SendAudioVideoStream2(); 992 SessionDescriptionInterface* offer = CreateOffer(NULL); 993 SetRemoteDescriptionWithoutError(offer); 994 995 mediastream_signaling_.SendAudioVideoStream1(); 996 SessionDescriptionInterface* answer = CreateAnswer(NULL); 997 SetLocalDescriptionWithoutError(answer); 998 999 const std::string session_id_orig = answer->session_id(); 1000 const std::string session_version_orig = answer->session_version(); 1001 1002 video_channel_ = media_engine_->GetVideoChannel(0); 1003 voice_channel_ = media_engine_->GetVoiceChannel(0); 1004 1005 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1006 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1007 1008 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1009 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1010 1011 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1012 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1013 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1014 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1015 1016 mediastream_signaling_.SendAudioVideoStream1And2(); 1017 offer = CreateOffer(NULL); 1018 SetRemoteDescriptionWithoutError(offer); 1019 1020 // Answer by turning off all send streams. 1021 mediastream_signaling_.SendNothing(); 1022 answer = CreateAnswer(NULL); 1023 1024 // Verify the session id is the same and the session version is 1025 // increased. 1026 EXPECT_EQ(session_id_orig, answer->session_id()); 1027 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig), 1028 talk_base::FromString<uint64>(answer->session_version())); 1029 SetLocalDescriptionWithoutError(answer); 1030 1031 ASSERT_EQ(2u, video_channel_->recv_streams().size()); 1032 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id); 1033 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id); 1034 ASSERT_EQ(2u, voice_channel_->recv_streams().size()); 1035 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id); 1036 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id); 1037 1038 // Make sure we have no send streams. 1039 EXPECT_EQ(0u, video_channel_->send_streams().size()); 1040 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 1041 } 1042 1043 // Test we will return fail when apply an offer that doesn't have 1044 // crypto enabled. 1045 TEST_F(WebRtcSessionTest, SetNonCryptoOffer) { 1046 Init(NULL); 1047 cricket::MediaSessionOptions options; 1048 options.has_video = true; 1049 JsepSessionDescription* offer = CreateRemoteOffer( 1050 options, cricket::SEC_DISABLED); 1051 ASSERT_TRUE(offer != NULL); 1052 VerifyNoCryptoParams(offer->description(), false); 1053 // SetRemoteDescription and SetLocalDescription will take the ownership of 1054 // the offer. 1055 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer); 1056 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 1057 ASSERT_TRUE(offer != NULL); 1058 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer); 1059 } 1060 1061 // Test we will return fail when apply an answer that doesn't have 1062 // crypto enabled. 1063 TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) { 1064 Init(NULL); 1065 SessionDescriptionInterface* offer = NULL; 1066 SessionDescriptionInterface* answer = NULL; 1067 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1068 // SetRemoteDescription and SetLocalDescription will take the ownership of 1069 // the offer. 1070 SetRemoteDescriptionWithoutError(offer); 1071 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer); 1072 } 1073 1074 // Test we will return fail when apply an answer that doesn't have 1075 // crypto enabled. 1076 TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) { 1077 Init(NULL); 1078 SessionDescriptionInterface* offer = NULL; 1079 SessionDescriptionInterface* answer = NULL; 1080 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1081 // SetRemoteDescription and SetLocalDescription will take the ownership of 1082 // the offer. 1083 SetLocalDescriptionWithoutError(offer); 1084 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer); 1085 } 1086 1087 // Test that we can create and set an offer with a DTLS fingerprint. 1088 TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) { 1089 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 1090 InitWithDtls(); 1091 mediastream_signaling_.SendAudioVideoStream1(); 1092 SessionDescriptionInterface* offer = CreateOffer(NULL); 1093 ASSERT_TRUE(offer != NULL); 1094 VerifyFingerprintStatus(offer->description(), true); 1095 // SetLocalDescription will take the ownership of the offer. 1096 SetLocalDescriptionWithoutError(offer); 1097 } 1098 1099 // Test that we can process an offer with a DTLS fingerprint 1100 // and that we return an answer with a fingerprint. 1101 TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) { 1102 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 1103 InitWithDtls(); 1104 SetFactoryDtlsSrtp(); 1105 cricket::MediaSessionOptions options; 1106 options.has_video = true; 1107 JsepSessionDescription* offer = CreateRemoteOffer(options); 1108 ASSERT_TRUE(offer != NULL); 1109 VerifyFingerprintStatus(offer->description(), true); 1110 1111 // SetRemoteDescription will take the ownership of the offer. 1112 SetRemoteDescriptionWithoutError(offer); 1113 1114 // Verify that we get a crypto fingerprint in the answer. 1115 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1116 ASSERT_TRUE(answer != NULL); 1117 VerifyFingerprintStatus(answer->description(), true); 1118 // Check that we don't have an a=crypto line in the answer. 1119 VerifyNoCryptoParams(answer->description(), true); 1120 1121 // Now set the local description, which should work, even without a=crypto. 1122 SetLocalDescriptionWithoutError(answer); 1123 } 1124 1125 // Test that even if we support DTLS, if the other side didn't offer a 1126 // fingerprint, we don't either. 1127 TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) { 1128 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 1129 InitWithDtls(); 1130 cricket::MediaSessionOptions options; 1131 options.has_video = true; 1132 JsepSessionDescription* offer = CreateRemoteOffer( 1133 options, cricket::SEC_REQUIRED); 1134 ASSERT_TRUE(offer != NULL); 1135 VerifyFingerprintStatus(offer->description(), false); 1136 1137 // SetRemoteDescription will take the ownership of 1138 // the offer. 1139 SetRemoteDescriptionWithoutError(offer); 1140 1141 // Verify that we don't get a crypto fingerprint in the answer. 1142 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1143 ASSERT_TRUE(answer != NULL); 1144 VerifyFingerprintStatus(answer->description(), false); 1145 1146 // Now set the local description. 1147 SetLocalDescriptionWithoutError(answer); 1148 } 1149 1150 TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) { 1151 Init(NULL); 1152 mediastream_signaling_.SendNothing(); 1153 // SetLocalDescription take ownership of offer. 1154 SessionDescriptionInterface* offer = CreateOffer(NULL); 1155 SetLocalDescriptionWithoutError(offer); 1156 1157 // SetLocalDescription take ownership of offer. 1158 SessionDescriptionInterface* offer2 = CreateOffer(NULL); 1159 SetLocalDescriptionWithoutError(offer2); 1160 } 1161 1162 TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) { 1163 Init(NULL); 1164 mediastream_signaling_.SendNothing(); 1165 // SetLocalDescription take ownership of offer. 1166 SessionDescriptionInterface* offer = CreateOffer(NULL); 1167 SetRemoteDescriptionWithoutError(offer); 1168 1169 SessionDescriptionInterface* offer2 = CreateOffer(NULL); 1170 SetRemoteDescriptionWithoutError(offer2); 1171 } 1172 1173 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) { 1174 Init(NULL); 1175 mediastream_signaling_.SendNothing(); 1176 SessionDescriptionInterface* offer = CreateOffer(NULL); 1177 SetLocalDescriptionWithoutError(offer); 1178 offer = CreateOffer(NULL); 1179 SetRemoteDescriptionExpectError( 1180 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE", 1181 offer); 1182 } 1183 1184 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) { 1185 Init(NULL); 1186 mediastream_signaling_.SendNothing(); 1187 SessionDescriptionInterface* offer = CreateOffer(NULL); 1188 SetRemoteDescriptionWithoutError(offer); 1189 offer = CreateOffer(NULL); 1190 SetLocalDescriptionExpectError( 1191 "Called with type in wrong state, type: " 1192 "offer state: STATE_RECEIVEDINITIATE", 1193 offer); 1194 } 1195 1196 TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) { 1197 Init(NULL); 1198 mediastream_signaling_.SendNothing(); 1199 SessionDescriptionInterface* offer = CreateRemoteOffer(); 1200 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE); 1201 1202 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>( 1203 CreateAnswer(NULL)); 1204 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 1205 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT); 1206 1207 mediastream_signaling_.SendAudioVideoStream1(); 1208 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>( 1209 CreateAnswer(NULL)); 1210 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 1211 1212 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT); 1213 1214 mediastream_signaling_.SendAudioVideoStream2(); 1215 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1216 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT); 1217 } 1218 1219 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) { 1220 Init(NULL); 1221 mediastream_signaling_.SendNothing(); 1222 SessionDescriptionInterface* offer = CreateOffer(NULL); 1223 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE); 1224 1225 JsepSessionDescription* pranswer = 1226 CreateRemoteAnswer(session_->local_description()); 1227 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 1228 1229 SetRemoteDescriptionExpectState(pranswer, 1230 BaseSession::STATE_RECEIVEDPRACCEPT); 1231 1232 mediastream_signaling_.SendAudioVideoStream1(); 1233 JsepSessionDescription* pranswer2 = 1234 CreateRemoteAnswer(session_->local_description()); 1235 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 1236 1237 SetRemoteDescriptionExpectState(pranswer2, 1238 BaseSession::STATE_RECEIVEDPRACCEPT); 1239 1240 mediastream_signaling_.SendAudioVideoStream2(); 1241 SessionDescriptionInterface* answer = 1242 CreateRemoteAnswer(session_->local_description()); 1243 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT); 1244 } 1245 1246 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) { 1247 Init(NULL); 1248 mediastream_signaling_.SendNothing(); 1249 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1250 CreateOffer(NULL)); 1251 SessionDescriptionInterface* answer = 1252 CreateRemoteAnswer(offer.get()); 1253 SetLocalDescriptionExpectError( 1254 "Called with type in wrong state, type: answer state: STATE_INIT", 1255 answer); 1256 } 1257 1258 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) { 1259 Init(NULL); 1260 mediastream_signaling_.SendNothing(); 1261 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1262 CreateOffer(NULL)); 1263 SessionDescriptionInterface* answer = 1264 CreateRemoteAnswer(offer.get()); 1265 SetRemoteDescriptionExpectError( 1266 "Called with type in wrong state, type: answer state: STATE_INIT", 1267 answer); 1268 } 1269 1270 TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) { 1271 Init(NULL); 1272 mediastream_signaling_.SendAudioVideoStream1(); 1273 1274 cricket::Candidate candidate; 1275 candidate.set_component(1); 1276 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate); 1277 1278 // Fail since we have not set a offer description. 1279 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1)); 1280 1281 SessionDescriptionInterface* offer = CreateOffer(NULL); 1282 SetLocalDescriptionWithoutError(offer); 1283 // Candidate should be allowed to add before remote description. 1284 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 1285 candidate.set_component(2); 1286 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate); 1287 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 1288 1289 SessionDescriptionInterface* answer = CreateRemoteAnswer( 1290 session_->local_description()); 1291 SetRemoteDescriptionWithoutError(answer); 1292 1293 // Verifying the candidates are copied properly from internal vector. 1294 const SessionDescriptionInterface* remote_desc = 1295 session_->remote_description(); 1296 ASSERT_TRUE(remote_desc != NULL); 1297 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1298 const IceCandidateCollection* candidates = 1299 remote_desc->candidates(kMediaContentIndex0); 1300 ASSERT_EQ(2u, candidates->count()); 1301 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1302 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid()); 1303 EXPECT_EQ(1, candidates->at(0)->candidate().component()); 1304 EXPECT_EQ(2, candidates->at(1)->candidate().component()); 1305 1306 candidate.set_component(2); 1307 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate); 1308 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3)); 1309 ASSERT_EQ(3u, candidates->count()); 1310 1311 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate); 1312 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate)); 1313 } 1314 1315 // Test that a remote candidate is added to the remote session description and 1316 // that it is retained if the remote session description is changed. 1317 TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) { 1318 Init(NULL); 1319 cricket::Candidate candidate1; 1320 candidate1.set_component(1); 1321 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0, 1322 candidate1); 1323 mediastream_signaling_.SendAudioVideoStream1(); 1324 CreateAndSetRemoteOfferAndLocalAnswer(); 1325 1326 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 1327 const SessionDescriptionInterface* remote_desc = 1328 session_->remote_description(); 1329 ASSERT_TRUE(remote_desc != NULL); 1330 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1331 const IceCandidateCollection* candidates = 1332 remote_desc->candidates(kMediaContentIndex0); 1333 ASSERT_EQ(1u, candidates->count()); 1334 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1335 1336 // Update the RemoteSessionDescription with a new session description and 1337 // a candidate and check that the new remote session description contains both 1338 // candidates. 1339 SessionDescriptionInterface* offer = CreateRemoteOffer(); 1340 cricket::Candidate candidate2; 1341 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 1342 candidate2); 1343 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2)); 1344 SetRemoteDescriptionWithoutError(offer); 1345 1346 remote_desc = session_->remote_description(); 1347 ASSERT_TRUE(remote_desc != NULL); 1348 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1349 candidates = remote_desc->candidates(kMediaContentIndex0); 1350 ASSERT_EQ(2u, candidates->count()); 1351 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1352 // Username and password have be updated with the TransportInfo of the 1353 // SessionDescription, won't be equal to the original one. 1354 candidate2.set_username(candidates->at(0)->candidate().username()); 1355 candidate2.set_password(candidates->at(0)->candidate().password()); 1356 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate())); 1357 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index()); 1358 // No need to verify the username and password. 1359 candidate1.set_username(candidates->at(1)->candidate().username()); 1360 candidate1.set_password(candidates->at(1)->candidate().password()); 1361 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate())); 1362 1363 // Test that the candidate is ignored if we can add the same candidate again. 1364 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 1365 } 1366 1367 // Test that local candidates are added to the local session description and 1368 // that they are retained if the local session description is changed. 1369 TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) { 1370 AddInterface(kClientAddr1); 1371 Init(NULL); 1372 mediastream_signaling_.SendAudioVideoStream1(); 1373 CreateAndSetRemoteOfferAndLocalAnswer(); 1374 1375 const SessionDescriptionInterface* local_desc = session_->local_description(); 1376 const IceCandidateCollection* candidates = 1377 local_desc->candidates(kMediaContentIndex0); 1378 ASSERT_TRUE(candidates != NULL); 1379 EXPECT_EQ(0u, candidates->count()); 1380 1381 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1382 1383 local_desc = session_->local_description(); 1384 candidates = local_desc->candidates(kMediaContentIndex0); 1385 ASSERT_TRUE(candidates != NULL); 1386 EXPECT_LT(0u, candidates->count()); 1387 candidates = local_desc->candidates(1); 1388 ASSERT_TRUE(candidates != NULL); 1389 EXPECT_LT(0u, candidates->count()); 1390 1391 // Update the session descriptions. 1392 mediastream_signaling_.SendAudioVideoStream1(); 1393 CreateAndSetRemoteOfferAndLocalAnswer(); 1394 1395 local_desc = session_->local_description(); 1396 candidates = local_desc->candidates(kMediaContentIndex0); 1397 ASSERT_TRUE(candidates != NULL); 1398 EXPECT_LT(0u, candidates->count()); 1399 candidates = local_desc->candidates(1); 1400 ASSERT_TRUE(candidates != NULL); 1401 EXPECT_LT(0u, candidates->count()); 1402 } 1403 1404 // Test that we can set a remote session description with remote candidates. 1405 TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) { 1406 Init(NULL); 1407 1408 cricket::Candidate candidate1; 1409 candidate1.set_component(1); 1410 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 1411 candidate1); 1412 mediastream_signaling_.SendAudioVideoStream1(); 1413 SessionDescriptionInterface* offer = CreateOffer(NULL); 1414 1415 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 1416 SetRemoteDescriptionWithoutError(offer); 1417 1418 const SessionDescriptionInterface* remote_desc = 1419 session_->remote_description(); 1420 ASSERT_TRUE(remote_desc != NULL); 1421 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1422 const IceCandidateCollection* candidates = 1423 remote_desc->candidates(kMediaContentIndex0); 1424 ASSERT_EQ(1u, candidates->count()); 1425 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1426 1427 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1428 SetLocalDescriptionWithoutError(answer); 1429 } 1430 1431 // Test that offers and answers contains ice candidates when Ice candidates have 1432 // been gathered. 1433 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) { 1434 AddInterface(kClientAddr1); 1435 Init(NULL); 1436 mediastream_signaling_.SendAudioVideoStream1(); 1437 // Ice is started but candidates are not provided until SetLocalDescription 1438 // is called. 1439 EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); 1440 EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); 1441 CreateAndSetRemoteOfferAndLocalAnswer(); 1442 // Wait until at least one local candidate has been collected. 1443 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(), 1444 kIceCandidatesTimeout); 1445 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(), 1446 kIceCandidatesTimeout); 1447 1448 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer( 1449 CreateOffer(NULL)); 1450 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL); 1451 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count()); 1452 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL); 1453 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count()); 1454 1455 SessionDescriptionInterface* remote_offer(CreateRemoteOffer()); 1456 SetRemoteDescriptionWithoutError(remote_offer); 1457 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1458 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL); 1459 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count()); 1460 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL); 1461 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count()); 1462 SetLocalDescriptionWithoutError(answer); 1463 } 1464 1465 // Verifies TransportProxy and media channels are created with content names 1466 // present in the SessionDescription. 1467 TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) { 1468 Init(NULL); 1469 mediastream_signaling_.SendAudioVideoStream1(); 1470 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1471 CreateOffer(NULL)); 1472 1473 // CreateOffer creates session description with the content names "audio" and 1474 // "video". Goal is to modify these content names and verify transport channel 1475 // proxy in the BaseSession, as proxies are created with the content names 1476 // present in SDP. 1477 std::string sdp; 1478 EXPECT_TRUE(offer->ToString(&sdp)); 1479 const std::string kAudioMid = "a=mid:audio"; 1480 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 1481 const std::string kVideoMid = "a=mid:video"; 1482 const std::string kVideoMidReplaceStr = "a=mid:video_content_name"; 1483 1484 // Replacing |audio| with |audio_content_name|. 1485 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 1486 kAudioMidReplaceStr.c_str(), 1487 kAudioMidReplaceStr.length(), 1488 &sdp); 1489 // Replacing |video| with |video_content_name|. 1490 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(), 1491 kVideoMidReplaceStr.c_str(), 1492 kVideoMidReplaceStr.length(), 1493 &sdp); 1494 1495 SessionDescriptionInterface* modified_offer = 1496 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 1497 1498 SetRemoteDescriptionWithoutError(modified_offer); 1499 1500 SessionDescriptionInterface* answer = 1501 CreateAnswer(NULL); 1502 SetLocalDescriptionWithoutError(answer); 1503 1504 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL); 1505 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL); 1506 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL); 1507 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL); 1508 } 1509 1510 // Test that an offer contains the correct media content descriptions based on 1511 // the send streams when no constraints have been set. 1512 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) { 1513 Init(NULL); 1514 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1515 CreateOffer(NULL)); 1516 ASSERT_TRUE(offer != NULL); 1517 const cricket::ContentInfo* content = 1518 cricket::GetFirstAudioContent(offer->description()); 1519 EXPECT_TRUE(content != NULL); 1520 content = cricket::GetFirstVideoContent(offer->description()); 1521 EXPECT_TRUE(content == NULL); 1522 } 1523 1524 // Test that an offer contains the correct media content descriptions based on 1525 // the send streams when no constraints have been set. 1526 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) { 1527 Init(NULL); 1528 // Test Audio only offer. 1529 mediastream_signaling_.UseOptionsAudioOnly(); 1530 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1531 CreateOffer(NULL)); 1532 const cricket::ContentInfo* content = 1533 cricket::GetFirstAudioContent(offer->description()); 1534 EXPECT_TRUE(content != NULL); 1535 content = cricket::GetFirstVideoContent(offer->description()); 1536 EXPECT_TRUE(content == NULL); 1537 1538 // Test Audio / Video offer. 1539 mediastream_signaling_.SendAudioVideoStream1(); 1540 offer.reset(CreateOffer(NULL)); 1541 content = cricket::GetFirstAudioContent(offer->description()); 1542 EXPECT_TRUE(content != NULL); 1543 content = cricket::GetFirstVideoContent(offer->description()); 1544 EXPECT_TRUE(content != NULL); 1545 } 1546 1547 // Test that an offer contains no media content descriptions if 1548 // kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false. 1549 TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) { 1550 Init(NULL); 1551 webrtc::FakeConstraints constraints_no_receive; 1552 constraints_no_receive.SetMandatoryReceiveAudio(false); 1553 constraints_no_receive.SetMandatoryReceiveVideo(false); 1554 1555 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1556 CreateOffer(&constraints_no_receive)); 1557 ASSERT_TRUE(offer != NULL); 1558 const cricket::ContentInfo* content = 1559 cricket::GetFirstAudioContent(offer->description()); 1560 EXPECT_TRUE(content == NULL); 1561 content = cricket::GetFirstVideoContent(offer->description()); 1562 EXPECT_TRUE(content == NULL); 1563 } 1564 1565 // Test that an offer contains only audio media content descriptions if 1566 // kOfferToReceiveAudio constraints are set to true. 1567 TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) { 1568 Init(NULL); 1569 webrtc::FakeConstraints constraints_audio_only; 1570 constraints_audio_only.SetMandatoryReceiveAudio(true); 1571 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1572 CreateOffer(&constraints_audio_only)); 1573 1574 const cricket::ContentInfo* content = 1575 cricket::GetFirstAudioContent(offer->description()); 1576 EXPECT_TRUE(content != NULL); 1577 content = cricket::GetFirstVideoContent(offer->description()); 1578 EXPECT_TRUE(content == NULL); 1579 } 1580 1581 // Test that an offer contains audio and video media content descriptions if 1582 // kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true. 1583 TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) { 1584 Init(NULL); 1585 // Test Audio / Video offer. 1586 webrtc::FakeConstraints constraints_audio_video; 1587 constraints_audio_video.SetMandatoryReceiveAudio(true); 1588 constraints_audio_video.SetMandatoryReceiveVideo(true); 1589 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1590 CreateOffer(&constraints_audio_video)); 1591 const cricket::ContentInfo* content = 1592 cricket::GetFirstAudioContent(offer->description()); 1593 1594 EXPECT_TRUE(content != NULL); 1595 content = cricket::GetFirstVideoContent(offer->description()); 1596 EXPECT_TRUE(content != NULL); 1597 1598 // TODO(perkj): Should the direction be set to SEND_ONLY if 1599 // The constraints is set to not receive audio or video but a track is added? 1600 } 1601 1602 // Test that an answer can not be created if the last remote description is not 1603 // an offer. 1604 TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) { 1605 Init(NULL); 1606 SessionDescriptionInterface* offer = CreateOffer(NULL); 1607 SetLocalDescriptionWithoutError(offer); 1608 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 1609 SetRemoteDescriptionWithoutError(answer); 1610 EXPECT_TRUE(CreateAnswer(NULL) == NULL); 1611 } 1612 1613 // Test that an answer contains the correct media content descriptions when no 1614 // constraints have been set. 1615 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) { 1616 Init(NULL); 1617 // Create a remote offer with audio and video content. 1618 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 1619 SetRemoteDescriptionWithoutError(offer.release()); 1620 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1621 CreateAnswer(NULL)); 1622 const cricket::ContentInfo* content = 1623 cricket::GetFirstAudioContent(answer->description()); 1624 ASSERT_TRUE(content != NULL); 1625 EXPECT_FALSE(content->rejected); 1626 1627 content = cricket::GetFirstVideoContent(answer->description()); 1628 ASSERT_TRUE(content != NULL); 1629 EXPECT_FALSE(content->rejected); 1630 } 1631 1632 // Test that an answer contains the correct media content descriptions when no 1633 // constraints have been set and the offer only contain audio. 1634 TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) { 1635 Init(NULL); 1636 // Create a remote offer with audio only. 1637 cricket::MediaSessionOptions options; 1638 options.has_audio = true; 1639 options.has_video = false; 1640 talk_base::scoped_ptr<JsepSessionDescription> offer( 1641 CreateRemoteOffer(options)); 1642 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL); 1643 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL); 1644 1645 SetRemoteDescriptionWithoutError(offer.release()); 1646 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1647 CreateAnswer(NULL)); 1648 const cricket::ContentInfo* content = 1649 cricket::GetFirstAudioContent(answer->description()); 1650 ASSERT_TRUE(content != NULL); 1651 EXPECT_FALSE(content->rejected); 1652 1653 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL); 1654 } 1655 1656 // Test that an answer contains the correct media content descriptions when no 1657 // constraints have been set. 1658 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) { 1659 Init(NULL); 1660 // Create a remote offer with audio and video content. 1661 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 1662 SetRemoteDescriptionWithoutError(offer.release()); 1663 // Test with a stream with tracks. 1664 mediastream_signaling_.SendAudioVideoStream1(); 1665 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1666 CreateAnswer(NULL)); 1667 const cricket::ContentInfo* content = 1668 cricket::GetFirstAudioContent(answer->description()); 1669 ASSERT_TRUE(content != NULL); 1670 EXPECT_FALSE(content->rejected); 1671 1672 content = cricket::GetFirstVideoContent(answer->description()); 1673 ASSERT_TRUE(content != NULL); 1674 EXPECT_FALSE(content->rejected); 1675 } 1676 1677 // Test that an answer contains the correct media content descriptions when 1678 // constraints have been set but no stream is sent. 1679 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) { 1680 Init(NULL); 1681 // Create a remote offer with audio and video content. 1682 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 1683 SetRemoteDescriptionWithoutError(offer.release()); 1684 1685 webrtc::FakeConstraints constraints_no_receive; 1686 constraints_no_receive.SetMandatoryReceiveAudio(false); 1687 constraints_no_receive.SetMandatoryReceiveVideo(false); 1688 1689 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1690 CreateAnswer(&constraints_no_receive)); 1691 const cricket::ContentInfo* content = 1692 cricket::GetFirstAudioContent(answer->description()); 1693 ASSERT_TRUE(content != NULL); 1694 EXPECT_TRUE(content->rejected); 1695 1696 content = cricket::GetFirstVideoContent(answer->description()); 1697 ASSERT_TRUE(content != NULL); 1698 EXPECT_TRUE(content->rejected); 1699 } 1700 1701 // Test that an answer contains the correct media content descriptions when 1702 // constraints have been set and streams are sent. 1703 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) { 1704 Init(NULL); 1705 // Create a remote offer with audio and video content. 1706 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 1707 SetRemoteDescriptionWithoutError(offer.release()); 1708 1709 webrtc::FakeConstraints constraints_no_receive; 1710 constraints_no_receive.SetMandatoryReceiveAudio(false); 1711 constraints_no_receive.SetMandatoryReceiveVideo(false); 1712 1713 // Test with a stream with tracks. 1714 mediastream_signaling_.SendAudioVideoStream1(); 1715 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1716 CreateAnswer(&constraints_no_receive)); 1717 1718 // TODO(perkj): Should the direction be set to SEND_ONLY? 1719 const cricket::ContentInfo* content = 1720 cricket::GetFirstAudioContent(answer->description()); 1721 ASSERT_TRUE(content != NULL); 1722 EXPECT_FALSE(content->rejected); 1723 1724 // TODO(perkj): Should the direction be set to SEND_ONLY? 1725 content = cricket::GetFirstVideoContent(answer->description()); 1726 ASSERT_TRUE(content != NULL); 1727 EXPECT_FALSE(content->rejected); 1728 } 1729 1730 TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) { 1731 AddCNCodecs(); 1732 Init(NULL); 1733 webrtc::FakeConstraints constraints; 1734 constraints.SetOptionalVAD(false); 1735 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1736 CreateOffer(&constraints)); 1737 const cricket::ContentInfo* content = 1738 cricket::GetFirstAudioContent(offer->description()); 1739 EXPECT_TRUE(content != NULL); 1740 EXPECT_TRUE(VerifyNoCNCodecs(content)); 1741 } 1742 1743 TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) { 1744 AddCNCodecs(); 1745 Init(NULL); 1746 // Create a remote offer with audio and video content. 1747 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 1748 SetRemoteDescriptionWithoutError(offer.release()); 1749 1750 webrtc::FakeConstraints constraints; 1751 constraints.SetOptionalVAD(false); 1752 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1753 CreateAnswer(&constraints)); 1754 const cricket::ContentInfo* content = 1755 cricket::GetFirstAudioContent(answer->description()); 1756 ASSERT_TRUE(content != NULL); 1757 EXPECT_TRUE(VerifyNoCNCodecs(content)); 1758 } 1759 1760 // This test verifies the call setup when remote answer with audio only and 1761 // later updates with video. 1762 TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) { 1763 Init(NULL); 1764 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 1765 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 1766 1767 mediastream_signaling_.SendAudioVideoStream1(); 1768 SessionDescriptionInterface* offer = CreateOffer(NULL); 1769 1770 cricket::MediaSessionOptions options; 1771 options.has_video = false; 1772 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options); 1773 1774 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 1775 // and answer; 1776 SetLocalDescriptionWithoutError(offer); 1777 SetRemoteDescriptionWithoutError(answer); 1778 1779 video_channel_ = media_engine_->GetVideoChannel(0); 1780 voice_channel_ = media_engine_->GetVoiceChannel(0); 1781 1782 ASSERT_TRUE(video_channel_ == NULL); 1783 1784 ASSERT_EQ(0u, voice_channel_->recv_streams().size()); 1785 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1786 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id); 1787 1788 // Let the remote end update the session descriptions, with Audio and Video. 1789 mediastream_signaling_.SendAudioVideoStream2(); 1790 CreateAndSetRemoteOfferAndLocalAnswer(); 1791 1792 video_channel_ = media_engine_->GetVideoChannel(0); 1793 voice_channel_ = media_engine_->GetVoiceChannel(0); 1794 1795 ASSERT_TRUE(video_channel_ != NULL); 1796 ASSERT_TRUE(voice_channel_ != NULL); 1797 1798 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1799 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1800 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 1801 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 1802 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1803 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1804 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 1805 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 1806 1807 // Change session back to audio only. 1808 mediastream_signaling_.UseOptionsAudioOnly(); 1809 CreateAndSetRemoteOfferAndLocalAnswer(); 1810 1811 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 1812 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1813 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 1814 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1815 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 1816 } 1817 1818 // This test verifies the call setup when remote answer with video only and 1819 // later updates with audio. 1820 TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) { 1821 Init(NULL); 1822 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 1823 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 1824 mediastream_signaling_.SendAudioVideoStream1(); 1825 SessionDescriptionInterface* offer = CreateOffer(NULL); 1826 1827 cricket::MediaSessionOptions options; 1828 options.has_audio = false; 1829 options.has_video = true; 1830 SessionDescriptionInterface* answer = CreateRemoteAnswer( 1831 offer, options, cricket::SEC_ENABLED); 1832 1833 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 1834 // and answer. 1835 SetLocalDescriptionWithoutError(offer); 1836 SetRemoteDescriptionWithoutError(answer); 1837 1838 video_channel_ = media_engine_->GetVideoChannel(0); 1839 voice_channel_ = media_engine_->GetVoiceChannel(0); 1840 1841 ASSERT_TRUE(voice_channel_ == NULL); 1842 ASSERT_TRUE(video_channel_ != NULL); 1843 1844 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 1845 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1846 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id); 1847 1848 // Update the session descriptions, with Audio and Video. 1849 mediastream_signaling_.SendAudioVideoStream2(); 1850 CreateAndSetRemoteOfferAndLocalAnswer(); 1851 1852 voice_channel_ = media_engine_->GetVoiceChannel(0); 1853 ASSERT_TRUE(voice_channel_ != NULL); 1854 1855 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1856 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1857 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 1858 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 1859 1860 // Change session back to video only. 1861 mediastream_signaling_.UseOptionsVideoOnly(); 1862 CreateAndSetRemoteOfferAndLocalAnswer(); 1863 1864 video_channel_ = media_engine_->GetVideoChannel(0); 1865 voice_channel_ = media_engine_->GetVoiceChannel(0); 1866 1867 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1868 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 1869 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1870 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 1871 } 1872 1873 TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) { 1874 Init(NULL); 1875 mediastream_signaling_.SendAudioVideoStream1(); 1876 scoped_ptr<SessionDescriptionInterface> offer( 1877 CreateOffer(NULL)); 1878 VerifyCryptoParams(offer->description()); 1879 SetRemoteDescriptionWithoutError(offer.release()); 1880 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 1881 VerifyCryptoParams(answer->description()); 1882 } 1883 1884 TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) { 1885 Init(NULL); 1886 session_->set_secure_policy(cricket::SEC_DISABLED); 1887 mediastream_signaling_.SendAudioVideoStream1(); 1888 scoped_ptr<SessionDescriptionInterface> offer( 1889 CreateOffer(NULL)); 1890 VerifyNoCryptoParams(offer->description(), false); 1891 } 1892 1893 TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) { 1894 Init(NULL); 1895 VerifyAnswerFromNonCryptoOffer(); 1896 } 1897 1898 TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) { 1899 Init(NULL); 1900 VerifyAnswerFromCryptoOffer(); 1901 } 1902 1903 TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) { 1904 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in 1905 // local description is removed by the application, BUNDLE flag should be 1906 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc. 1907 Init(NULL); 1908 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) == 1909 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1910 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 1911 CreateOffer(NULL)); 1912 cricket::SessionDescription* offer_copy = 1913 offer->description()->Copy(); 1914 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 1915 JsepSessionDescription* modified_offer = 1916 new JsepSessionDescription(JsepSessionDescription::kOffer); 1917 modified_offer->Initialize(offer_copy, "1", "1"); 1918 1919 SetLocalDescriptionWithoutError(modified_offer); 1920 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1921 } 1922 1923 TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) { 1924 Init(NULL); 1925 mediastream_signaling_.SendAudioVideoStream1(); 1926 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) == 1927 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1928 FakeConstraints constraints; 1929 constraints.SetMandatoryUseRtpMux(true); 1930 SessionDescriptionInterface* offer = CreateOffer(&constraints); 1931 SetLocalDescriptionWithoutError(offer); 1932 mediastream_signaling_.SendAudioVideoStream2(); 1933 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 1934 CreateRemoteAnswer(session_->local_description())); 1935 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 1936 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 1937 JsepSessionDescription* modified_answer = 1938 new JsepSessionDescription(JsepSessionDescription::kAnswer); 1939 modified_answer->Initialize(answer_copy, "1", "1"); 1940 SetRemoteDescriptionWithoutError(modified_answer); 1941 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) == 1942 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1943 1944 video_channel_ = media_engine_->GetVideoChannel(0); 1945 voice_channel_ = media_engine_->GetVoiceChannel(0); 1946 1947 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1948 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1949 1950 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1951 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1952 1953 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1954 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1955 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1956 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1957 } 1958 1959 // This test verifies that SetLocalDescription and SetRemoteDescription fails 1960 // if BUNDLE is enabled but rtcp-mux is disabled in m-lines. 1961 TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) { 1962 WebRtcSessionTest::Init(NULL); 1963 mediastream_signaling_.SendAudioVideoStream1(); 1964 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) == 1965 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1966 FakeConstraints constraints; 1967 constraints.SetMandatoryUseRtpMux(true); 1968 SessionDescriptionInterface* offer = CreateOffer(&constraints); 1969 std::string offer_str; 1970 offer->ToString(&offer_str); 1971 // Disable rtcp-mux 1972 const std::string rtcp_mux = "rtcp-mux"; 1973 const std::string xrtcp_mux = "xrtcp-mux"; 1974 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(), 1975 xrtcp_mux.c_str(), xrtcp_mux.length(), 1976 &offer_str); 1977 JsepSessionDescription *local_offer = 1978 new JsepSessionDescription(JsepSessionDescription::kOffer); 1979 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL)); 1980 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer); 1981 JsepSessionDescription *remote_offer = 1982 new JsepSessionDescription(JsepSessionDescription::kOffer); 1983 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL)); 1984 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer); 1985 // Trying unmodified SDP. 1986 SetLocalDescriptionWithoutError(offer); 1987 } 1988 1989 TEST_F(WebRtcSessionTest, SetAudioPlayout) { 1990 Init(NULL); 1991 mediastream_signaling_.SendAudioVideoStream1(); 1992 CreateAndSetRemoteOfferAndLocalAnswer(); 1993 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 1994 ASSERT_TRUE(channel != NULL); 1995 ASSERT_EQ(1u, channel->recv_streams().size()); 1996 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc(); 1997 double left_vol, right_vol; 1998 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 1999 EXPECT_EQ(1, left_vol); 2000 EXPECT_EQ(1, right_vol); 2001 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 2002 session_->SetAudioPlayout(receive_ssrc, false, renderer.get()); 2003 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 2004 EXPECT_EQ(0, left_vol); 2005 EXPECT_EQ(0, right_vol); 2006 EXPECT_EQ(0, renderer->channel_id()); 2007 session_->SetAudioPlayout(receive_ssrc, true, NULL); 2008 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 2009 EXPECT_EQ(1, left_vol); 2010 EXPECT_EQ(1, right_vol); 2011 EXPECT_EQ(-1, renderer->channel_id()); 2012 } 2013 2014 TEST_F(WebRtcSessionTest, SetAudioSend) { 2015 Init(NULL); 2016 mediastream_signaling_.SendAudioVideoStream1(); 2017 CreateAndSetRemoteOfferAndLocalAnswer(); 2018 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2019 ASSERT_TRUE(channel != NULL); 2020 ASSERT_EQ(1u, channel->send_streams().size()); 2021 uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2022 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2023 2024 cricket::AudioOptions options; 2025 options.echo_cancellation.Set(true); 2026 2027 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 2028 session_->SetAudioSend(send_ssrc, false, options, renderer.get()); 2029 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 2030 EXPECT_FALSE(channel->options().echo_cancellation.IsSet()); 2031 EXPECT_EQ(0, renderer->channel_id()); 2032 2033 session_->SetAudioSend(send_ssrc, true, options, NULL); 2034 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2035 bool value; 2036 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value)); 2037 EXPECT_TRUE(value); 2038 EXPECT_EQ(-1, renderer->channel_id()); 2039 } 2040 2041 TEST_F(WebRtcSessionTest, SetVideoPlayout) { 2042 Init(NULL); 2043 mediastream_signaling_.SendAudioVideoStream1(); 2044 CreateAndSetRemoteOfferAndLocalAnswer(); 2045 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 2046 ASSERT_TRUE(channel != NULL); 2047 ASSERT_LT(0u, channel->renderers().size()); 2048 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 2049 ASSERT_EQ(1u, channel->recv_streams().size()); 2050 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc(); 2051 cricket::FakeVideoRenderer renderer; 2052 session_->SetVideoPlayout(receive_ssrc, true, &renderer); 2053 EXPECT_TRUE(channel->renderers().begin()->second == &renderer); 2054 session_->SetVideoPlayout(receive_ssrc, false, &renderer); 2055 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 2056 } 2057 2058 TEST_F(WebRtcSessionTest, SetVideoSend) { 2059 Init(NULL); 2060 mediastream_signaling_.SendAudioVideoStream1(); 2061 CreateAndSetRemoteOfferAndLocalAnswer(); 2062 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 2063 ASSERT_TRUE(channel != NULL); 2064 ASSERT_EQ(1u, channel->send_streams().size()); 2065 uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2066 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2067 cricket::VideoOptions* options = NULL; 2068 session_->SetVideoSend(send_ssrc, false, options); 2069 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 2070 session_->SetVideoSend(send_ssrc, true, options); 2071 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2072 } 2073 2074 TEST_F(WebRtcSessionTest, CanNotInsertDtmf) { 2075 TestCanInsertDtmf(false); 2076 } 2077 2078 TEST_F(WebRtcSessionTest, CanInsertDtmf) { 2079 TestCanInsertDtmf(true); 2080 } 2081 2082 TEST_F(WebRtcSessionTest, InsertDtmf) { 2083 // Setup 2084 Init(NULL); 2085 mediastream_signaling_.SendAudioVideoStream1(); 2086 CreateAndSetRemoteOfferAndLocalAnswer(); 2087 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2088 EXPECT_EQ(0U, channel->dtmf_info_queue().size()); 2089 2090 // Insert DTMF 2091 const int expected_flags = DF_SEND; 2092 const int expected_duration = 90; 2093 session_->InsertDtmf(kAudioTrack1, 0, expected_duration); 2094 session_->InsertDtmf(kAudioTrack1, 1, expected_duration); 2095 session_->InsertDtmf(kAudioTrack1, 2, expected_duration); 2096 2097 // Verify 2098 ASSERT_EQ(3U, channel->dtmf_info_queue().size()); 2099 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2100 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0, 2101 expected_duration, expected_flags)); 2102 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1, 2103 expected_duration, expected_flags)); 2104 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2, 2105 expected_duration, expected_flags)); 2106 } 2107 2108 // This test verifies the |initiator| flag when session initiates the call. 2109 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) { 2110 Init(NULL); 2111 EXPECT_FALSE(session_->initiator()); 2112 SessionDescriptionInterface* offer = CreateOffer(NULL); 2113 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2114 SetLocalDescriptionWithoutError(offer); 2115 EXPECT_TRUE(session_->initiator()); 2116 SetRemoteDescriptionWithoutError(answer); 2117 EXPECT_TRUE(session_->initiator()); 2118 } 2119 2120 // This test verifies the |initiator| flag when session receives the call. 2121 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) { 2122 Init(NULL); 2123 EXPECT_FALSE(session_->initiator()); 2124 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2125 SetRemoteDescriptionWithoutError(offer); 2126 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2127 2128 EXPECT_FALSE(session_->initiator()); 2129 SetLocalDescriptionWithoutError(answer); 2130 EXPECT_FALSE(session_->initiator()); 2131 } 2132 2133 // This test verifies the ice protocol type at initiator of the call 2134 // if |a=ice-options:google-ice| is present in answer. 2135 TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) { 2136 Init(NULL); 2137 mediastream_signaling_.SendAudioVideoStream1(); 2138 SessionDescriptionInterface* offer = CreateOffer(NULL); 2139 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 2140 CreateRemoteAnswer(offer)); 2141 SetLocalDescriptionWithoutError(offer); 2142 std::string sdp; 2143 EXPECT_TRUE(answer->ToString(&sdp)); 2144 // Adding ice-options to the session level. 2145 InjectAfter("t=0 0\r\n", 2146 "a=ice-options:google-ice\r\n", 2147 &sdp); 2148 SessionDescriptionInterface* answer_with_gice = 2149 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2150 SetRemoteDescriptionWithoutError(answer_with_gice); 2151 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE); 2152 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE); 2153 } 2154 2155 // This test verifies the ice protocol type at initiator of the call 2156 // if ICE RFC5245 is supported in answer. 2157 TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) { 2158 Init(NULL); 2159 mediastream_signaling_.SendAudioVideoStream1(); 2160 SessionDescriptionInterface* offer = CreateOffer(NULL); 2161 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2162 SetLocalDescriptionWithoutError(offer); 2163 2164 SetRemoteDescriptionWithoutError(answer); 2165 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245); 2166 VerifyTransportType("video", cricket::ICEPROTO_RFC5245); 2167 } 2168 2169 // This test verifies the ice protocol type at receiver side of the call if 2170 // receiver decides to use google-ice. 2171 TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) { 2172 Init(NULL); 2173 mediastream_signaling_.SendAudioVideoStream1(); 2174 SessionDescriptionInterface* offer = CreateOffer(NULL); 2175 SetRemoteDescriptionWithoutError(offer); 2176 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 2177 CreateAnswer(NULL)); 2178 std::string sdp; 2179 EXPECT_TRUE(answer->ToString(&sdp)); 2180 // Adding ice-options to the session level. 2181 InjectAfter("t=0 0\r\n", 2182 "a=ice-options:google-ice\r\n", 2183 &sdp); 2184 SessionDescriptionInterface* answer_with_gice = 2185 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2186 SetLocalDescriptionWithoutError(answer_with_gice); 2187 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE); 2188 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE); 2189 } 2190 2191 // This test verifies the ice protocol type at receiver side of the call if 2192 // receiver decides to use ice RFC 5245. 2193 TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) { 2194 Init(NULL); 2195 mediastream_signaling_.SendAudioVideoStream1(); 2196 SessionDescriptionInterface* offer = CreateOffer(NULL); 2197 SetRemoteDescriptionWithoutError(offer); 2198 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2199 SetLocalDescriptionWithoutError(answer); 2200 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245); 2201 VerifyTransportType("video", cricket::ICEPROTO_RFC5245); 2202 } 2203 2204 // This test verifies the session state when ICE RFC5245 in offer and 2205 // ICE google-ice in answer. 2206 TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) { 2207 Init(NULL); 2208 mediastream_signaling_.SendAudioVideoStream1(); 2209 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 2210 CreateOffer(NULL)); 2211 std::string offer_str; 2212 offer->ToString(&offer_str); 2213 // Disable google-ice 2214 const std::string gice_option = "google-ice"; 2215 const std::string xgoogle_xice = "xgoogle-xice"; 2216 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(), 2217 xgoogle_xice.c_str(), xgoogle_xice.length(), 2218 &offer_str); 2219 JsepSessionDescription *ice_only_offer = 2220 new JsepSessionDescription(JsepSessionDescription::kOffer); 2221 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL)); 2222 SetLocalDescriptionWithoutError(ice_only_offer); 2223 std::string original_offer_sdp; 2224 EXPECT_TRUE(offer->ToString(&original_offer_sdp)); 2225 SessionDescriptionInterface* pranswer_with_gice = 2226 CreateSessionDescription(JsepSessionDescription::kPrAnswer, 2227 original_offer_sdp, NULL); 2228 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed, 2229 pranswer_with_gice); 2230 SessionDescriptionInterface* answer_with_gice = 2231 CreateSessionDescription(JsepSessionDescription::kAnswer, 2232 original_offer_sdp, NULL); 2233 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed, 2234 answer_with_gice); 2235 } 2236 2237 // Verifing local offer and remote answer have matching m-lines as per RFC 3264. 2238 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) { 2239 Init(NULL); 2240 mediastream_signaling_.SendAudioVideoStream1(); 2241 SessionDescriptionInterface* offer = CreateOffer(NULL); 2242 SetLocalDescriptionWithoutError(offer); 2243 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 2244 CreateRemoteAnswer(session_->local_description())); 2245 2246 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 2247 answer_copy->RemoveContentByName("video"); 2248 JsepSessionDescription* modified_answer = 2249 new JsepSessionDescription(JsepSessionDescription::kAnswer); 2250 2251 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 2252 answer->session_id(), 2253 answer->session_version())); 2254 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer); 2255 2256 // Modifying content names. 2257 std::string sdp; 2258 EXPECT_TRUE(answer->ToString(&sdp)); 2259 const std::string kAudioMid = "a=mid:audio"; 2260 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 2261 2262 // Replacing |audio| with |audio_content_name|. 2263 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 2264 kAudioMidReplaceStr.c_str(), 2265 kAudioMidReplaceStr.length(), 2266 &sdp); 2267 2268 SessionDescriptionInterface* modified_answer1 = 2269 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2270 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1); 2271 2272 SetRemoteDescriptionWithoutError(answer.release()); 2273 } 2274 2275 // Verifying remote offer and local answer have matching m-lines as per 2276 // RFC 3264. 2277 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) { 2278 Init(NULL); 2279 mediastream_signaling_.SendAudioVideoStream1(); 2280 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2281 SetRemoteDescriptionWithoutError(offer); 2282 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2283 2284 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 2285 answer_copy->RemoveContentByName("video"); 2286 JsepSessionDescription* modified_answer = 2287 new JsepSessionDescription(JsepSessionDescription::kAnswer); 2288 2289 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 2290 answer->session_id(), 2291 answer->session_version())); 2292 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer); 2293 SetLocalDescriptionWithoutError(answer); 2294 } 2295 2296 // This test verifies that WebRtcSession does not start candidate allocation 2297 // before SetLocalDescription is called. 2298 TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) { 2299 Init(NULL); 2300 mediastream_signaling_.SendAudioVideoStream1(); 2301 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2302 cricket::Candidate candidate; 2303 candidate.set_component(1); 2304 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 2305 candidate); 2306 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 2307 cricket::Candidate candidate1; 2308 candidate1.set_component(1); 2309 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1, 2310 candidate1); 2311 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1)); 2312 SetRemoteDescriptionWithoutError(offer); 2313 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL); 2314 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL); 2315 2316 // Pump for 1 second and verify that no candidates are generated. 2317 talk_base::Thread::Current()->ProcessMessages(1000); 2318 EXPECT_TRUE(observer_.mline_0_candidates_.empty()); 2319 EXPECT_TRUE(observer_.mline_1_candidates_.empty()); 2320 2321 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2322 SetLocalDescriptionWithoutError(answer); 2323 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated()); 2324 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated()); 2325 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 2326 } 2327 2328 // This test verifies that crypto parameter is updated in local session 2329 // description as per security policy set in MediaSessionDescriptionFactory. 2330 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) { 2331 Init(NULL); 2332 mediastream_signaling_.SendAudioVideoStream1(); 2333 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 2334 CreateOffer(NULL)); 2335 2336 // Making sure SetLocalDescription correctly sets crypto value in 2337 // SessionDescription object after de-serialization of sdp string. The value 2338 // will be set as per MediaSessionDescriptionFactory. 2339 std::string offer_str; 2340 offer->ToString(&offer_str); 2341 SessionDescriptionInterface* jsep_offer_str = 2342 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 2343 SetLocalDescriptionWithoutError(jsep_offer_str); 2344 EXPECT_TRUE(session_->voice_channel()->secure_required()); 2345 EXPECT_TRUE(session_->video_channel()->secure_required()); 2346 } 2347 2348 // This test verifies the crypto parameter when security is disabled. 2349 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) { 2350 Init(NULL); 2351 mediastream_signaling_.SendAudioVideoStream1(); 2352 session_->set_secure_policy(cricket::SEC_DISABLED); 2353 talk_base::scoped_ptr<SessionDescriptionInterface> offer( 2354 CreateOffer(NULL)); 2355 2356 // Making sure SetLocalDescription correctly sets crypto value in 2357 // SessionDescription object after de-serialization of sdp string. The value 2358 // will be set as per MediaSessionDescriptionFactory. 2359 std::string offer_str; 2360 offer->ToString(&offer_str); 2361 SessionDescriptionInterface *jsep_offer_str = 2362 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 2363 SetLocalDescriptionWithoutError(jsep_offer_str); 2364 EXPECT_FALSE(session_->voice_channel()->secure_required()); 2365 EXPECT_FALSE(session_->video_channel()->secure_required()); 2366 } 2367 2368 // This test verifies that an answer contains new ufrag and password if an offer 2369 // with new ufrag and password is received. 2370 TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { 2371 Init(NULL); 2372 cricket::MediaSessionOptions options; 2373 options.has_audio = true; 2374 options.has_video = true; 2375 talk_base::scoped_ptr<JsepSessionDescription> offer( 2376 CreateRemoteOffer(options)); 2377 SetRemoteDescriptionWithoutError(offer.release()); 2378 2379 mediastream_signaling_.SendAudioVideoStream1(); 2380 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 2381 CreateAnswer(NULL)); 2382 SetLocalDescriptionWithoutError(answer.release()); 2383 2384 // Receive an offer with new ufrag and password. 2385 options.transport_options.ice_restart = true; 2386 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1( 2387 CreateRemoteOffer(options, session_->remote_description())); 2388 SetRemoteDescriptionWithoutError(updated_offer1.release()); 2389 2390 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1( 2391 CreateAnswer(NULL)); 2392 2393 CompareIceUfragAndPassword(updated_answer1->description(), 2394 session_->local_description()->description(), 2395 false); 2396 2397 SetLocalDescriptionWithoutError(updated_answer1.release()); 2398 } 2399 2400 // This test verifies that an answer contains old ufrag and password if an offer 2401 // with old ufrag and password is received. 2402 TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) { 2403 Init(NULL); 2404 cricket::MediaSessionOptions options; 2405 options.has_audio = true; 2406 options.has_video = true; 2407 talk_base::scoped_ptr<JsepSessionDescription> offer( 2408 CreateRemoteOffer(options)); 2409 SetRemoteDescriptionWithoutError(offer.release()); 2410 2411 mediastream_signaling_.SendAudioVideoStream1(); 2412 talk_base::scoped_ptr<SessionDescriptionInterface> answer( 2413 CreateAnswer(NULL)); 2414 SetLocalDescriptionWithoutError(answer.release()); 2415 2416 // Receive an offer without changed ufrag or password. 2417 options.transport_options.ice_restart = false; 2418 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2( 2419 CreateRemoteOffer(options, session_->remote_description())); 2420 SetRemoteDescriptionWithoutError(updated_offer2.release()); 2421 2422 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2( 2423 CreateAnswer(NULL)); 2424 2425 CompareIceUfragAndPassword(updated_answer2->description(), 2426 session_->local_description()->description(), 2427 true); 2428 2429 SetLocalDescriptionWithoutError(updated_answer2.release()); 2430 } 2431 2432 TEST_F(WebRtcSessionTest, TestSessionContentError) { 2433 Init(NULL); 2434 mediastream_signaling_.SendAudioVideoStream1(); 2435 SessionDescriptionInterface* offer = CreateOffer(NULL); 2436 const std::string session_id_orig = offer->session_id(); 2437 const std::string session_version_orig = offer->session_version(); 2438 SetLocalDescriptionWithoutError(offer); 2439 2440 video_channel_ = media_engine_->GetVideoChannel(0); 2441 video_channel_->set_fail_set_send_codecs(true); 2442 2443 mediastream_signaling_.SendAudioVideoStream2(); 2444 SessionDescriptionInterface* answer = 2445 CreateRemoteAnswer(session_->local_description()); 2446 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer); 2447 } 2448 2449 // Runs the loopback call test with BUNDLE and STUN disabled. 2450 TEST_F(WebRtcSessionTest, TestIceStatesBasic) { 2451 // Lets try with only UDP ports. 2452 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | 2453 cricket::PORTALLOCATOR_DISABLE_TCP | 2454 cricket::PORTALLOCATOR_DISABLE_STUN | 2455 cricket::PORTALLOCATOR_DISABLE_RELAY); 2456 TestLoopbackCall(); 2457 } 2458 2459 // Regression-test for a crash which should have been an error. 2460 TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) { 2461 Init(NULL); 2462 cricket::MediaSessionOptions options; 2463 options.has_audio = true; 2464 options.has_video = true; 2465 2466 session_->SetError(cricket::BaseSession::ERROR_CONTENT); 2467 SessionDescriptionInterface* offer = CreateRemoteOffer(options); 2468 SessionDescriptionInterface* answer = 2469 CreateRemoteAnswer(offer, options); 2470 SetRemoteDescriptionExpectError(kSessionError, offer); 2471 SetLocalDescriptionExpectError(kSessionError, answer); 2472 // Not crashing is our success. 2473 } 2474 2475 TEST_F(WebRtcSessionTest, TestRtpDataChannel) { 2476 constraints_.reset(new FakeConstraints()); 2477 constraints_->AddOptional( 2478 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 2479 Init(NULL); 2480 2481 SetLocalDescriptionWithDataChannel(); 2482 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 2483 } 2484 2485 TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) { 2486 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2487 2488 constraints_.reset(new FakeConstraints()); 2489 constraints_->AddOptional( 2490 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 2491 constraints_->AddOptional( 2492 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true); 2493 constraints_->AddOptional( 2494 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true); 2495 Init(NULL); 2496 2497 SetLocalDescriptionWithDataChannel(); 2498 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 2499 } 2500 2501 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) { 2502 constraints_.reset(new FakeConstraints()); 2503 constraints_->AddOptional( 2504 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true); 2505 Init(NULL); 2506 2507 SetLocalDescriptionWithDataChannel(); 2508 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type()); 2509 } 2510 2511 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) { 2512 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2513 2514 constraints_.reset(new FakeConstraints()); 2515 constraints_->AddOptional( 2516 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true); 2517 constraints_->AddOptional( 2518 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true); 2519 Init(NULL); 2520 2521 SetLocalDescriptionWithDataChannel(); 2522 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 2523 } 2524 2525 // Verifies that CreateOffer succeeds when CreateOffer is called before async 2526 // identity generation is finished. 2527 TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) { 2528 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2529 InitWithAsyncDtls(false); 2530 2531 EXPECT_TRUE(session_->waiting_for_identity()); 2532 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL)); 2533 EXPECT_TRUE(offer != NULL); 2534 } 2535 2536 // Verifies that CreateAnswer succeeds when CreateOffer is called before async 2537 // identity generation is finished. 2538 TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) { 2539 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2540 InitWithAsyncDtls(false); 2541 2542 cricket::MediaSessionOptions options; 2543 scoped_ptr<JsepSessionDescription> offer( 2544 CreateRemoteOffer(options, cricket::SEC_REQUIRED)); 2545 ASSERT_TRUE(offer.get() != NULL); 2546 SetRemoteDescriptionWithoutError(offer.release()); 2547 2548 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 2549 EXPECT_TRUE(answer != NULL); 2550 } 2551 2552 // Verifies that CreateOffer succeeds when CreateOffer is called after async 2553 // identity generation is finished. 2554 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) { 2555 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2556 InitWithAsyncDtls(false); 2557 2558 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000); 2559 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL)); 2560 EXPECT_TRUE(offer != NULL); 2561 } 2562 2563 // Verifies that CreateOffer fails when CreateOffer is called after async 2564 // identity generation fails. 2565 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) { 2566 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2567 InitWithAsyncDtls(true); 2568 2569 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000); 2570 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL)); 2571 EXPECT_TRUE(offer == NULL); 2572 } 2573 2574 // Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made 2575 // before async identity generation is finished. 2576 TEST_F(WebRtcSessionTest, 2577 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) { 2578 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2579 VerifyMultipleAsyncCreateDescription( 2580 true, CreateSessionDescriptionRequest::kOffer); 2581 } 2582 2583 // Verifies that CreateOffer fails when Multiple CreateOffer calls are made 2584 // before async identity generation fails. 2585 TEST_F(WebRtcSessionTest, 2586 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) { 2587 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2588 VerifyMultipleAsyncCreateDescription( 2589 false, CreateSessionDescriptionRequest::kOffer); 2590 } 2591 2592 // Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made 2593 // before async identity generation is finished. 2594 TEST_F(WebRtcSessionTest, 2595 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) { 2596 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2597 VerifyMultipleAsyncCreateDescription( 2598 true, CreateSessionDescriptionRequest::kAnswer); 2599 } 2600 2601 // Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made 2602 // before async identity generation fails. 2603 TEST_F(WebRtcSessionTest, 2604 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) { 2605 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp); 2606 VerifyMultipleAsyncCreateDescription( 2607 false, CreateSessionDescriptionRequest::kAnswer); 2608 } 2609 // TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test 2610 // currently fails because upon disconnection and reconnection OnIceComplete is 2611 // called more than once without returning to IceGatheringGathering. 2612