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/test/fakeconstraints.h" 34 #include "talk/app/webrtc/test/fakedtlsidentityservice.h" 35 #include "talk/app/webrtc/test/fakemediastreamsignaling.h" 36 #include "talk/app/webrtc/videotrack.h" 37 #include "talk/app/webrtc/webrtcsession.h" 38 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" 39 #include "talk/media/base/fakemediaengine.h" 40 #include "talk/media/base/fakevideorenderer.h" 41 #include "talk/media/base/mediachannel.h" 42 #include "talk/media/devices/fakedevicemanager.h" 43 #include "talk/p2p/base/stunserver.h" 44 #include "talk/p2p/base/teststunserver.h" 45 #include "talk/p2p/base/testturnserver.h" 46 #include "talk/p2p/client/basicportallocator.h" 47 #include "talk/session/media/channelmanager.h" 48 #include "talk/session/media/mediasession.h" 49 #include "webrtc/base/fakenetwork.h" 50 #include "webrtc/base/firewallsocketserver.h" 51 #include "webrtc/base/gunit.h" 52 #include "webrtc/base/logging.h" 53 #include "webrtc/base/network.h" 54 #include "webrtc/base/physicalsocketserver.h" 55 #include "webrtc/base/ssladapter.h" 56 #include "webrtc/base/sslstreamadapter.h" 57 #include "webrtc/base/stringutils.h" 58 #include "webrtc/base/thread.h" 59 #include "webrtc/base/virtualsocketserver.h" 60 61 #define MAYBE_SKIP_TEST(feature) \ 62 if (!(feature())) { \ 63 LOG(LS_INFO) << "Feature disabled... skipping"; \ 64 return; \ 65 } 66 67 using cricket::BaseSession; 68 using cricket::DF_PLAY; 69 using cricket::DF_SEND; 70 using cricket::FakeVoiceMediaChannel; 71 using cricket::NS_GINGLE_P2P; 72 using cricket::NS_JINGLE_ICE_UDP; 73 using cricket::TransportInfo; 74 using rtc::SocketAddress; 75 using rtc::scoped_ptr; 76 using rtc::Thread; 77 using webrtc::CreateSessionDescription; 78 using webrtc::CreateSessionDescriptionObserver; 79 using webrtc::CreateSessionDescriptionRequest; 80 using webrtc::DTLSIdentityRequestObserver; 81 using webrtc::DTLSIdentityServiceInterface; 82 using webrtc::FakeConstraints; 83 using webrtc::IceCandidateCollection; 84 using webrtc::JsepIceCandidate; 85 using webrtc::JsepSessionDescription; 86 using webrtc::PeerConnectionFactoryInterface; 87 using webrtc::PeerConnectionInterface; 88 using webrtc::SessionDescriptionInterface; 89 using webrtc::StreamCollection; 90 using webrtc::WebRtcSession; 91 using webrtc::kBundleWithoutRtcpMux; 92 using webrtc::kCreateChannelFailed; 93 using webrtc::kInvalidSdp; 94 using webrtc::kMlineMismatch; 95 using webrtc::kPushDownTDFailed; 96 using webrtc::kSdpWithoutIceUfragPwd; 97 using webrtc::kSdpWithoutDtlsFingerprint; 98 using webrtc::kSdpWithoutSdesCrypto; 99 using webrtc::kSessionError; 100 using webrtc::kSessionErrorDesc; 101 using webrtc::kMaxUnsignalledRecvStreams; 102 103 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 104 105 static const int kClientAddrPort = 0; 106 static const char kClientAddrHost1[] = "11.11.11.11"; 107 static const char kClientAddrHost2[] = "22.22.22.22"; 108 static const char kStunAddrHost[] = "99.99.99.1"; 109 static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478); 110 static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0); 111 static const char kTurnUsername[] = "test"; 112 static const char kTurnPassword[] = "test"; 113 114 static const char kSessionVersion[] = "1"; 115 116 // Media index of candidates belonging to the first media content. 117 static const int kMediaContentIndex0 = 0; 118 static const char kMediaContentName0[] = "audio"; 119 120 // Media index of candidates belonging to the second media content. 121 static const int kMediaContentIndex1 = 1; 122 static const char kMediaContentName1[] = "video"; 123 124 static const int kIceCandidatesTimeout = 10000; 125 126 static const char kFakeDtlsFingerprint[] = 127 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:" 128 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24"; 129 130 static const char kTooLongIceUfragPwd[] = 131 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 132 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 133 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 134 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"; 135 136 // Add some extra |newlines| to the |message| after |line|. 137 static void InjectAfter(const std::string& line, 138 const std::string& newlines, 139 std::string* message) { 140 const std::string tmp = line + newlines; 141 rtc::replace_substrs(line.c_str(), line.length(), 142 tmp.c_str(), tmp.length(), message); 143 } 144 145 class MockIceObserver : public webrtc::IceObserver { 146 public: 147 MockIceObserver() 148 : oncandidatesready_(false), 149 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), 150 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) { 151 } 152 153 virtual void OnIceConnectionChange( 154 PeerConnectionInterface::IceConnectionState new_state) { 155 ice_connection_state_ = new_state; 156 } 157 virtual void OnIceGatheringChange( 158 PeerConnectionInterface::IceGatheringState new_state) { 159 // We can never transition back to "new". 160 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state); 161 ice_gathering_state_ = new_state; 162 163 // oncandidatesready_ really means "ICE gathering is complete". 164 // This if statement ensures that this value remains correct when we 165 // transition from kIceGatheringComplete to kIceGatheringGathering. 166 if (new_state == PeerConnectionInterface::kIceGatheringGathering) { 167 oncandidatesready_ = false; 168 } 169 } 170 171 // Found a new candidate. 172 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { 173 switch (candidate->sdp_mline_index()) { 174 case kMediaContentIndex0: 175 mline_0_candidates_.push_back(candidate->candidate()); 176 break; 177 case kMediaContentIndex1: 178 mline_1_candidates_.push_back(candidate->candidate()); 179 break; 180 default: 181 ASSERT(false); 182 } 183 184 // The ICE gathering state should always be Gathering when a candidate is 185 // received (or possibly Completed in the case of the final candidate). 186 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_); 187 } 188 189 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange. 190 virtual void OnIceComplete() { 191 EXPECT_FALSE(oncandidatesready_); 192 oncandidatesready_ = true; 193 194 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should 195 // be called approximately simultaneously. For ease of testing, this 196 // check additionally requires that they be called in the above order. 197 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete, 198 ice_gathering_state_); 199 } 200 201 bool oncandidatesready_; 202 std::vector<cricket::Candidate> mline_0_candidates_; 203 std::vector<cricket::Candidate> mline_1_candidates_; 204 PeerConnectionInterface::IceConnectionState ice_connection_state_; 205 PeerConnectionInterface::IceGatheringState ice_gathering_state_; 206 }; 207 208 class WebRtcSessionForTest : public webrtc::WebRtcSession { 209 public: 210 WebRtcSessionForTest(cricket::ChannelManager* cmgr, 211 rtc::Thread* signaling_thread, 212 rtc::Thread* worker_thread, 213 cricket::PortAllocator* port_allocator, 214 webrtc::IceObserver* ice_observer, 215 webrtc::MediaStreamSignaling* mediastream_signaling) 216 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator, 217 mediastream_signaling) { 218 RegisterIceObserver(ice_observer); 219 } 220 virtual ~WebRtcSessionForTest() {} 221 222 using cricket::BaseSession::GetTransportProxy; 223 using webrtc::WebRtcSession::SetAudioPlayout; 224 using webrtc::WebRtcSession::SetAudioSend; 225 using webrtc::WebRtcSession::SetCaptureDevice; 226 using webrtc::WebRtcSession::SetVideoPlayout; 227 using webrtc::WebRtcSession::SetVideoSend; 228 }; 229 230 class WebRtcSessionCreateSDPObserverForTest 231 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> { 232 public: 233 enum State { 234 kInit, 235 kFailed, 236 kSucceeded, 237 }; 238 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {} 239 240 // CreateSessionDescriptionObserver implementation. 241 virtual void OnSuccess(SessionDescriptionInterface* desc) { 242 description_.reset(desc); 243 state_ = kSucceeded; 244 } 245 virtual void OnFailure(const std::string& error) { 246 state_ = kFailed; 247 } 248 249 SessionDescriptionInterface* description() { return description_.get(); } 250 251 SessionDescriptionInterface* ReleaseDescription() { 252 return description_.release(); 253 } 254 255 State state() const { return state_; } 256 257 protected: 258 ~WebRtcSessionCreateSDPObserverForTest() {} 259 260 private: 261 rtc::scoped_ptr<SessionDescriptionInterface> description_; 262 State state_; 263 }; 264 265 class FakeAudioRenderer : public cricket::AudioRenderer { 266 public: 267 FakeAudioRenderer() : channel_id_(-1), sink_(NULL) {} 268 virtual ~FakeAudioRenderer() { 269 if (sink_) 270 sink_->OnClose(); 271 } 272 273 virtual void AddChannel(int channel_id) OVERRIDE { 274 ASSERT(channel_id_ == -1); 275 channel_id_ = channel_id; 276 } 277 virtual void RemoveChannel(int channel_id) OVERRIDE { 278 ASSERT(channel_id == channel_id_); 279 channel_id_ = -1; 280 } 281 virtual void SetSink(Sink* sink) OVERRIDE { 282 sink_ = sink; 283 } 284 285 int channel_id() const { return channel_id_; } 286 cricket::AudioRenderer::Sink* sink() const { return sink_; } 287 private: 288 int channel_id_; 289 cricket::AudioRenderer::Sink* sink_; 290 }; 291 292 class WebRtcSessionTest : public testing::Test { 293 protected: 294 // TODO Investigate why ChannelManager crashes, if it's created 295 // after stun_server. 296 WebRtcSessionTest() 297 : media_engine_(new cricket::FakeMediaEngine()), 298 data_engine_(new cricket::FakeDataEngine()), 299 device_manager_(new cricket::FakeDeviceManager()), 300 channel_manager_(new cricket::ChannelManager( 301 media_engine_, data_engine_, device_manager_, 302 new cricket::CaptureManager(), rtc::Thread::Current())), 303 tdesc_factory_(new cricket::TransportDescriptionFactory()), 304 desc_factory_(new cricket::MediaSessionDescriptionFactory( 305 channel_manager_.get(), tdesc_factory_.get())), 306 pss_(new rtc::PhysicalSocketServer), 307 vss_(new rtc::VirtualSocketServer(pss_.get())), 308 fss_(new rtc::FirewallSocketServer(vss_.get())), 309 ss_scope_(fss_.get()), 310 stun_socket_addr_(rtc::SocketAddress(kStunAddrHost, 311 cricket::STUN_SERVER_PORT)), 312 stun_server_(Thread::Current(), stun_socket_addr_), 313 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr), 314 mediastream_signaling_(channel_manager_.get()), 315 ice_type_(PeerConnectionInterface::kAll) { 316 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID); 317 318 cricket::ServerAddresses stun_servers; 319 stun_servers.insert(stun_socket_addr_); 320 allocator_.reset(new cricket::BasicPortAllocator( 321 &network_manager_, 322 stun_servers, 323 SocketAddress(), SocketAddress(), SocketAddress())); 324 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 325 cricket::PORTALLOCATOR_DISABLE_RELAY | 326 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 327 EXPECT_TRUE(channel_manager_->Init()); 328 desc_factory_->set_add_legacy_streams(false); 329 allocator_->set_step_delay(cricket::kMinimumStepDelay); 330 } 331 332 static void SetUpTestCase() { 333 rtc::InitializeSSL(); 334 } 335 336 static void TearDownTestCase() { 337 rtc::CleanupSSL(); 338 } 339 340 void AddInterface(const SocketAddress& addr) { 341 network_manager_.AddInterface(addr); 342 } 343 344 void SetIceTransportType(PeerConnectionInterface::IceTransportsType type) { 345 ice_type_ = type; 346 } 347 348 void Init(DTLSIdentityServiceInterface* identity_service) { 349 ASSERT_TRUE(session_.get() == NULL); 350 session_.reset(new WebRtcSessionForTest( 351 channel_manager_.get(), rtc::Thread::Current(), 352 rtc::Thread::Current(), allocator_.get(), 353 &observer_, 354 &mediastream_signaling_)); 355 356 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 357 observer_.ice_connection_state_); 358 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 359 observer_.ice_gathering_state_); 360 361 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(), 362 identity_service, ice_type_)); 363 } 364 365 void InitWithDtmfCodec() { 366 // Add kTelephoneEventCodec for dtmf test. 367 const cricket::AudioCodec kTelephoneEventCodec( 368 106, "telephone-event", 8000, 0, 1, 0); 369 std::vector<cricket::AudioCodec> codecs; 370 codecs.push_back(kTelephoneEventCodec); 371 media_engine_->SetAudioCodecs(codecs); 372 desc_factory_->set_audio_codecs(codecs); 373 Init(NULL); 374 } 375 376 void InitWithDtls(bool identity_request_should_fail = false) { 377 FakeIdentityService* identity_service = new FakeIdentityService(); 378 identity_service->set_should_fail(identity_request_should_fail); 379 Init(identity_service); 380 } 381 382 // Creates a local offer and applies it. Starts ice. 383 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function 384 // to decide which streams to create. 385 void InitiateCall() { 386 SessionDescriptionInterface* offer = CreateOffer(); 387 SetLocalDescriptionWithoutError(offer); 388 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew != 389 observer_.ice_gathering_state_, 390 kIceCandidatesTimeout); 391 } 392 393 SessionDescriptionInterface* CreateOffer() { 394 PeerConnectionInterface::RTCOfferAnswerOptions options; 395 options.offer_to_receive_audio = 396 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 397 398 return CreateOffer(options); 399 } 400 401 SessionDescriptionInterface* CreateOffer( 402 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { 403 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 404 observer = new WebRtcSessionCreateSDPObserverForTest(); 405 session_->CreateOffer(observer, options); 406 EXPECT_TRUE_WAIT( 407 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 408 2000); 409 return observer->ReleaseDescription(); 410 } 411 412 SessionDescriptionInterface* CreateAnswer( 413 const webrtc::MediaConstraintsInterface* constraints) { 414 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer 415 = new WebRtcSessionCreateSDPObserverForTest(); 416 session_->CreateAnswer(observer, constraints); 417 EXPECT_TRUE_WAIT( 418 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 419 2000); 420 return observer->ReleaseDescription(); 421 } 422 423 bool ChannelsExist() const { 424 return (session_->voice_channel() != NULL && 425 session_->video_channel() != NULL); 426 } 427 428 void CheckTransportChannels() const { 429 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL); 430 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL); 431 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL); 432 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL); 433 } 434 435 void VerifyCryptoParams(const cricket::SessionDescription* sdp) { 436 ASSERT_TRUE(session_.get() != NULL); 437 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 438 ASSERT_TRUE(content != NULL); 439 const cricket::AudioContentDescription* audio_content = 440 static_cast<const cricket::AudioContentDescription*>( 441 content->description); 442 ASSERT_TRUE(audio_content != NULL); 443 ASSERT_EQ(1U, audio_content->cryptos().size()); 444 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size()); 445 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 446 audio_content->cryptos()[0].cipher_suite); 447 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 448 audio_content->protocol()); 449 450 content = cricket::GetFirstVideoContent(sdp); 451 ASSERT_TRUE(content != NULL); 452 const cricket::VideoContentDescription* video_content = 453 static_cast<const cricket::VideoContentDescription*>( 454 content->description); 455 ASSERT_TRUE(video_content != NULL); 456 ASSERT_EQ(1U, video_content->cryptos().size()); 457 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 458 video_content->cryptos()[0].cipher_suite); 459 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size()); 460 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 461 video_content->protocol()); 462 } 463 464 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) { 465 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 466 ASSERT_TRUE(content != NULL); 467 const cricket::AudioContentDescription* audio_content = 468 static_cast<const cricket::AudioContentDescription*>( 469 content->description); 470 ASSERT_TRUE(audio_content != NULL); 471 ASSERT_EQ(0U, audio_content->cryptos().size()); 472 473 content = cricket::GetFirstVideoContent(sdp); 474 ASSERT_TRUE(content != NULL); 475 const cricket::VideoContentDescription* video_content = 476 static_cast<const cricket::VideoContentDescription*>( 477 content->description); 478 ASSERT_TRUE(video_content != NULL); 479 ASSERT_EQ(0U, video_content->cryptos().size()); 480 481 if (dtls) { 482 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 483 audio_content->protocol()); 484 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 485 video_content->protocol()); 486 } else { 487 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 488 audio_content->protocol()); 489 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 490 video_content->protocol()); 491 } 492 } 493 494 // Set the internal fake description factories to do DTLS-SRTP. 495 void SetFactoryDtlsSrtp() { 496 desc_factory_->set_secure(cricket::SEC_DISABLED); 497 std::string identity_name = "WebRTC" + 498 rtc::ToString(rtc::CreateRandomId()); 499 identity_.reset(rtc::SSLIdentity::Generate(identity_name)); 500 tdesc_factory_->set_identity(identity_.get()); 501 tdesc_factory_->set_secure(cricket::SEC_REQUIRED); 502 } 503 504 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp, 505 bool expected) { 506 const TransportInfo* audio = sdp->GetTransportInfoByName("audio"); 507 ASSERT_TRUE(audio != NULL); 508 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL); 509 const TransportInfo* video = sdp->GetTransportInfoByName("video"); 510 ASSERT_TRUE(video != NULL); 511 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL); 512 } 513 514 void VerifyAnswerFromNonCryptoOffer() { 515 // Create an SDP without Crypto. 516 cricket::MediaSessionOptions options; 517 options.has_video = true; 518 JsepSessionDescription* offer( 519 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 520 ASSERT_TRUE(offer != NULL); 521 VerifyNoCryptoParams(offer->description(), false); 522 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, 523 offer); 524 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL); 525 // Answer should be NULL as no crypto params in offer. 526 ASSERT_TRUE(answer == NULL); 527 } 528 529 void VerifyAnswerFromCryptoOffer() { 530 cricket::MediaSessionOptions options; 531 options.has_video = true; 532 options.bundle_enabled = true; 533 scoped_ptr<JsepSessionDescription> offer( 534 CreateRemoteOffer(options, cricket::SEC_REQUIRED)); 535 ASSERT_TRUE(offer.get() != NULL); 536 VerifyCryptoParams(offer->description()); 537 SetRemoteDescriptionWithoutError(offer.release()); 538 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 539 ASSERT_TRUE(answer.get() != NULL); 540 VerifyCryptoParams(answer->description()); 541 } 542 543 void SetAndVerifyNumUnsignalledRecvStreams( 544 int value_set, int value_expected) { 545 constraints_.reset(new FakeConstraints()); 546 constraints_->AddOptional( 547 webrtc::MediaConstraintsInterface::kNumUnsignalledRecvStreams, 548 value_set); 549 session_.reset(); 550 Init(NULL); 551 mediastream_signaling_.SendAudioVideoStream1(); 552 SessionDescriptionInterface* offer = CreateOffer(); 553 554 SetLocalDescriptionWithoutError(offer); 555 556 video_channel_ = media_engine_->GetVideoChannel(0); 557 558 ASSERT_TRUE(video_channel_ != NULL); 559 cricket::VideoOptions video_options; 560 EXPECT_TRUE(video_channel_->GetOptions(&video_options)); 561 EXPECT_EQ(value_expected, 562 video_options.unsignalled_recv_stream_limit.GetWithDefaultIfUnset(-1)); 563 } 564 565 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1, 566 const cricket::SessionDescription* desc2, 567 bool expect_equal) { 568 if (desc1->contents().size() != desc2->contents().size()) { 569 EXPECT_FALSE(expect_equal); 570 return; 571 } 572 573 const cricket::ContentInfos& contents = desc1->contents(); 574 cricket::ContentInfos::const_iterator it = contents.begin(); 575 576 for (; it != contents.end(); ++it) { 577 const cricket::TransportDescription* transport_desc1 = 578 desc1->GetTransportDescriptionByName(it->name); 579 const cricket::TransportDescription* transport_desc2 = 580 desc2->GetTransportDescriptionByName(it->name); 581 if (!transport_desc1 || !transport_desc2) { 582 EXPECT_FALSE(expect_equal); 583 return; 584 } 585 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd || 586 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) { 587 EXPECT_FALSE(expect_equal); 588 return; 589 } 590 } 591 EXPECT_TRUE(expect_equal); 592 } 593 594 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc, 595 std::string *sdp) { 596 const cricket::SessionDescription* desc = current_desc->description(); 597 EXPECT_TRUE(current_desc->ToString(sdp)); 598 599 const cricket::ContentInfos& contents = desc->contents(); 600 cricket::ContentInfos::const_iterator it = contents.begin(); 601 // Replace ufrag and pwd lines with empty strings. 602 for (; it != contents.end(); ++it) { 603 const cricket::TransportDescription* transport_desc = 604 desc->GetTransportDescriptionByName(it->name); 605 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag 606 + "\r\n"; 607 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd 608 + "\r\n"; 609 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(), 610 "", 0, 611 sdp); 612 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(), 613 "", 0, 614 sdp); 615 } 616 } 617 618 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc, 619 const std::string& modified_ice_ufrag, 620 const std::string& modified_ice_pwd, 621 std::string* sdp) { 622 const cricket::SessionDescription* desc = current_desc->description(); 623 EXPECT_TRUE(current_desc->ToString(sdp)); 624 625 const cricket::ContentInfos& contents = desc->contents(); 626 cricket::ContentInfos::const_iterator it = contents.begin(); 627 // Replace ufrag and pwd lines with |modified_ice_ufrag| and 628 // |modified_ice_pwd| strings. 629 for (; it != contents.end(); ++it) { 630 const cricket::TransportDescription* transport_desc = 631 desc->GetTransportDescriptionByName(it->name); 632 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag 633 + "\r\n"; 634 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd 635 + "\r\n"; 636 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n"; 637 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n"; 638 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(), 639 mod_ufrag.c_str(), mod_ufrag.length(), 640 sdp); 641 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(), 642 mod_pwd.c_str(), mod_pwd.length(), 643 sdp); 644 } 645 } 646 647 // Creates a remote offer and and applies it as a remote description, 648 // creates a local answer and applies is as a local description. 649 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function 650 // to decide which local and remote streams to create. 651 void CreateAndSetRemoteOfferAndLocalAnswer() { 652 SessionDescriptionInterface* offer = CreateRemoteOffer(); 653 SetRemoteDescriptionWithoutError(offer); 654 SessionDescriptionInterface* answer = CreateAnswer(NULL); 655 SetLocalDescriptionWithoutError(answer); 656 } 657 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) { 658 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL)); 659 } 660 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc, 661 BaseSession::State expected_state) { 662 SetLocalDescriptionWithoutError(desc); 663 EXPECT_EQ(expected_state, session_->state()); 664 } 665 void SetLocalDescriptionExpectError(const std::string& action, 666 const std::string& expected_error, 667 SessionDescriptionInterface* desc) { 668 std::string error; 669 EXPECT_FALSE(session_->SetLocalDescription(desc, &error)); 670 std::string sdp_type = "local "; 671 sdp_type.append(action); 672 EXPECT_NE(std::string::npos, error.find(sdp_type)); 673 EXPECT_NE(std::string::npos, error.find(expected_error)); 674 } 675 void SetLocalDescriptionOfferExpectError(const std::string& expected_error, 676 SessionDescriptionInterface* desc) { 677 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer, 678 expected_error, desc); 679 } 680 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error, 681 SessionDescriptionInterface* desc) { 682 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer, 683 expected_error, desc); 684 } 685 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) { 686 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL)); 687 } 688 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc, 689 BaseSession::State expected_state) { 690 SetRemoteDescriptionWithoutError(desc); 691 EXPECT_EQ(expected_state, session_->state()); 692 } 693 void SetRemoteDescriptionExpectError(const std::string& action, 694 const std::string& expected_error, 695 SessionDescriptionInterface* desc) { 696 std::string error; 697 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error)); 698 std::string sdp_type = "remote "; 699 sdp_type.append(action); 700 EXPECT_NE(std::string::npos, error.find(sdp_type)); 701 EXPECT_NE(std::string::npos, error.find(expected_error)); 702 } 703 void SetRemoteDescriptionOfferExpectError( 704 const std::string& expected_error, SessionDescriptionInterface* desc) { 705 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer, 706 expected_error, desc); 707 } 708 void SetRemoteDescriptionPranswerExpectError( 709 const std::string& expected_error, SessionDescriptionInterface* desc) { 710 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer, 711 expected_error, desc); 712 } 713 void SetRemoteDescriptionAnswerExpectError( 714 const std::string& expected_error, SessionDescriptionInterface* desc) { 715 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer, 716 expected_error, desc); 717 } 718 719 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer, 720 SessionDescriptionInterface** nocrypto_answer) { 721 // Create a SDP without Crypto. 722 cricket::MediaSessionOptions options; 723 options.has_video = true; 724 options.bundle_enabled = true; 725 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); 726 ASSERT_TRUE(*offer != NULL); 727 VerifyCryptoParams((*offer)->description()); 728 729 *nocrypto_answer = CreateRemoteAnswer(*offer, options, 730 cricket::SEC_DISABLED); 731 EXPECT_TRUE(*nocrypto_answer != NULL); 732 } 733 734 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer, 735 SessionDescriptionInterface** nodtls_answer) { 736 cricket::MediaSessionOptions options; 737 options.has_video = true; 738 options.bundle_enabled = true; 739 740 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer( 741 CreateRemoteOffer(options, cricket::SEC_ENABLED)); 742 743 *nodtls_answer = 744 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED); 745 EXPECT_TRUE(*nodtls_answer != NULL); 746 VerifyFingerprintStatus((*nodtls_answer)->description(), false); 747 VerifyCryptoParams((*nodtls_answer)->description()); 748 749 SetFactoryDtlsSrtp(); 750 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); 751 ASSERT_TRUE(*offer != NULL); 752 VerifyFingerprintStatus((*offer)->description(), true); 753 VerifyCryptoParams((*offer)->description()); 754 } 755 756 JsepSessionDescription* CreateRemoteOfferWithVersion( 757 cricket::MediaSessionOptions options, 758 cricket::SecurePolicy secure_policy, 759 const std::string& session_version, 760 const SessionDescriptionInterface* current_desc) { 761 std::string session_id = rtc::ToString(rtc::CreateRandomId64()); 762 const cricket::SessionDescription* cricket_desc = NULL; 763 if (current_desc) { 764 cricket_desc = current_desc->description(); 765 session_id = current_desc->session_id(); 766 } 767 768 desc_factory_->set_secure(secure_policy); 769 JsepSessionDescription* offer( 770 new JsepSessionDescription(JsepSessionDescription::kOffer)); 771 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc), 772 session_id, session_version)) { 773 delete offer; 774 offer = NULL; 775 } 776 return offer; 777 } 778 JsepSessionDescription* CreateRemoteOffer( 779 cricket::MediaSessionOptions options) { 780 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 781 kSessionVersion, NULL); 782 } 783 JsepSessionDescription* CreateRemoteOffer( 784 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) { 785 return CreateRemoteOfferWithVersion( 786 options, sdes_policy, kSessionVersion, NULL); 787 } 788 JsepSessionDescription* CreateRemoteOffer( 789 cricket::MediaSessionOptions options, 790 const SessionDescriptionInterface* current_desc) { 791 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 792 kSessionVersion, current_desc); 793 } 794 795 JsepSessionDescription* CreateRemoteOfferWithSctpPort( 796 const char* sctp_stream_name, int new_port, 797 cricket::MediaSessionOptions options) { 798 options.data_channel_type = cricket::DCT_SCTP; 799 options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel", 800 sctp_stream_name); 801 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options)); 802 } 803 804 // Takes ownership of offer_basis (and deletes it). 805 JsepSessionDescription* ChangeSDPSctpPort( 806 int new_port, webrtc::SessionDescriptionInterface *offer_basis) { 807 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new 808 // SessionDescription from the mutated string. 809 const char* default_port_str = "5000"; 810 char new_port_str[16]; 811 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port); 812 std::string offer_str; 813 offer_basis->ToString(&offer_str); 814 rtc::replace_substrs(default_port_str, strlen(default_port_str), 815 new_port_str, strlen(new_port_str), 816 &offer_str); 817 JsepSessionDescription* offer = new JsepSessionDescription( 818 offer_basis->type()); 819 delete offer_basis; 820 offer->Initialize(offer_str, NULL); 821 return offer; 822 } 823 824 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX() 825 // before this function to decide which streams to create. 826 JsepSessionDescription* CreateRemoteOffer() { 827 cricket::MediaSessionOptions options; 828 mediastream_signaling_.GetOptionsForAnswer(NULL, &options); 829 return CreateRemoteOffer(options, session_->remote_description()); 830 } 831 832 JsepSessionDescription* CreateRemoteAnswer( 833 const SessionDescriptionInterface* offer, 834 cricket::MediaSessionOptions options, 835 cricket::SecurePolicy policy) { 836 desc_factory_->set_secure(policy); 837 const std::string session_id = 838 rtc::ToString(rtc::CreateRandomId64()); 839 JsepSessionDescription* answer( 840 new JsepSessionDescription(JsepSessionDescription::kAnswer)); 841 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(), 842 options, NULL), 843 session_id, kSessionVersion)) { 844 delete answer; 845 answer = NULL; 846 } 847 return answer; 848 } 849 850 JsepSessionDescription* CreateRemoteAnswer( 851 const SessionDescriptionInterface* offer, 852 cricket::MediaSessionOptions options) { 853 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 854 } 855 856 // Creates an answer session description with streams based on 857 // |mediastream_signaling_|. Call 858 // mediastream_signaling_.UseOptionsWithStreamX() before this function 859 // to decide which streams to create. 860 JsepSessionDescription* CreateRemoteAnswer( 861 const SessionDescriptionInterface* offer) { 862 cricket::MediaSessionOptions options; 863 mediastream_signaling_.GetOptionsForAnswer(NULL, &options); 864 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 865 } 866 867 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) { 868 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 869 Init(NULL); 870 mediastream_signaling_.SendAudioVideoStream1(); 871 872 PeerConnectionInterface::RTCOfferAnswerOptions options; 873 options.use_rtp_mux = bundle; 874 875 SessionDescriptionInterface* offer = CreateOffer(options); 876 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 877 // and answer. 878 SetLocalDescriptionWithoutError(offer); 879 880 rtc::scoped_ptr<SessionDescriptionInterface> answer( 881 CreateRemoteAnswer(session_->local_description())); 882 std::string sdp; 883 EXPECT_TRUE(answer->ToString(&sdp)); 884 885 size_t expected_candidate_num = 2; 886 if (!rtcp_mux) { 887 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex 888 // for rtp and rtcp. 889 expected_candidate_num = 4; 890 // Disable rtcp-mux from the answer 891 const std::string kRtcpMux = "a=rtcp-mux"; 892 const std::string kXRtcpMux = "a=xrtcp-mux"; 893 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(), 894 kXRtcpMux.c_str(), kXRtcpMux.length(), 895 &sdp); 896 } 897 898 SessionDescriptionInterface* new_answer = CreateSessionDescription( 899 JsepSessionDescription::kAnswer, sdp, NULL); 900 901 // SetRemoteDescription to enable rtcp mux. 902 SetRemoteDescriptionWithoutError(new_answer); 903 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 904 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size()); 905 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size()); 906 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) { 907 cricket::Candidate c0 = observer_.mline_0_candidates_[i]; 908 cricket::Candidate c1 = observer_.mline_1_candidates_[i]; 909 if (bundle) { 910 EXPECT_TRUE(c0.IsEquivalent(c1)); 911 } else { 912 EXPECT_FALSE(c0.IsEquivalent(c1)); 913 } 914 } 915 } 916 // Tests that we can only send DTMF when the dtmf codec is supported. 917 void TestCanInsertDtmf(bool can) { 918 if (can) { 919 InitWithDtmfCodec(); 920 } else { 921 Init(NULL); 922 } 923 mediastream_signaling_.SendAudioVideoStream1(); 924 CreateAndSetRemoteOfferAndLocalAnswer(); 925 EXPECT_FALSE(session_->CanInsertDtmf("")); 926 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1)); 927 } 928 929 // The method sets up a call from the session to itself, in a loopback 930 // arrangement. It also uses a firewall rule to create a temporary 931 // disconnection, and then a permanent disconnection. 932 // This code is placed in a method so that it can be invoked 933 // by multiple tests with different allocators (e.g. with and without BUNDLE). 934 // While running the call, this method also checks if the session goes through 935 // the correct sequence of ICE states when a connection is established, 936 // broken, and re-established. 937 // The Connection state should go: 938 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed 939 // -> Failed. 940 // The Gathering state should go: New -> Gathering -> Completed. 941 void TestLoopbackCall() { 942 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 943 Init(NULL); 944 mediastream_signaling_.SendAudioVideoStream1(); 945 SessionDescriptionInterface* offer = CreateOffer(); 946 947 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 948 observer_.ice_gathering_state_); 949 SetLocalDescriptionWithoutError(offer); 950 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 951 observer_.ice_connection_state_); 952 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering, 953 observer_.ice_gathering_state_, 954 kIceCandidatesTimeout); 955 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 956 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete, 957 observer_.ice_gathering_state_, 958 kIceCandidatesTimeout); 959 960 std::string sdp; 961 offer->ToString(&sdp); 962 SessionDescriptionInterface* desc = 963 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp); 964 ASSERT_TRUE(desc != NULL); 965 SetRemoteDescriptionWithoutError(desc); 966 967 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking, 968 observer_.ice_connection_state_, 969 kIceCandidatesTimeout); 970 971 // The ice connection state is "Connected" too briefly to catch in a test. 972 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, 973 observer_.ice_connection_state_, 974 kIceCandidatesTimeout); 975 976 // Adding firewall rule to block ping requests, which should cause 977 // transport channel failure. 978 fss_->AddRule(false, 979 rtc::FP_ANY, 980 rtc::FD_ANY, 981 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 982 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, 983 observer_.ice_connection_state_, 984 kIceCandidatesTimeout); 985 986 // Clearing the rules, session should move back to completed state. 987 fss_->ClearRules(); 988 // Session is automatically calling OnSignalingReady after creation of 989 // new portallocator session which will allocate new set of candidates. 990 991 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, 992 observer_.ice_connection_state_, 993 kIceCandidatesTimeout); 994 995 // Now we block ping requests and wait until the ICE connection transitions 996 // to the Failed state. This will take at least 30 seconds because it must 997 // wait for the Port to timeout. 998 int port_timeout = 30000; 999 fss_->AddRule(false, 1000 rtc::FP_ANY, 1001 rtc::FD_ANY, 1002 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1003 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed, 1004 observer_.ice_connection_state_, 1005 kIceCandidatesTimeout + port_timeout); 1006 } 1007 1008 void VerifyTransportType(const std::string& content_name, 1009 cricket::TransportProtocol protocol) { 1010 const cricket::Transport* transport = session_->GetTransport(content_name); 1011 ASSERT_TRUE(transport != NULL); 1012 EXPECT_EQ(protocol, transport->protocol()); 1013 } 1014 1015 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory. 1016 void AddCNCodecs() { 1017 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0); 1018 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0); 1019 1020 // Add kCNCodec for dtmf test. 1021 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();; 1022 codecs.push_back(kCNCodec1); 1023 codecs.push_back(kCNCodec2); 1024 media_engine_->SetAudioCodecs(codecs); 1025 desc_factory_->set_audio_codecs(codecs); 1026 } 1027 1028 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) { 1029 const cricket::ContentDescription* description = content->description; 1030 ASSERT(description != NULL); 1031 const cricket::AudioContentDescription* audio_content_desc = 1032 static_cast<const cricket::AudioContentDescription*>(description); 1033 ASSERT(audio_content_desc != NULL); 1034 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) { 1035 if (audio_content_desc->codecs()[i].name == "CN") 1036 return false; 1037 } 1038 return true; 1039 } 1040 1041 void SetLocalDescriptionWithDataChannel() { 1042 webrtc::InternalDataChannelInit dci; 1043 dci.reliable = false; 1044 session_->CreateDataChannel("datachannel", &dci); 1045 SessionDescriptionInterface* offer = CreateOffer(); 1046 SetLocalDescriptionWithoutError(offer); 1047 } 1048 1049 void VerifyMultipleAsyncCreateDescription( 1050 bool success, CreateSessionDescriptionRequest::Type type) { 1051 InitWithDtls(!success); 1052 SetFactoryDtlsSrtp(); 1053 if (type == CreateSessionDescriptionRequest::kAnswer) { 1054 cricket::MediaSessionOptions options; 1055 scoped_ptr<JsepSessionDescription> offer( 1056 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 1057 ASSERT_TRUE(offer.get() != NULL); 1058 SetRemoteDescriptionWithoutError(offer.release()); 1059 } 1060 1061 PeerConnectionInterface::RTCOfferAnswerOptions options; 1062 const int kNumber = 3; 1063 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 1064 observers[kNumber]; 1065 for (int i = 0; i < kNumber; ++i) { 1066 observers[i] = new WebRtcSessionCreateSDPObserverForTest(); 1067 if (type == CreateSessionDescriptionRequest::kOffer) { 1068 session_->CreateOffer(observers[i], options); 1069 } else { 1070 session_->CreateAnswer(observers[i], NULL); 1071 } 1072 } 1073 1074 WebRtcSessionCreateSDPObserverForTest::State expected_state = 1075 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded : 1076 WebRtcSessionCreateSDPObserverForTest::kFailed; 1077 1078 for (int i = 0; i < kNumber; ++i) { 1079 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000); 1080 if (success) { 1081 EXPECT_TRUE(observers[i]->description() != NULL); 1082 } else { 1083 EXPECT_TRUE(observers[i]->description() == NULL); 1084 } 1085 } 1086 } 1087 1088 void ConfigureAllocatorWithTurn() { 1089 cricket::RelayServerConfig relay_server(cricket::RELAY_TURN); 1090 cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword); 1091 relay_server.credentials = credentials; 1092 relay_server.ports.push_back(cricket::ProtocolAddress( 1093 kTurnUdpIntAddr, cricket::PROTO_UDP, false)); 1094 allocator_->AddRelay(relay_server); 1095 allocator_->set_step_delay(cricket::kMinimumStepDelay); 1096 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 1097 cricket::PORTALLOCATOR_ENABLE_BUNDLE); 1098 } 1099 1100 cricket::FakeMediaEngine* media_engine_; 1101 cricket::FakeDataEngine* data_engine_; 1102 cricket::FakeDeviceManager* device_manager_; 1103 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; 1104 rtc::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_; 1105 rtc::scoped_ptr<rtc::SSLIdentity> identity_; 1106 rtc::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_; 1107 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_; 1108 rtc::scoped_ptr<rtc::VirtualSocketServer> vss_; 1109 rtc::scoped_ptr<rtc::FirewallSocketServer> fss_; 1110 rtc::SocketServerScope ss_scope_; 1111 rtc::SocketAddress stun_socket_addr_; 1112 cricket::TestStunServer stun_server_; 1113 cricket::TestTurnServer turn_server_; 1114 rtc::FakeNetworkManager network_manager_; 1115 rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_; 1116 PeerConnectionFactoryInterface::Options options_; 1117 rtc::scoped_ptr<FakeConstraints> constraints_; 1118 FakeMediaStreamSignaling mediastream_signaling_; 1119 rtc::scoped_ptr<WebRtcSessionForTest> session_; 1120 MockIceObserver observer_; 1121 cricket::FakeVideoMediaChannel* video_channel_; 1122 cricket::FakeVoiceMediaChannel* voice_channel_; 1123 PeerConnectionInterface::IceTransportsType ice_type_; 1124 }; 1125 1126 TEST_F(WebRtcSessionTest, TestInitializeWithDtls) { 1127 InitWithDtls(); 1128 // SDES is disabled when DTLS is on. 1129 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy()); 1130 } 1131 1132 TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) { 1133 Init(NULL); 1134 // SDES is required if DTLS is off. 1135 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy()); 1136 } 1137 1138 TEST_F(WebRtcSessionTest, TestSessionCandidates) { 1139 TestSessionCandidatesWithBundleRtcpMux(false, false); 1140 } 1141 1142 // Below test cases (TestSessionCandidatesWith*) verify the candidates gathered 1143 // with rtcp-mux and/or bundle. 1144 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) { 1145 TestSessionCandidatesWithBundleRtcpMux(false, true); 1146 } 1147 1148 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) { 1149 TestSessionCandidatesWithBundleRtcpMux(true, true); 1150 } 1151 1152 TEST_F(WebRtcSessionTest, TestMultihomeCandidates) { 1153 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1154 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1155 Init(NULL); 1156 mediastream_signaling_.SendAudioVideoStream1(); 1157 InitiateCall(); 1158 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1159 EXPECT_EQ(8u, observer_.mline_0_candidates_.size()); 1160 EXPECT_EQ(8u, observer_.mline_1_candidates_.size()); 1161 } 1162 1163 TEST_F(WebRtcSessionTest, TestStunError) { 1164 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1165 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1166 fss_->AddRule(false, 1167 rtc::FP_UDP, 1168 rtc::FD_ANY, 1169 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1170 Init(NULL); 1171 mediastream_signaling_.SendAudioVideoStream1(); 1172 InitiateCall(); 1173 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it. 1174 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1175 EXPECT_EQ(6u, observer_.mline_0_candidates_.size()); 1176 EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); 1177 } 1178 1179 // Test session delivers no candidates gathered when constraint set to "none". 1180 TEST_F(WebRtcSessionTest, TestIceTransportsNone) { 1181 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1182 SetIceTransportType(PeerConnectionInterface::kNone); 1183 Init(NULL); 1184 mediastream_signaling_.SendAudioVideoStream1(); 1185 InitiateCall(); 1186 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1187 EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); 1188 EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); 1189 } 1190 1191 // Test session delivers only relay candidates gathered when constaint set to 1192 // "relay". 1193 TEST_F(WebRtcSessionTest, TestIceTransportsRelay) { 1194 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1195 ConfigureAllocatorWithTurn(); 1196 SetIceTransportType(PeerConnectionInterface::kRelay); 1197 Init(NULL); 1198 mediastream_signaling_.SendAudioVideoStream1(); 1199 InitiateCall(); 1200 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1201 EXPECT_EQ(2u, observer_.mline_0_candidates_.size()); 1202 EXPECT_EQ(2u, observer_.mline_1_candidates_.size()); 1203 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) { 1204 EXPECT_EQ(cricket::RELAY_PORT_TYPE, 1205 observer_.mline_0_candidates_[i].type()); 1206 } 1207 for (size_t i = 0; i < observer_.mline_1_candidates_.size(); ++i) { 1208 EXPECT_EQ(cricket::RELAY_PORT_TYPE, 1209 observer_.mline_1_candidates_[i].type()); 1210 } 1211 } 1212 1213 // Test session delivers all candidates gathered when constaint set to "all". 1214 TEST_F(WebRtcSessionTest, TestIceTransportsAll) { 1215 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1216 SetIceTransportType(PeerConnectionInterface::kAll); 1217 Init(NULL); 1218 mediastream_signaling_.SendAudioVideoStream1(); 1219 InitiateCall(); 1220 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1221 // Host + STUN. By default allocator is disabled to gather relay candidates. 1222 EXPECT_EQ(4u, observer_.mline_0_candidates_.size()); 1223 EXPECT_EQ(4u, observer_.mline_1_candidates_.size()); 1224 } 1225 1226 TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) { 1227 Init(NULL); 1228 SessionDescriptionInterface* offer = NULL; 1229 // Since |offer| is NULL, there's no way to tell if it's an offer or answer. 1230 std::string unknown_action; 1231 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer); 1232 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer); 1233 } 1234 1235 // Test creating offers and receive answers and make sure the 1236 // media engine creates the expected send and receive streams. 1237 TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) { 1238 Init(NULL); 1239 mediastream_signaling_.SendAudioVideoStream1(); 1240 SessionDescriptionInterface* offer = CreateOffer(); 1241 const std::string session_id_orig = offer->session_id(); 1242 const std::string session_version_orig = offer->session_version(); 1243 SetLocalDescriptionWithoutError(offer); 1244 1245 mediastream_signaling_.SendAudioVideoStream2(); 1246 SessionDescriptionInterface* answer = 1247 CreateRemoteAnswer(session_->local_description()); 1248 SetRemoteDescriptionWithoutError(answer); 1249 1250 video_channel_ = media_engine_->GetVideoChannel(0); 1251 voice_channel_ = media_engine_->GetVoiceChannel(0); 1252 1253 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1254 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1255 1256 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1257 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1258 1259 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1260 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1261 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1262 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1263 1264 // Create new offer without send streams. 1265 mediastream_signaling_.SendNothing(); 1266 offer = CreateOffer(); 1267 1268 // Verify the session id is the same and the session version is 1269 // increased. 1270 EXPECT_EQ(session_id_orig, offer->session_id()); 1271 EXPECT_LT(rtc::FromString<uint64>(session_version_orig), 1272 rtc::FromString<uint64>(offer->session_version())); 1273 1274 SetLocalDescriptionWithoutError(offer); 1275 EXPECT_EQ(0u, video_channel_->send_streams().size()); 1276 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 1277 1278 mediastream_signaling_.SendAudioVideoStream2(); 1279 answer = CreateRemoteAnswer(session_->local_description()); 1280 SetRemoteDescriptionWithoutError(answer); 1281 1282 // Make sure the receive streams have not changed. 1283 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1284 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1285 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1286 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1287 } 1288 1289 // Test receiving offers and creating answers and make sure the 1290 // media engine creates the expected send and receive streams. 1291 TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) { 1292 Init(NULL); 1293 mediastream_signaling_.SendAudioVideoStream2(); 1294 SessionDescriptionInterface* offer = CreateOffer(); 1295 VerifyCryptoParams(offer->description()); 1296 SetRemoteDescriptionWithoutError(offer); 1297 1298 mediastream_signaling_.SendAudioVideoStream1(); 1299 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1300 VerifyCryptoParams(answer->description()); 1301 SetLocalDescriptionWithoutError(answer); 1302 1303 const std::string session_id_orig = answer->session_id(); 1304 const std::string session_version_orig = answer->session_version(); 1305 1306 video_channel_ = media_engine_->GetVideoChannel(0); 1307 voice_channel_ = media_engine_->GetVoiceChannel(0); 1308 1309 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1310 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1311 1312 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1313 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1314 1315 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1316 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1317 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1318 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1319 1320 mediastream_signaling_.SendAudioVideoStream1And2(); 1321 offer = CreateOffer(); 1322 SetRemoteDescriptionWithoutError(offer); 1323 1324 // Answer by turning off all send streams. 1325 mediastream_signaling_.SendNothing(); 1326 answer = CreateAnswer(NULL); 1327 1328 // Verify the session id is the same and the session version is 1329 // increased. 1330 EXPECT_EQ(session_id_orig, answer->session_id()); 1331 EXPECT_LT(rtc::FromString<uint64>(session_version_orig), 1332 rtc::FromString<uint64>(answer->session_version())); 1333 SetLocalDescriptionWithoutError(answer); 1334 1335 ASSERT_EQ(2u, video_channel_->recv_streams().size()); 1336 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id); 1337 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id); 1338 ASSERT_EQ(2u, voice_channel_->recv_streams().size()); 1339 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id); 1340 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id); 1341 1342 // Make sure we have no send streams. 1343 EXPECT_EQ(0u, video_channel_->send_streams().size()); 1344 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 1345 } 1346 1347 TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) { 1348 Init(NULL); 1349 media_engine_->set_fail_create_channel(true); 1350 1351 SessionDescriptionInterface* offer = CreateOffer(); 1352 ASSERT_TRUE(offer != NULL); 1353 // SetRemoteDescription and SetLocalDescription will take the ownership of 1354 // the offer. 1355 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer); 1356 offer = CreateOffer(); 1357 ASSERT_TRUE(offer != NULL); 1358 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer); 1359 } 1360 1361 // 1362 // Tests for creating/setting SDP under different SDES/DTLS polices: 1363 // 1364 // --DTLS off and SDES on 1365 // TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer: 1366 // set local/remote offer/answer with crypto --> success 1367 // TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto ---> 1368 // failure 1369 // TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto --> 1370 // failure 1371 // TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto --> 1372 // failure 1373 // 1374 // --DTLS on and SDES off 1375 // TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer: 1376 // set local/remote offer/answer with DTLS fingerprint --> success 1377 // TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS 1378 // fingerprint --> failure 1379 // TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint 1380 // --> failure 1381 // TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint 1382 // --> failure 1383 // 1384 // --Encryption disabled: DTLS off and SDES off 1385 // TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote 1386 // answer without SDES or DTLS --> success 1387 // TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local 1388 // answer without SDES or DTLS --> success 1389 // 1390 1391 // Test that we return a failure when applying a remote/local offer that doesn't 1392 // have cryptos enabled when DTLS is off. 1393 TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) { 1394 Init(NULL); 1395 cricket::MediaSessionOptions options; 1396 options.has_video = true; 1397 JsepSessionDescription* offer = CreateRemoteOffer( 1398 options, cricket::SEC_DISABLED); 1399 ASSERT_TRUE(offer != NULL); 1400 VerifyNoCryptoParams(offer->description(), false); 1401 // SetRemoteDescription and SetLocalDescription will take the ownership of 1402 // the offer. 1403 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer); 1404 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 1405 ASSERT_TRUE(offer != NULL); 1406 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer); 1407 } 1408 1409 // Test that we return a failure when applying a local answer that doesn't have 1410 // cryptos enabled when DTLS is off. 1411 TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) { 1412 Init(NULL); 1413 SessionDescriptionInterface* offer = NULL; 1414 SessionDescriptionInterface* answer = NULL; 1415 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1416 // SetRemoteDescription and SetLocalDescription will take the ownership of 1417 // the offer. 1418 SetRemoteDescriptionWithoutError(offer); 1419 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer); 1420 } 1421 1422 // Test we will return fail when apply an remote answer that doesn't have 1423 // crypto enabled when DTLS is off. 1424 TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) { 1425 Init(NULL); 1426 SessionDescriptionInterface* offer = NULL; 1427 SessionDescriptionInterface* answer = NULL; 1428 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1429 // SetRemoteDescription and SetLocalDescription will take the ownership of 1430 // the offer. 1431 SetLocalDescriptionWithoutError(offer); 1432 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer); 1433 } 1434 1435 // Test that we accept an offer with a DTLS fingerprint when DTLS is on 1436 // and that we return an answer with a DTLS fingerprint. 1437 TEST_F(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) { 1438 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1439 mediastream_signaling_.SendAudioVideoStream1(); 1440 InitWithDtls(); 1441 SetFactoryDtlsSrtp(); 1442 cricket::MediaSessionOptions options; 1443 options.has_video = true; 1444 JsepSessionDescription* offer = 1445 CreateRemoteOffer(options, cricket::SEC_DISABLED); 1446 ASSERT_TRUE(offer != NULL); 1447 VerifyFingerprintStatus(offer->description(), true); 1448 VerifyNoCryptoParams(offer->description(), true); 1449 1450 // SetRemoteDescription will take the ownership of the offer. 1451 SetRemoteDescriptionWithoutError(offer); 1452 1453 // Verify that we get a crypto fingerprint in the answer. 1454 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1455 ASSERT_TRUE(answer != NULL); 1456 VerifyFingerprintStatus(answer->description(), true); 1457 // Check that we don't have an a=crypto line in the answer. 1458 VerifyNoCryptoParams(answer->description(), true); 1459 1460 // Now set the local description, which should work, even without a=crypto. 1461 SetLocalDescriptionWithoutError(answer); 1462 } 1463 1464 // Test that we set a local offer with a DTLS fingerprint when DTLS is on 1465 // and then we accept a remote answer with a DTLS fingerprint successfully. 1466 TEST_F(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) { 1467 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1468 mediastream_signaling_.SendAudioVideoStream1(); 1469 InitWithDtls(); 1470 SetFactoryDtlsSrtp(); 1471 1472 // Verify that we get a crypto fingerprint in the answer. 1473 SessionDescriptionInterface* offer = CreateOffer(); 1474 ASSERT_TRUE(offer != NULL); 1475 VerifyFingerprintStatus(offer->description(), true); 1476 // Check that we don't have an a=crypto line in the offer. 1477 VerifyNoCryptoParams(offer->description(), true); 1478 1479 // Now set the local description, which should work, even without a=crypto. 1480 SetLocalDescriptionWithoutError(offer); 1481 1482 cricket::MediaSessionOptions options; 1483 options.has_video = true; 1484 JsepSessionDescription* answer = 1485 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); 1486 ASSERT_TRUE(answer != NULL); 1487 VerifyFingerprintStatus(answer->description(), true); 1488 VerifyNoCryptoParams(answer->description(), true); 1489 1490 // SetRemoteDescription will take the ownership of the answer. 1491 SetRemoteDescriptionWithoutError(answer); 1492 } 1493 1494 // Test that if we support DTLS and the other side didn't offer a fingerprint, 1495 // we will fail to set the remote description. 1496 TEST_F(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) { 1497 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1498 InitWithDtls(); 1499 cricket::MediaSessionOptions options; 1500 options.has_video = true; 1501 options.bundle_enabled = true; 1502 JsepSessionDescription* offer = CreateRemoteOffer( 1503 options, cricket::SEC_REQUIRED); 1504 ASSERT_TRUE(offer != NULL); 1505 VerifyFingerprintStatus(offer->description(), false); 1506 VerifyCryptoParams(offer->description()); 1507 1508 // SetRemoteDescription will take the ownership of the offer. 1509 SetRemoteDescriptionOfferExpectError( 1510 kSdpWithoutDtlsFingerprint, offer); 1511 1512 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED); 1513 // SetLocalDescription will take the ownership of the offer. 1514 SetLocalDescriptionOfferExpectError( 1515 kSdpWithoutDtlsFingerprint, offer); 1516 } 1517 1518 // Test that we return a failure when applying a local answer that doesn't have 1519 // a DTLS fingerprint when DTLS is required. 1520 TEST_F(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) { 1521 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1522 InitWithDtls(); 1523 SessionDescriptionInterface* offer = NULL; 1524 SessionDescriptionInterface* answer = NULL; 1525 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer); 1526 1527 // SetRemoteDescription and SetLocalDescription will take the ownership of 1528 // the offer and answer. 1529 SetRemoteDescriptionWithoutError(offer); 1530 SetLocalDescriptionAnswerExpectError( 1531 kSdpWithoutDtlsFingerprint, answer); 1532 } 1533 1534 // Test that we return a failure when applying a remote answer that doesn't have 1535 // a DTLS fingerprint when DTLS is required. 1536 TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) { 1537 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1538 InitWithDtls(); 1539 SessionDescriptionInterface* offer = CreateOffer(); 1540 cricket::MediaSessionOptions options; 1541 options.has_video = true; 1542 JsepSessionDescription* answer = 1543 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED); 1544 1545 // SetRemoteDescription and SetLocalDescription will take the ownership of 1546 // the offer and answer. 1547 SetLocalDescriptionWithoutError(offer); 1548 SetRemoteDescriptionAnswerExpectError( 1549 kSdpWithoutDtlsFingerprint, answer); 1550 } 1551 1552 // Test that we create a local offer without SDES or DTLS and accept a remote 1553 // answer without SDES or DTLS when encryption is disabled. 1554 TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) { 1555 mediastream_signaling_.SendAudioVideoStream1(); 1556 options_.disable_encryption = true; 1557 InitWithDtls(); 1558 1559 // Verify that we get a crypto fingerprint in the answer. 1560 SessionDescriptionInterface* offer = CreateOffer(); 1561 ASSERT_TRUE(offer != NULL); 1562 VerifyFingerprintStatus(offer->description(), false); 1563 // Check that we don't have an a=crypto line in the offer. 1564 VerifyNoCryptoParams(offer->description(), false); 1565 1566 // Now set the local description, which should work, even without a=crypto. 1567 SetLocalDescriptionWithoutError(offer); 1568 1569 cricket::MediaSessionOptions options; 1570 options.has_video = true; 1571 JsepSessionDescription* answer = 1572 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); 1573 ASSERT_TRUE(answer != NULL); 1574 VerifyFingerprintStatus(answer->description(), false); 1575 VerifyNoCryptoParams(answer->description(), false); 1576 1577 // SetRemoteDescription will take the ownership of the answer. 1578 SetRemoteDescriptionWithoutError(answer); 1579 } 1580 1581 // Test that we create a local answer without SDES or DTLS and accept a remote 1582 // offer without SDES or DTLS when encryption is disabled. 1583 TEST_F(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) { 1584 options_.disable_encryption = true; 1585 InitWithDtls(); 1586 1587 cricket::MediaSessionOptions options; 1588 options.has_video = true; 1589 JsepSessionDescription* offer = 1590 CreateRemoteOffer(options, cricket::SEC_DISABLED); 1591 ASSERT_TRUE(offer != NULL); 1592 VerifyFingerprintStatus(offer->description(), false); 1593 VerifyNoCryptoParams(offer->description(), false); 1594 1595 // SetRemoteDescription will take the ownership of the offer. 1596 SetRemoteDescriptionWithoutError(offer); 1597 1598 // Verify that we get a crypto fingerprint in the answer. 1599 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1600 ASSERT_TRUE(answer != NULL); 1601 VerifyFingerprintStatus(answer->description(), false); 1602 // Check that we don't have an a=crypto line in the answer. 1603 VerifyNoCryptoParams(answer->description(), false); 1604 1605 // Now set the local description, which should work, even without a=crypto. 1606 SetLocalDescriptionWithoutError(answer); 1607 } 1608 1609 TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) { 1610 Init(NULL); 1611 mediastream_signaling_.SendNothing(); 1612 // SetLocalDescription take ownership of offer. 1613 SessionDescriptionInterface* offer = CreateOffer(); 1614 SetLocalDescriptionWithoutError(offer); 1615 1616 // SetLocalDescription take ownership of offer. 1617 SessionDescriptionInterface* offer2 = CreateOffer(); 1618 SetLocalDescriptionWithoutError(offer2); 1619 } 1620 1621 TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) { 1622 Init(NULL); 1623 mediastream_signaling_.SendNothing(); 1624 // SetLocalDescription take ownership of offer. 1625 SessionDescriptionInterface* offer = CreateOffer(); 1626 SetRemoteDescriptionWithoutError(offer); 1627 1628 SessionDescriptionInterface* offer2 = CreateOffer(); 1629 SetRemoteDescriptionWithoutError(offer2); 1630 } 1631 1632 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) { 1633 Init(NULL); 1634 mediastream_signaling_.SendNothing(); 1635 SessionDescriptionInterface* offer = CreateOffer(); 1636 SetLocalDescriptionWithoutError(offer); 1637 offer = CreateOffer(); 1638 SetRemoteDescriptionOfferExpectError( 1639 "Called in wrong state: STATE_SENTINITIATE", offer); 1640 } 1641 1642 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) { 1643 Init(NULL); 1644 mediastream_signaling_.SendNothing(); 1645 SessionDescriptionInterface* offer = CreateOffer(); 1646 SetRemoteDescriptionWithoutError(offer); 1647 offer = CreateOffer(); 1648 SetLocalDescriptionOfferExpectError( 1649 "Called in wrong state: STATE_RECEIVEDINITIATE", offer); 1650 } 1651 1652 TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) { 1653 Init(NULL); 1654 mediastream_signaling_.SendNothing(); 1655 SessionDescriptionInterface* offer = CreateRemoteOffer(); 1656 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE); 1657 1658 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>( 1659 CreateAnswer(NULL)); 1660 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 1661 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT); 1662 1663 mediastream_signaling_.SendAudioVideoStream1(); 1664 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>( 1665 CreateAnswer(NULL)); 1666 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 1667 1668 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT); 1669 1670 mediastream_signaling_.SendAudioVideoStream2(); 1671 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1672 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT); 1673 } 1674 1675 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) { 1676 Init(NULL); 1677 mediastream_signaling_.SendNothing(); 1678 SessionDescriptionInterface* offer = CreateOffer(); 1679 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE); 1680 1681 JsepSessionDescription* pranswer = 1682 CreateRemoteAnswer(session_->local_description()); 1683 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 1684 1685 SetRemoteDescriptionExpectState(pranswer, 1686 BaseSession::STATE_RECEIVEDPRACCEPT); 1687 1688 mediastream_signaling_.SendAudioVideoStream1(); 1689 JsepSessionDescription* pranswer2 = 1690 CreateRemoteAnswer(session_->local_description()); 1691 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 1692 1693 SetRemoteDescriptionExpectState(pranswer2, 1694 BaseSession::STATE_RECEIVEDPRACCEPT); 1695 1696 mediastream_signaling_.SendAudioVideoStream2(); 1697 SessionDescriptionInterface* answer = 1698 CreateRemoteAnswer(session_->local_description()); 1699 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT); 1700 } 1701 1702 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) { 1703 Init(NULL); 1704 mediastream_signaling_.SendNothing(); 1705 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 1706 1707 SessionDescriptionInterface* answer = 1708 CreateRemoteAnswer(offer.get()); 1709 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT", 1710 answer); 1711 } 1712 1713 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) { 1714 Init(NULL); 1715 mediastream_signaling_.SendNothing(); 1716 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 1717 1718 SessionDescriptionInterface* answer = 1719 CreateRemoteAnswer(offer.get()); 1720 SetRemoteDescriptionAnswerExpectError( 1721 "Called in wrong state: STATE_INIT", answer); 1722 } 1723 1724 TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) { 1725 Init(NULL); 1726 mediastream_signaling_.SendAudioVideoStream1(); 1727 1728 cricket::Candidate candidate; 1729 candidate.set_component(1); 1730 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate); 1731 1732 // Fail since we have not set a offer description. 1733 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1)); 1734 1735 SessionDescriptionInterface* offer = CreateOffer(); 1736 SetLocalDescriptionWithoutError(offer); 1737 // Candidate should be allowed to add before remote description. 1738 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 1739 candidate.set_component(2); 1740 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate); 1741 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 1742 1743 SessionDescriptionInterface* answer = CreateRemoteAnswer( 1744 session_->local_description()); 1745 SetRemoteDescriptionWithoutError(answer); 1746 1747 // Verifying the candidates are copied properly from internal vector. 1748 const SessionDescriptionInterface* remote_desc = 1749 session_->remote_description(); 1750 ASSERT_TRUE(remote_desc != NULL); 1751 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1752 const IceCandidateCollection* candidates = 1753 remote_desc->candidates(kMediaContentIndex0); 1754 ASSERT_EQ(2u, candidates->count()); 1755 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1756 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid()); 1757 EXPECT_EQ(1, candidates->at(0)->candidate().component()); 1758 EXPECT_EQ(2, candidates->at(1)->candidate().component()); 1759 1760 // |ice_candidate3| is identical to |ice_candidate2|. It can be added 1761 // successfully, but the total count of candidates will not increase. 1762 candidate.set_component(2); 1763 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate); 1764 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3)); 1765 ASSERT_EQ(2u, candidates->count()); 1766 1767 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate); 1768 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate)); 1769 } 1770 1771 // Test that a remote candidate is added to the remote session description and 1772 // that it is retained if the remote session description is changed. 1773 TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) { 1774 Init(NULL); 1775 cricket::Candidate candidate1; 1776 candidate1.set_component(1); 1777 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0, 1778 candidate1); 1779 mediastream_signaling_.SendAudioVideoStream1(); 1780 CreateAndSetRemoteOfferAndLocalAnswer(); 1781 1782 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 1783 const SessionDescriptionInterface* remote_desc = 1784 session_->remote_description(); 1785 ASSERT_TRUE(remote_desc != NULL); 1786 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1787 const IceCandidateCollection* candidates = 1788 remote_desc->candidates(kMediaContentIndex0); 1789 ASSERT_EQ(1u, candidates->count()); 1790 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1791 1792 // Update the RemoteSessionDescription with a new session description and 1793 // a candidate and check that the new remote session description contains both 1794 // candidates. 1795 SessionDescriptionInterface* offer = CreateRemoteOffer(); 1796 cricket::Candidate candidate2; 1797 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 1798 candidate2); 1799 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2)); 1800 SetRemoteDescriptionWithoutError(offer); 1801 1802 remote_desc = session_->remote_description(); 1803 ASSERT_TRUE(remote_desc != NULL); 1804 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1805 candidates = remote_desc->candidates(kMediaContentIndex0); 1806 ASSERT_EQ(2u, candidates->count()); 1807 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1808 // Username and password have be updated with the TransportInfo of the 1809 // SessionDescription, won't be equal to the original one. 1810 candidate2.set_username(candidates->at(0)->candidate().username()); 1811 candidate2.set_password(candidates->at(0)->candidate().password()); 1812 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate())); 1813 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index()); 1814 // No need to verify the username and password. 1815 candidate1.set_username(candidates->at(1)->candidate().username()); 1816 candidate1.set_password(candidates->at(1)->candidate().password()); 1817 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate())); 1818 1819 // Test that the candidate is ignored if we can add the same candidate again. 1820 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 1821 } 1822 1823 // Test that local candidates are added to the local session description and 1824 // that they are retained if the local session description is changed. 1825 TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) { 1826 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1827 Init(NULL); 1828 mediastream_signaling_.SendAudioVideoStream1(); 1829 CreateAndSetRemoteOfferAndLocalAnswer(); 1830 1831 const SessionDescriptionInterface* local_desc = session_->local_description(); 1832 const IceCandidateCollection* candidates = 1833 local_desc->candidates(kMediaContentIndex0); 1834 ASSERT_TRUE(candidates != NULL); 1835 EXPECT_EQ(0u, candidates->count()); 1836 1837 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1838 1839 local_desc = session_->local_description(); 1840 candidates = local_desc->candidates(kMediaContentIndex0); 1841 ASSERT_TRUE(candidates != NULL); 1842 EXPECT_LT(0u, candidates->count()); 1843 candidates = local_desc->candidates(1); 1844 ASSERT_TRUE(candidates != NULL); 1845 EXPECT_LT(0u, candidates->count()); 1846 1847 // Update the session descriptions. 1848 mediastream_signaling_.SendAudioVideoStream1(); 1849 CreateAndSetRemoteOfferAndLocalAnswer(); 1850 1851 local_desc = session_->local_description(); 1852 candidates = local_desc->candidates(kMediaContentIndex0); 1853 ASSERT_TRUE(candidates != NULL); 1854 EXPECT_LT(0u, candidates->count()); 1855 candidates = local_desc->candidates(1); 1856 ASSERT_TRUE(candidates != NULL); 1857 EXPECT_LT(0u, candidates->count()); 1858 } 1859 1860 // Test that we can set a remote session description with remote candidates. 1861 TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) { 1862 Init(NULL); 1863 1864 cricket::Candidate candidate1; 1865 candidate1.set_component(1); 1866 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 1867 candidate1); 1868 mediastream_signaling_.SendAudioVideoStream1(); 1869 SessionDescriptionInterface* offer = CreateOffer(); 1870 1871 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 1872 SetRemoteDescriptionWithoutError(offer); 1873 1874 const SessionDescriptionInterface* remote_desc = 1875 session_->remote_description(); 1876 ASSERT_TRUE(remote_desc != NULL); 1877 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 1878 const IceCandidateCollection* candidates = 1879 remote_desc->candidates(kMediaContentIndex0); 1880 ASSERT_EQ(1u, candidates->count()); 1881 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 1882 1883 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1884 SetLocalDescriptionWithoutError(answer); 1885 } 1886 1887 // Test that offers and answers contains ice candidates when Ice candidates have 1888 // been gathered. 1889 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) { 1890 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1891 Init(NULL); 1892 mediastream_signaling_.SendAudioVideoStream1(); 1893 // Ice is started but candidates are not provided until SetLocalDescription 1894 // is called. 1895 EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); 1896 EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); 1897 CreateAndSetRemoteOfferAndLocalAnswer(); 1898 // Wait until at least one local candidate has been collected. 1899 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(), 1900 kIceCandidatesTimeout); 1901 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(), 1902 kIceCandidatesTimeout); 1903 1904 rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer()); 1905 1906 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL); 1907 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count()); 1908 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL); 1909 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count()); 1910 1911 SessionDescriptionInterface* remote_offer(CreateRemoteOffer()); 1912 SetRemoteDescriptionWithoutError(remote_offer); 1913 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1914 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL); 1915 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count()); 1916 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL); 1917 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count()); 1918 SetLocalDescriptionWithoutError(answer); 1919 } 1920 1921 // Verifies TransportProxy and media channels are created with content names 1922 // present in the SessionDescription. 1923 TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) { 1924 Init(NULL); 1925 mediastream_signaling_.SendAudioVideoStream1(); 1926 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 1927 1928 // CreateOffer creates session description with the content names "audio" and 1929 // "video". Goal is to modify these content names and verify transport channel 1930 // proxy in the BaseSession, as proxies are created with the content names 1931 // present in SDP. 1932 std::string sdp; 1933 EXPECT_TRUE(offer->ToString(&sdp)); 1934 const std::string kAudioMid = "a=mid:audio"; 1935 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 1936 const std::string kVideoMid = "a=mid:video"; 1937 const std::string kVideoMidReplaceStr = "a=mid:video_content_name"; 1938 1939 // Replacing |audio| with |audio_content_name|. 1940 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 1941 kAudioMidReplaceStr.c_str(), 1942 kAudioMidReplaceStr.length(), 1943 &sdp); 1944 // Replacing |video| with |video_content_name|. 1945 rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(), 1946 kVideoMidReplaceStr.c_str(), 1947 kVideoMidReplaceStr.length(), 1948 &sdp); 1949 1950 SessionDescriptionInterface* modified_offer = 1951 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 1952 1953 SetRemoteDescriptionWithoutError(modified_offer); 1954 1955 SessionDescriptionInterface* answer = 1956 CreateAnswer(NULL); 1957 SetLocalDescriptionWithoutError(answer); 1958 1959 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL); 1960 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL); 1961 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL); 1962 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL); 1963 } 1964 1965 // Test that an offer contains the correct media content descriptions based on 1966 // the send streams when no constraints have been set. 1967 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) { 1968 Init(NULL); 1969 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 1970 1971 ASSERT_TRUE(offer != NULL); 1972 const cricket::ContentInfo* content = 1973 cricket::GetFirstAudioContent(offer->description()); 1974 EXPECT_TRUE(content != NULL); 1975 content = cricket::GetFirstVideoContent(offer->description()); 1976 EXPECT_TRUE(content == NULL); 1977 } 1978 1979 // Test that an offer contains the correct media content descriptions based on 1980 // the send streams when no constraints have been set. 1981 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) { 1982 Init(NULL); 1983 // Test Audio only offer. 1984 mediastream_signaling_.UseOptionsAudioOnly(); 1985 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 1986 1987 const cricket::ContentInfo* content = 1988 cricket::GetFirstAudioContent(offer->description()); 1989 EXPECT_TRUE(content != NULL); 1990 content = cricket::GetFirstVideoContent(offer->description()); 1991 EXPECT_TRUE(content == NULL); 1992 1993 // Test Audio / Video offer. 1994 mediastream_signaling_.SendAudioVideoStream1(); 1995 offer.reset(CreateOffer()); 1996 content = cricket::GetFirstAudioContent(offer->description()); 1997 EXPECT_TRUE(content != NULL); 1998 content = cricket::GetFirstVideoContent(offer->description()); 1999 EXPECT_TRUE(content != NULL); 2000 } 2001 2002 // Test that an offer contains no media content descriptions if 2003 // kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false. 2004 TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) { 2005 Init(NULL); 2006 PeerConnectionInterface::RTCOfferAnswerOptions options; 2007 options.offer_to_receive_audio = 0; 2008 options.offer_to_receive_video = 0; 2009 2010 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2011 CreateOffer(options)); 2012 2013 ASSERT_TRUE(offer != NULL); 2014 const cricket::ContentInfo* content = 2015 cricket::GetFirstAudioContent(offer->description()); 2016 EXPECT_TRUE(content == NULL); 2017 content = cricket::GetFirstVideoContent(offer->description()); 2018 EXPECT_TRUE(content == NULL); 2019 } 2020 2021 // Test that an offer contains only audio media content descriptions if 2022 // kOfferToReceiveAudio constraints are set to true. 2023 TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) { 2024 Init(NULL); 2025 PeerConnectionInterface::RTCOfferAnswerOptions options; 2026 options.offer_to_receive_audio = 2027 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2028 2029 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2030 CreateOffer(options)); 2031 2032 const cricket::ContentInfo* content = 2033 cricket::GetFirstAudioContent(offer->description()); 2034 EXPECT_TRUE(content != NULL); 2035 content = cricket::GetFirstVideoContent(offer->description()); 2036 EXPECT_TRUE(content == NULL); 2037 } 2038 2039 // Test that an offer contains audio and video media content descriptions if 2040 // kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true. 2041 TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) { 2042 Init(NULL); 2043 // Test Audio / Video offer. 2044 PeerConnectionInterface::RTCOfferAnswerOptions options; 2045 options.offer_to_receive_audio = 2046 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2047 options.offer_to_receive_video = 2048 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2049 2050 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2051 CreateOffer(options)); 2052 2053 const cricket::ContentInfo* content = 2054 cricket::GetFirstAudioContent(offer->description()); 2055 EXPECT_TRUE(content != NULL); 2056 2057 content = cricket::GetFirstVideoContent(offer->description()); 2058 EXPECT_TRUE(content != NULL); 2059 2060 // Sets constraints to false and verifies that audio/video contents are 2061 // removed. 2062 options.offer_to_receive_audio = 0; 2063 options.offer_to_receive_video = 0; 2064 offer.reset(CreateOffer(options)); 2065 2066 content = cricket::GetFirstAudioContent(offer->description()); 2067 EXPECT_TRUE(content == NULL); 2068 content = cricket::GetFirstVideoContent(offer->description()); 2069 EXPECT_TRUE(content == NULL); 2070 } 2071 2072 // Test that an answer can not be created if the last remote description is not 2073 // an offer. 2074 TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) { 2075 Init(NULL); 2076 SessionDescriptionInterface* offer = CreateOffer(); 2077 SetLocalDescriptionWithoutError(offer); 2078 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2079 SetRemoteDescriptionWithoutError(answer); 2080 EXPECT_TRUE(CreateAnswer(NULL) == NULL); 2081 } 2082 2083 // Test that an answer contains the correct media content descriptions when no 2084 // constraints have been set. 2085 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) { 2086 Init(NULL); 2087 // Create a remote offer with audio and video content. 2088 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2089 SetRemoteDescriptionWithoutError(offer.release()); 2090 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2091 CreateAnswer(NULL)); 2092 const cricket::ContentInfo* content = 2093 cricket::GetFirstAudioContent(answer->description()); 2094 ASSERT_TRUE(content != NULL); 2095 EXPECT_FALSE(content->rejected); 2096 2097 content = cricket::GetFirstVideoContent(answer->description()); 2098 ASSERT_TRUE(content != NULL); 2099 EXPECT_FALSE(content->rejected); 2100 } 2101 2102 // Test that an answer contains the correct media content descriptions when no 2103 // constraints have been set and the offer only contain audio. 2104 TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) { 2105 Init(NULL); 2106 // Create a remote offer with audio only. 2107 cricket::MediaSessionOptions options; 2108 2109 rtc::scoped_ptr<JsepSessionDescription> offer( 2110 CreateRemoteOffer(options)); 2111 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL); 2112 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL); 2113 2114 SetRemoteDescriptionWithoutError(offer.release()); 2115 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2116 CreateAnswer(NULL)); 2117 const cricket::ContentInfo* content = 2118 cricket::GetFirstAudioContent(answer->description()); 2119 ASSERT_TRUE(content != NULL); 2120 EXPECT_FALSE(content->rejected); 2121 2122 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL); 2123 } 2124 2125 // Test that an answer contains the correct media content descriptions when no 2126 // constraints have been set. 2127 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) { 2128 Init(NULL); 2129 // Create a remote offer with audio and video content. 2130 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2131 SetRemoteDescriptionWithoutError(offer.release()); 2132 // Test with a stream with tracks. 2133 mediastream_signaling_.SendAudioVideoStream1(); 2134 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2135 CreateAnswer(NULL)); 2136 const cricket::ContentInfo* content = 2137 cricket::GetFirstAudioContent(answer->description()); 2138 ASSERT_TRUE(content != NULL); 2139 EXPECT_FALSE(content->rejected); 2140 2141 content = cricket::GetFirstVideoContent(answer->description()); 2142 ASSERT_TRUE(content != NULL); 2143 EXPECT_FALSE(content->rejected); 2144 } 2145 2146 // Test that an answer contains the correct media content descriptions when 2147 // constraints have been set but no stream is sent. 2148 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) { 2149 Init(NULL); 2150 // Create a remote offer with audio and video content. 2151 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2152 SetRemoteDescriptionWithoutError(offer.release()); 2153 2154 webrtc::FakeConstraints constraints_no_receive; 2155 constraints_no_receive.SetMandatoryReceiveAudio(false); 2156 constraints_no_receive.SetMandatoryReceiveVideo(false); 2157 2158 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2159 CreateAnswer(&constraints_no_receive)); 2160 const cricket::ContentInfo* content = 2161 cricket::GetFirstAudioContent(answer->description()); 2162 ASSERT_TRUE(content != NULL); 2163 EXPECT_TRUE(content->rejected); 2164 2165 content = cricket::GetFirstVideoContent(answer->description()); 2166 ASSERT_TRUE(content != NULL); 2167 EXPECT_TRUE(content->rejected); 2168 } 2169 2170 // Test that an answer contains the correct media content descriptions when 2171 // constraints have been set and streams are sent. 2172 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) { 2173 Init(NULL); 2174 // Create a remote offer with audio and video content. 2175 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2176 SetRemoteDescriptionWithoutError(offer.release()); 2177 2178 webrtc::FakeConstraints constraints_no_receive; 2179 constraints_no_receive.SetMandatoryReceiveAudio(false); 2180 constraints_no_receive.SetMandatoryReceiveVideo(false); 2181 2182 // Test with a stream with tracks. 2183 mediastream_signaling_.SendAudioVideoStream1(); 2184 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2185 CreateAnswer(&constraints_no_receive)); 2186 2187 // TODO(perkj): Should the direction be set to SEND_ONLY? 2188 const cricket::ContentInfo* content = 2189 cricket::GetFirstAudioContent(answer->description()); 2190 ASSERT_TRUE(content != NULL); 2191 EXPECT_FALSE(content->rejected); 2192 2193 // TODO(perkj): Should the direction be set to SEND_ONLY? 2194 content = cricket::GetFirstVideoContent(answer->description()); 2195 ASSERT_TRUE(content != NULL); 2196 EXPECT_FALSE(content->rejected); 2197 } 2198 2199 TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) { 2200 AddCNCodecs(); 2201 Init(NULL); 2202 PeerConnectionInterface::RTCOfferAnswerOptions options; 2203 options.offer_to_receive_audio = 2204 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2205 options.voice_activity_detection = false; 2206 2207 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2208 CreateOffer(options)); 2209 2210 const cricket::ContentInfo* content = 2211 cricket::GetFirstAudioContent(offer->description()); 2212 EXPECT_TRUE(content != NULL); 2213 EXPECT_TRUE(VerifyNoCNCodecs(content)); 2214 } 2215 2216 TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) { 2217 AddCNCodecs(); 2218 Init(NULL); 2219 // Create a remote offer with audio and video content. 2220 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2221 SetRemoteDescriptionWithoutError(offer.release()); 2222 2223 webrtc::FakeConstraints constraints; 2224 constraints.SetOptionalVAD(false); 2225 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2226 CreateAnswer(&constraints)); 2227 const cricket::ContentInfo* content = 2228 cricket::GetFirstAudioContent(answer->description()); 2229 ASSERT_TRUE(content != NULL); 2230 EXPECT_TRUE(VerifyNoCNCodecs(content)); 2231 } 2232 2233 // This test verifies the call setup when remote answer with audio only and 2234 // later updates with video. 2235 TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) { 2236 Init(NULL); 2237 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 2238 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 2239 2240 mediastream_signaling_.SendAudioVideoStream1(); 2241 SessionDescriptionInterface* offer = CreateOffer(); 2242 2243 cricket::MediaSessionOptions options; 2244 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options); 2245 2246 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 2247 // and answer; 2248 SetLocalDescriptionWithoutError(offer); 2249 SetRemoteDescriptionWithoutError(answer); 2250 2251 video_channel_ = media_engine_->GetVideoChannel(0); 2252 voice_channel_ = media_engine_->GetVoiceChannel(0); 2253 2254 ASSERT_TRUE(video_channel_ == NULL); 2255 2256 ASSERT_EQ(0u, voice_channel_->recv_streams().size()); 2257 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2258 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id); 2259 2260 // Let the remote end update the session descriptions, with Audio and Video. 2261 mediastream_signaling_.SendAudioVideoStream2(); 2262 CreateAndSetRemoteOfferAndLocalAnswer(); 2263 2264 video_channel_ = media_engine_->GetVideoChannel(0); 2265 voice_channel_ = media_engine_->GetVoiceChannel(0); 2266 2267 ASSERT_TRUE(video_channel_ != NULL); 2268 ASSERT_TRUE(voice_channel_ != NULL); 2269 2270 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 2271 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2272 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 2273 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 2274 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2275 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2276 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2277 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2278 2279 // Change session back to audio only. 2280 mediastream_signaling_.UseOptionsAudioOnly(); 2281 CreateAndSetRemoteOfferAndLocalAnswer(); 2282 2283 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 2284 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2285 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2286 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2287 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2288 } 2289 2290 // This test verifies the call setup when remote answer with video only and 2291 // later updates with audio. 2292 TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) { 2293 Init(NULL); 2294 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 2295 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 2296 mediastream_signaling_.SendAudioVideoStream1(); 2297 SessionDescriptionInterface* offer = CreateOffer(); 2298 2299 cricket::MediaSessionOptions options; 2300 options.has_audio = false; 2301 options.has_video = true; 2302 SessionDescriptionInterface* answer = CreateRemoteAnswer( 2303 offer, options, cricket::SEC_ENABLED); 2304 2305 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 2306 // and answer. 2307 SetLocalDescriptionWithoutError(offer); 2308 SetRemoteDescriptionWithoutError(answer); 2309 2310 video_channel_ = media_engine_->GetVideoChannel(0); 2311 voice_channel_ = media_engine_->GetVoiceChannel(0); 2312 2313 ASSERT_TRUE(voice_channel_ == NULL); 2314 ASSERT_TRUE(video_channel_ != NULL); 2315 2316 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 2317 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2318 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id); 2319 2320 // Update the session descriptions, with Audio and Video. 2321 mediastream_signaling_.SendAudioVideoStream2(); 2322 CreateAndSetRemoteOfferAndLocalAnswer(); 2323 2324 voice_channel_ = media_engine_->GetVoiceChannel(0); 2325 ASSERT_TRUE(voice_channel_ != NULL); 2326 2327 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2328 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2329 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2330 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2331 2332 // Change session back to video only. 2333 mediastream_signaling_.UseOptionsVideoOnly(); 2334 CreateAndSetRemoteOfferAndLocalAnswer(); 2335 2336 video_channel_ = media_engine_->GetVideoChannel(0); 2337 voice_channel_ = media_engine_->GetVoiceChannel(0); 2338 2339 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 2340 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 2341 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2342 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 2343 } 2344 2345 TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) { 2346 Init(NULL); 2347 mediastream_signaling_.SendAudioVideoStream1(); 2348 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2349 VerifyCryptoParams(offer->description()); 2350 SetRemoteDescriptionWithoutError(offer.release()); 2351 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 2352 VerifyCryptoParams(answer->description()); 2353 } 2354 2355 TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) { 2356 options_.disable_encryption = true; 2357 Init(NULL); 2358 mediastream_signaling_.SendAudioVideoStream1(); 2359 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2360 VerifyNoCryptoParams(offer->description(), false); 2361 } 2362 2363 TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) { 2364 Init(NULL); 2365 VerifyAnswerFromNonCryptoOffer(); 2366 } 2367 2368 TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) { 2369 Init(NULL); 2370 VerifyAnswerFromCryptoOffer(); 2371 } 2372 2373 // This test verifies that setLocalDescription fails if 2374 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP. 2375 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) { 2376 Init(NULL); 2377 mediastream_signaling_.SendAudioVideoStream1(); 2378 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2379 2380 std::string sdp; 2381 RemoveIceUfragPwdLines(offer.get(), &sdp); 2382 SessionDescriptionInterface* modified_offer = 2383 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2384 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer); 2385 } 2386 2387 // This test verifies that setRemoteDescription fails if 2388 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP. 2389 TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) { 2390 Init(NULL); 2391 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 2392 std::string sdp; 2393 RemoveIceUfragPwdLines(offer.get(), &sdp); 2394 SessionDescriptionInterface* modified_offer = 2395 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2396 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer); 2397 } 2398 2399 // This test verifies that setLocalDescription fails if local offer has 2400 // too short ice ufrag and pwd strings. 2401 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) { 2402 Init(NULL); 2403 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245); 2404 mediastream_signaling_.SendAudioVideoStream1(); 2405 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2406 2407 std::string sdp; 2408 // Modifying ice ufrag and pwd in local offer with strings smaller than the 2409 // recommended values of 4 and 22 bytes respectively. 2410 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp); 2411 SessionDescriptionInterface* modified_offer = 2412 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2413 std::string error; 2414 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error)); 2415 2416 // Test with string greater than 256. 2417 sdp.clear(); 2418 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd, 2419 &sdp); 2420 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp, 2421 NULL); 2422 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error)); 2423 } 2424 2425 // This test verifies that setRemoteDescription fails if remote offer has 2426 // too short ice ufrag and pwd strings. 2427 TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) { 2428 Init(NULL); 2429 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245); 2430 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 2431 std::string sdp; 2432 // Modifying ice ufrag and pwd in remote offer with strings smaller than the 2433 // recommended values of 4 and 22 bytes respectively. 2434 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp); 2435 SessionDescriptionInterface* modified_offer = 2436 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2437 std::string error; 2438 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error)); 2439 2440 sdp.clear(); 2441 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd, 2442 &sdp); 2443 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp, 2444 NULL); 2445 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error)); 2446 } 2447 2448 TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) { 2449 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in 2450 // local description is removed by the application, BUNDLE flag should be 2451 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc. 2452 Init(NULL); 2453 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & 2454 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE); 2455 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2456 2457 cricket::SessionDescription* offer_copy = 2458 offer->description()->Copy(); 2459 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 2460 JsepSessionDescription* modified_offer = 2461 new JsepSessionDescription(JsepSessionDescription::kOffer); 2462 modified_offer->Initialize(offer_copy, "1", "1"); 2463 2464 SetLocalDescriptionWithoutError(modified_offer); 2465 EXPECT_FALSE(allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE); 2466 } 2467 2468 TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) { 2469 Init(NULL); 2470 mediastream_signaling_.SendAudioVideoStream1(); 2471 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & 2472 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE); 2473 2474 PeerConnectionInterface::RTCOfferAnswerOptions options; 2475 options.use_rtp_mux = true; 2476 2477 SessionDescriptionInterface* offer = CreateOffer(options); 2478 2479 SetLocalDescriptionWithoutError(offer); 2480 mediastream_signaling_.SendAudioVideoStream2(); 2481 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2482 CreateRemoteAnswer(session_->local_description())); 2483 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 2484 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 2485 JsepSessionDescription* modified_answer = 2486 new JsepSessionDescription(JsepSessionDescription::kAnswer); 2487 modified_answer->Initialize(answer_copy, "1", "1"); 2488 SetRemoteDescriptionWithoutError(modified_answer); 2489 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & 2490 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE); 2491 2492 video_channel_ = media_engine_->GetVideoChannel(0); 2493 voice_channel_ = media_engine_->GetVoiceChannel(0); 2494 2495 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 2496 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 2497 2498 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2499 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 2500 2501 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2502 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 2503 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2504 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 2505 } 2506 2507 // This test verifies that SetLocalDescription and SetRemoteDescription fails 2508 // if BUNDLE is enabled but rtcp-mux is disabled in m-lines. 2509 TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) { 2510 WebRtcSessionTest::Init(NULL); 2511 mediastream_signaling_.SendAudioVideoStream1(); 2512 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & 2513 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE); 2514 2515 PeerConnectionInterface::RTCOfferAnswerOptions options; 2516 options.use_rtp_mux = true; 2517 2518 SessionDescriptionInterface* offer = CreateOffer(options); 2519 std::string offer_str; 2520 offer->ToString(&offer_str); 2521 // Disable rtcp-mux 2522 const std::string rtcp_mux = "rtcp-mux"; 2523 const std::string xrtcp_mux = "xrtcp-mux"; 2524 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(), 2525 xrtcp_mux.c_str(), xrtcp_mux.length(), 2526 &offer_str); 2527 JsepSessionDescription *local_offer = 2528 new JsepSessionDescription(JsepSessionDescription::kOffer); 2529 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL)); 2530 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer); 2531 JsepSessionDescription *remote_offer = 2532 new JsepSessionDescription(JsepSessionDescription::kOffer); 2533 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL)); 2534 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer); 2535 // Trying unmodified SDP. 2536 SetLocalDescriptionWithoutError(offer); 2537 } 2538 2539 TEST_F(WebRtcSessionTest, SetAudioPlayout) { 2540 Init(NULL); 2541 mediastream_signaling_.SendAudioVideoStream1(); 2542 CreateAndSetRemoteOfferAndLocalAnswer(); 2543 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2544 ASSERT_TRUE(channel != NULL); 2545 ASSERT_EQ(1u, channel->recv_streams().size()); 2546 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc(); 2547 double left_vol, right_vol; 2548 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 2549 EXPECT_EQ(1, left_vol); 2550 EXPECT_EQ(1, right_vol); 2551 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 2552 session_->SetAudioPlayout(receive_ssrc, false, renderer.get()); 2553 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 2554 EXPECT_EQ(0, left_vol); 2555 EXPECT_EQ(0, right_vol); 2556 EXPECT_EQ(0, renderer->channel_id()); 2557 session_->SetAudioPlayout(receive_ssrc, true, NULL); 2558 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol)); 2559 EXPECT_EQ(1, left_vol); 2560 EXPECT_EQ(1, right_vol); 2561 EXPECT_EQ(-1, renderer->channel_id()); 2562 } 2563 2564 TEST_F(WebRtcSessionTest, SetAudioSend) { 2565 Init(NULL); 2566 mediastream_signaling_.SendAudioVideoStream1(); 2567 CreateAndSetRemoteOfferAndLocalAnswer(); 2568 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2569 ASSERT_TRUE(channel != NULL); 2570 ASSERT_EQ(1u, channel->send_streams().size()); 2571 uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2572 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2573 2574 cricket::AudioOptions options; 2575 options.echo_cancellation.Set(true); 2576 2577 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 2578 session_->SetAudioSend(send_ssrc, false, options, renderer.get()); 2579 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 2580 EXPECT_FALSE(channel->options().echo_cancellation.IsSet()); 2581 EXPECT_EQ(0, renderer->channel_id()); 2582 EXPECT_TRUE(renderer->sink() != NULL); 2583 2584 // This will trigger SetSink(NULL) to the |renderer|. 2585 session_->SetAudioSend(send_ssrc, true, options, NULL); 2586 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2587 bool value; 2588 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value)); 2589 EXPECT_TRUE(value); 2590 EXPECT_EQ(-1, renderer->channel_id()); 2591 EXPECT_TRUE(renderer->sink() == NULL); 2592 } 2593 2594 TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) { 2595 Init(NULL); 2596 mediastream_signaling_.SendAudioVideoStream1(); 2597 CreateAndSetRemoteOfferAndLocalAnswer(); 2598 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2599 ASSERT_TRUE(channel != NULL); 2600 ASSERT_EQ(1u, channel->send_streams().size()); 2601 uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2602 2603 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 2604 cricket::AudioOptions options; 2605 session_->SetAudioSend(send_ssrc, true, options, renderer.get()); 2606 EXPECT_TRUE(renderer->sink() != NULL); 2607 2608 // Delete the |renderer| and it will trigger OnClose() to the sink, and this 2609 // will invalidate the |renderer_| pointer in the sink and prevent getting a 2610 // SetSink(NULL) callback afterwards. 2611 renderer.reset(); 2612 2613 // This will trigger SetSink(NULL) if no OnClose() callback. 2614 session_->SetAudioSend(send_ssrc, true, options, NULL); 2615 } 2616 2617 TEST_F(WebRtcSessionTest, SetVideoPlayout) { 2618 Init(NULL); 2619 mediastream_signaling_.SendAudioVideoStream1(); 2620 CreateAndSetRemoteOfferAndLocalAnswer(); 2621 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 2622 ASSERT_TRUE(channel != NULL); 2623 ASSERT_LT(0u, channel->renderers().size()); 2624 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 2625 ASSERT_EQ(1u, channel->recv_streams().size()); 2626 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc(); 2627 cricket::FakeVideoRenderer renderer; 2628 session_->SetVideoPlayout(receive_ssrc, true, &renderer); 2629 EXPECT_TRUE(channel->renderers().begin()->second == &renderer); 2630 session_->SetVideoPlayout(receive_ssrc, false, &renderer); 2631 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 2632 } 2633 2634 TEST_F(WebRtcSessionTest, SetVideoSend) { 2635 Init(NULL); 2636 mediastream_signaling_.SendAudioVideoStream1(); 2637 CreateAndSetRemoteOfferAndLocalAnswer(); 2638 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 2639 ASSERT_TRUE(channel != NULL); 2640 ASSERT_EQ(1u, channel->send_streams().size()); 2641 uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2642 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2643 cricket::VideoOptions* options = NULL; 2644 session_->SetVideoSend(send_ssrc, false, options); 2645 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 2646 session_->SetVideoSend(send_ssrc, true, options); 2647 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 2648 } 2649 2650 TEST_F(WebRtcSessionTest, CanNotInsertDtmf) { 2651 TestCanInsertDtmf(false); 2652 } 2653 2654 TEST_F(WebRtcSessionTest, CanInsertDtmf) { 2655 TestCanInsertDtmf(true); 2656 } 2657 2658 TEST_F(WebRtcSessionTest, InsertDtmf) { 2659 // Setup 2660 Init(NULL); 2661 mediastream_signaling_.SendAudioVideoStream1(); 2662 CreateAndSetRemoteOfferAndLocalAnswer(); 2663 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 2664 EXPECT_EQ(0U, channel->dtmf_info_queue().size()); 2665 2666 // Insert DTMF 2667 const int expected_flags = DF_SEND; 2668 const int expected_duration = 90; 2669 session_->InsertDtmf(kAudioTrack1, 0, expected_duration); 2670 session_->InsertDtmf(kAudioTrack1, 1, expected_duration); 2671 session_->InsertDtmf(kAudioTrack1, 2, expected_duration); 2672 2673 // Verify 2674 ASSERT_EQ(3U, channel->dtmf_info_queue().size()); 2675 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc(); 2676 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0, 2677 expected_duration, expected_flags)); 2678 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1, 2679 expected_duration, expected_flags)); 2680 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2, 2681 expected_duration, expected_flags)); 2682 } 2683 2684 // This test verifies the |initiator| flag when session initiates the call. 2685 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) { 2686 Init(NULL); 2687 EXPECT_FALSE(session_->initiator()); 2688 SessionDescriptionInterface* offer = CreateOffer(); 2689 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2690 SetLocalDescriptionWithoutError(offer); 2691 EXPECT_TRUE(session_->initiator()); 2692 SetRemoteDescriptionWithoutError(answer); 2693 EXPECT_TRUE(session_->initiator()); 2694 } 2695 2696 // This test verifies the |initiator| flag when session receives the call. 2697 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) { 2698 Init(NULL); 2699 EXPECT_FALSE(session_->initiator()); 2700 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2701 SetRemoteDescriptionWithoutError(offer); 2702 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2703 2704 EXPECT_FALSE(session_->initiator()); 2705 SetLocalDescriptionWithoutError(answer); 2706 EXPECT_FALSE(session_->initiator()); 2707 } 2708 2709 // This test verifies the ice protocol type at initiator of the call 2710 // if |a=ice-options:google-ice| is present in answer. 2711 TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) { 2712 Init(NULL); 2713 mediastream_signaling_.SendAudioVideoStream1(); 2714 SessionDescriptionInterface* offer = CreateOffer(); 2715 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2716 CreateRemoteAnswer(offer)); 2717 SetLocalDescriptionWithoutError(offer); 2718 std::string sdp; 2719 EXPECT_TRUE(answer->ToString(&sdp)); 2720 // Adding ice-options to the session level. 2721 InjectAfter("t=0 0\r\n", 2722 "a=ice-options:google-ice\r\n", 2723 &sdp); 2724 SessionDescriptionInterface* answer_with_gice = 2725 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2726 SetRemoteDescriptionWithoutError(answer_with_gice); 2727 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE); 2728 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE); 2729 } 2730 2731 // This test verifies the ice protocol type at initiator of the call 2732 // if ICE RFC5245 is supported in answer. 2733 TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) { 2734 Init(NULL); 2735 mediastream_signaling_.SendAudioVideoStream1(); 2736 SessionDescriptionInterface* offer = CreateOffer(); 2737 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2738 SetLocalDescriptionWithoutError(offer); 2739 2740 SetRemoteDescriptionWithoutError(answer); 2741 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245); 2742 VerifyTransportType("video", cricket::ICEPROTO_RFC5245); 2743 } 2744 2745 // This test verifies the ice protocol type at receiver side of the call if 2746 // receiver decides to use google-ice. 2747 TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) { 2748 Init(NULL); 2749 mediastream_signaling_.SendAudioVideoStream1(); 2750 SessionDescriptionInterface* offer = CreateOffer(); 2751 SetRemoteDescriptionWithoutError(offer); 2752 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2753 CreateAnswer(NULL)); 2754 std::string sdp; 2755 EXPECT_TRUE(answer->ToString(&sdp)); 2756 // Adding ice-options to the session level. 2757 InjectAfter("t=0 0\r\n", 2758 "a=ice-options:google-ice\r\n", 2759 &sdp); 2760 SessionDescriptionInterface* answer_with_gice = 2761 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2762 SetLocalDescriptionWithoutError(answer_with_gice); 2763 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE); 2764 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE); 2765 } 2766 2767 // This test verifies the ice protocol type at receiver side of the call if 2768 // receiver decides to use ice RFC 5245. 2769 TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) { 2770 Init(NULL); 2771 mediastream_signaling_.SendAudioVideoStream1(); 2772 SessionDescriptionInterface* offer = CreateOffer(); 2773 SetRemoteDescriptionWithoutError(offer); 2774 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2775 SetLocalDescriptionWithoutError(answer); 2776 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245); 2777 VerifyTransportType("video", cricket::ICEPROTO_RFC5245); 2778 } 2779 2780 // This test verifies the session state when ICE RFC5245 in offer and 2781 // ICE google-ice in answer. 2782 TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) { 2783 Init(NULL); 2784 mediastream_signaling_.SendAudioVideoStream1(); 2785 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2786 2787 std::string offer_str; 2788 offer->ToString(&offer_str); 2789 // Disable google-ice 2790 const std::string gice_option = "google-ice"; 2791 const std::string xgoogle_xice = "xgoogle-xice"; 2792 rtc::replace_substrs(gice_option.c_str(), gice_option.length(), 2793 xgoogle_xice.c_str(), xgoogle_xice.length(), 2794 &offer_str); 2795 JsepSessionDescription *ice_only_offer = 2796 new JsepSessionDescription(JsepSessionDescription::kOffer); 2797 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL)); 2798 SetLocalDescriptionWithoutError(ice_only_offer); 2799 std::string original_offer_sdp; 2800 EXPECT_TRUE(offer->ToString(&original_offer_sdp)); 2801 SessionDescriptionInterface* pranswer_with_gice = 2802 CreateSessionDescription(JsepSessionDescription::kPrAnswer, 2803 original_offer_sdp, NULL); 2804 SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed, 2805 pranswer_with_gice); 2806 SessionDescriptionInterface* answer_with_gice = 2807 CreateSessionDescription(JsepSessionDescription::kAnswer, 2808 original_offer_sdp, NULL); 2809 SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed, 2810 answer_with_gice); 2811 } 2812 2813 // Verifing local offer and remote answer have matching m-lines as per RFC 3264. 2814 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) { 2815 Init(NULL); 2816 mediastream_signaling_.SendAudioVideoStream1(); 2817 SessionDescriptionInterface* offer = CreateOffer(); 2818 SetLocalDescriptionWithoutError(offer); 2819 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2820 CreateRemoteAnswer(session_->local_description())); 2821 2822 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 2823 answer_copy->RemoveContentByName("video"); 2824 JsepSessionDescription* modified_answer = 2825 new JsepSessionDescription(JsepSessionDescription::kAnswer); 2826 2827 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 2828 answer->session_id(), 2829 answer->session_version())); 2830 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer); 2831 2832 // Different content names. 2833 std::string sdp; 2834 EXPECT_TRUE(answer->ToString(&sdp)); 2835 const std::string kAudioMid = "a=mid:audio"; 2836 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 2837 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 2838 kAudioMidReplaceStr.c_str(), 2839 kAudioMidReplaceStr.length(), 2840 &sdp); 2841 SessionDescriptionInterface* modified_answer1 = 2842 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2843 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1); 2844 2845 // Different media types. 2846 EXPECT_TRUE(answer->ToString(&sdp)); 2847 const std::string kAudioMline = "m=audio"; 2848 const std::string kAudioMlineReplaceStr = "m=video"; 2849 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(), 2850 kAudioMlineReplaceStr.c_str(), 2851 kAudioMlineReplaceStr.length(), 2852 &sdp); 2853 SessionDescriptionInterface* modified_answer2 = 2854 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 2855 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2); 2856 2857 SetRemoteDescriptionWithoutError(answer.release()); 2858 } 2859 2860 // Verifying remote offer and local answer have matching m-lines as per 2861 // RFC 3264. 2862 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) { 2863 Init(NULL); 2864 mediastream_signaling_.SendAudioVideoStream1(); 2865 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2866 SetRemoteDescriptionWithoutError(offer); 2867 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2868 2869 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 2870 answer_copy->RemoveContentByName("video"); 2871 JsepSessionDescription* modified_answer = 2872 new JsepSessionDescription(JsepSessionDescription::kAnswer); 2873 2874 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 2875 answer->session_id(), 2876 answer->session_version())); 2877 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer); 2878 SetLocalDescriptionWithoutError(answer); 2879 } 2880 2881 // This test verifies that WebRtcSession does not start candidate allocation 2882 // before SetLocalDescription is called. 2883 TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) { 2884 Init(NULL); 2885 mediastream_signaling_.SendAudioVideoStream1(); 2886 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2887 cricket::Candidate candidate; 2888 candidate.set_component(1); 2889 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 2890 candidate); 2891 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 2892 cricket::Candidate candidate1; 2893 candidate1.set_component(1); 2894 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1, 2895 candidate1); 2896 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1)); 2897 SetRemoteDescriptionWithoutError(offer); 2898 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL); 2899 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL); 2900 2901 // Pump for 1 second and verify that no candidates are generated. 2902 rtc::Thread::Current()->ProcessMessages(1000); 2903 EXPECT_TRUE(observer_.mline_0_candidates_.empty()); 2904 EXPECT_TRUE(observer_.mline_1_candidates_.empty()); 2905 2906 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2907 SetLocalDescriptionWithoutError(answer); 2908 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated()); 2909 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated()); 2910 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 2911 } 2912 2913 // This test verifies that crypto parameter is updated in local session 2914 // description as per security policy set in MediaSessionDescriptionFactory. 2915 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) { 2916 Init(NULL); 2917 mediastream_signaling_.SendAudioVideoStream1(); 2918 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2919 2920 // Making sure SetLocalDescription correctly sets crypto value in 2921 // SessionDescription object after de-serialization of sdp string. The value 2922 // will be set as per MediaSessionDescriptionFactory. 2923 std::string offer_str; 2924 offer->ToString(&offer_str); 2925 SessionDescriptionInterface* jsep_offer_str = 2926 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 2927 SetLocalDescriptionWithoutError(jsep_offer_str); 2928 EXPECT_TRUE(session_->voice_channel()->secure_required()); 2929 EXPECT_TRUE(session_->video_channel()->secure_required()); 2930 } 2931 2932 // This test verifies the crypto parameter when security is disabled. 2933 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) { 2934 options_.disable_encryption = true; 2935 Init(NULL); 2936 mediastream_signaling_.SendAudioVideoStream1(); 2937 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2938 2939 // Making sure SetLocalDescription correctly sets crypto value in 2940 // SessionDescription object after de-serialization of sdp string. The value 2941 // will be set as per MediaSessionDescriptionFactory. 2942 std::string offer_str; 2943 offer->ToString(&offer_str); 2944 SessionDescriptionInterface *jsep_offer_str = 2945 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 2946 SetLocalDescriptionWithoutError(jsep_offer_str); 2947 EXPECT_FALSE(session_->voice_channel()->secure_required()); 2948 EXPECT_FALSE(session_->video_channel()->secure_required()); 2949 } 2950 2951 // This test verifies that an answer contains new ufrag and password if an offer 2952 // with new ufrag and password is received. 2953 TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { 2954 Init(NULL); 2955 cricket::MediaSessionOptions options; 2956 options.has_video = true; 2957 rtc::scoped_ptr<JsepSessionDescription> offer( 2958 CreateRemoteOffer(options)); 2959 SetRemoteDescriptionWithoutError(offer.release()); 2960 2961 mediastream_signaling_.SendAudioVideoStream1(); 2962 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2963 CreateAnswer(NULL)); 2964 SetLocalDescriptionWithoutError(answer.release()); 2965 2966 // Receive an offer with new ufrag and password. 2967 options.transport_options.ice_restart = true; 2968 rtc::scoped_ptr<JsepSessionDescription> updated_offer1( 2969 CreateRemoteOffer(options, session_->remote_description())); 2970 SetRemoteDescriptionWithoutError(updated_offer1.release()); 2971 2972 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer1( 2973 CreateAnswer(NULL)); 2974 2975 CompareIceUfragAndPassword(updated_answer1->description(), 2976 session_->local_description()->description(), 2977 false); 2978 2979 SetLocalDescriptionWithoutError(updated_answer1.release()); 2980 } 2981 2982 // This test verifies that an answer contains old ufrag and password if an offer 2983 // with old ufrag and password is received. 2984 TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) { 2985 Init(NULL); 2986 cricket::MediaSessionOptions options; 2987 options.has_video = true; 2988 rtc::scoped_ptr<JsepSessionDescription> offer( 2989 CreateRemoteOffer(options)); 2990 SetRemoteDescriptionWithoutError(offer.release()); 2991 2992 mediastream_signaling_.SendAudioVideoStream1(); 2993 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2994 CreateAnswer(NULL)); 2995 SetLocalDescriptionWithoutError(answer.release()); 2996 2997 // Receive an offer without changed ufrag or password. 2998 options.transport_options.ice_restart = false; 2999 rtc::scoped_ptr<JsepSessionDescription> updated_offer2( 3000 CreateRemoteOffer(options, session_->remote_description())); 3001 SetRemoteDescriptionWithoutError(updated_offer2.release()); 3002 3003 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer2( 3004 CreateAnswer(NULL)); 3005 3006 CompareIceUfragAndPassword(updated_answer2->description(), 3007 session_->local_description()->description(), 3008 true); 3009 3010 SetLocalDescriptionWithoutError(updated_answer2.release()); 3011 } 3012 3013 TEST_F(WebRtcSessionTest, TestSessionContentError) { 3014 Init(NULL); 3015 mediastream_signaling_.SendAudioVideoStream1(); 3016 SessionDescriptionInterface* offer = CreateOffer(); 3017 const std::string session_id_orig = offer->session_id(); 3018 const std::string session_version_orig = offer->session_version(); 3019 SetLocalDescriptionWithoutError(offer); 3020 3021 video_channel_ = media_engine_->GetVideoChannel(0); 3022 video_channel_->set_fail_set_send_codecs(true); 3023 3024 mediastream_signaling_.SendAudioVideoStream2(); 3025 SessionDescriptionInterface* answer = 3026 CreateRemoteAnswer(session_->local_description()); 3027 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer); 3028 } 3029 3030 // Runs the loopback call test with BUNDLE and STUN disabled. 3031 TEST_F(WebRtcSessionTest, TestIceStatesBasic) { 3032 // Lets try with only UDP ports. 3033 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | 3034 cricket::PORTALLOCATOR_DISABLE_TCP | 3035 cricket::PORTALLOCATOR_DISABLE_STUN | 3036 cricket::PORTALLOCATOR_DISABLE_RELAY); 3037 TestLoopbackCall(); 3038 } 3039 3040 // Runs the loopback call test with BUNDLE and STUN enabled. 3041 TEST_F(WebRtcSessionTest, TestIceStatesBundle) { 3042 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | 3043 cricket::PORTALLOCATOR_ENABLE_BUNDLE | 3044 cricket::PORTALLOCATOR_DISABLE_TCP | 3045 cricket::PORTALLOCATOR_DISABLE_RELAY); 3046 TestLoopbackCall(); 3047 } 3048 3049 TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) { 3050 Init(NULL); 3051 cricket::MediaSessionOptions options; 3052 options.has_video = true; 3053 3054 cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT; 3055 std::string error_code_str = "ERROR_CONTENT"; 3056 std::string error_desc = "Fake session error description."; 3057 session_->SetError(error_code, error_desc); 3058 3059 SessionDescriptionInterface* offer = CreateRemoteOffer(options); 3060 SessionDescriptionInterface* answer = 3061 CreateRemoteAnswer(offer, options); 3062 3063 std::string action; 3064 std::ostringstream session_error_msg; 3065 session_error_msg << kSessionError << error_code_str << ". "; 3066 session_error_msg << kSessionErrorDesc << error_desc << "."; 3067 SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer); 3068 SetLocalDescriptionExpectError(action, session_error_msg.str(), answer); 3069 } 3070 3071 TEST_F(WebRtcSessionTest, TestRtpDataChannel) { 3072 constraints_.reset(new FakeConstraints()); 3073 constraints_->AddOptional( 3074 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 3075 Init(NULL); 3076 3077 SetLocalDescriptionWithDataChannel(); 3078 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 3079 } 3080 3081 TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) { 3082 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3083 3084 constraints_.reset(new FakeConstraints()); 3085 constraints_->AddOptional( 3086 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 3087 options_.disable_sctp_data_channels = false; 3088 3089 InitWithDtls(); 3090 3091 SetLocalDescriptionWithDataChannel(); 3092 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 3093 } 3094 3095 TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) { 3096 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3097 3098 InitWithDtls(); 3099 3100 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3101 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL); 3102 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL); 3103 } 3104 3105 TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) { 3106 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3107 SetFactoryDtlsSrtp(); 3108 InitWithDtls(); 3109 3110 // Create remote offer with SCTP. 3111 cricket::MediaSessionOptions options; 3112 options.data_channel_type = cricket::DCT_SCTP; 3113 JsepSessionDescription* offer = 3114 CreateRemoteOffer(options, cricket::SEC_DISABLED); 3115 SetRemoteDescriptionWithoutError(offer); 3116 3117 // Verifies the answer contains SCTP. 3118 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 3119 EXPECT_TRUE(answer != NULL); 3120 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL); 3121 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL); 3122 } 3123 3124 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) { 3125 constraints_.reset(new FakeConstraints()); 3126 constraints_->AddOptional( 3127 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false); 3128 InitWithDtls(); 3129 3130 SetLocalDescriptionWithDataChannel(); 3131 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type()); 3132 } 3133 3134 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) { 3135 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3136 3137 InitWithDtls(); 3138 3139 SetLocalDescriptionWithDataChannel(); 3140 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 3141 } 3142 3143 TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) { 3144 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3145 options_.disable_sctp_data_channels = true; 3146 InitWithDtls(); 3147 3148 SetLocalDescriptionWithDataChannel(); 3149 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type()); 3150 } 3151 3152 TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) { 3153 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3154 const int new_send_port = 9998; 3155 const int new_recv_port = 7775; 3156 3157 InitWithDtls(); 3158 SetFactoryDtlsSrtp(); 3159 3160 // By default, don't actually add the codecs to desc_factory_; they don't 3161 // actually get serialized for SCTP in BuildMediaDescription(). Instead, 3162 // let the session description get parsed. That'll get the proper codecs 3163 // into the stream. 3164 cricket::MediaSessionOptions options; 3165 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort( 3166 "stream1", new_send_port, options); 3167 3168 // SetRemoteDescription will take the ownership of the offer. 3169 SetRemoteDescriptionWithoutError(offer); 3170 3171 SessionDescriptionInterface* answer = ChangeSDPSctpPort( 3172 new_recv_port, CreateAnswer(NULL)); 3173 ASSERT_TRUE(answer != NULL); 3174 3175 // Now set the local description, which'll take ownership of the answer. 3176 SetLocalDescriptionWithoutError(answer); 3177 3178 // TEST PLAN: Set the port number to something new, set it in the SDP, 3179 // and pass it all the way down. 3180 webrtc::InternalDataChannelInit dci; 3181 dci.reliable = true; 3182 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 3183 rtc::scoped_refptr<webrtc::DataChannel> dc = 3184 session_->CreateDataChannel("datachannel", &dci); 3185 3186 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0); 3187 int portnum = -1; 3188 ASSERT_TRUE(ch != NULL); 3189 ASSERT_EQ(1UL, ch->send_codecs().size()); 3190 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id); 3191 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName, 3192 ch->send_codecs()[0].name.c_str())); 3193 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort, 3194 &portnum)); 3195 EXPECT_EQ(new_send_port, portnum); 3196 3197 ASSERT_EQ(1UL, ch->recv_codecs().size()); 3198 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id); 3199 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName, 3200 ch->recv_codecs()[0].name.c_str())); 3201 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort, 3202 &portnum)); 3203 EXPECT_EQ(new_recv_port, portnum); 3204 } 3205 3206 // Verifies that CreateOffer succeeds when CreateOffer is called before async 3207 // identity generation is finished. 3208 TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) { 3209 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3210 InitWithDtls(); 3211 3212 EXPECT_TRUE(session_->waiting_for_identity()); 3213 mediastream_signaling_.SendAudioVideoStream1(); 3214 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3215 3216 EXPECT_TRUE(offer != NULL); 3217 VerifyNoCryptoParams(offer->description(), true); 3218 VerifyFingerprintStatus(offer->description(), true); 3219 } 3220 3221 // Verifies that CreateAnswer succeeds when CreateOffer is called before async 3222 // identity generation is finished. 3223 TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) { 3224 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3225 InitWithDtls(); 3226 SetFactoryDtlsSrtp(); 3227 3228 cricket::MediaSessionOptions options; 3229 options.has_video = true; 3230 scoped_ptr<JsepSessionDescription> offer( 3231 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 3232 ASSERT_TRUE(offer.get() != NULL); 3233 SetRemoteDescriptionWithoutError(offer.release()); 3234 3235 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 3236 EXPECT_TRUE(answer != NULL); 3237 VerifyNoCryptoParams(answer->description(), true); 3238 VerifyFingerprintStatus(answer->description(), true); 3239 } 3240 3241 // Verifies that CreateOffer succeeds when CreateOffer is called after async 3242 // identity generation is finished. 3243 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) { 3244 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3245 InitWithDtls(); 3246 3247 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000); 3248 3249 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3250 EXPECT_TRUE(offer != NULL); 3251 } 3252 3253 // Verifies that CreateOffer fails when CreateOffer is called after async 3254 // identity generation fails. 3255 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) { 3256 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3257 InitWithDtls(true); 3258 3259 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000); 3260 3261 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3262 EXPECT_TRUE(offer == NULL); 3263 } 3264 3265 // Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made 3266 // before async identity generation is finished. 3267 TEST_F(WebRtcSessionTest, 3268 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) { 3269 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3270 VerifyMultipleAsyncCreateDescription( 3271 true, CreateSessionDescriptionRequest::kOffer); 3272 } 3273 3274 // Verifies that CreateOffer fails when Multiple CreateOffer calls are made 3275 // before async identity generation fails. 3276 TEST_F(WebRtcSessionTest, 3277 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) { 3278 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3279 VerifyMultipleAsyncCreateDescription( 3280 false, CreateSessionDescriptionRequest::kOffer); 3281 } 3282 3283 // Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made 3284 // before async identity generation is finished. 3285 TEST_F(WebRtcSessionTest, 3286 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) { 3287 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3288 VerifyMultipleAsyncCreateDescription( 3289 true, CreateSessionDescriptionRequest::kAnswer); 3290 } 3291 3292 // Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made 3293 // before async identity generation fails. 3294 TEST_F(WebRtcSessionTest, 3295 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) { 3296 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3297 VerifyMultipleAsyncCreateDescription( 3298 false, CreateSessionDescriptionRequest::kAnswer); 3299 } 3300 3301 // Verifies that setRemoteDescription fails when DTLS is disabled and the remote 3302 // offer has no SDES crypto but only DTLS fingerprint. 3303 TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) { 3304 // Init without DTLS. 3305 Init(NULL); 3306 // Create a remote offer with secured transport disabled. 3307 cricket::MediaSessionOptions options; 3308 JsepSessionDescription* offer(CreateRemoteOffer( 3309 options, cricket::SEC_DISABLED)); 3310 // Adds a DTLS fingerprint to the remote offer. 3311 cricket::SessionDescription* sdp = offer->description(); 3312 TransportInfo* audio = sdp->GetTransportInfoByName("audio"); 3313 ASSERT_TRUE(audio != NULL); 3314 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL); 3315 audio->description.identity_fingerprint.reset( 3316 rtc::SSLFingerprint::CreateFromRfc4572( 3317 rtc::DIGEST_SHA_256, kFakeDtlsFingerprint)); 3318 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, 3319 offer); 3320 } 3321 3322 // This test verifies DSCP is properly applied on the media channels. 3323 TEST_F(WebRtcSessionTest, TestDscpConstraint) { 3324 constraints_.reset(new FakeConstraints()); 3325 constraints_->AddOptional( 3326 webrtc::MediaConstraintsInterface::kEnableDscp, true); 3327 Init(NULL); 3328 mediastream_signaling_.SendAudioVideoStream1(); 3329 SessionDescriptionInterface* offer = CreateOffer(); 3330 3331 SetLocalDescriptionWithoutError(offer); 3332 3333 video_channel_ = media_engine_->GetVideoChannel(0); 3334 voice_channel_ = media_engine_->GetVoiceChannel(0); 3335 3336 ASSERT_TRUE(video_channel_ != NULL); 3337 ASSERT_TRUE(voice_channel_ != NULL); 3338 cricket::AudioOptions audio_options; 3339 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options)); 3340 cricket::VideoOptions video_options; 3341 EXPECT_TRUE(video_channel_->GetOptions(&video_options)); 3342 EXPECT_TRUE(audio_options.dscp.IsSet()); 3343 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false)); 3344 EXPECT_TRUE(video_options.dscp.IsSet()); 3345 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false)); 3346 } 3347 3348 TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) { 3349 constraints_.reset(new FakeConstraints()); 3350 constraints_->AddOptional( 3351 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate, 3352 true); 3353 Init(NULL); 3354 mediastream_signaling_.SendAudioVideoStream1(); 3355 SessionDescriptionInterface* offer = CreateOffer(); 3356 3357 SetLocalDescriptionWithoutError(offer); 3358 3359 video_channel_ = media_engine_->GetVideoChannel(0); 3360 3361 ASSERT_TRUE(video_channel_ != NULL); 3362 cricket::VideoOptions video_options; 3363 EXPECT_TRUE(video_channel_->GetOptions(&video_options)); 3364 EXPECT_TRUE( 3365 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)); 3366 } 3367 3368 TEST_F(WebRtcSessionTest, TestNumUnsignalledRecvStreamsConstraint) { 3369 // Number of unsignalled receiving streams should be between 0 and 3370 // kMaxUnsignalledRecvStreams. 3371 SetAndVerifyNumUnsignalledRecvStreams(10, 10); 3372 SetAndVerifyNumUnsignalledRecvStreams(kMaxUnsignalledRecvStreams + 1, 3373 kMaxUnsignalledRecvStreams); 3374 SetAndVerifyNumUnsignalledRecvStreams(-1, 0); 3375 } 3376 3377 TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) { 3378 constraints_.reset(new FakeConstraints()); 3379 constraints_->AddOptional( 3380 webrtc::MediaConstraintsInterface::kCombinedAudioVideoBwe, 3381 true); 3382 Init(NULL); 3383 mediastream_signaling_.SendAudioVideoStream1(); 3384 SessionDescriptionInterface* offer = CreateOffer(); 3385 3386 SetLocalDescriptionWithoutError(offer); 3387 3388 voice_channel_ = media_engine_->GetVoiceChannel(0); 3389 3390 ASSERT_TRUE(voice_channel_ != NULL); 3391 cricket::AudioOptions audio_options; 3392 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options)); 3393 EXPECT_TRUE( 3394 audio_options.combined_audio_video_bwe.GetWithDefaultIfUnset(false)); 3395 } 3396 3397 // Tests that we can renegotiate new media content with ICE candidates in the 3398 // new remote SDP. 3399 TEST_F(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) { 3400 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3401 InitWithDtls(); 3402 SetFactoryDtlsSrtp(); 3403 3404 mediastream_signaling_.UseOptionsAudioOnly(); 3405 SessionDescriptionInterface* offer = CreateOffer(); 3406 SetLocalDescriptionWithoutError(offer); 3407 3408 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 3409 SetRemoteDescriptionWithoutError(answer); 3410 3411 cricket::MediaSessionOptions options; 3412 options.has_video = true; 3413 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 3414 3415 cricket::Candidate candidate1; 3416 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000)); 3417 candidate1.set_component(1); 3418 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1, 3419 candidate1); 3420 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 3421 SetRemoteDescriptionWithoutError(offer); 3422 3423 answer = CreateAnswer(NULL); 3424 SetLocalDescriptionWithoutError(answer); 3425 } 3426 3427 // Tests that we can renegotiate new media content with ICE candidates separated 3428 // from the remote SDP. 3429 TEST_F(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) { 3430 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3431 InitWithDtls(); 3432 SetFactoryDtlsSrtp(); 3433 3434 mediastream_signaling_.UseOptionsAudioOnly(); 3435 SessionDescriptionInterface* offer = CreateOffer(); 3436 SetLocalDescriptionWithoutError(offer); 3437 3438 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 3439 SetRemoteDescriptionWithoutError(answer); 3440 3441 cricket::MediaSessionOptions options; 3442 options.has_video = true; 3443 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 3444 SetRemoteDescriptionWithoutError(offer); 3445 3446 cricket::Candidate candidate1; 3447 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000)); 3448 candidate1.set_component(1); 3449 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1, 3450 candidate1); 3451 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate)); 3452 3453 answer = CreateAnswer(NULL); 3454 SetLocalDescriptionWithoutError(answer); 3455 } 3456 3457 // TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test 3458 // currently fails because upon disconnection and reconnection OnIceComplete is 3459 // called more than once without returning to IceGatheringGathering. 3460